subfont 6.11.0 → 6.12.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.
- package/CHANGELOG.md +8 -0
- package/lib/normalizeFontPropertyValue.js +3 -0
- package/lib/subsetFonts.js +82 -32
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
### v6.12.0 (2022-09-07)
|
|
2
|
+
|
|
3
|
+
- [Refactor repeated code into helper function](https://github.com/Munter/subfont/commit/5335d931957cadc150fed1c5d548ee6b6e245636) ([Andreas Lind](mailto:andreaslindpetersen@gmail.com))
|
|
4
|
+
- [Clamp the used variation axis values to the available interval](https://github.com/Munter/subfont/commit/1429c0f35720ee8dadb691138eb4cfa3c1c86150) ([Andreas Lind](mailto:andreaslindpetersen@gmail.com))
|
|
5
|
+
- [Detech unused slnt variation axis ranges](https://github.com/Munter/subfont/commit/dc4be1598ba1ba0e65d8269d0fa2d25aa528357d) ([Andreas Lind](mailto:andreaslindpetersen@gmail.com))
|
|
6
|
+
- [Report variation axes that only use the default value as unused rather than underutilized](https://github.com/Munter/subfont/commit/12082590898407f558d9540347778272ddb9d197) ([Andreas Lind](mailto:andreaslindpetersen@gmail.com))
|
|
7
|
+
- [Detect unused wdth variation axis ranges](https://github.com/Munter/subfont/commit/d7758eb3c9a45a49768aac12c36ed897a0c4b467) ([Andreas Lind](mailto:andreaslindpetersen@gmail.com))
|
|
8
|
+
|
|
1
9
|
### v6.11.0 (2022-09-04)
|
|
2
10
|
|
|
3
11
|
- [Treat wdth as a standard axis \(but unsupported for now\)](https://github.com/Munter/subfont/commit/20d539750448134cca0a82f2cc98f85d9a6be068) ([Andreas Lind](mailto:andreaslindpetersen@gmail.com))
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const cssFontWeightNames = require('css-font-weight-names');
|
|
2
2
|
const initialValueByProp = require('./initialValueByProp');
|
|
3
3
|
const unquote = require('./unquote');
|
|
4
|
+
const normalizeFontStretch = require('font-snapper/lib/normalizeFontStretch');
|
|
4
5
|
|
|
5
6
|
function normalizeFontPropertyValue(propName, value) {
|
|
6
7
|
const propNameLowerCase = propName.toLowerCase();
|
|
@@ -22,6 +23,8 @@ function normalizeFontPropertyValue(propName, value) {
|
|
|
22
23
|
} else {
|
|
23
24
|
return value;
|
|
24
25
|
}
|
|
26
|
+
} else if (propNameLowerCase === 'font-stretch') {
|
|
27
|
+
return normalizeFontStretch(value);
|
|
25
28
|
} else if (typeof value === 'string' && propNameLowerCase !== 'src') {
|
|
26
29
|
return value.toLowerCase();
|
|
27
30
|
}
|
package/lib/subsetFonts.js
CHANGED
|
@@ -213,6 +213,10 @@ function groupTextsByFontFamilyProps(
|
|
|
213
213
|
fontVariationSettings: textAndProps.props['font-variation-settings'],
|
|
214
214
|
fontStyle,
|
|
215
215
|
fontWeight,
|
|
216
|
+
fontStretch: normalizeFontPropertyValue(
|
|
217
|
+
'font-stretch',
|
|
218
|
+
textAndProps.props['font-stretch']
|
|
219
|
+
),
|
|
216
220
|
animationTimingFunction:
|
|
217
221
|
textAndProps.props['animation-timing-function'],
|
|
218
222
|
props,
|
|
@@ -234,6 +238,9 @@ function groupTextsByFontFamilyProps(
|
|
|
234
238
|
);
|
|
235
239
|
const fontStyles = new Set(textsPropsArray.map((obj) => obj.fontStyle));
|
|
236
240
|
const fontWeights = new Set(textsPropsArray.map((obj) => obj.fontWeight));
|
|
241
|
+
const fontStretches = new Set(
|
|
242
|
+
textsPropsArray.map((obj) => obj.fontStretch)
|
|
243
|
+
);
|
|
237
244
|
const fontVariationSettings = new Set(
|
|
238
245
|
textsPropsArray
|
|
239
246
|
.map((obj) => obj.fontVariationSettings)
|
|
@@ -274,6 +281,7 @@ function groupTextsByFontFamilyProps(
|
|
|
274
281
|
fontUrl,
|
|
275
282
|
fontFamilies,
|
|
276
283
|
fontStyles,
|
|
284
|
+
fontStretches,
|
|
277
285
|
fontWeights,
|
|
278
286
|
fontVariationSettings,
|
|
279
287
|
hasOutOfBoundsAnimationTimingFunction,
|
|
@@ -638,6 +646,9 @@ function cssAssetIsEmpty(cssAsset) {
|
|
|
638
646
|
}
|
|
639
647
|
|
|
640
648
|
function parseFontWeightRange(str) {
|
|
649
|
+
if (typeof str === 'undefined' || str === 'auto') {
|
|
650
|
+
return [-Infinity, Infinity];
|
|
651
|
+
}
|
|
641
652
|
let minFontWeight = 400;
|
|
642
653
|
let maxFontWeight = 400;
|
|
643
654
|
const fontWeightTokens = str.split(/\s+/).map((str) => parseFloat(str));
|
|
@@ -653,6 +664,27 @@ function parseFontWeightRange(str) {
|
|
|
653
664
|
return [minFontWeight, maxFontWeight];
|
|
654
665
|
}
|
|
655
666
|
|
|
667
|
+
function parseFontStretchRange(str) {
|
|
668
|
+
if (typeof str === 'undefined' || str.toLowerCase() === 'auto') {
|
|
669
|
+
return [-Infinity, Infinity];
|
|
670
|
+
}
|
|
671
|
+
let minFontStretch = 100;
|
|
672
|
+
let maxFontStretch = 100;
|
|
673
|
+
const fontStretchTokens = str
|
|
674
|
+
.split(/\s+/)
|
|
675
|
+
.map((str) => normalizeFontPropertyValue('font-stretch', str));
|
|
676
|
+
if (
|
|
677
|
+
[1, 2].includes(fontStretchTokens.length) &&
|
|
678
|
+
!fontStretchTokens.some(isNaN)
|
|
679
|
+
) {
|
|
680
|
+
minFontStretch = maxFontStretch = fontStretchTokens[0];
|
|
681
|
+
if (fontStretchTokens.length === 2) {
|
|
682
|
+
maxFontStretch = fontStretchTokens[1];
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
return [minFontStretch, maxFontStretch];
|
|
686
|
+
}
|
|
687
|
+
|
|
656
688
|
function warnAboutMissingGlyphs(htmlOrSvgAssetTextsWithProps, assetGraph) {
|
|
657
689
|
const missingGlyphsErrors = [];
|
|
658
690
|
|
|
@@ -744,8 +776,9 @@ These glyphs are used on your site, but they don't exist in the font you applied
|
|
|
744
776
|
}
|
|
745
777
|
|
|
746
778
|
const standardVariationAxes = new Set(['wght', 'wdth', 'ital', 'slnt', 'opsz']);
|
|
747
|
-
//
|
|
748
|
-
|
|
779
|
+
// It would be very hard to trace statically which values of opsz (font-optical-sizing)
|
|
780
|
+
// are going to be used, so we ignore that one:
|
|
781
|
+
const ignoredVariationAxes = new Set(['opsz']);
|
|
749
782
|
|
|
750
783
|
function renderNumberRange(min, max) {
|
|
751
784
|
if (min === max) {
|
|
@@ -762,60 +795,72 @@ function warnAboutUnusedVariationAxes(
|
|
|
762
795
|
const seenAxisValuesByFontUrlAndAxisName = new Map();
|
|
763
796
|
const outOfBoundsAxesByFontUrl = new Map();
|
|
764
797
|
|
|
798
|
+
function noteUsedValue(fontUrl, axisName, axisValue) {
|
|
799
|
+
let seenAxes = seenAxisValuesByFontUrlAndAxisName.get(fontUrl);
|
|
800
|
+
if (!seenAxes) {
|
|
801
|
+
seenAxes = new Map();
|
|
802
|
+
seenAxisValuesByFontUrlAndAxisName.set(fontUrl, seenAxes);
|
|
803
|
+
}
|
|
804
|
+
if (seenAxes.has(axisName)) {
|
|
805
|
+
seenAxes.get(axisName).push(axisValue);
|
|
806
|
+
} else {
|
|
807
|
+
seenAxes.set(axisName, [axisValue]);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
|
|
765
811
|
for (const { fontUsages } of htmlOrSvgAssetTextsWithProps) {
|
|
766
812
|
for (const {
|
|
767
813
|
fontUrl,
|
|
768
|
-
fontVariationSettings,
|
|
769
814
|
fontStyles,
|
|
770
815
|
fontWeights,
|
|
816
|
+
fontStretches,
|
|
817
|
+
fontVariationSettings,
|
|
771
818
|
hasOutOfBoundsAnimationTimingFunction,
|
|
772
819
|
props,
|
|
773
820
|
} of fontUsages) {
|
|
774
|
-
let seenAxes = seenAxisValuesByFontUrlAndAxisName.get(fontUrl);
|
|
775
|
-
if (!seenAxes) {
|
|
776
|
-
seenAxes = new Map();
|
|
777
|
-
seenAxisValuesByFontUrlAndAxisName.set(fontUrl, seenAxes);
|
|
778
|
-
}
|
|
779
|
-
const seenItalValues = [];
|
|
780
821
|
if (fontStyles.has('italic')) {
|
|
781
|
-
|
|
822
|
+
noteUsedValue(fontUrl, 'ital', 1);
|
|
782
823
|
}
|
|
783
824
|
// If any font-style value except italic is seen (including normal or oblique)
|
|
784
825
|
// we're also utilizing value 0:
|
|
785
826
|
if (fontStyles.size > fontStyles.has('italic') ? 1 : 0) {
|
|
786
|
-
|
|
827
|
+
noteUsedValue(fontUrl, 'ital', 0);
|
|
787
828
|
}
|
|
788
|
-
if (
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
829
|
+
if (fontStyles.has('oblique')) {
|
|
830
|
+
// https://www.w3.org/TR/css-fonts-4/#font-style-prop
|
|
831
|
+
// oblique <angle>?
|
|
832
|
+
// [...] The lack of an <angle> represents 14deg.
|
|
833
|
+
noteUsedValue(fontUrl, 'slnt', 14);
|
|
834
|
+
}
|
|
835
|
+
// If any font-style value except oblique is seen (including normal or italic)
|
|
836
|
+
// we're also utilizing value 0:
|
|
837
|
+
if (fontStyles.size > fontStyles.has('oblique') ? 1 : 0) {
|
|
838
|
+
noteUsedValue(fontUrl, 'slnt', 0);
|
|
794
839
|
}
|
|
795
840
|
|
|
796
841
|
const minMaxFontWeight = parseFontWeightRange(props['font-weight']);
|
|
797
|
-
const seenFontWeightValues = [];
|
|
798
842
|
for (const fontWeight of fontWeights) {
|
|
799
|
-
|
|
843
|
+
noteUsedValue(
|
|
844
|
+
fontUrl,
|
|
845
|
+
'wght',
|
|
846
|
+
_.clamp(fontWeight, ...minMaxFontWeight)
|
|
847
|
+
);
|
|
800
848
|
}
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
849
|
+
|
|
850
|
+
const minMaxFontStretch = parseFontStretchRange(props['font-stretch']);
|
|
851
|
+
for (const fontStrech of fontStretches) {
|
|
852
|
+
noteUsedValue(
|
|
853
|
+
fontUrl,
|
|
854
|
+
'wdth',
|
|
855
|
+
_.clamp(fontStrech, ...minMaxFontStretch)
|
|
856
|
+
);
|
|
807
857
|
}
|
|
808
858
|
|
|
809
859
|
for (const fontVariationSettingsValue of fontVariationSettings) {
|
|
810
860
|
for (const [axisName, axisValue] of parseFontVariationSettings(
|
|
811
861
|
fontVariationSettingsValue
|
|
812
862
|
)) {
|
|
813
|
-
|
|
814
|
-
if (seenAxisValues) {
|
|
815
|
-
seenAxisValues.push(axisValue);
|
|
816
|
-
} else {
|
|
817
|
-
seenAxes.set(axisName, [axisValue]);
|
|
818
|
-
}
|
|
863
|
+
noteUsedValue(fontUrl, axisName, axisValue);
|
|
819
864
|
if (hasOutOfBoundsAnimationTimingFunction) {
|
|
820
865
|
let outOfBoundsAxes = outOfBoundsAxesByFontUrl.get(fontUrl);
|
|
821
866
|
if (!outOfBoundsAxes) {
|
|
@@ -850,8 +895,13 @@ function warnAboutUnusedVariationAxes(
|
|
|
850
895
|
if (ignoredVariationAxes.has(name)) {
|
|
851
896
|
continue;
|
|
852
897
|
}
|
|
898
|
+
let usedValues = [];
|
|
853
899
|
if (seenAxisValuesByAxisName.has(name) && !outOfBoundsAxes.has(name)) {
|
|
854
|
-
|
|
900
|
+
usedValues = [...seenAxisValuesByAxisName.get(name)].map((usedValue) =>
|
|
901
|
+
_.clamp(usedValue, min, max)
|
|
902
|
+
);
|
|
903
|
+
}
|
|
904
|
+
if (!usedValues.every((value) => value === defaultValue)) {
|
|
855
905
|
if (!standardVariationAxes.has(name)) {
|
|
856
906
|
usedValues.push(defaultValue);
|
|
857
907
|
}
|