subfont 6.10.0 → 6.11.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 CHANGED
@@ -1,3 +1,10 @@
1
+ ### v6.11.0 (2022-09-04)
2
+
3
+ - [Treat wdth as a standard axis \(but unsupported for now\)](https://github.com/Munter/subfont/commit/20d539750448134cca0a82f2cc98f85d9a6be068) ([Andreas Lind](mailto:andreaslindpetersen@gmail.com))
4
+ - [Detect unused ital variation axis ranges](https://github.com/Munter/subfont/commit/b848b21b66cdbcd0ff313690ba49a4bc9b9f90a4) ([Andreas Lind](mailto:andreaslindpetersen@gmail.com))
5
+ - [Don't assume that the display name of a variation axis equals its name](https://github.com/Munter/subfont/commit/4fcf7df801de01b2d3aef3d5f1ea3d697779ffda) ([Andreas Lind](mailto:andreaslindpetersen@gmail.com))
6
+ - [Detect unused wght variation axis ranges](https://github.com/Munter/subfont/commit/6a964d609f21bf2c9dad96da1d16d9c32c28dbfd) ([Andreas Lind](mailto:andreaslindpetersen@gmail.com))
7
+
1
8
  ### v6.10.0 (2022-08-29)
2
9
 
3
10
  - [Update @hookun\/parse-animation-shorthand to ^0.1.4 to make sure we get the fix for hookhookun\/parse-animation-shorthand\#16](https://github.com/Munter/subfont/commit/4db17826245e289e987c6dc02d3f67ebf5891e6f) ([Andreas Lind](mailto:andreas.lind@workday.com))
@@ -12,7 +12,7 @@ module.exports = function* parseFontVariationSettings(value) {
12
12
  if (token.type !== 'string') {
13
13
  return;
14
14
  }
15
- axisName = token.value.toUpperCase();
15
+ axisName = token.value;
16
16
  state = 'AFTER_AXIS_NAME';
17
17
  break;
18
18
  }
@@ -194,10 +194,25 @@ function groupTextsByFontFamilyProps(
194
194
  const { relations, ...props } = activeFontFaceDeclaration;
195
195
  const fontUrl = getPreferredFontUrl(relations);
196
196
 
197
+ const fontStyle = normalizeFontPropertyValue(
198
+ 'font-style',
199
+ textAndProps.props['font-style']
200
+ );
201
+
202
+ let fontWeight = normalizeFontPropertyValue(
203
+ 'font-weight',
204
+ textAndProps.props['font-weight']
205
+ );
206
+ if (fontWeight === 'normal') {
207
+ fontWeight = 400;
208
+ }
209
+
197
210
  return {
198
211
  htmlOrSvgAsset: textAndProps.htmlOrSvgAsset,
199
212
  text: textAndProps.text,
200
213
  fontVariationSettings: textAndProps.props['font-variation-settings'],
214
+ fontStyle,
215
+ fontWeight,
201
216
  animationTimingFunction:
202
217
  textAndProps.props['animation-timing-function'],
203
218
  props,
@@ -217,6 +232,8 @@ function groupTextsByFontFamilyProps(
217
232
  const fontFamilies = new Set(
218
233
  textsPropsArray.map((obj) => obj.props['font-family'])
219
234
  );
235
+ const fontStyles = new Set(textsPropsArray.map((obj) => obj.fontStyle));
236
+ const fontWeights = new Set(textsPropsArray.map((obj) => obj.fontWeight));
220
237
  const fontVariationSettings = new Set(
221
238
  textsPropsArray
222
239
  .map((obj) => obj.fontVariationSettings)
@@ -256,6 +273,8 @@ function groupTextsByFontFamilyProps(
256
273
  props: { ...textsPropsArray[0].props },
257
274
  fontUrl,
258
275
  fontFamilies,
276
+ fontStyles,
277
+ fontWeights,
259
278
  fontVariationSettings,
260
279
  hasOutOfBoundsAnimationTimingFunction,
261
280
  preload,
@@ -618,6 +637,22 @@ function cssAssetIsEmpty(cssAsset) {
618
637
  );
619
638
  }
620
639
 
640
+ function parseFontWeightRange(str) {
641
+ let minFontWeight = 400;
642
+ let maxFontWeight = 400;
643
+ const fontWeightTokens = str.split(/\s+/).map((str) => parseFloat(str));
644
+ if (
645
+ [1, 2].includes(fontWeightTokens.length) &&
646
+ !fontWeightTokens.some(isNaN)
647
+ ) {
648
+ minFontWeight = maxFontWeight = fontWeightTokens[0];
649
+ if (fontWeightTokens.length === 2) {
650
+ maxFontWeight = fontWeightTokens[1];
651
+ }
652
+ }
653
+ return [minFontWeight, maxFontWeight];
654
+ }
655
+
621
656
  function warnAboutMissingGlyphs(htmlOrSvgAssetTextsWithProps, assetGraph) {
622
657
  const missingGlyphsErrors = [];
623
658
 
@@ -708,9 +743,19 @@ These glyphs are used on your site, but they don't exist in the font you applied
708
743
  }
709
744
  }
710
745
 
711
- const standardVariationAxes = new Set(['WGHT', 'ITAL', 'SLNT', 'OPSZ']);
746
+ const standardVariationAxes = new Set(['wght', 'wdth', 'ital', 'slnt', 'opsz']);
747
+ // Tracing the ranges of these standard axes require a bit more work, so just skip them for now:
748
+ const ignoredVariationAxes = new Set(['wdth', 'slnt', 'opsz']);
749
+
750
+ function renderNumberRange(min, max) {
751
+ if (min === max) {
752
+ return String(min);
753
+ } else {
754
+ return `${min}-${max}`;
755
+ }
756
+ }
712
757
 
713
- function warnAboutUnusedCustomVariationAxes(
758
+ function warnAboutUnusedVariationAxes(
714
759
  htmlOrSvgAssetTextsWithProps,
715
760
  assetGraph
716
761
  ) {
@@ -721,13 +766,45 @@ function warnAboutUnusedCustomVariationAxes(
721
766
  for (const {
722
767
  fontUrl,
723
768
  fontVariationSettings,
769
+ fontStyles,
770
+ fontWeights,
724
771
  hasOutOfBoundsAnimationTimingFunction,
772
+ props,
725
773
  } of fontUsages) {
726
774
  let seenAxes = seenAxisValuesByFontUrlAndAxisName.get(fontUrl);
727
775
  if (!seenAxes) {
728
776
  seenAxes = new Map();
729
777
  seenAxisValuesByFontUrlAndAxisName.set(fontUrl, seenAxes);
730
778
  }
779
+ const seenItalValues = [];
780
+ if (fontStyles.has('italic')) {
781
+ seenItalValues.push(1);
782
+ }
783
+ // If any font-style value except italic is seen (including normal or oblique)
784
+ // we're also utilizing value 0:
785
+ if (fontStyles.size > fontStyles.has('italic') ? 1 : 0) {
786
+ seenItalValues.push(0);
787
+ }
788
+ if (seenItalValues.length > 0) {
789
+ if (seenAxes.has('ital')) {
790
+ seenAxes.get('ital').push(...seenItalValues);
791
+ } else {
792
+ seenAxes.set('ital', seenItalValues);
793
+ }
794
+ }
795
+
796
+ const minMaxFontWeight = parseFontWeightRange(props['font-weight']);
797
+ const seenFontWeightValues = [];
798
+ for (const fontWeight of fontWeights) {
799
+ seenFontWeightValues.push(_.clamp(fontWeight, ...minMaxFontWeight));
800
+ }
801
+ if (seenFontWeightValues.length > 0) {
802
+ if (seenAxes.has('wght')) {
803
+ seenAxes.get('wght').push(...seenFontWeightValues);
804
+ } else {
805
+ seenAxes.set('wght', seenFontWeightValues);
806
+ }
807
+ }
731
808
 
732
809
  for (const fontVariationSettingsValue of fontVariationSettings) {
733
810
  for (const [axisName, axisValue] of parseFontVariationSettings(
@@ -767,26 +844,22 @@ function warnAboutUnusedCustomVariationAxes(
767
844
  }
768
845
  const unusedAxes = [];
769
846
  const underutilizedAxes = [];
770
- for (const { name, min, max, default: defaultValue } of Object.values(
847
+ for (const [name, { min, max, default: defaultValue }] of Object.entries(
771
848
  font.variationAxes
772
849
  )) {
773
- const axisName = name.toUpperCase();
774
- if (standardVariationAxes.has(axisName)) {
850
+ if (ignoredVariationAxes.has(name)) {
775
851
  continue;
776
852
  }
777
- if (
778
- seenAxisValuesByAxisName.has(axisName) &&
779
- !outOfBoundsAxes.has(axisName)
780
- ) {
781
- const usedValues = [
782
- defaultValue,
783
- ...seenAxisValuesByAxisName.get(axisName),
784
- ];
853
+ if (seenAxisValuesByAxisName.has(name) && !outOfBoundsAxes.has(name)) {
854
+ const usedValues = [...seenAxisValuesByAxisName.get(name)];
855
+ if (!standardVariationAxes.has(name)) {
856
+ usedValues.push(defaultValue);
857
+ }
785
858
  const minUsed = Math.min(...usedValues);
786
859
  const maxUsed = Math.max(...usedValues);
787
860
  if (minUsed > min || maxUsed < max) {
788
861
  underutilizedAxes.push({
789
- name: axisName,
862
+ name,
790
863
  minUsed,
791
864
  maxUsed,
792
865
  min,
@@ -794,7 +867,7 @@ function warnAboutUnusedCustomVariationAxes(
794
867
  });
795
868
  }
796
869
  } else {
797
- unusedAxes.push(axisName);
870
+ unusedAxes.push(name);
798
871
  }
799
872
  }
800
873
 
@@ -807,7 +880,10 @@ function warnAboutUnusedCustomVariationAxes(
807
880
  message += ` Underutilized axes:\n${underutilizedAxes
808
881
  .map(
809
882
  ({ name, min, max, minUsed, maxUsed }) =>
810
- ` ${name}: ${minUsed}-${maxUsed} used (${min}-${max} available)`
883
+ ` ${name}: ${renderNumberRange(
884
+ minUsed,
885
+ maxUsed
886
+ )} used (${min}-${max} available)`
811
887
  )
812
888
  .join('\n')}\n`;
813
889
  }
@@ -817,7 +893,7 @@ function warnAboutUnusedCustomVariationAxes(
817
893
 
818
894
  if (warnings.length > 0) {
819
895
  assetGraph.info(
820
- new Error(`🪓 Unused custom variation axes detected in your variable fonts.
896
+ new Error(`🪓 Unused variation axes detected in your variable fonts.
821
897
  The below variable fonts contain custom axes that do not appear to be fully used on any of your pages.
822
898
  This bloats your fonts and also the subset fonts that subfont creates.
823
899
  Consider removing the unused axis ranges using a tool like Slice <https://slice-gui.netlify.app/>
@@ -1112,7 +1188,7 @@ async function subsetFonts(
1112
1188
  );
1113
1189
 
1114
1190
  warnAboutMissingGlyphs(htmlOrSvgAssetTextsWithProps, assetGraph);
1115
- warnAboutUnusedCustomVariationAxes(htmlOrSvgAssetTextsWithProps, assetGraph);
1191
+ warnAboutUnusedVariationAxes(htmlOrSvgAssetTextsWithProps, assetGraph);
1116
1192
 
1117
1193
  // Insert subsets:
1118
1194
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "subfont",
3
- "version": "6.10.0",
3
+ "version": "6.11.0",
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"