mirror of
https://github.com/ful1e5/Bibata_Cursor.git
synced 2025-05-23 11:36:55 -04:00
🔥 Bibata Core Package
This commit is contained in:
parent
656bb2bb0d
commit
afe7211306
10 changed files with 1 additions and 1 deletions
25
packages/core/package.json
Normal file
25
packages/core/package.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "bibata-core",
|
||||
"version": "1.0.0",
|
||||
"description": "Common code inside Bibata Project",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"author": "Kaiz Khatri",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/chalk": "^2.2.0",
|
||||
"@types/ora": "^3.2.0",
|
||||
"@types/pixelmatch": "^5.2.1",
|
||||
"@types/pngjs": "^3.4.2",
|
||||
"@types/puppeteer": "^3.0.1",
|
||||
"typescript": "^3.9.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.0",
|
||||
"ora": "^5.0.0",
|
||||
"pixelmatch": "^5.2.1",
|
||||
"pngjs": "^5.0.0",
|
||||
"puppeteer": "^5.2.1"
|
||||
}
|
||||
}
|
4
packages/core/src/index.ts
Normal file
4
packages/core/src/index.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
import { renderCursors } from "./render";
|
||||
import { spinner } from "./utils/spinner";
|
||||
|
||||
export { spinner, renderCursors };
|
127
packages/core/src/render.ts
Normal file
127
packages/core/src/render.ts
Normal file
|
@ -0,0 +1,127 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
import chalk from "chalk";
|
||||
import puppeteer from "puppeteer";
|
||||
|
||||
import { generateRenderTemplate } from "./utils/htmlTemplate";
|
||||
import { matchImages } from "./utils/matchImages";
|
||||
import { saveFrames } from "./utils/saveFrames";
|
||||
import { getKeyName } from "./utils/getKeyName";
|
||||
import { spinner } from "./utils/spinner";
|
||||
import { Config, Frames } from "./types";
|
||||
|
||||
const renderCursors = async (configs: Record<string, Config>) => {
|
||||
const browser = await puppeteer.launch({
|
||||
ignoreDefaultArgs: [" --single-process ", "--no-sandbox"],
|
||||
headless: true
|
||||
});
|
||||
|
||||
let outDir = "";
|
||||
for (let [
|
||||
schema,
|
||||
{ bitmapsDir, staticCursors, animatedCursors }
|
||||
] of Object.entries(configs)) {
|
||||
// Checking Bitmaps Dir
|
||||
if (!fs.existsSync(bitmapsDir)) {
|
||||
fs.mkdirSync(bitmapsDir);
|
||||
}
|
||||
|
||||
// Spinner
|
||||
spinner.text = `Generating ${chalk.magentaBright(schema)} bitmaps ...`;
|
||||
spinner.start();
|
||||
|
||||
// Render
|
||||
try {
|
||||
for (let svgPath of staticCursors) {
|
||||
const buffer = fs.readFileSync(path.resolve(svgPath), "utf8");
|
||||
if (!buffer) throw new Error(`${svgPath} File Read error`);
|
||||
|
||||
// Generating HTML Template
|
||||
const data = buffer.toString();
|
||||
const template = generateRenderTemplate(data);
|
||||
|
||||
// config
|
||||
const bitmapName = `${path.basename(svgPath, ".svg")}.png`;
|
||||
const out = path.resolve(bitmapsDir, bitmapName);
|
||||
|
||||
// Render
|
||||
const page = await browser.newPage();
|
||||
await page.setContent(template);
|
||||
|
||||
await page.waitForSelector("#container");
|
||||
const svgElement = await page.$("#container svg");
|
||||
if (!svgElement) throw new Error("svg element not found");
|
||||
await svgElement.screenshot({ omitBackground: true, path: out });
|
||||
|
||||
await page.close();
|
||||
}
|
||||
|
||||
for (let svgPath of animatedCursors) {
|
||||
const buffer = fs.readFileSync(svgPath, "utf8");
|
||||
if (!buffer) throw new Error(`${svgPath} File Read error`);
|
||||
|
||||
// Generating HTML Template
|
||||
const data = buffer.toString();
|
||||
const template = generateRenderTemplate(data);
|
||||
|
||||
const page = await browser.newPage();
|
||||
await page.setContent(template, { waitUntil: "networkidle2" });
|
||||
|
||||
await page.waitForSelector("#container");
|
||||
const svgElement = await page.$("#container svg");
|
||||
if (!svgElement) throw new Error("svg element not found");
|
||||
|
||||
// Render Config
|
||||
let index = 1;
|
||||
let breakRendering = false;
|
||||
const frames: Frames = {};
|
||||
const firstKey = getKeyName(index, svgPath);
|
||||
|
||||
console.log("Rendering", path.basename(svgPath), "...");
|
||||
console.log(firstKey);
|
||||
|
||||
// 1st Frame
|
||||
frames[firstKey] = {
|
||||
buffer: await svgElement.screenshot({
|
||||
omitBackground: true,
|
||||
encoding: "binary"
|
||||
})
|
||||
};
|
||||
|
||||
// Pushing frames until it match to 1st frame
|
||||
index++;
|
||||
while (!breakRendering) {
|
||||
const newFrame = await svgElement.screenshot({
|
||||
omitBackground: true,
|
||||
encoding: "binary"
|
||||
});
|
||||
const key = getKeyName(index, svgPath);
|
||||
console.log(key);
|
||||
const diff = matchImages({
|
||||
img1Buff: frames[firstKey].buffer,
|
||||
img2Buff: newFrame
|
||||
});
|
||||
|
||||
if (!(diff < 700)) {
|
||||
frames[key] = { buffer: newFrame };
|
||||
} else {
|
||||
breakRendering = true;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
saveFrames({ frames, bitmapsDir });
|
||||
|
||||
await page.close();
|
||||
}
|
||||
spinner.succeed();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
spinner.fail();
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
console.log(`🎉 Bitmaps stored at ${chalk.greenBright(outDir)}`);
|
||||
};
|
||||
|
||||
export { renderCursors };
|
13
packages/core/src/types.ts
Normal file
13
packages/core/src/types.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
interface Config {
|
||||
staticCursors: string[];
|
||||
animatedCursors: string[];
|
||||
bitmapsDir: string;
|
||||
}
|
||||
|
||||
interface Frames {
|
||||
[fileName: string]: {
|
||||
buffer: Buffer;
|
||||
};
|
||||
}
|
||||
|
||||
export { Config, Frames };
|
14
packages/core/src/utils/getKeyName.ts
Normal file
14
packages/core/src/utils/getKeyName.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import path from "path";
|
||||
|
||||
export const frameNumber = (index: number, endIndex: number) => {
|
||||
let result = "" + index;
|
||||
while (result.length < endIndex) {
|
||||
result = "0" + result;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export const getKeyName = (index: number, fileName: string) => {
|
||||
const frame = frameNumber(index, 2);
|
||||
return `${path.basename(fileName, ".svg")}-${frame}.png`;
|
||||
};
|
19
packages/core/src/utils/htmlTemplate.ts
Normal file
19
packages/core/src/utils/htmlTemplate.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
export const template = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Eggy Render Template</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<svginjection>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
export const generateRenderTemplate = (svg: string) =>
|
||||
template.replace("<svginjection>", svg);
|
19
packages/core/src/utils/matchImages.ts
Normal file
19
packages/core/src/utils/matchImages.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { PNG } from "pngjs";
|
||||
import pixelmatch from "pixelmatch";
|
||||
|
||||
interface MatchImagesArgs {
|
||||
img1Buff: Buffer;
|
||||
img2Buff: Buffer;
|
||||
}
|
||||
|
||||
export const matchImages = ({ img1Buff, img2Buff }: MatchImagesArgs) => {
|
||||
const img1 = PNG.sync.read(img1Buff);
|
||||
const img2 = PNG.sync.read(img2Buff);
|
||||
const { width, height } = img1;
|
||||
|
||||
const diff = new PNG({ width, height });
|
||||
|
||||
return pixelmatch(img1.data, img2.data, diff.data, width, height, {
|
||||
threshold: 0.25
|
||||
});
|
||||
};
|
15
packages/core/src/utils/saveFrames.ts
Normal file
15
packages/core/src/utils/saveFrames.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { Frames } from "../types";
|
||||
|
||||
interface SaveFramesArgs {
|
||||
frames: Frames;
|
||||
bitmapsDir: string;
|
||||
}
|
||||
|
||||
export const saveFrames = ({ frames, bitmapsDir }: SaveFramesArgs) => {
|
||||
for (let [fileName, { buffer }] of Object.entries(frames)) {
|
||||
const out_path = path.resolve(bitmapsDir, fileName);
|
||||
fs.writeFileSync(out_path, buffer, { encoding: "binary" });
|
||||
}
|
||||
};
|
9
packages/core/src/utils/spinner.ts
Normal file
9
packages/core/src/utils/spinner.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import ora from "ora";
|
||||
|
||||
const spinner = ora();
|
||||
|
||||
spinner.color = "yellow";
|
||||
|
||||
spinner.spinner = { interval: 150, frames: ["📷", "📸"] };
|
||||
|
||||
export { spinner };
|
12
packages/core/tsconfig.json
Normal file
12
packages/core/tsconfig.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"composite": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue