From 80b231d5ec1675dc8a4eaba7a021e757230ff796 Mon Sep 17 00:00:00 2001 From: Wenzhuo Liu Date: Sat, 9 Dec 2023 17:40:16 +0800 Subject: [PATCH] feat(rehype-typst): add font caching (#436) --- .../lib/cached-font-middleware.js | 53 +++++++++++++++++++ projects/rehype-typst/lib/index.js | 4 +- projects/rehype-typst/package.json | 1 + projects/rehype-typst/test.js | 1 + yarn.lock | 15 ++++++ 5 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 projects/rehype-typst/lib/cached-font-middleware.js diff --git a/projects/rehype-typst/lib/cached-font-middleware.js b/projects/rehype-typst/lib/cached-font-middleware.js new file mode 100644 index 00000000..fbbb3f70 --- /dev/null +++ b/projects/rehype-typst/lib/cached-font-middleware.js @@ -0,0 +1,53 @@ +import { preloadFontAssets } from '@myriaddreamin/typst.ts/dist/esm/options.init.mjs'; +import * as fs from 'fs'; +import * as path from 'path'; +import { HttpsProxyAgent } from 'https-proxy-agent'; + +export async function cachedFontInitOptions() { + const { existsSync, mkdirSync, readFileSync, writeFileSync } = fs; + const fetcher = (await import('node-fetch')).default; + const dataDir = + process.env.APPDATA || + (process.platform == 'darwin' + ? process.env.HOME + '/Library/Preferences' + : process.env.HOME + '/.local/share'); + + const cacheDir = path.join(dataDir, 'typst/fonts'); + + return { + beforeBuild: [ + preloadFontAssets({ + assets: ['text', 'cjk', 'emoji'], + fetcher: async (url, init) => { + const cachePath = path.join(cacheDir, url.toString().replace(/[^a-zA-Z0-9]/g, '_')); + if (existsSync(cachePath)) { + const font_res = { + arrayBuffer: async () => { + return readFileSync(cachePath).buffer; + }, + }; + + return font_res; + } + + console.log('loading remote font:', url); + const proxyOption = process.env.HTTPS_PROXY + ? { agent: new HttpsProxyAgent(process.env.HTTPS_PROXY) } + : {}; + + const font_res = await fetcher(url, { + ...proxyOption, + ...((init) || {}), + }); + const buffer = await font_res.arrayBuffer(); + mkdirSync(path.dirname(cachePath), { recursive: true }); + writeFileSync(cachePath, Buffer.from(buffer)); + font_res.arrayBuffer = async () => { + return buffer; + }; + return font_res; + }, + }), + ], + }; +} diff --git a/projects/rehype-typst/lib/index.js b/projects/rehype-typst/lib/index.js index 19f3402a..1a3ffdc9 100644 --- a/projects/rehype-typst/lib/index.js +++ b/projects/rehype-typst/lib/index.js @@ -8,13 +8,13 @@ import { fromHtmlIsomorphic } from 'hast-util-from-html-isomorphic' import { toText } from 'hast-util-to-text' import { $typst } from '@myriaddreamin/typst.ts/dist/esm/contrib/snippet.mjs' - import { SKIP, visitParents } from 'unist-util-visit-parents' - +import { cachedFontInitOptions } from './cached-font-middleware.js' /** @type {Readonly} */ const emptyOptions = {} /** @type {ReadonlyArray} */ const emptyClasses = [] +$typst.setCompilerInitOptions(await cachedFontInitOptions()); await $typst.svg({ mainContent: '' }) diff --git a/projects/rehype-typst/package.json b/projects/rehype-typst/package.json index e3a329ec..f0747c45 100644 --- a/projects/rehype-typst/package.json +++ b/projects/rehype-typst/package.json @@ -19,6 +19,7 @@ "@types/katex": "^0.16.0", "hast-util-from-html-isomorphic": "^2.0.0", "hast-util-to-text": "^4.0.0", + "https-proxy-agent": "^7.0.2", "unist-util-visit-parents": "^6.0.0", "vfile": "^6.0.0" }, diff --git a/projects/rehype-typst/test.js b/projects/rehype-typst/test.js index ba57f3cd..143def16 100644 --- a/projects/rehype-typst/test.js +++ b/projects/rehype-typst/test.js @@ -32,5 +32,6 @@ unified() .use(rehypeTypst) .use(rehypeStringify) .process(test_code, (err, file) => { + if (err) throw err console.log(String(file)) }) diff --git a/yarn.lock b/yarn.lock index 3bdafec9..e13727f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3324,6 +3324,13 @@ agent-base@6, agent-base@^6.0.2: dependencies: debug "4" +agent-base@^7.0.2: + version "7.1.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434" + integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg== + dependencies: + debug "^4.3.4" + agentkeepalive@^4.2.1: version "4.5.0" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" @@ -6420,6 +6427,14 @@ https-proxy-agent@5.0.1, https-proxy-agent@^5.0.0: agent-base "6" debug "4" +https-proxy-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b" + integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA== + dependencies: + agent-base "^7.0.2" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"