@turntrout/subfont 1.7.1 → 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 (147) hide show
  1. package/CLAUDE.md +39 -13
  2. package/README.md +24 -14
  3. package/lib/FontTracerPool.d.ts +1 -0
  4. package/lib/FontTracerPool.d.ts.map +1 -1
  5. package/lib/FontTracerPool.js +46 -24
  6. package/lib/FontTracerPool.js.map +1 -1
  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/codepointMaps.d.ts +4 -0
  12. package/lib/codepointMaps.d.ts.map +1 -0
  13. package/lib/codepointMaps.js +99 -0
  14. package/lib/codepointMaps.js.map +1 -0
  15. package/lib/collectFeatureGlyphIds.d.ts +3 -0
  16. package/lib/collectFeatureGlyphIds.d.ts.map +1 -0
  17. package/lib/collectFeatureGlyphIds.js +124 -138
  18. package/lib/collectFeatureGlyphIds.js.map +1 -0
  19. package/lib/collectTextsByPage.d.ts +41 -0
  20. package/lib/collectTextsByPage.d.ts.map +1 -0
  21. package/lib/collectTextsByPage.js +726 -965
  22. package/lib/collectTextsByPage.js.map +1 -0
  23. package/lib/concurrencyLimit.d.ts +3 -0
  24. package/lib/concurrencyLimit.d.ts.map +1 -0
  25. package/lib/concurrencyLimit.js +12 -11
  26. package/lib/concurrencyLimit.js.map +1 -0
  27. package/lib/escapeJsStringLiteral.d.ts +3 -0
  28. package/lib/escapeJsStringLiteral.d.ts.map +1 -0
  29. package/lib/escapeJsStringLiteral.js +7 -6
  30. package/lib/escapeJsStringLiteral.js.map +1 -0
  31. package/lib/extractReferencedCustomPropertyNames.d.ts +3 -0
  32. package/lib/extractReferencedCustomPropertyNames.d.ts.map +1 -0
  33. package/lib/extractReferencedCustomPropertyNames.js +15 -16
  34. package/lib/extractReferencedCustomPropertyNames.js.map +1 -0
  35. package/lib/extractVisibleText.d.ts +7 -0
  36. package/lib/extractVisibleText.d.ts.map +1 -0
  37. package/lib/extractVisibleText.js +110 -119
  38. package/lib/extractVisibleText.js.map +1 -0
  39. package/lib/findCustomPropertyDefinitions.d.ts +8 -0
  40. package/lib/findCustomPropertyDefinitions.d.ts.map +1 -0
  41. package/lib/findCustomPropertyDefinitions.js +41 -48
  42. package/lib/findCustomPropertyDefinitions.js.map +1 -0
  43. package/lib/fontConverter.d.ts +2 -0
  44. package/lib/fontConverter.d.ts.map +1 -0
  45. package/lib/fontConverter.js +40 -21
  46. package/lib/fontConverter.js.map +1 -0
  47. package/lib/fontConverterWorker.d.ts +2 -0
  48. package/lib/fontConverterWorker.d.ts.map +1 -0
  49. package/lib/fontConverterWorker.js +52 -15
  50. package/lib/fontConverterWorker.js.map +1 -0
  51. package/lib/fontFaceHelpers.d.ts +64 -0
  52. package/lib/fontFaceHelpers.d.ts.map +1 -0
  53. package/lib/fontFaceHelpers.js +237 -249
  54. package/lib/fontFaceHelpers.js.map +1 -0
  55. package/lib/fontFeatureHelpers.d.ts +30 -0
  56. package/lib/fontFeatureHelpers.d.ts.map +1 -0
  57. package/lib/fontFeatureHelpers.js +277 -212
  58. package/lib/fontFeatureHelpers.js.map +1 -0
  59. package/lib/fontTracerWorker.d.ts +11 -0
  60. package/lib/fontTracerWorker.d.ts.map +1 -0
  61. package/lib/fontTracerWorker.js +94 -60
  62. package/lib/fontTracerWorker.js.map +1 -0
  63. package/lib/gatherStylesheetsWithPredicates.d.ts +26 -0
  64. package/lib/gatherStylesheetsWithPredicates.d.ts.map +1 -0
  65. package/lib/gatherStylesheetsWithPredicates.js +75 -84
  66. package/lib/gatherStylesheetsWithPredicates.js.map +1 -0
  67. package/lib/getCssRulesByProperty.d.ts +29 -0
  68. package/lib/getCssRulesByProperty.d.ts.map +1 -0
  69. package/lib/getCssRulesByProperty.js +316 -316
  70. package/lib/getCssRulesByProperty.js.map +1 -0
  71. package/lib/getFontInfo.d.ts +11 -0
  72. package/lib/getFontInfo.d.ts.map +1 -0
  73. package/lib/getFontInfo.js +31 -33
  74. package/lib/getFontInfo.js.map +1 -0
  75. package/lib/initialValueByProp.d.ts +3 -0
  76. package/lib/initialValueByProp.d.ts.map +1 -0
  77. package/lib/initialValueByProp.js +20 -17
  78. package/lib/initialValueByProp.js.map +1 -0
  79. package/lib/injectSubsetDefinitions.d.ts +3 -0
  80. package/lib/injectSubsetDefinitions.d.ts.map +1 -0
  81. package/lib/injectSubsetDefinitions.js +55 -59
  82. package/lib/injectSubsetDefinitions.js.map +1 -0
  83. package/lib/normalizeFontPropertyValue.d.ts +3 -0
  84. package/lib/normalizeFontPropertyValue.d.ts.map +1 -0
  85. package/lib/normalizeFontPropertyValue.js +59 -54
  86. package/lib/normalizeFontPropertyValue.js.map +1 -0
  87. package/lib/parseCommandLineOptions.d.ts +9 -0
  88. package/lib/parseCommandLineOptions.d.ts.map +1 -0
  89. package/lib/parseCommandLineOptions.js +145 -149
  90. package/lib/parseCommandLineOptions.js.map +1 -0
  91. package/lib/parseFontVariationSettings.d.ts +3 -0
  92. package/lib/parseFontVariationSettings.d.ts.map +1 -0
  93. package/lib/parseFontVariationSettings.js +38 -36
  94. package/lib/parseFontVariationSettings.js.map +1 -0
  95. package/lib/progress.d.ts +27 -0
  96. package/lib/progress.d.ts.map +1 -0
  97. package/lib/progress.js +51 -54
  98. package/lib/progress.js.map +1 -0
  99. package/lib/sfntCache.d.ts +4 -0
  100. package/lib/sfntCache.d.ts.map +1 -0
  101. package/lib/sfntCache.js +67 -25
  102. package/lib/sfntCache.js.map +1 -0
  103. package/lib/stripLocalTokens.d.ts +3 -0
  104. package/lib/stripLocalTokens.d.ts.map +1 -0
  105. package/lib/stripLocalTokens.js +23 -21
  106. package/lib/stripLocalTokens.js.map +1 -0
  107. package/lib/subfont.d.ts +22 -1
  108. package/lib/subfont.d.ts.map +1 -1
  109. package/lib/subfont.js +7 -6
  110. package/lib/subfont.js.map +1 -1
  111. package/lib/subsetFontWithGlyphs.d.ts +4 -0
  112. package/lib/subsetFontWithGlyphs.d.ts.map +1 -1
  113. package/lib/subsetFontWithGlyphs.js +73 -14
  114. package/lib/subsetFontWithGlyphs.js.map +1 -1
  115. package/lib/subsetFonts.d.ts +1 -5
  116. package/lib/subsetFonts.d.ts.map +1 -1
  117. package/lib/subsetFonts.js +18 -17
  118. package/lib/subsetFonts.js.map +1 -1
  119. package/lib/subsetGeneration.d.ts +3 -6
  120. package/lib/subsetGeneration.d.ts.map +1 -1
  121. package/lib/subsetGeneration.js +42 -9
  122. package/lib/subsetGeneration.js.map +1 -1
  123. package/lib/types/shared.d.ts +11 -0
  124. package/lib/types/shared.d.ts.map +1 -0
  125. package/lib/types/shared.js +3 -0
  126. package/lib/types/shared.js.map +1 -0
  127. package/lib/unicodeRange.d.ts +3 -0
  128. package/lib/unicodeRange.d.ts.map +1 -0
  129. package/lib/unicodeRange.js +17 -30
  130. package/lib/unicodeRange.js.map +1 -0
  131. package/lib/unquote.d.ts +3 -0
  132. package/lib/unquote.d.ts.map +1 -0
  133. package/lib/unquote.js +18 -25
  134. package/lib/unquote.js.map +1 -0
  135. package/lib/variationAxes.d.ts +33 -0
  136. package/lib/variationAxes.d.ts.map +1 -0
  137. package/lib/variationAxes.js +127 -157
  138. package/lib/variationAxes.js.map +1 -0
  139. package/lib/warnAboutMissingGlyphs.d.ts +43 -0
  140. package/lib/warnAboutMissingGlyphs.d.ts.map +1 -0
  141. package/lib/warnAboutMissingGlyphs.js +139 -147
  142. package/lib/warnAboutMissingGlyphs.js.map +1 -0
  143. package/lib/wasmQueue.d.ts +3 -0
  144. package/lib/wasmQueue.d.ts.map +1 -0
  145. package/lib/wasmQueue.js +13 -10
  146. package/lib/wasmQueue.js.map +1 -0
  147. package/package.json +3 -2
