subfont 7.0.0 → 7.1.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.
- package/CHANGELOG.md +8 -0
- package/lib/getFontInfo.js +27 -0
- package/lib/subsetFonts.js +35 -41
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
### v7.1.1 (2023-05-07)
|
|
2
|
+
|
|
3
|
+
- [Fix file name generation when the font-family contains backslash Fixes \#171](https://github.com/Munter/subfont/commit/1cff3c4095680569ecf50d017035730eb4bd0cc0) ([Andreas Lind](mailto:andreaslindpetersen@gmail.com))
|
|
4
|
+
|
|
5
|
+
### v7.1.0 (2023-04-15)
|
|
6
|
+
|
|
7
|
+
- [#170](https://github.com/Munter/subfont/pull/170) Use harfbuzzjs instead of fontkit ([Andreas Lind](mailto:andreaslindpetersen@gmail.com))
|
|
8
|
+
|
|
1
9
|
### v7.0.0 (2023-04-08)
|
|
2
10
|
|
|
3
11
|
#### Pull requests
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const fontverter = require('fontverter');
|
|
2
|
+
|
|
3
|
+
async function getFontInfoFromBuffer(buffer) {
|
|
4
|
+
const harfbuzzJs = await require('harfbuzzjs');
|
|
5
|
+
|
|
6
|
+
const blob = harfbuzzJs.createBlob(await fontverter.convert(buffer, 'sfnt')); // Load the font data into something Harfbuzz can use
|
|
7
|
+
const face = harfbuzzJs.createFace(blob, 0); // Select the first font in the file (there's normally only one!)
|
|
8
|
+
|
|
9
|
+
const fontInfo = {
|
|
10
|
+
characterSet: Array.from(face.collectUnicodes()),
|
|
11
|
+
variationAxes: face.getAxisInfos(),
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
face.destroy();
|
|
15
|
+
blob.destroy();
|
|
16
|
+
|
|
17
|
+
return fontInfo;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const fontInfoPromiseByBuffer = new WeakMap();
|
|
21
|
+
|
|
22
|
+
module.exports = function getFontInfo(buffer) {
|
|
23
|
+
if (!fontInfoPromiseByBuffer.has(buffer)) {
|
|
24
|
+
fontInfoPromiseByBuffer.set(buffer, getFontInfoFromBuffer(buffer));
|
|
25
|
+
}
|
|
26
|
+
return fontInfoPromiseByBuffer.get(buffer);
|
|
27
|
+
};
|
package/lib/subsetFonts.js
CHANGED
|
@@ -20,13 +20,13 @@ const injectSubsetDefinitions = require('./injectSubsetDefinitions');
|
|
|
20
20
|
const cssFontParser = require('css-font-parser');
|
|
21
21
|
const cssListHelpers = require('css-list-helpers');
|
|
22
22
|
const LinesAndColumns = require('lines-and-columns').default;
|
|
23
|
-
const fontkit = require('fontkit');
|
|
24
23
|
const crypto = require('crypto');
|
|
25
24
|
|
|
26
25
|
const unquote = require('./unquote');
|
|
27
26
|
const normalizeFontPropertyValue = require('./normalizeFontPropertyValue');
|
|
28
27
|
const getCssRulesByProperty = require('./getCssRulesByProperty');
|
|
29
28
|
const unicodeRange = require('./unicodeRange');
|
|
29
|
+
const getFontInfo = require('./getFontInfo');
|
|
30
30
|
|
|
31
31
|
const googleFontsCssUrlRegex = /^(?:https?:)?\/\/fonts\.googleapis\.com\/css/;
|
|
32
32
|
|
|
@@ -383,26 +383,17 @@ function getSubsetPromiseId(fontUsage, format, variationAxes = null) {
|
|
|
383
383
|
].join('\x1d');
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
-
function
|
|
387
|
-
|
|
388
|
-
return fontkit.create(assetGraph.findAssets({ url })[0].rawSrc);
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
function getFullyPinnedVariationAxes(
|
|
393
|
-
fontkitMemoizer,
|
|
386
|
+
async function getFullyPinnedVariationAxes(
|
|
387
|
+
assetGraph,
|
|
394
388
|
fontUrl,
|
|
395
389
|
seenAxisValuesByFontUrlAndAxisName
|
|
396
390
|
) {
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
// Don't break if we encounter an invalid font or one that's unsupported by fontkit
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
391
|
+
const fontInfo = await getFontInfo(
|
|
392
|
+
assetGraph.findAssets({ url: fontUrl })[0].rawSrc
|
|
393
|
+
);
|
|
394
|
+
|
|
404
395
|
let variationAxes;
|
|
405
|
-
const fontVariationEntries = Object.entries(
|
|
396
|
+
const fontVariationEntries = Object.entries(fontInfo.variationAxes);
|
|
406
397
|
const seenAxisValuesByAxisName =
|
|
407
398
|
seenAxisValuesByFontUrlAndAxisName.get(fontUrl);
|
|
408
399
|
if (fontVariationEntries.length > 0 && seenAxisValuesByAxisName) {
|
|
@@ -435,7 +426,6 @@ async function getSubsetsForFontUsage(
|
|
|
435
426
|
htmlOrSvgAssetTextsWithProps,
|
|
436
427
|
formats,
|
|
437
428
|
seenAxisValuesByFontUrlAndAxisName,
|
|
438
|
-
fontkitMemoizer,
|
|
439
429
|
instance = false
|
|
440
430
|
) {
|
|
441
431
|
const allFonts = [];
|
|
@@ -480,8 +470,8 @@ async function getSubsetsForFontUsage(
|
|
|
480
470
|
const text = fontUsage.text;
|
|
481
471
|
let variationAxes;
|
|
482
472
|
if (instance) {
|
|
483
|
-
variationAxes = getFullyPinnedVariationAxes(
|
|
484
|
-
|
|
473
|
+
variationAxes = await getFullyPinnedVariationAxes(
|
|
474
|
+
assetGraph,
|
|
485
475
|
fontUsage.fontUrl,
|
|
486
476
|
seenAxisValuesByFontUrlAndAxisName
|
|
487
477
|
);
|
|
@@ -681,7 +671,7 @@ async function createSelfHostedGoogleFontsCssAsset(
|
|
|
681
671
|
lines.push(` src: ${srcFragments.join(', ')};`);
|
|
682
672
|
lines.push(
|
|
683
673
|
` unicode-range: ${unicodeRange(
|
|
684
|
-
|
|
674
|
+
(await getFontInfo(cssFontFaceSrc.to.rawSrc)).characterSet
|
|
685
675
|
)};`
|
|
686
676
|
);
|
|
687
677
|
lines.push('}');
|
|
@@ -761,7 +751,10 @@ function parseFontStretchRange(str) {
|
|
|
761
751
|
return [minFontStretch, maxFontStretch];
|
|
762
752
|
}
|
|
763
753
|
|
|
764
|
-
function warnAboutMissingGlyphs(
|
|
754
|
+
async function warnAboutMissingGlyphs(
|
|
755
|
+
htmlOrSvgAssetTextsWithProps,
|
|
756
|
+
assetGraph
|
|
757
|
+
) {
|
|
765
758
|
const missingGlyphsErrors = [];
|
|
766
759
|
|
|
767
760
|
for (const {
|
|
@@ -771,9 +764,9 @@ function warnAboutMissingGlyphs(htmlOrSvgAssetTextsWithProps, assetGraph) {
|
|
|
771
764
|
} of htmlOrSvgAssetTextsWithProps) {
|
|
772
765
|
for (const fontUsage of fontUsages) {
|
|
773
766
|
if (fontUsage.subsets) {
|
|
774
|
-
const characterSet =
|
|
767
|
+
const { characterSet } = await getFontInfo(
|
|
775
768
|
Object.values(fontUsage.subsets)[0]
|
|
776
|
-
)
|
|
769
|
+
);
|
|
777
770
|
|
|
778
771
|
let missedAny = false;
|
|
779
772
|
for (const char of [...fontUsage.pageText]) {
|
|
@@ -953,12 +946,11 @@ function getVariationAxisUsage(htmlOrSvgAssetTextsWithProps) {
|
|
|
953
946
|
return { seenAxisValuesByFontUrlAndAxisName, outOfBoundsAxesByFontUrl };
|
|
954
947
|
}
|
|
955
948
|
|
|
956
|
-
function warnAboutUnusedVariationAxes(
|
|
949
|
+
async function warnAboutUnusedVariationAxes(
|
|
957
950
|
assetGraph,
|
|
958
951
|
seenAxisValuesByFontUrlAndAxisName,
|
|
959
952
|
outOfBoundsAxesByFontUrl,
|
|
960
|
-
notFullyInstancedFontUrls
|
|
961
|
-
fontkitMemoizer
|
|
953
|
+
notFullyInstancedFontUrls
|
|
962
954
|
) {
|
|
963
955
|
const warnings = [];
|
|
964
956
|
for (const [
|
|
@@ -969,17 +961,20 @@ function warnAboutUnusedVariationAxes(
|
|
|
969
961
|
continue;
|
|
970
962
|
}
|
|
971
963
|
const outOfBoundsAxes = outOfBoundsAxesByFontUrl.get(fontUrl) || new Set();
|
|
972
|
-
let
|
|
964
|
+
let fontInfo;
|
|
973
965
|
try {
|
|
974
|
-
|
|
966
|
+
fontInfo = await getFontInfo(
|
|
967
|
+
assetGraph.findAssets({ url: fontUrl })[0].rawSrc
|
|
968
|
+
);
|
|
975
969
|
} catch (err) {
|
|
976
|
-
// Don't break if we encounter an invalid font
|
|
970
|
+
// Don't break if we encounter an invalid font
|
|
977
971
|
continue;
|
|
978
972
|
}
|
|
973
|
+
|
|
979
974
|
const unusedAxes = [];
|
|
980
975
|
const underutilizedAxes = [];
|
|
981
976
|
for (const [name, { min, max, default: defaultValue }] of Object.entries(
|
|
982
|
-
|
|
977
|
+
fontInfo.variationAxes
|
|
983
978
|
)) {
|
|
984
979
|
if (ignoredVariationAxes.has(name)) {
|
|
985
980
|
continue;
|
|
@@ -1290,7 +1285,8 @@ async function subsetFonts(
|
|
|
1290
1285
|
let originalCodepoints;
|
|
1291
1286
|
try {
|
|
1292
1287
|
// Guard against 'Unknown font format' errors
|
|
1293
|
-
originalCodepoints =
|
|
1288
|
+
originalCodepoints = (await getFontInfo(originalFont.rawSrc))
|
|
1289
|
+
.characterSet;
|
|
1294
1290
|
} catch (err) {}
|
|
1295
1291
|
if (originalCodepoints) {
|
|
1296
1292
|
const usedCodepoints = getCodepoints(fontUsage.text);
|
|
@@ -1323,25 +1319,21 @@ async function subsetFonts(
|
|
|
1323
1319
|
const { seenAxisValuesByFontUrlAndAxisName, outOfBoundsAxesByFontUrl } =
|
|
1324
1320
|
getVariationAxisUsage(htmlOrSvgAssetTextsWithProps);
|
|
1325
1321
|
|
|
1326
|
-
const fontkitMemoizer = createFontkitMemoizer(assetGraph);
|
|
1327
|
-
|
|
1328
1322
|
// Generate subsets:
|
|
1329
1323
|
const { notFullyInstancedFontUrls } = await getSubsetsForFontUsage(
|
|
1330
1324
|
assetGraph,
|
|
1331
1325
|
htmlOrSvgAssetTextsWithProps,
|
|
1332
1326
|
formats,
|
|
1333
1327
|
seenAxisValuesByFontUrlAndAxisName,
|
|
1334
|
-
fontkitMemoizer,
|
|
1335
1328
|
instance
|
|
1336
1329
|
);
|
|
1337
1330
|
|
|
1338
|
-
warnAboutMissingGlyphs(htmlOrSvgAssetTextsWithProps, assetGraph);
|
|
1339
|
-
warnAboutUnusedVariationAxes(
|
|
1331
|
+
await warnAboutMissingGlyphs(htmlOrSvgAssetTextsWithProps, assetGraph);
|
|
1332
|
+
await warnAboutUnusedVariationAxes(
|
|
1340
1333
|
assetGraph,
|
|
1341
1334
|
seenAxisValuesByFontUrlAndAxisName,
|
|
1342
1335
|
outOfBoundsAxesByFontUrl,
|
|
1343
|
-
notFullyInstancedFontUrls
|
|
1344
|
-
fontkitMemoizer
|
|
1336
|
+
notFullyInstancedFontUrls
|
|
1345
1337
|
);
|
|
1346
1338
|
|
|
1347
1339
|
// Insert subsets:
|
|
@@ -1483,9 +1475,11 @@ async function subsetFonts(
|
|
|
1483
1475
|
.split(/\s+/)
|
|
1484
1476
|
.map((token) => normalizeFontPropertyValue('font-weight', token))
|
|
1485
1477
|
.join('_');
|
|
1486
|
-
const fileNamePrefix = `${unquote(
|
|
1478
|
+
const fileNamePrefix = `${unquote(
|
|
1479
|
+
cssFontParser.parseFontFamily(nameProps[0])[0]
|
|
1480
|
+
)
|
|
1487
1481
|
.replace(/__subset$/, '')
|
|
1488
|
-
.replace(/
|
|
1482
|
+
.replace(/[^a-z0-9_-]/gi, '_')}-${fontWeightRangeStr}${
|
|
1489
1483
|
nameProps[2] === 'italic' ? 'i' : ''
|
|
1490
1484
|
}`;
|
|
1491
1485
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "subfont",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.1.1",
|
|
4
4
|
"description": "Speeds up your pages initial paint by automatically subsetting local or Google fonts and loading them optimally",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=10.0.0"
|
|
@@ -55,9 +55,9 @@
|
|
|
55
55
|
"css-list-helpers": "^2.0.0",
|
|
56
56
|
"font-snapper": "^1.2.0",
|
|
57
57
|
"font-tracer": "^3.6.0",
|
|
58
|
-
"fontkit": "^1.8.0",
|
|
59
58
|
"fontverter": "^2.0.0",
|
|
60
59
|
"gettemporaryfilepath": "^1.0.1",
|
|
60
|
+
"harfbuzzjs": "^0.3.3",
|
|
61
61
|
"lines-and-columns": "^1.1.6",
|
|
62
62
|
"lodash": "^4.17.15",
|
|
63
63
|
"memoizesync": "^1.1.1",
|