@turntrout/subfont 1.7.0 → 1.8.0

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.
Files changed (151) hide show
  1. package/CLAUDE.md +39 -13
  2. package/README.md +24 -14
  3. package/lib/FontTracerPool.d.ts +38 -0
  4. package/lib/FontTracerPool.d.ts.map +1 -0
  5. package/lib/FontTracerPool.js +230 -217
  6. package/lib/FontTracerPool.js.map +1 -0
  7. package/lib/HeadlessBrowser.d.ts +18 -0
  8. package/lib/HeadlessBrowser.d.ts.map +1 -0
  9. package/lib/HeadlessBrowser.js +216 -210
  10. package/lib/HeadlessBrowser.js.map +1 -0
  11. package/lib/cli.d.ts +3 -0
  12. package/lib/cli.d.ts.map +1 -0
  13. package/lib/cli.js +15 -12
  14. package/lib/cli.js.map +1 -0
  15. package/lib/codepointMaps.d.ts +4 -0
  16. package/lib/codepointMaps.d.ts.map +1 -0
  17. package/lib/codepointMaps.js +99 -0
  18. package/lib/codepointMaps.js.map +1 -0
  19. package/lib/collectFeatureGlyphIds.d.ts +3 -0
  20. package/lib/collectFeatureGlyphIds.d.ts.map +1 -0
  21. package/lib/collectFeatureGlyphIds.js +124 -138
  22. package/lib/collectFeatureGlyphIds.js.map +1 -0
  23. package/lib/collectTextsByPage.d.ts +41 -0
  24. package/lib/collectTextsByPage.d.ts.map +1 -0
  25. package/lib/collectTextsByPage.js +726 -965
  26. package/lib/collectTextsByPage.js.map +1 -0
  27. package/lib/concurrencyLimit.d.ts +3 -0
  28. package/lib/concurrencyLimit.d.ts.map +1 -0
  29. package/lib/concurrencyLimit.js +12 -11
  30. package/lib/concurrencyLimit.js.map +1 -0
  31. package/lib/escapeJsStringLiteral.d.ts +3 -0
  32. package/lib/escapeJsStringLiteral.d.ts.map +1 -0
  33. package/lib/escapeJsStringLiteral.js +7 -6
  34. package/lib/escapeJsStringLiteral.js.map +1 -0
  35. package/lib/extractReferencedCustomPropertyNames.d.ts +3 -0
  36. package/lib/extractReferencedCustomPropertyNames.d.ts.map +1 -0
  37. package/lib/extractReferencedCustomPropertyNames.js +15 -16
  38. package/lib/extractReferencedCustomPropertyNames.js.map +1 -0
  39. package/lib/extractVisibleText.d.ts +7 -0
  40. package/lib/extractVisibleText.d.ts.map +1 -0
  41. package/lib/extractVisibleText.js +110 -119
  42. package/lib/extractVisibleText.js.map +1 -0
  43. package/lib/findCustomPropertyDefinitions.d.ts +8 -0
  44. package/lib/findCustomPropertyDefinitions.d.ts.map +1 -0
  45. package/lib/findCustomPropertyDefinitions.js +41 -48
  46. package/lib/findCustomPropertyDefinitions.js.map +1 -0
  47. package/lib/fontConverter.d.ts +2 -0
  48. package/lib/fontConverter.d.ts.map +1 -0
  49. package/lib/fontConverter.js +40 -21
  50. package/lib/fontConverter.js.map +1 -0
  51. package/lib/fontConverterWorker.d.ts +2 -0
  52. package/lib/fontConverterWorker.d.ts.map +1 -0
  53. package/lib/fontConverterWorker.js +52 -15
  54. package/lib/fontConverterWorker.js.map +1 -0
  55. package/lib/fontFaceHelpers.d.ts +64 -0
  56. package/lib/fontFaceHelpers.d.ts.map +1 -0
  57. package/lib/fontFaceHelpers.js +237 -249
  58. package/lib/fontFaceHelpers.js.map +1 -0
  59. package/lib/fontFeatureHelpers.d.ts +30 -0
  60. package/lib/fontFeatureHelpers.d.ts.map +1 -0
  61. package/lib/fontFeatureHelpers.js +277 -212
  62. package/lib/fontFeatureHelpers.js.map +1 -0
  63. package/lib/fontTracerWorker.d.ts +11 -0
  64. package/lib/fontTracerWorker.d.ts.map +1 -0
  65. package/lib/fontTracerWorker.js +94 -60
  66. package/lib/fontTracerWorker.js.map +1 -0
  67. package/lib/gatherStylesheetsWithPredicates.d.ts +26 -0
  68. package/lib/gatherStylesheetsWithPredicates.d.ts.map +1 -0
  69. package/lib/gatherStylesheetsWithPredicates.js +75 -84
  70. package/lib/gatherStylesheetsWithPredicates.js.map +1 -0
  71. package/lib/getCssRulesByProperty.d.ts +29 -0
  72. package/lib/getCssRulesByProperty.d.ts.map +1 -0
  73. package/lib/getCssRulesByProperty.js +316 -316
  74. package/lib/getCssRulesByProperty.js.map +1 -0
  75. package/lib/getFontInfo.d.ts +11 -0
  76. package/lib/getFontInfo.d.ts.map +1 -0
  77. package/lib/getFontInfo.js +31 -33
  78. package/lib/getFontInfo.js.map +1 -0
  79. package/lib/initialValueByProp.d.ts +3 -0
  80. package/lib/initialValueByProp.d.ts.map +1 -0
  81. package/lib/initialValueByProp.js +20 -17
  82. package/lib/initialValueByProp.js.map +1 -0
  83. package/lib/injectSubsetDefinitions.d.ts +3 -0
  84. package/lib/injectSubsetDefinitions.d.ts.map +1 -0
  85. package/lib/injectSubsetDefinitions.js +55 -59
  86. package/lib/injectSubsetDefinitions.js.map +1 -0
  87. package/lib/normalizeFontPropertyValue.d.ts +3 -0
  88. package/lib/normalizeFontPropertyValue.d.ts.map +1 -0
  89. package/lib/normalizeFontPropertyValue.js +59 -54
  90. package/lib/normalizeFontPropertyValue.js.map +1 -0
  91. package/lib/parseCommandLineOptions.d.ts +9 -0
  92. package/lib/parseCommandLineOptions.d.ts.map +1 -0
  93. package/lib/parseCommandLineOptions.js +145 -149
  94. package/lib/parseCommandLineOptions.js.map +1 -0
  95. package/lib/parseFontVariationSettings.d.ts +3 -0
  96. package/lib/parseFontVariationSettings.d.ts.map +1 -0
  97. package/lib/parseFontVariationSettings.js +38 -36
  98. package/lib/parseFontVariationSettings.js.map +1 -0
  99. package/lib/progress.d.ts +27 -0
  100. package/lib/progress.d.ts.map +1 -0
  101. package/lib/progress.js +51 -54
  102. package/lib/progress.js.map +1 -0
  103. package/lib/sfntCache.d.ts +4 -0
  104. package/lib/sfntCache.d.ts.map +1 -0
  105. package/lib/sfntCache.js +67 -25
  106. package/lib/sfntCache.js.map +1 -0
  107. package/lib/stripLocalTokens.d.ts +3 -0
  108. package/lib/stripLocalTokens.d.ts.map +1 -0
  109. package/lib/stripLocalTokens.js +23 -21
  110. package/lib/stripLocalTokens.js.map +1 -0
  111. package/lib/subfont.d.ts +54 -0
  112. package/lib/subfont.d.ts.map +1 -0
  113. package/lib/subfont.js +531 -629
  114. package/lib/subfont.js.map +1 -0
  115. package/lib/subsetFontWithGlyphs.d.ts +21 -0
  116. package/lib/subsetFontWithGlyphs.d.ts.map +1 -0
  117. package/lib/subsetFontWithGlyphs.js +285 -259
  118. package/lib/subsetFontWithGlyphs.js.map +1 -0
  119. package/lib/subsetFonts.d.ts +55 -0
  120. package/lib/subsetFonts.d.ts.map +1 -0
  121. package/lib/subsetFonts.js +899 -1200
  122. package/lib/subsetFonts.js.map +1 -0
  123. package/lib/subsetGeneration.d.ts +36 -0
  124. package/lib/subsetGeneration.d.ts.map +1 -0
  125. package/lib/subsetGeneration.js +328 -325
  126. package/lib/subsetGeneration.js.map +1 -0
  127. package/lib/types/shared.d.ts +11 -0
  128. package/lib/types/shared.d.ts.map +1 -0
  129. package/lib/types/shared.js +3 -0
  130. package/lib/types/shared.js.map +1 -0
  131. package/lib/unicodeRange.d.ts +3 -0
  132. package/lib/unicodeRange.d.ts.map +1 -0
  133. package/lib/unicodeRange.js +17 -30
  134. package/lib/unicodeRange.js.map +1 -0
  135. package/lib/unquote.d.ts +3 -0
  136. package/lib/unquote.d.ts.map +1 -0
  137. package/lib/unquote.js +18 -25
  138. package/lib/unquote.js.map +1 -0
  139. package/lib/variationAxes.d.ts +33 -0
  140. package/lib/variationAxes.d.ts.map +1 -0
  141. package/lib/variationAxes.js +127 -157
  142. package/lib/variationAxes.js.map +1 -0
  143. package/lib/warnAboutMissingGlyphs.d.ts +43 -0
  144. package/lib/warnAboutMissingGlyphs.d.ts.map +1 -0
  145. package/lib/warnAboutMissingGlyphs.js +139 -147
  146. package/lib/warnAboutMissingGlyphs.js.map +1 -0
  147. package/lib/wasmQueue.d.ts +3 -0
  148. package/lib/wasmQueue.d.ts.map +1 -0
  149. package/lib/wasmQueue.js +13 -10
  150. package/lib/wasmQueue.js.map +1 -0
  151. package/package.json +12 -2