@@ -1,173 +1,143 @@
1
- const getFontInfo = require('./getFontInfo');
2
- const parseFontVariationSettings = require('./parseFontVariationSettings');
3
-
4
- const standardVariationAxes = new Set(['wght', 'wdth', 'ital', 'slnt', 'opsz']);
5
-
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderNumberRange = renderNumberRange;
4
+ exports.getVariationAxisUsage = getVariationAxisUsage;
5
+ exports.getVariationAxisBounds = getVariationAxisBounds;
6
+ const getFontInfo = require("./getFontInfo");
7
+ const parseFontVariationSettings = require("./parseFontVariationSettings");
6
8
  // CSS oblique without an explicit <angle> defaults to 14deg. The OpenType slnt
7
9
  // axis uses the opposite sign convention (positive = counter-clockwise), so
8
10
  // CSS maps oblique to slnt -14.
9
11
  const DEFAULT_OBLIQUE_SLNT = -14;
10
-
11
- // When no opsz values are determined from font-variation-settings, the axis is
12
- // pinned to its default value rather than preserving the full range, which can
13
- // significantly bloat variable font subsets.
14
- const ignoredVariationAxes = new Set();
15
-
16
12
  function clamp(value, min, max) {
17
- return Math.min(Math.max(value, min), max);
13
+ return Math.min(Math.max(value, min), max);
18
14
  }
