@liiift-studio/sanity-font-manager 2.5.4 → 2.5.6
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.
- package/dist/index.js +16198 -16170
- package/dist/index.mjs +16100 -16070
- package/package.json +1 -1
- package/src/utils/parseFont.js +33 -7
- package/src/utils/setupDecompressors.js +22 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liiift-studio/sanity-font-manager",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.6",
|
|
4
4
|
"description": "Sanity Studio plugin — full font management suite with batch upload, format conversion, metadata extraction, CSS generation, collection/pair generation, and script variant support. Supports Sanity v3, v4, and v5.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Liiift Studio",
|
package/src/utils/parseFont.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
// Async font parser —
|
|
2
|
-
// Decompressor globals (pako, unbrotli) are set by setupDecompressors.js
|
|
3
|
-
// which is imported at the top of index.js before this module loads.
|
|
1
|
+
// Async font parser — decompressor globals must be set before lib-font is imported
|
|
4
2
|
|
|
3
|
+
import './setupDecompressors.js';
|
|
5
4
|
import { Font } from 'lib-font';
|
|
6
5
|
|
|
7
6
|
/** Maximum font file size accepted for parsing (50 MB) */
|
|
8
7
|
const MAX_FONT_FILE_SIZE = 50 * 1024 * 1024;
|
|
9
8
|
|
|
9
|
+
/** Parse timeout — prevents hanging if lib-font silently fails (30 seconds) */
|
|
10
|
+
const PARSE_TIMEOUT_MS = 30000;
|
|
11
|
+
|
|
10
12
|
/**
|
|
11
13
|
* Parse a font file from an ArrayBuffer.
|
|
12
14
|
* Returns a lib-font Font object with all tables accessible via font.opentype.tables.*.
|
|
@@ -14,7 +16,7 @@ const MAX_FONT_FILE_SIZE = 50 * 1024 * 1024;
|
|
|
14
16
|
* @param {ArrayBuffer} buffer - Raw font file bytes
|
|
15
17
|
* @param {string} filename - Original filename (used for format detection by lib-font)
|
|
16
18
|
* @returns {Promise<import('lib-font').Font>} Parsed lib-font Font object
|
|
17
|
-
* @throws {Error} If the file exceeds MAX_FONT_FILE_SIZE or
|
|
19
|
+
* @throws {Error} If the file exceeds MAX_FONT_FILE_SIZE, parsing fails, or times out
|
|
18
20
|
*/
|
|
19
21
|
export async function parseFont(buffer, filename) {
|
|
20
22
|
if (buffer.byteLength > MAX_FONT_FILE_SIZE) {
|
|
@@ -22,9 +24,33 @@ export async function parseFont(buffer, filename) {
|
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
return new Promise((resolve, reject) => {
|
|
27
|
+
let settled = false;
|
|
28
|
+
|
|
29
|
+
const settle = (fn) => (...args) => {
|
|
30
|
+
if (!settled) {
|
|
31
|
+
settled = true;
|
|
32
|
+
clearTimeout(timer);
|
|
33
|
+
fn(...args);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Timeout guard — prevents infinite hang if lib-font fails silently
|
|
38
|
+
const timer = setTimeout(() => {
|
|
39
|
+
settle(reject)(new Error(`Parsing timed out for ${filename} (${PARSE_TIMEOUT_MS / 1000}s). The file may be corrupted or in an unsupported format.`));
|
|
40
|
+
}, PARSE_TIMEOUT_MS);
|
|
41
|
+
|
|
25
42
|
const font = new Font('font', { skipStyleSheet: true });
|
|
26
|
-
font.onload = (evt) => resolve(evt.detail.font);
|
|
27
|
-
font.onerror = (evt) =>
|
|
28
|
-
|
|
43
|
+
font.onload = settle((evt) => resolve(evt.detail.font));
|
|
44
|
+
font.onerror = settle((evt) => {
|
|
45
|
+
const msg = evt.detail?.message || `Failed to parse ${filename}`;
|
|
46
|
+
reject(new Error(msg));
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
font.fromDataBuffer(buffer, filename);
|
|
51
|
+
} catch (err) {
|
|
52
|
+
// Catches synchronous throws from WOFF2 constructor when brotli is missing
|
|
53
|
+
settle(reject)(new Error(`${filename}: ${err.message}`));
|
|
54
|
+
}
|
|
29
55
|
});
|
|
30
56
|
}
|
|
@@ -1,10 +1,27 @@
|
|
|
1
1
|
// Sets up globalThis.pako and globalThis.unbrotli for lib-font WOFF/WOFF2 decompression.
|
|
2
|
-
//
|
|
3
|
-
// It runs synchronously at module evaluation time to set the globals.
|
|
2
|
+
// Must be imported before lib-font.
|
|
4
3
|
|
|
5
4
|
import pako from 'pako';
|
|
6
|
-
import '../vendor/unbrotli.js';
|
|
7
5
|
|
|
6
|
+
// Set pako for WOFF (zlib) decompression
|
|
8
7
|
globalThis.pako = pako;
|
|
9
|
-
|
|
10
|
-
//
|
|
8
|
+
|
|
9
|
+
// Set unbrotli for WOFF2 (brotli) decompression
|
|
10
|
+
// The vendor unbrotli.js UMD sets globalThis.unbrotli in browser contexts.
|
|
11
|
+
// In Node/bundler contexts it exports via module.exports instead.
|
|
12
|
+
// We use a side-effect import and then check if the global was set.
|
|
13
|
+
import '../vendor/unbrotli.js';
|
|
14
|
+
|
|
15
|
+
// If the UMD didn't set the global (CJS path in Node/bundler), try to require it
|
|
16
|
+
if (!globalThis.unbrotli) {
|
|
17
|
+
try {
|
|
18
|
+
// In bundler context, the UMD file's module.exports is available
|
|
19
|
+
// tsup will resolve this at build time
|
|
20
|
+
const brotli = require('../vendor/unbrotli.js');
|
|
21
|
+
if (typeof brotli === 'function') {
|
|
22
|
+
globalThis.unbrotli = brotli;
|
|
23
|
+
}
|
|
24
|
+
} catch {
|
|
25
|
+
// Silently fail — WOFF2 parsing will error gracefully
|
|
26
|
+
}
|
|
27
|
+
}
|