🔥 Bibata Core Package

This commit is contained in:
ful1e5 2020-08-31 17:38:23 +05:30
parent 656bb2bb0d
commit afe7211306
10 changed files with 1 additions and 1 deletions

View 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"
}
}

View 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
View 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 };

View file

@ -0,0 +1,13 @@
interface Config {
staticCursors: string[];
animatedCursors: string[];
bitmapsDir: string;
}
interface Frames {
[fileName: string]: {
buffer: Buffer;
};
}
export { Config, Frames };

View 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`;
};

View 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);

View 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
});
};

View 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" });
}
};

View file

@ -0,0 +1,9 @@
import ora from "ora";
const spinner = ora();
spinner.color = "yellow";
spinner.spinner = { interval: 150, frames: ["📷", "📸"] };
export { spinner };

View file

@ -0,0 +1,12 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"composite": true,
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
}