19
-
20
15
  function renderNumberRange(min, max) {
21
- if (min === max) {
22
- return String(min);
23
- } else {
24
- return `${min}-${max}`;
25
- }
26
- }
27
-
28
- function getVariationAxisUsage(
29
- htmlOrSvgAssetTextsWithProps,
30
- parseFontWeightRange,
31
- parseFontStretchRange
32
- ) {
33
- const seenAxisValuesByFontUrlAndAxisName = new Map();
34
-
35
- function noteUsedValue(fontUrl, axisName, axisValue) {
36
- let seenAxes = seenAxisValuesByFontUrlAndAxisName.get(fontUrl);
37
- if (!seenAxes) {
38
- seenAxes = new Map();
39
- seenAxisValuesByFontUrlAndAxisName.set(fontUrl, seenAxes);
16
+ if (min === max) {
17
+ return String(min);
40
18
  }
41
- if (seenAxes.has(axisName)) {
42
- seenAxes.get(axisName).add(axisValue);
43
- } else {
44
- seenAxes.set(axisName, new Set([axisValue]));
19
+ else {
20
+ return `${min}-${max}`;
45
21
  }
46
- }
47
-
48
- // Since fontUsages are built from shared templates, all pages produce
49
- // the same fontStyles/fontWeights/etc. for a given fontUrl. Process
50
- // each unique fontUrl only once to avoid num_pages × redundant iterations.
51
- const seenFontUrls = new Set();
52
- for (const { fontUsages } of htmlOrSvgAssetTextsWithProps) {
53
- for (const {
54
- fontUrl,
55
- fontStyles,
56
- fontWeights,
57
- fontStretches,
58
- fontVariationSettings,
59
- props,
60
- } of fontUsages) {
61
- if (seenFontUrls.has(fontUrl)) continue;
62
- seenFontUrls.add(fontUrl);
63
- if (fontStyles.has('italic')) {
64
- noteUsedValue(fontUrl, 'ital', 1);
65
- }
66
- // If any font-style value except italic is seen (including normal or oblique)
67
- // we're also utilizing value 0:
68
- if (fontStyles.size > (fontStyles.has('italic') ? 1 : 0)) {
69
- noteUsedValue(fontUrl, 'ital', 0);
70
- }
71
- if (fontStyles.has('oblique')) {
72
- // https://www.w3.org/TR/css-fonts-4/#font-style-prop
73
- // oblique <angle>?
74
- // [...] The lack of an <angle> represents 14deg.
75
- // And also:
76
- // Note: the OpenType slnt axis is defined with a positive angle meaning a counter-clockwise slant, the opposite direction to CSS.
77
- // The CSS implementation will take this into account when using variations to produce oblique faces.
78
- noteUsedValue(fontUrl, 'slnt', DEFAULT_OBLIQUE_SLNT);
79
- }
80
- // If any font-style value except oblique is seen (including normal or italic)
81
- // we're also utilizing value 0:
82
- if (fontStyles.size > (fontStyles.has('oblique') ? 1 : 0)) {
83
- noteUsedValue(fontUrl, 'slnt', 0);
84
- }
85
-
86
- const minMaxFontWeight = parseFontWeightRange(props['font-weight']);
87
- for (const fontWeight of fontWeights) {
88
- noteUsedValue(fontUrl, 'wght', clamp(fontWeight, ...minMaxFontWeight));
89
- }
90
-
91
- const minMaxFontStretch = parseFontStretchRange(props['font-stretch']);
92
- for (const fontStretch of fontStretches) {
93
- noteUsedValue(
94
- fontUrl,
95
- 'wdth',
96
- clamp(fontStretch, ...minMaxFontStretch)
97
- );
98
- }
99
-
100
- for (const fontVariationSettingsValue of fontVariationSettings) {
101
- for (const [axisName, axisValue] of parseFontVariationSettings(
102
- fontVariationSettingsValue
103
- )) {
104
- noteUsedValue(fontUrl, axisName, axisValue);
22
+ }
23
+ function getVariationAxisUsage(htmlOrSvgAssetTextsWithProps, parseFontWeightRange, parseFontStretchRange) {
24
+ const seenAxisValuesByFontUrlAndAxisName = new Map();
25
+ function noteUsedValue(fontUrl, axisName, axisValue) {
26
+ let seenAxes = seenAxisValuesByFontUrlAndAxisName.get(fontUrl);
27
+ if (!seenAxes) {
28
+ seenAxes = new Map();
29
+ seenAxisValuesByFontUrlAndAxisName.set(fontUrl, seenAxes);
30
+ }
31
+ const existing = seenAxes.get(axisName);
32
+ if (existing) {
33
+ existing.add(axisValue);
34
+ }
35
+ else {
36
+ seenAxes.set(axisName, new Set([axisValue]));
105
37
  }
106
- }
107
38
  }
108
- }
109
-
110
- return { seenAxisValuesByFontUrlAndAxisName };
39
+ // Since fontUsages are built from shared templates, all pages produce
40
+ // the same fontStyles/fontWeights/etc. for a given fontUrl. Process
41
+ // each unique fontUrl only once to avoid num_pages × redundant iterations.
42
+ const seenFontUrls = new Set();
43
+ for (const { fontUsages } of htmlOrSvgAssetTextsWithProps) {
44
+ for (const { fontUrl, fontStyles, fontWeights, fontStretches, fontVariationSettings, props, } of fontUsages) {
45
+ if (seenFontUrls.has(fontUrl))
46
+ continue;
47
+ seenFontUrls.add(fontUrl);
48
+ if (fontStyles.has('italic')) {
49
+ noteUsedValue(fontUrl, 'ital', 1);
50
+ }
51
+ // If any font-style value except italic is seen (including normal or oblique)
52
+ // we're also utilizing value 0:
53
+ if (fontStyles.size > (fontStyles.has('italic') ? 1 : 0)) {
54
+ noteUsedValue(fontUrl, 'ital', 0);
55
+ }
56
+ if (fontStyles.has('oblique')) {
57
+ noteUsedValue(fontUrl, 'slnt', DEFAULT_OBLIQUE_SLNT);
58
+ }
59
+ // If any font-style value except oblique is seen (including normal or italic)
60
+ // we're also utilizing value 0:
61
+ if (fontStyles.size > (fontStyles.has('oblique') ? 1 : 0)) {
62
+ noteUsedValue(fontUrl, 'slnt', 0);
63
+ }
64
+ const minMaxFontWeight = parseFontWeightRange(props['font-weight']);
65
+ for (const fontWeight of fontWeights) {
66
+ noteUsedValue(fontUrl, 'wght', clamp(fontWeight, ...minMaxFontWeight));
67
+ }
68
+ const minMaxFontStretch = parseFontStretchRange(props['font-stretch']);
69
+ for (const fontStretch of fontStretches) {
70
+ noteUsedValue(fontUrl, 'wdth', clamp(fontStretch, ...minMaxFontStretch));
71
+ }
72
+ for (const fontVariationSettingsValue of fontVariationSettings) {
73
+ for (const [axisName, axisValue] of parseFontVariationSettings(fontVariationSettingsValue)) {
74
+ noteUsedValue(fontUrl, axisName, axisValue);
75
+ }
76
+ }
77
+ }
78
+ }
79
+ return { seenAxisValuesByFontUrlAndAxisName };
111
80
  }
112
-
113
- async function getVariationAxisBounds(
114
- fontAssetsByUrl,
115
- fontUrl,
116
- seenAxisValuesByFontUrlAndAxisName
117
- ) {
118
- let fontInfo;
119
- try {
120
- fontInfo = await getFontInfo(fontAssetsByUrl.get(fontUrl).rawSrc);
121
- } catch {
122
- // Invalid font -- skip instancing, return safe defaults
123
- return {
124
- fullyInstanced: false,
125
- numAxesPinned: 0,
126
- numAxesReduced: 0,
127
- variationAxes: {},
128
- };
129
- }
130
-
131
- const variationAxes = {};
132
- let fullyInstanced = true;
133
- let numAxesPinned = 0;
134
- let numAxesReduced = 0;
135
- const fontVariationEntries = Object.entries(fontInfo.variationAxes);
136
- const seenAxisValuesByAxisName =
137
- seenAxisValuesByFontUrlAndAxisName.get(fontUrl);
138
- if (fontVariationEntries.length > 0 && seenAxisValuesByAxisName) {
139
- for (const [
140
- axisName,
141
- { min, max, default: defaultValue },
142
- ] of fontVariationEntries) {
143
- let seenAxisValues = seenAxisValuesByAxisName.get(axisName);
144
- if (!seenAxisValues && !ignoredVariationAxes.has(axisName)) {
145
- seenAxisValues = new Set([defaultValue]);
146
- }
147
- if (seenAxisValues && seenAxisValues.size === 1) {
148
- variationAxes[axisName] = clamp([...seenAxisValues][0], min, max);
149
- numAxesPinned += 1;
150
- } else if (seenAxisValues) {
151
- const minSeenValue = Math.min(...seenAxisValues);
152
- const maxSeenValue = Math.max(...seenAxisValues);
153
- variationAxes[axisName] = {
154
- min: Math.max(minSeenValue, min),
155
- max: Math.min(maxSeenValue, max),
81
+ async function getVariationAxisBounds(fontAssetsByUrl, fontUrl, seenAxisValuesByFontUrlAndAxisName) {
82
+ let fontInfo;
83
+ try {
84
+ const asset = fontAssetsByUrl.get(fontUrl);
85
+ if (!asset) {
86
+ return {
87
+ fullyInstanced: false,
88
+ numAxesPinned: 0,
89
+ numAxesReduced: 0,
90
+ variationAxes: {},
91
+ };
92
+ }
93
+ fontInfo = await getFontInfo(asset.rawSrc);
94
+ }
95
+ catch {
96
+ // Invalid font -- skip instancing, return safe defaults
97
+ return {
98
+ fullyInstanced: false,
99
+ numAxesPinned: 0,
100
+ numAxesReduced: 0,
101
+ variationAxes: {},
156
102
  };
157
- fullyInstanced = false;
158
- if (minSeenValue > min || maxSeenValue < max) {
159
- numAxesReduced += 1;
103
+ }
104
+ const variationAxes = {};
105
+ let fullyInstanced = true;
106
+ let numAxesPinned = 0;
107
+ let numAxesReduced = 0;
108
+ const fontVariationEntries = Object.entries(fontInfo.variationAxes);
109
+ const seenAxisValuesByAxisName = seenAxisValuesByFontUrlAndAxisName.get(fontUrl);
110
+ if (fontVariationEntries.length > 0 && seenAxisValuesByAxisName) {
111
+ for (const [axisName, { min, max, default: defaultValue },] of fontVariationEntries) {
112
+ let seenAxisValues = seenAxisValuesByAxisName.get(axisName);
113
+ if (!seenAxisValues) {
114
+ seenAxisValues = new Set([defaultValue]);
115
+ }
116
+ if (seenAxisValues.size === 1) {
117
+ const [only] = seenAxisValues;
118
+ variationAxes[axisName] = clamp(only, min, max);
119
+ numAxesPinned += 1;
120
+ }
121
+ else {
122
+ let minSeenValue = Infinity;
123
+ let maxSeenValue = -Infinity;
124
+ for (const v of seenAxisValues) {
125
+ if (v < minSeenValue)
126
+ minSeenValue = v;
127
+ if (v > maxSeenValue)
128
+ maxSeenValue = v;
129
+ }
130
+ variationAxes[axisName] = {
131
+ min: Math.max(minSeenValue, min),
132
+ max: Math.min(maxSeenValue, max),
133
+ };
134
+ fullyInstanced = false;
135
+ if (minSeenValue > min || maxSeenValue < max) {
136
+ numAxesReduced += 1;
137
+ }
138
+ }
160
139
  }
161
- }
162
140
  }
163
- }
164
- return { fullyInstanced, numAxesPinned, numAxesReduced, variationAxes };
141
+ return { fullyInstanced, numAxesPinned, numAxesReduced, variationAxes };
165
142
  }
166
-
167
- module.exports = {
168
- standardVariationAxes,
169
- ignoredVariationAxes,
170
- renderNumberRange,
171
- getVariationAxisUsage,
172
- getVariationAxisBounds,
173
- };
143
+ //# sourceMappingURL=variationAxes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variationAxes.js","sourceRoot":"","sources":["../src/variationAxes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ interface AtRuleLike {
2
+ some(predicate: (node: {
3
+ prop?: string;
4
+ }) => boolean): boolean;
5
+ append(decl: {
6
+ prop: string;
7
+ value: string;
8
+ }): void;
9
+ }
10
+ interface FontFaceRelationLike {
11
+ from: {
12
+ markDirty(): void;
13
+ };
14
+ node: AtRuleLike;
15
+ }
16
+ interface FontFaceDeclaration {
17
+ 'font-family'?: string;
18
+ relations: FontFaceRelationLike[];
19
+ }
20
+ interface FontUsageLike {
21
+ subsets?: Record<string, Buffer | Uint8Array>;
22
+ pageText: string;
23
+ fontFamilies: Set<string>;
24
+ codepoints: {
25
+ original: number[];
26
+ };
27
+ props: Record<string, string>;
28
+ }
29
+ interface AssetTextEntry {
30
+ htmlOrSvgAsset: {
31
+ text: string;
32
+ urlOrDescription: string;
33
+ };
34
+ fontUsages: FontUsageLike[];
35
+ accumulatedFontFaceDeclarations: FontFaceDeclaration[];
36
+ }
37
+ interface AssetGraphLike {
38
+ warn(err: Error): void;
39
+ info(err: Error): void;
40
+ }
41
+ declare function warnAboutMissingGlyphs(htmlOrSvgAssetTextsWithProps: AssetTextEntry[], assetGraph: AssetGraphLike): Promise<void>;
42
+ export = warnAboutMissingGlyphs;
43
+ //# sourceMappingURL=warnAboutMissingGlyphs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warnAboutMissingGlyphs.d.ts","sourceRoot":"","sources":["../src/warnAboutMissingGlyphs.ts"],"names":[],"mappings":"AAIA,UAAU,UAAU;IAClB,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,GAAG,OAAO,CAAC;IAC/D,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACrD;AAED,UAAU,oBAAoB;IAC5B,IAAI,EAAE;QAAE,SAAS,IAAI,IAAI,CAAA;KAAE,CAAC;IAG5B,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,UAAU,mBAAmB;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,oBAAoB,EAAE,CAAC;CACnC;AAED,UAAU,aAAa;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,UAAU,EAAE;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,UAAU,cAAc;IACtB,cAAc,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3D,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,+BAA+B,EAAE,mBAAmB,EAAE,CAAC;CACxD;AAED,UAAU,cAAc;IACtB,IAAI,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,CAAC;CACxB;AAED,iBAAe,sBAAsB,CACnC,4BAA4B,EAAE,cAAc,EAAE,EAC9C,UAAU,EAAE,cAAc,GACzB,OAAO,CAAC,IAAI,CAAC,CAoLf;AAED,SAAS,sBAAsB,CAAC"}
@@ -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