Skip to content

Commit

Permalink
optimize svg loading, run tsc in lint to check types, don't include e…
Browse files Browse the repository at this point in the history
…xtra copies of the fonts in the assets folder
  • Loading branch information
easrng committed May 30, 2024
1 parent 8342b1e commit 70379f0
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 44 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"main": "index.js",
"scripts": {
"test": "jest test/*",
"lint": "eslint \"./src\" \"./test\" --ext .js,.ts",
"lint": "tsc && eslint \"./src\" \"./test\" --ext .js,.ts",
"build": "rollup -c rollup.config.js",
"watch": "rollup --watch -c rollup.config.js",
"dev": "rollup --watch -c rollup.config.js & sirv ./ --port 8000 -D"
Expand Down
2 changes: 1 addition & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default {
typescript({noEmitOnError: !process.env.ROLLUP_WATCH}),
copy({
targets: [
{ src: 'src/assets/**/*', dest: 'dist/assets' }
{ src: 'src/assets/*', dest: 'dist/assets' }
]
})
]
Expand Down
7 changes: 4 additions & 3 deletions src/html/loading-screen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,14 @@ const loadingScreenTemplate = h('template',
position: absolute;
top: 0;
left: 0;
right: 100%;
right: 0;
bottom: 0;
background-color: rgba(22, 117, 206, 1);
transform: translateX(-100%);
}
#loading-bar-progress.active {
/* transition: right 0.05s linear; */
/* transition: ease 0.05s linear; */
}
#error-message {
Expand Down Expand Up @@ -140,7 +141,7 @@ export class LoadingScreenElement extends HTMLElement {
const progress = this.totalAssets === 0 ?
0 :
this.loadedAssets / this.totalAssets;
loadingBarProgress.style.right = `${(1 - progress) * 100}%`;
loadingBarProgress.style.transform = `translateX(-${(1 - progress) * 100}%)`;
}
}

Expand Down
78 changes: 40 additions & 38 deletions src/load-svg.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Rectangle from './rectangle.js';
import toBase64 from './util/to-base64.js';

const fonts = {
'Sans Serif': './assets/fonts/NotoSans-Medium.woff2',
Expand All @@ -13,39 +12,39 @@ const fonts = {

type FontName = keyof typeof fonts;

const loadedFonts: Record<FontName, Promise<string> | null> = {
'Sans Serif': null,
'Serif': null,
'Handwriting': null,
'Marker': null,
'Curly': null,
'Pixel': null,
'Scratch': null,
};
const isFont = Object.prototype.hasOwnProperty.bind(fonts) as (font: unknown) => font is keyof typeof fonts;

const fontPromises: Partial<Record<FontName, Promise<void>>> = {};

const fontURLs: Partial<Record<FontName, string>> = {};

// Load fonts for SVG costumes on-demand.
const loadFonts = async(fontNames: Iterable<string>): Promise<Record<FontName, string>> => {
const loadFonts = async(fontNames: Iterable<string>) => {
const promises: Promise<void>[] = [];
for (const name of fontNames) {
if (!Object.prototype.hasOwnProperty.call(loadedFonts, name)) {
if (!isFont(name)) {
continue;
}
if (loadedFonts[name as FontName] === null) {
loadedFonts[name as FontName] = fetch(import.meta.resolve(fonts[name as FontName]))
.then(response => response.blob())
.then(blob => blob.arrayBuffer())
.then(buffer => {
const base64 = toBase64(new Uint8Array(buffer));
return `data:font/woff2;base64,${base64}`;
});
}
}

const fontURLs = {} as Record<FontName, string>;
const fontPromises = await Promise.all(Object.values(loadedFonts));
for (let i = 0; i < fontPromises.length; i++) {
fontURLs[Object.keys(loadedFonts)[i] as FontName] = fontPromises[i]!;
const cachedPromise = fontPromises[name];
promises.push(
!cachedPromise ?
fontPromises[name] = fetch(import.meta.resolve(fonts[name]))
.then(response => response.blob())
.then(blob => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
fontURLs[name] = reader.result as string;
resolve();
};
reader.onerror = () => {
reject(reader.error);
};
reader.readAsDataURL(blob);
})) :
cachedPromise,
);
}
return fontURLs;
await Promise.all(promises);
};

const loadSVG = async(src: Blob): Promise<{url: string; viewBox: Rectangle}> => {
Expand Down Expand Up @@ -89,22 +88,25 @@ const loadSVG = async(src: Blob): Promise<{url: string; viewBox: Rectangle}> =>
}

if (foundFonts.size > 0) {
const fontURLs = await loadFonts(foundFonts.values());
await loadFonts(foundFonts.values());

const css = [];

// Inject fonts as data URLs into the SVG
for (const fontName of foundFonts) {
if (!Object.prototype.hasOwnProperty.call(fonts, fontName)) {
continue;
const fontURL = isFont(fontName) && fontURLs[fontName];
if (fontURL) {
css.push("@font-face{font-family:'", fontName, "';src:url('", fontURL, "')}");
}
const defs = svgDOM.createElementNS('http://www.w3.org/2000/svg', 'defs');
const style = svgDOM.createElementNS('http://www.w3.org/2000/svg', 'style');
style.setAttribute('type', 'text/css');
defs.appendChild(style);
const fontURL = fontURLs[fontName as FontName];
style.append(`@font-face { font-family: '${fontName}'; src: url(${JSON.stringify(fontURL)}); }`);
svgTag.insertBefore(defs, svgTag.firstChild);
}

const defs = svgDOM.createElementNS('http://www.w3.org/2000/svg', 'defs');
const style = svgDOM.createElementNS('http://www.w3.org/2000/svg', 'style');
style.setAttribute('type', 'text/css');
defs.appendChild(style);
style.append(...css);
svgTag.insertBefore(defs, svgTag.firstChild);

src = new Blob([new XMLSerializer().serializeToString(svgDOM)], {type: 'image/svg+xml'});
}
}
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
"sourceMap": true,
"strictNullChecks": true,
"strict": true,
"skipLibCheck": true,
"module": "Node16",
"target": "ES2022",
"noErrorTruncation": true,
"outDir": "dist",
"noEmit": true,
"lib": ["ESNext", "dom"]
},
"include": ["src/**/*", "test/**/*", "./*.cjs"]
Expand Down

0 comments on commit 70379f0

Please sign in to comment.