@glissade/core 0.12.0-pre.1 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,8 +16,14 @@ type AxisTuple = Record<string, number>;
16
16
  interface RegisterFontInit {
17
17
  /** The CSS family name to register under (the §3.6 asset-id convention). */
18
18
  family: string;
19
- /** Raw font bytes (a path is read to bytes by the caller before this point). */
20
- src: FontSource;
19
+ /**
20
+ * The font source: raw bytes (`Uint8Array | ArrayBuffer`) OR — node-side only —
21
+ * a string filesystem path, which this subpath fs-reads to bytes for you. The
22
+ * string form is a `registerFont`/`ingestFont` convenience; it lives on the
23
+ * export/prepare-only `@glissade/core/font-ingest` subpath (`node:fs` is fine
24
+ * here, it never reaches the embed bundle).
25
+ */
26
+ src: FontSource | string;
21
27
  weight?: number | undefined;
22
28
  style?: 'normal' | 'italic' | undefined;
23
29
  /**
@@ -37,6 +37,28 @@ const MAGIC = {
37
37
  function asUint8(src) {
38
38
  return src instanceof Uint8Array ? src : new Uint8Array(src);
39
39
  }
40
+ /**
41
+ * Resolve a `registerFont`/`ingestFont` `src` to raw bytes. A string is treated
42
+ * as a node-side filesystem PATH and read here via a dynamic `node:fs/promises`
43
+ * import — this subpath is export/prepare-only, so `node:fs` never reaches the
44
+ * embed bundle (the §4.4 leak-guard whitelists this). A `Uint8Array|ArrayBuffer`
45
+ * passes straight through unchanged. An unreadable path throws a clear
46
+ * FontIngestError naming the path (never the downstream "too short" sniff error).
47
+ */
48
+ async function resolveSource(src) {
49
+ if (typeof src !== "string") return asUint8(src);
50
+ let readFile;
51
+ try {
52
+ ({readFile} = await import("node:fs/promises"));
53
+ } catch (err) {
54
+ throw new FontIngestError(`registerFont received a string path ('${src}') but the filesystem is not available here (node-only) — pass Uint8Array bytes instead. (${String(err?.message ?? err)})`);
55
+ }
56
+ try {
57
+ return await readFile(src);
58
+ } catch (err) {
59
+ throw new FontIngestError(`could not read font file '${src}': ${String(err?.message ?? err)}`);
60
+ }
61
+ }
40
62
  /** Sniff the leading 4 bytes; throws on input that is not a recognized font. */
41
63
  function sniffFontFormat(src) {
42
64
  const u8 = asUint8(src);
@@ -100,8 +122,8 @@ function retainAllText(coverage) {
100
122
  * path), keeping the common case off the wasm boundary.
101
123
  */
102
124
  async function ingestFont(init) {
103
- const sourceFormat = sniffFontFormat(init.src);
104
- const input = asUint8(init.src);
125
+ const input = await resolveSource(init.src);
126
+ const sourceFormat = sniffFontFormat(input);
105
127
  const weight = init.weight ?? 400;
106
128
  const style = init.style ?? "normal";
107
129
  const fallback = init.fallback ? [...init.fallback] : [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glissade/core",
3
- "version": "0.12.0-pre.1",
3
+ "version": "0.12.1",
4
4
  "description": "glissade core: signals, tracks, timeline document, evaluation, easing, springs, seeded RNG. Zero DOM/Node dependencies.",
5
5
  "license": "Apache-2.0",
6
6
  "engines": {