diff --git a/package.json b/package.json index 329d9ed..8462b7e 100644 --- a/package.json +++ b/package.json @@ -50,10 +50,9 @@ "browser": "./dist/src/api-wasm-locator-browser.js", "default": "./dist/src/api-wasm-locator-node.js" }, - "#backend": { - "buildtime": "./src/backend-node.js", - "browser": "./dist/src/backend-browser.js", - "default": "./dist/src/backend-node.js" + "#register-default-environment": { + "browser": "./dist/src/environment-browser.js", + "default": "./dist/src/environment-node.js" } }, "scripts": { diff --git a/src/api.ts b/src/api.ts index 9dc9b60..ab77520 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,3 +1,4 @@ +import '#register-default-environment'; import {HTMLElement, TextNode} from './dom.js'; import {DeclaredStyle, getOriginStyle, computeElementStyle} from './style.js'; import {registerFont, unregisterFont, getFontUrls, RegisterFontOptions} from './text-font.js'; diff --git a/src/backend-browser.ts b/src/backend-browser.ts deleted file mode 100644 index 869be11..0000000 --- a/src/backend-browser.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type {FaceMatch} from './text-font.js'; - -// TypeScript does not support different possibilities of runtime environments, -// so the types loaded are for node. To add the browser environment too would -// add too many globals. -// -// https://gist.github.com/RyanCavanaugh/702ebd1ca2fc060e58e634b4e30c1c1c -declare const document: any; -declare const FontFace: any; - -export function registerPaintFont(match: FaceMatch, buffer: Uint8Array, filename: string) { - const descriptor = match.toCssDescriptor(); - const face = new FontFace(descriptor.family, buffer, descriptor); - document.fonts.add(face); -} diff --git a/src/backend-node.ts b/src/backend-node.ts deleted file mode 100644 index 891fa7d..0000000 --- a/src/backend-node.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type {FaceMatch} from './text-font.js'; -import {fileURLToPath} from 'url'; - -const alreadyRegistered = new Set(); - -try { - var canvas = await import('canvas'); -} catch (e) { -} - -export function registerPaintFont(match: FaceMatch, buffer: Uint8Array, url: URL) { - const filename = fileURLToPath(url); - if (canvas?.registerFont && !alreadyRegistered.has(filename)) { - const descriptor = match.toCssDescriptor(); - canvas.registerFont(filename, descriptor); - alreadyRegistered.add(filename); - } -} diff --git a/src/environment-browser.ts b/src/environment-browser.ts new file mode 100644 index 0000000..bdd35b7 --- /dev/null +++ b/src/environment-browser.ts @@ -0,0 +1,17 @@ +import {environment, defaultEnvironment} from './environment.js'; + +// TypeScript does not support different possibilities of runtime environments, +// so the types loaded are for node. To add the browser environment too would +// add too many globals. +// +// https://gist.github.com/RyanCavanaugh/702ebd1ca2fc060e58e634b4e30c1c1c +declare const document: any; +declare const FontFace: any; + +if (environment.registerFont === defaultEnvironment.registerFont) { + environment.registerFont = function (match, buffer, url) { + const descriptor = match.toCssDescriptor(); + const face = new FontFace(descriptor.family, buffer, descriptor); + document.fonts.add(face); + }; +} diff --git a/src/environment-node.ts b/src/environment-node.ts new file mode 100644 index 0000000..23f1584 --- /dev/null +++ b/src/environment-node.ts @@ -0,0 +1,22 @@ +import {environment, defaultEnvironment} from './environment.js'; +import {fileURLToPath} from 'url'; + +const alreadyRegistered = new Set(); + +let canvas: typeof import('canvas') | undefined; + +try { + canvas = await import('canvas'); +} catch (e) { +} + +if (canvas?.registerFont && environment.registerFont === defaultEnvironment.registerFont) { + environment.registerFont = (match, buffer, url) => { + const filename = fileURLToPath(url); + if (canvas?.registerFont && !alreadyRegistered.has(filename)) { + const descriptor = match.toCssDescriptor(); + canvas.registerFont(filename, descriptor); + alreadyRegistered.add(filename); + } + }; +} diff --git a/src/environment.ts b/src/environment.ts new file mode 100644 index 0000000..785f0b0 --- /dev/null +++ b/src/environment.ts @@ -0,0 +1,13 @@ +import type {FaceMatch} from './text-font.js'; + +export interface Environment { + registerFont(match: FaceMatch, buffer: Uint8Array, url: URL): void; +} + +export const defaultEnvironment: Environment = { + registerFont() { + throw new Error('Invalid build! Your bundler needs to support "exports" in package.json.'); + } +}; + +export const environment = {...defaultEnvironment}; diff --git a/src/text-font.ts b/src/text-font.ts index b3c4a6a..e145657 100644 --- a/src/text-font.ts +++ b/src/text-font.ts @@ -2,7 +2,7 @@ import * as hb from './text-harfbuzz.js'; import langCoverage from '../gen/lang-script-coverage.js'; import wasm from './wasm.js'; import {HbSet, hb_tag, HB_OT_TAG_GSUB, HB_OT_TAG_GPOS, HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX} from './text-harfbuzz.js'; -import {registerPaintFont} from '#backend'; +import {environment} from './environment.js'; import {nameToCode, tagToCode} from '../gen/script-names.js'; import subsetIdToUrls from '../gen/system-fonts-database.js'; import UnicodeTrie from './text-unicode-trie.js'; @@ -511,7 +511,7 @@ export async function registerFont( const match = new FaceMatch(blob, 0, stringUrl); - if (options.paint) registerPaintFont(match, buffer, url); + if (options.paint) environment.registerFont(match, buffer, url); registeredFonts.set(stringUrl, match);