mirror of
https://github.com/excalidraw/excalidraw.git
synced 2024-11-02 03:25:53 +01:00
Build tweaks for server-side, fixes - WIP
This commit is contained in:
parent
6ce17a80c4
commit
1e19a446b8
@ -62,10 +62,8 @@ export class ExcalidrawFontFace implements IExcalidrawFontFace {
|
||||
|
||||
return new Promise<string>((resolve) => {
|
||||
this.getContent(codePoints).then((content) => {
|
||||
resolve(`@font-face {
|
||||
font-family: ${this.fontFace.family};
|
||||
src: url(${content});
|
||||
}`);
|
||||
resolve(`
|
||||
@font-face { font-family: ${this.fontFace.family}; src: url(${content}); }`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -15,16 +15,13 @@ const load = (): Promise<{
|
||||
}> => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
WebAssembly.instantiate(binary).then((module) => {
|
||||
const module = await WebAssembly.instantiate(binary);
|
||||
const harfbuzzJsWasm = module.instance.exports;
|
||||
// @ts-expect-error since `.buffer` is custom prop
|
||||
const heapu8 = new Uint8Array(harfbuzzJsWasm.memory.buffer);
|
||||
|
||||
const hbSubset = {
|
||||
subset: (
|
||||
fontBuffer: ArrayBuffer,
|
||||
codePoints: ReadonlySet<number>,
|
||||
) => {
|
||||
subset: (fontBuffer: ArrayBuffer, codePoints: ReadonlySet<number>) => {
|
||||
return bindings.subset(
|
||||
harfbuzzJsWasm,
|
||||
heapu8,
|
||||
@ -35,7 +32,6 @@ const load = (): Promise<{
|
||||
};
|
||||
|
||||
resolve(hbSubset);
|
||||
});
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ const Module = (function () {
|
||||
moduleOverrides[key] = Module[key];
|
||||
}
|
||||
}
|
||||
|
||||
let arguments_ = [];
|
||||
let thisProgram = "./this.program";
|
||||
let quit_ = function (status, toThrow) {
|
||||
@ -3917,6 +3918,7 @@ const Module = (function () {
|
||||
let calledRun;
|
||||
Module.then = function (func) {
|
||||
if (calledRun) {
|
||||
throw new Error("1 This error should be silently swallowed");
|
||||
func(Module);
|
||||
} else {
|
||||
const old = Module.onRuntimeInitialized;
|
||||
@ -3924,6 +3926,7 @@ const Module = (function () {
|
||||
if (old) {
|
||||
old();
|
||||
}
|
||||
throw new Error("This error should be silently swallowed 1");
|
||||
func(Module);
|
||||
};
|
||||
}
|
||||
@ -4046,3 +4049,5 @@ const Module = (function () {
|
||||
})();
|
||||
|
||||
export default Module;
|
||||
|
||||
|
||||
|
@ -15,12 +15,6 @@ const load = (): Promise<{
|
||||
}> => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
// initializing the module manually, so that we could pass in the wasm binary
|
||||
bindings({ wasmBinary: binary }).then(
|
||||
(module: {
|
||||
woff2Enc: (buffer: ArrayBuffer, byteLength: number) => Vector;
|
||||
woff2Dec: (buffer: ArrayBuffer, byteLength: number) => Vector;
|
||||
}) => {
|
||||
// re-map from internal vector into byte array
|
||||
function convertFromVecToUint8Array(vector: Vector): Uint8Array {
|
||||
const arr = [];
|
||||
@ -31,6 +25,13 @@ const load = (): Promise<{
|
||||
return new Uint8Array(arr);
|
||||
}
|
||||
|
||||
// TODO_CHINESE: bindings implements .then, but rejections will still likely be not caught
|
||||
// initializing the module manually, so that we could pass in the wasm binary
|
||||
const module: {
|
||||
woff2Enc: (buffer: ArrayBuffer, byteLength: number) => Vector;
|
||||
woff2Dec: (buffer: ArrayBuffer, byteLength: number) => Vector;
|
||||
} = await bindings({ wasmBinary: binary });
|
||||
|
||||
// re-exporting only compress and decompress functions (also avoids infinite loop inside emscripten bindings)
|
||||
const woff2 = {
|
||||
compress: (buffer: ArrayBuffer) =>
|
||||
@ -44,8 +45,6 @@ const load = (): Promise<{
|
||||
};
|
||||
|
||||
resolve(woff2);
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ export class WorkerPool<T, R> {
|
||||
},
|
||||
) {
|
||||
this.workerUrl = workerUrl;
|
||||
// by default, active & idle workers will be terminated after 10 seconds of inactivity
|
||||
this.workerTTL = options.ttl || 10_000;
|
||||
// by default, active & idle workers will be terminated after 5 seconds of inactivity
|
||||
this.workerTTL = options.ttl || 5_000;
|
||||
|
||||
this.initWorker = options.initWorker;
|
||||
}
|
||||
|
@ -82,7 +82,6 @@ const rawConfig = {
|
||||
entryPoints: ["index.ts"],
|
||||
bundle: true,
|
||||
format: "esm",
|
||||
packages: "external",
|
||||
};
|
||||
|
||||
// const BASE_PATH = `${path.resolve(`${__dirname}/..`)}`;
|
||||
|
6
scripts/woff2/assets/CHANGELOG.md
Normal file
6
scripts/woff2/assets/CHANGELOG.md
Normal file
@ -0,0 +1,6 @@
|
||||
# 1. Created "XiaolaiNotoEmoji" through FontForge
|
||||
|
||||
- Merged `XiaolaiSC-Regular.ttf` with `NotoEmoji-Regular.ttf` (kept in the codebasefor future reference)
|
||||
- Adjusted glyphs of the merged font to fit the Em box
|
||||
- Added merged copyright & license
|
||||
- Generated versions for different Em sizes 1000 and 2048 (otherwise pyftmerge throws)
|
BIN
scripts/woff2/assets/XiaolaiNotoEmoji-1000.ttf
Normal file
BIN
scripts/woff2/assets/XiaolaiNotoEmoji-1000.ttf
Normal file
Binary file not shown.
BIN
scripts/woff2/assets/XiaolaiNotoEmoji-2048.ttf
Normal file
BIN
scripts/woff2/assets/XiaolaiNotoEmoji-2048.ttf
Normal file
Binary file not shown.
BIN
scripts/woff2/assets/XiaolaiSC-Regular.ttf
Normal file
BIN
scripts/woff2/assets/XiaolaiSC-Regular.ttf
Normal file
Binary file not shown.
@ -47,7 +47,7 @@ module.exports.woff2BrowserPlugin = () => {
|
||||
* 2. convert all the imported fonts (including those from cdn) at build time into .ttf (since Resvg does not support woff2, neither inlined dataurls - https://github.com/RazrFalcon/resvg/issues/541)
|
||||
* - merging multiple woff2 into one ttf (for same families with different unicode ranges)
|
||||
* - deduplicating glyphs due to the merge process
|
||||
* - merging emoji font for each
|
||||
* - merging fallback font for each
|
||||
* - printing out font metrics
|
||||
*
|
||||
* @returns {import("esbuild").Plugin}
|
||||
@ -176,6 +176,11 @@ module.exports.woff2ServerPlugin = (options = {}) => {
|
||||
|
||||
// for now we are interested in the regular families only
|
||||
for (const [family, { Regular }] of sortedFonts) {
|
||||
if (family === "Xiaolai SC") {
|
||||
// don't generate ttf for Xiaolai SC, as we have it hardcoded
|
||||
continue;
|
||||
}
|
||||
|
||||
const baseFont = Regular[0];
|
||||
|
||||
const tempFilePaths = Regular.map((_, index) =>
|
||||
@ -192,41 +197,34 @@ module.exports.woff2ServerPlugin = (options = {}) => {
|
||||
fs.writeFileSync(tempFilePaths[index], font.write({ type: "ttf" }));
|
||||
}
|
||||
|
||||
const emojiFilePath = path.resolve(
|
||||
const fallbackFilePath2048 = path.resolve(
|
||||
__dirname,
|
||||
"./assets/NotoEmoji-Regular.ttf",
|
||||
);
|
||||
|
||||
const emojiBuffer = fs.readFileSync(emojiFilePath);
|
||||
const emojiFont = Font.create(emojiBuffer, { type: "ttf" });
|
||||
|
||||
// hack so that:
|
||||
// - emoji font has same metrics as the base font, otherwise pyftmerge throws due to different unitsPerEm
|
||||
// - emoji font glyphs are adjusted based to the base font glyphs, otherwise the glyphs don't match
|
||||
const patchedEmojiFont = Font.create({
|
||||
...baseFont.data,
|
||||
glyf: baseFont.find({ unicode: [65] }), // adjust based on the "A" glyph (does not have to be first)
|
||||
}).merge(emojiFont, { adjustGlyf: true });
|
||||
|
||||
const emojiTempFilePath = path.resolve(
|
||||
outputDir,
|
||||
`temp_${family}_Emoji.ttf`,
|
||||
);
|
||||
fs.writeFileSync(
|
||||
emojiTempFilePath,
|
||||
patchedEmojiFont.write({ type: "ttf" }),
|
||||
"./assets/XiaolaiNotoEmoji-2048.ttf",
|
||||
);
|
||||
const fallbackFilePath1000 = path.resolve(
|
||||
__dirname,
|
||||
"./assets/XiaolaiNotoEmoji-1000.ttf",
|
||||
);
|
||||
|
||||
const fallbackBuffer = fs.readFileSync(fallbackFilePath2048);
|
||||
const fallbackFont = Font.create(fallbackBuffer, { type: "ttf" });
|
||||
const mergedFontPath = path.resolve(outputDir, `${family}.ttf`);
|
||||
|
||||
if (baseFont.data.head.unitsPerEm !== 1000) {
|
||||
execSync(
|
||||
`pyftmerge --output-file="${mergedFontPath}" "${tempFilePaths.join(
|
||||
'" "',
|
||||
)}" "${emojiTempFilePath}"`,
|
||||
)}" "${fallbackFilePath2048}"`,
|
||||
);
|
||||
} else {
|
||||
execSync(
|
||||
`pyftmerge --output-file="${mergedFontPath}" "${tempFilePaths.join(
|
||||
'" "',
|
||||
)}" "${fallbackFilePath1000}"`,
|
||||
);
|
||||
}
|
||||
|
||||
// cleanup
|
||||
fs.rmSync(emojiTempFilePath);
|
||||
for (const path of tempFilePaths) {
|
||||
fs.rmSync(path);
|
||||
}
|
||||
@ -243,8 +241,8 @@ module.exports.woff2ServerPlugin = (options = {}) => {
|
||||
...mergedFont.data,
|
||||
name: {
|
||||
...mergedFont.data.name,
|
||||
copyright: `${baseFont.data.name.copyright} & ${emojiFont.data.name.copyright}`,
|
||||
licence: `${baseFont.data.name.licence} & ${emojiFont.data.name.licence}`,
|
||||
copyright: `${baseFont.data.name.copyright} & ${fallbackFont.data.name.copyright}`,
|
||||
licence: `${baseFont.data.name.licence} & ${fallbackFont.data.name.licence}`,
|
||||
},
|
||||
});
|
||||
|
||||
@ -255,7 +253,7 @@ module.exports.woff2ServerPlugin = (options = {}) => {
|
||||
console.info(`Generated "${family}"`);
|
||||
if (Regular.length > 1) {
|
||||
console.info(
|
||||
`- by merging ${Regular.length} woff2 files and 1 emoji ttf file`,
|
||||
`- by merging ${Regular.length} woff2 files and 1 fallback ttf file`,
|
||||
);
|
||||
}
|
||||
console.info(
|
||||
|
Loading…
Reference in New Issue
Block a user