@@ -1,155 +1,147 @@
1
- const LinesAndColumns = require('lines-and-columns').default;
2
- const getFontInfo = require('./getFontInfo');
3
- const unicodeRange = require('./unicodeRange');
4
-
5
- async function warnAboutMissingGlyphs(
6
- htmlOrSvgAssetTextsWithProps,
7
- assetGraph
8
- ) {
9
- const missingGlyphsErrors = [];
10
-
11
- // Collect all unique subset buffers and parse them concurrently.
12
- // getFontInfo internally serializes harfbuzzjs WASM calls, so
13
- // Promise.all just queues them up rather than running in parallel.
14
- const uniqueSubsetBuffers = new Map();
15
- for (const { fontUsages } of htmlOrSvgAssetTextsWithProps) {
16
- for (const fontUsage of fontUsages) {
17
- if (!fontUsage.subsets) continue;
18
- const subsetBuffer = Object.values(fontUsage.subsets)[0];
19
- if (!uniqueSubsetBuffers.has(subsetBuffer)) {
20
- uniqueSubsetBuffers.set(
21
- subsetBuffer,
22
- getFontInfo(subsetBuffer)
23
- .then((info) => new Set(info.characterSet))
24
- .catch((err) => {
25
- assetGraph.warn(err);
26
- return null;
27
- })
28
- );
29
- }
30
- }
31
- }
32
- const subsetCharSetCache = new Map();
33
- await Promise.all(
34
- [...uniqueSubsetBuffers.entries()].map(async ([buffer, promise]) => {
35
- subsetCharSetCache.set(buffer, await promise);
36
- })
37
- );
38
-
39
- for (const {
40
- htmlOrSvgAsset,
41
- fontUsages,
42
- accumulatedFontFaceDeclarations,
43
- } of htmlOrSvgAssetTextsWithProps) {
44
- let linesAndColumns;
45
- // Dedupe scans for the same missing char across different fontUsages on
46
- // this page. On KaTeX-heavy pages the same symbol is often missing in
47
- // several font-families, and each scan is an O(N) walk of the HTML text.
48
- const charLookupCache = new Map();
49
- const lookupChar = (char) => {
50
- let cached = charLookupCache.get(char);
51
- if (cached) return cached;
52
- let firstLocation;
53
- let occurrences = 0;
54
- if (char.length > 0) {
55
- const sourceText = htmlOrSvgAsset.text;
56
- let searchIdx = 0;
57
- while (true) {
58
- const charIdx = sourceText.indexOf(char, searchIdx);
59
- if (charIdx === -1) break;
60
- occurrences++;
61
- if (occurrences === 1) {
62
- if (!linesAndColumns) {
63
- linesAndColumns = new LinesAndColumns(sourceText);
1
+ "use strict";
2
+ const lines_and_columns_1 = require("lines-and-columns");
3
+ const getFontInfo = require("./getFontInfo");
4
+ const unicodeRange = require("./unicodeRange");
5
+ async function warnAboutMissingGlyphs(htmlOrSvgAssetTextsWithProps, assetGraph) {
6
+ const missingGlyphsErrors = [];
7
+ // Collect all unique subset buffers and parse them concurrently.
8
+ // getFontInfo internally serializes harfbuzzjs WASM calls, so
9
+ // Promise.all just queues them up rather than running in parallel.
10
+ const uniqueSubsetBuffers = new Map();
11
+ for (const { fontUsages } of htmlOrSvgAssetTextsWithProps) {
12
+ for (const fontUsage of fontUsages) {
13
+ if (!fontUsage.subsets)
14
+ continue;
15
+ const subsetBuffer = Object.values(fontUsage.subsets)[0];
16
+ if (!uniqueSubsetBuffers.has(subsetBuffer)) {
17
+ uniqueSubsetBuffers.set(subsetBuffer, getFontInfo(subsetBuffer)
18
+ .then((info) => new Set(info.characterSet))
19
+ // eslint-disable-next-line no-restricted-syntax
20
+ .catch((rawErr) => {
21
+ assetGraph.warn(rawErr);
22
+ return null;
23
+ }));
64
24
  }
65
- const position = linesAndColumns.locationForIndex(charIdx);
66
- firstLocation = `${htmlOrSvgAsset.urlOrDescription}:${
67
- position.line + 1
68
- }:${position.column + 1}`;
69
- }
70
- searchIdx = charIdx + char.length;
71
- }
72
- }
73
- if (!firstLocation) {
74
- firstLocation = `${htmlOrSvgAsset.urlOrDescription} (generated content)`;
75
- }
76
- cached = { firstLocation, occurrences };
77
- charLookupCache.set(char, cached);
78
- return cached;
79
- };
80
- for (const fontUsage of fontUsages) {
81
- if (!fontUsage.subsets) continue;
82
- const subsetBuffer = Object.values(fontUsage.subsets)[0];
83
- const characterSetLookup = subsetCharSetCache.get(subsetBuffer);
84
- if (!characterSetLookup) continue; // getFontInfo failed on subset; already warned
85
-
86
- let missedAny = false;
87
- for (const char of fontUsage.pageText) {
88
- // Turns out that browsers don't mind that these are missing:
89
- if (char === '\t' || char === '\n') {
90
- continue;
91
- }
92
-
93
- const codePoint = char.codePointAt(0);
94
-
95
- const isMissing = !characterSetLookup.has(codePoint);
96
-
97
- if (isMissing) {
98
- // Report only the first location plus a count of remaining
99
- // occurrences. A character like U+200B can appear thousands of
100
- // times on a page and per-occurrence lines drown the log.
101
- const { firstLocation, occurrences } = lookupChar(char);
102
-
103
- missingGlyphsErrors.push({
104
- codePoint,
105
- char,
106
- htmlOrSvgAsset,
107
- fontUsage,
108
- location: firstLocation,
109
- occurrences,
110
- });
111
- missedAny = true;
112
25
  }
113
- }
114
- if (missedAny) {
115
- const fontFaces = accumulatedFontFaceDeclarations.filter((fontFace) =>
116
- fontUsage.fontFamilies.has(fontFace['font-family'])
117
- );
118
- for (const fontFace of fontFaces) {
119
- const cssFontFaceSrc = fontFace.relations[0];
120
- const fontFaceDeclaration = cssFontFaceSrc.node;
121
- if (
122
- !fontFaceDeclaration.some((node) => node.prop === 'unicode-range')
123
- ) {
124
- fontFaceDeclaration.append({
125
- prop: 'unicode-range',
126
- value: unicodeRange(fontUsage.codepoints.original),
127
- });
128
- cssFontFaceSrc.from.markDirty();
129
- }
26
+ }
27
+ const subsetCharSetCache = new Map();
28
+ await Promise.all([...uniqueSubsetBuffers.entries()].map(async ([buffer, promise]) => {
29
+ subsetCharSetCache.set(buffer, await promise);
30
+ }));
31
+ // Codepoint unions per @font-face declaration, keyed by the at-rule node.
32
+ // Built across all fontUsages on a page, then flushed in a single append
33
+ // per @font-face so multiple fontUsages sharing a family don't lose data.
34
+ const unicodeRangeAccumulator = new Map();
35
+ for (const { htmlOrSvgAsset, fontUsages, accumulatedFontFaceDeclarations, } of htmlOrSvgAssetTextsWithProps) {
36
+ let linesAndColumns;
37
+ // Dedupe scans for the same missing char across different fontUsages on
38
+ // this page. On KaTeX-heavy pages the same symbol is often missing in
39
+ // several font-families, and each scan is an O(N) walk of the HTML text.
40
+ const charLookupCache = new Map();
41
+ const lookupChar = (char) => {
42
+ const cachedHit = charLookupCache.get(char);
43
+ if (cachedHit)
44
+ return cachedHit;
45
+ let firstLocation;
46
+ let occurrences = 0;
47
+ if (char.length > 0) {
48
+ const sourceText = htmlOrSvgAsset.text;
49
+ let searchIdx = 0;
50
+ while (true) {
51
+ const charIdx = sourceText.indexOf(char, searchIdx);
52
+ if (charIdx === -1)
53
+ break;
54
+ occurrences++;
55
+ if (occurrences === 1) {
56
+ if (!linesAndColumns) {
57
+ linesAndColumns = new lines_and_columns_1.LinesAndColumns(sourceText);
58
+ }
59
+ const position = linesAndColumns.locationForIndex(charIdx);
60
+ firstLocation = `${htmlOrSvgAsset.urlOrDescription}:${position.line + 1}:${position.column + 1}`;
61
+ }
62
+ searchIdx = charIdx + char.length;
63
+ }
64
+ }
65
+ if (!firstLocation) {
66
+ firstLocation = `${htmlOrSvgAsset.urlOrDescription} (generated content)`;
67
+ }
68
+ const result = { firstLocation, occurrences };
69
+ charLookupCache.set(char, result);
70
+ return result;
71
+ };
72
+ for (const fontUsage of fontUsages) {
73
+ if (!fontUsage.subsets)
74
+ continue;
75
+ const subsetBuffer = Object.values(fontUsage.subsets)[0];
76
+ const characterSetLookup = subsetCharSetCache.get(subsetBuffer);
77
+ if (!characterSetLookup)
78
+ continue; // getFontInfo failed on subset; already warned
79
+ let missedAny = false;
80
+ for (const char of fontUsage.pageText) {
81
+ // Turns out that browsers don't mind that these are missing:
82
+ if (char === '\t' || char === '\n') {
83
+ continue;
84
+ }
85
+ const codePoint = char.codePointAt(0);
86
+ if (codePoint === undefined)
87
+ continue;
88
+ const isMissing = !characterSetLookup.has(codePoint);
89
+ if (isMissing) {
90
+ // Report only the first location plus a count of remaining
91
+ // occurrences. A character like U+200B can appear thousands of
92
+ // times on a page and per-occurrence lines drown the log.
93
+ const { firstLocation, occurrences } = lookupChar(char);
94
+ missingGlyphsErrors.push({
95
+ codePoint,
96
+ char,
97
+ htmlOrSvgAsset,
98
+ fontUsage,
99
+ location: firstLocation,
100
+ occurrences,
101
+ });
102
+ missedAny = true;
103
+ }
104
+ }
105
+ if (missedAny) {
106
+ for (const fontFace of accumulatedFontFaceDeclarations) {
107
+ const family = fontFace['font-family'];
108
+ if (!family || !fontUsage.fontFamilies.has(family))
109
+ continue;
110
+ const relation = fontFace.relations[0];
111
+ const node = relation.node;
112
+ if (node.some((decl) => decl.prop === 'unicode-range'))
113
+ continue;
114
+ let entry = unicodeRangeAccumulator.get(node);
115
+ if (!entry) {
116
+ entry = { relation, codepoints: new Set() };
117
+ unicodeRangeAccumulator.set(node, entry);
118
+ }
119
+ for (const cp of fontUsage.codepoints.original) {
120
+ entry.codepoints.add(cp);
121
+ }
122
+ }
123
+ }
130
124
  }
131
- }
132
125
  }
133
- }
134
-
135
- if (missingGlyphsErrors.length) {
136
- const errorLog = missingGlyphsErrors.map(
137
- ({ char, fontUsage, location, occurrences }) => {
138
- const extra = occurrences > 1 ? ` (+${occurrences - 1} more)` : '';
139
- return `- \\u{${char.codePointAt(0).toString(16)}} (${char}) in font-family '${
140
- fontUsage.props['font-family']
141
- }' (${fontUsage.props['font-weight']}/${
142
- fontUsage.props['font-style']
143
- }) at ${location}${extra}`;
144
- }
145
- );
146
-
147
- const message = `Missing glyph fallback detected.
126
+ // Flush accumulated unicode-range declarations: one append per @font-face,
127
+ // covering every fontUsage that mapped to it.
128
+ for (const { relation, codepoints } of unicodeRangeAccumulator.values()) {
129
+ relation.node.append({
130
+ prop: 'unicode-range',
131
+ value: unicodeRange([...codepoints]),
132
+ });
133
+ relation.from.markDirty();
134
+ }
135
+ if (missingGlyphsErrors.length) {
136
+ const errorLog = missingGlyphsErrors.map(({ char, fontUsage, location, occurrences }) => {
137
+ const extra = occurrences > 1 ? ` (+${occurrences - 1} more)` : '';
138
+ return `- \\u{${char.codePointAt(0).toString(16)}} (${char}) in font-family '${fontUsage.props['font-family']}' (${fontUsage.props['font-weight']}/${fontUsage.props['font-style']}) at ${location}${extra}`;
139
+ });
140
+ const message = `Missing glyph fallback detected.
148
141
  When your primary webfont doesn't contain the glyphs you use, browsers that don't support unicode-range will load your fallback fonts, which will be a potential waste of bandwidth.
149
142
  These glyphs are used on your site, but they don't exist in the font you applied to them:`;
150
-
151
- assetGraph.info(new Error(`${message}\n${errorLog.join('\n')}`));
152
- }
143
+ assetGraph.info(new Error(`${message}\n${errorLog.join('\n')}`));
144
+ }
153
145
  }
154
-
155
146
  module.exports = warnAboutMissingGlyphs;
147
+ //# sourceMappingURL=warnAboutMissingGlyphs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warnAboutMissingGlyphs.js","sourceRoot":"","sources":["../src/warnAboutMissingGlyphs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare function enqueue<T>(fn: () => Promise<T>): Promise<T>;
2
+ export = enqueue;
3
+ //# sourceMappingURL=wasmQueue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasmQueue.d.ts","sourceRoot":"","sources":["../src/wasmQueue.ts"],"names":[],"mappings":"AASA,iBAAS,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAepD;AAED,SAAS,OAAO,CAAC"}
package/lib/wasmQueue.js CHANGED
@@ -1,18 +1,21 @@
1
+ "use strict";
1
2
  // Shared serialization queue for harfbuzzjs WASM calls.
2
3
  // harfbuzzjs returns corrupt results when multiple calls run concurrently
3
4
  // on the shared module instance. This queue ensures only one WASM
4
5
  // operation runs at a time across getFontInfo and collectFeatureGlyphIds.
6
+ //
7
+ // The previous task's resolved value is irrelevant — the queue only sequences
8
+ // in-flight work — so we erase it via .then(() => undefined).
5
9
  let queue = Promise.resolve();
6
-
7
10
  function enqueue(fn) {
8
- // Chain fn after the previous task settles. Both handlers wrap fn() in
9
- // an arrow to avoid leaking the previous result/error as an argument.
10
- // The error handler ensures a prior rejection doesn't block the queue.
11
- queue = queue.then(
12
- () => fn(),
13
- () => fn()
14
- );
15
- return queue;
11
+ // Chain fn after the previous task settles. Both handlers wrap fn() in
12
+ // an arrow to avoid leaking the previous result/error as an argument.
13
+ // The error handler ensures a prior rejection doesn't block the queue.
14
+ const next = queue.then(() => fn(), () => fn());
15
+ // Discard the resolved value (and swallow rejections for queue advancement
16
+ // only — the caller sees the original promise via `next`).
17
+ queue = next.then(() => undefined, () => undefined);
18
+ return next;
16
19
  }
17
-
18
20
  module.exports = enqueue;
21
+ //# sourceMappingURL=wasmQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasmQueue.js","sourceRoot":"","sources":["../src/wasmQueue.ts"],"names":[],"mappings":";AAAA,wDAAwD;AACxD,0EAA0E;AAC1E,kEAAkE;AAClE,0EAA0E;AAC1E,EAAE;AACF,8EAA8E;AAC9E,8DAA8D;AAC9D,IAAI,KAAK,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;AAE7C,SAAS,OAAO,CAAI,EAAoB;IACtC,uEAAuE;IACvE,sEAAsE;IACtE,uEAAuE;IACvE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CACrB,GAAG,EAAE,CAAC,EAAE,EAAE,EACV,GAAG,EAAE,CAAC,EAAE,EAAE,CACX,CAAC;IACF,2EAA2E;IAC3E,2DAA2D;IAC3D,KAAK,GAAG,IAAI,CAAC,IAAI,CACf,GAAG,EAAE,CAAC,SAAS,EACf,GAAG,EAAE,CAAC,SAAS,CAChB,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,iBAAS,OAAO,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turntrout/subfont",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Automatically subset web fonts to only the characters used on your pages. Fork of Munter/subfont with modern defaults.",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -68,6 +68,8 @@
68
68
  "yargs": "^17.7.2"
69
69
  },
70
70
  "devDependencies": {
71
+ "@types/node": "^20.0.0",
72
+ "@types/yargs": "^17.0.0",
71
73
  "canvas": "npm:@napi-rs/canvas@^0.1.97",
72
74
  "combos": "^0.2.0",
73
75
  "coveralls": "^3.0.9",
@@ -86,7 +88,11 @@
86
88
  "prettier": "^3.0.0",
87
89
  "proxyquire": "^2.1.1",
88
90
  "puppeteer": "^24.39.1",
91
+ "rimraf": "^6.0.0",
89
92
  "sinon": "^19.0.0",
93
+ "subset-font": "^2.5.0",
94
+ "typescript": "^5.6.0",
95
+ "typescript-eslint": "^8.59.0",
90
96
  "unexpected": "^11.8.1",
91
97
  "unexpected-check": "^2.3.1",
92
98
  "unexpected-resemble": "^5.0.1",
@@ -94,7 +100,11 @@
94
100
  "unexpected-sinon": "^10.11.2"
95
101
  },
96
102
  "scripts": {
97
- "lint": "eslint . && prettier --check '**/*.{js,md}'",
103
+ "build": "tsc && chmod +x lib/cli.js",
104
+ "clean": "rimraf 'lib/*.{js,d.ts,d.ts.map,js.map}'",
105
+ "typecheck": "tsc --noEmit",
106
+ "lint": "eslint . && prettier --check '**/*.{js,ts,md}'",
107
+ "pretest": "npm run build",
98
108
  "test": "mocha && npm run lint",
99
109
  "coverage": "nyc --reporter=lcov --reporter=text -- mocha",
100
110
  "check-coverage": "nyc check-coverage",