From eb819535f61a06a170991952d2f174a787caaff7 Mon Sep 17 00:00:00 2001 From: squidfunk Date: Sun, 21 Feb 2021 17:35:11 +0100 Subject: [PATCH] Added asset manifest generation --- src/assets/stylesheets/main/_typeset.scss | 4 +- src/base.html | 4 +- tools/index.ts | 63 +++++++++++++++++------ tools/resolve/index.ts | 22 ++++++++ 4 files changed, 74 insertions(+), 19 deletions(-) diff --git a/src/assets/stylesheets/main/_typeset.scss b/src/assets/stylesheets/main/_typeset.scss index 31f6cb6aa..00513453c 100644 --- a/src/assets/stylesheets/main/_typeset.scss +++ b/src/assets/stylesheets/main/_typeset.scss @@ -36,7 +36,7 @@ input { color: var(--md-typeset-color); font-feature-settings: "kern", "liga"; font-family: - var(--md-text-font-family,) + var(--md-text-font-family, _), -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif; } @@ -47,7 +47,7 @@ kbd { color: var(--md-typeset-color); font-feature-settings: "kern"; font-family: - var(--md-code-font-family,) + var(--md-code-font-family, _), SFMono-Regular, Consolas, Menlo, monospace; } diff --git a/src/base.html b/src/base.html index 110ca287c..9a4d5892b 100644 --- a/src/base.html +++ b/src/base.html @@ -120,8 +120,8 @@ /> {% endif %} diff --git a/tools/index.ts b/tools/index.ts index 4c3903f9d..2f5f05d14 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -24,17 +24,21 @@ import { createHash } from "crypto" import * as fs from "fs/promises" import { minify as minhtml } from "html-minifier" import * as path from "path" -import { concat, defer, from, merge, of } from "rxjs" +import { EMPTY, concat, defer, from, merge, of } from "rxjs" import { concatMap, map, + mergeMap, switchMap, - takeWhile + toArray } from "rxjs/operators" -import { extendDefaultPlugins, optimize } from "svgo" +import { + extendDefaultPlugins, + optimize +} from "svgo" -import { copyAll } from "./copy" -import { base, resolve } from "./resolve" +import { copy, copyAll } from "./copy" +import { base, cachebust, resolve } from "./resolve" import { transformScript, transformStyle @@ -176,24 +180,53 @@ const javascripts$ = resolve("**/{bundle,search}.ts", { cwd: "src" }) ) /* Add content hashes to assets and replace occurrences */ -const manifest$ = defer(() => resolve(`${base}/**/*.{css,js}`) +const manifest$ = defer(() => process.argv.includes("--optimize") + ? resolve("**/*.{css,js}", { cwd: base }) + : EMPTY +) .pipe( - takeWhile(() => process.argv.includes("--optimize")), - concatMap(asset => from(fs.readFile(asset, "utf8")) + concatMap(file => from(fs.readFile(`${base}/${file}`, "utf8")) .pipe( map(data => createHash("sha256").update(data).digest("hex")), - switchMap(hash => of(`${asset}`, `${asset}.map`) + switchMap(hash => of(`${file}`, `${file}.map`) .pipe( - switchMap(file => fs.rename( - file, - file.replace(/\b(?=\.)/, `.${hash.slice(0, 8)}.min`) - )) + concatMap(part => cachebust(part, hash, { cwd: base })) ) ) ) - ) + ), + toArray(), + map(tuples => new Map(tuples)), + mergeMap(manifest => concat( + + // TODO: split this into two. manifest + cachebust! + ...["base.html", "overrides/main.html"] + .map(file => copy({ + src: `${base}/${file}`, + out: `${base}/${file}`, + transform: async data => [...manifest.entries()] + .reduce((content, [key, value]) => content + .replace( + new RegExp(`('|")${key}\\1`, "g"), + `$1${value}$1` + ), + data + ) + })), + + // TODO: interate this into the actual compilation... + ...[...manifest.keys()] + .filter(file => !file.endsWith(".map")) + .map(file => copy({ + src: `${base}/${manifest.get(file)!}`, + out: `${base}/${manifest.get(file)!}`, + transform: async data => data.replace( + path.basename(file), + path.basename(manifest.get(file)!), + ) + })) + )) ) -) /* Copy Lunr.js search stemmers and segmenter */ const stemmers$ = ["min/*.js", "tinyseg.js"] diff --git a/tools/resolve/index.ts b/tools/resolve/index.ts index bf48314f8..cfcab2623 100644 --- a/tools/resolve/index.ts +++ b/tools/resolve/index.ts @@ -81,3 +81,25 @@ export function mkdir( mapTo(directory) ) } + +/** + * Cachebust a file using a content hash + * + * @param file - File + * @param hash - Content hash + * @param options - Options + * + * @returns Cachebusting tuple observable + */ +export function cachebust( + file: string, hash: string, options: ResolveOptions +): Observable<[string, string]> { + const name = file.replace(/\b(?=\.)/, `.${hash.slice(0, 8)}.min`) + return from(fs.rename( + `${options.cwd}/${file}`, + `${options.cwd}/${name}` + )) + .pipe( + mapTo([file, name]) + ) +}