Optimize spacing variants' building

This commit is contained in:
be5invis 2022-09-15 18:50:29 -07:00
parent b7a59ee481
commit 12a4f1edb1
14 changed files with 775 additions and 372 deletions

View file

@ -0,0 +1,80 @@
import fs from "fs";
import { FontIo, Ot } from "ot-builder";
import { assignFontNames, createNamingDictFromArgv } from "./gen/meta/naming.mjs";
export default main;
async function main(argv) {
const font = await readTTF(argv);
const naming = createNamingDictFromArgv(argv);
assignFontNames(font, naming, false);
switch (argv.shape.spacing) {
case "term":
deriveTerm(font);
break;
case "fixed":
deriveTerm(font);
deriveFixed(font);
break;
}
await saveTTF(argv, font);
}
// To derive -Term variants, simply apply NWID
function deriveTerm(font) {
const gsub = font.gsub;
let nwidMap = new Map();
for (const feature of gsub.features) {
if (feature.tag !== "NWID") continue;
for (const lookup of feature.lookups) {
if (!(lookup instanceof Ot.Gsub.Single)) continue;
for (const [from, to] of lookup.mapping) {
nwidMap.set(from, to);
}
}
}
for (const [ch, g] of [...font.cmap.unicode.entries()]) {
const narrow = nwidMap.get(g);
if (narrow) font.cmap.unicode.set(ch, narrow);
}
for (const [ch, vs, g] of [...font.cmap.vs.entries()]) {
const narrow = nwidMap.get(g);
if (narrow) font.cmap.vs.set(ch, vs, narrow);
}
}
// In FontConfig, a font is considered "monospace" if and only if all encoded non-combining
// characters (AW > 0) have the same width. We use this method to validate whether our
// "Fixed" subfamilies are properly built.
function deriveFixed(font) {
const unitWidth = font.os2.xAvgCharWidth;
for (const [ch, g] of [...font.cmap.unicode.entries()]) {
const advanceWidth = g.horizontal.end - g.horizontal.start;
if (!(advanceWidth === 0 || advanceWidth === unitWidth)) font.cmap.unicode.delete(ch);
}
for (const [ch, vs, g] of [...font.cmap.vs.entries()]) {
const advanceWidth = g.horizontal.end - g.horizontal.start;
if (!(advanceWidth === 0 || advanceWidth === unitWidth)) font.cmap.vs.delete(ch, vs);
}
}
async function readTTF(argv) {
const buf = await fs.promises.readFile(argv.i);
const sfnt = FontIo.readSfntOtf(buf);
const font = FontIo.readFont(sfnt, Ot.ListGlyphStoreFactory);
return font;
}
async function saveTTF(argv, font) {
const sfnt = FontIo.writeFont(font, {
glyphStore: { statOs2XAvgCharWidth: false },
generateDummyDigitalSignature: true
});
const buf = FontIo.writeSfntOtf(sfnt);
await fs.promises.writeFile(argv.o, buf);
}

View file

@ -1,20 +1,22 @@
import { buildGlyphs } from "../glyphs/index.mjs";
import { copyFontMetrics } from "../meta/aesthetics.mjs";
import { assignFontNames } from "../meta/naming.mjs";
import { buildOtl } from "../otl/index.mjs";
import * as Caching from "./caching/index.mjs";
import { CreateEmptyFont } from "./empty-font.mjs";
import { finalizeFont } from "./finalize/index.mjs";
import { CreateEmptyFont } from "./meta/empty-font.mjs";
import { assignFontNames } from "./meta/naming.mjs";
import { convertOtd } from "./otd-conv/index.mjs";
("use strict");
export async function buildFont(argv, para) {
const gs = buildGlyphs(para);
const baseFont = CreateEmptyFont(argv);
assignFontNames(para, baseFont);
assignFontNames(baseFont, para.naming, para.isQuasiProportional);
const gs = buildGlyphs(para);
copyFontMetrics(gs.fontMetrics, baseFont);
const otl = buildOtl(para, gs.glyphStore);
// Regulate
const excludeChars = new Set();
if (para.excludedCharRanges) {

View file

@ -15,9 +15,10 @@ function assignSubRank(glyphStore) {
let sr = 0;
for (const g of glyphStore.glyphs()) g.subRank = sr++;
}
// In FontConfig, a font is considered "monospace" if and only if all non-combining characters
// (AW > 0) have the same width. We use this method to validate whether our "Fixed" subfamilies
// are properly built.
// In FontConfig, a font is considered "monospace" if and only if all encoded non-combining
// characters (AW > 0) have the same width. We use this method to validate whether our
// "Fixed" subfamilies are properly built.
function validateMonospace(para, glyphStore) {
let awSet = new Set();
for (const [u, g] of glyphStore.encodedEntries()) {

View file

@ -0,0 +1,241 @@
import { Ot } from "ot-builder";
import semver from "semver";
export function createNamingDictFromArgv(argv) {
return {
family: argv.menu.family,
version: argv.menu.version,
weight: argv.menu.weight - 0,
width: argv.menu.width - 0,
slope: argv.menu.slope
};
}
export function assignFontNames(font, naming, isQuasiProportional) {
// Clear existing names
font.name.records.length = 0;
// Preferred names
const family = naming.family.trim();
const style = getStyle(naming.weight, naming.width, naming.slope);
nameFont(font, Ot.Name.NameID.PreferredFamily, family);
nameFont(font, Ot.Name.NameID.PreferredSubfamily, style);
nameFont(font, Ot.Name.NameID.WwsFamily, family);
nameFont(font, Ot.Name.NameID.WwsSubfamily, style);
// Compat banes
const compat = getStyleLinkedStyles(naming.weight, naming.width, naming.slope);
let compatFamily = family;
if (compat.familySuffix !== " Regular") compatFamily = family + " " + compat.familySuffix;
if (compatFamily.length >= 31) compatFamily = family + " " + compat.familySuffixShort;
nameFont(font, Ot.Name.NameID.LegacyFamily, compatFamily);
nameFont(font, Ot.Name.NameID.LegacySubfamily, compat.style);
// Unique and Full name
const uniqueName = `${family} ${style} ${naming.version}`;
const fullName = style !== "Regular" ? `${family} ${style}` : family;
const postscriptName = fullName.replace(/ /g, "-");
nameFont(font, Ot.Name.NameID.UniqueFontId, uniqueName);
nameFont(font, Ot.Name.NameID.FullFontName, fullName);
nameFont(font, Ot.Name.NameID.PostscriptName, postscriptName);
// Weight, width and slope numbers
font.os2.usWeightClass = naming.weight;
font.os2.usWidthClass = naming.width;
font.os2.panose.bWeight = 1 + naming.weight / 100;
font.os2.sFamilyClass = 0x809;
// HEAD and OS/2 flags
const isItalic = naming.slope === "italic";
const isOblique = naming.slope === "oblique";
const isBold = naming.weight > 650;
// prettier-ignore
font.os2.fsSelection = accumulateFlags(
[Ot.Os2.FsSelection.OBLIQUE, isOblique],
[Ot.Os2.FsSelection.BOLD, isBold],
[Ot.Os2.FsSelection.ITALIC, isItalic || isOblique],
[Ot.Os2.FsSelection.REGULAR, !isBold && !isItalic && !isOblique],
[Ot.Os2.FsSelection.USE_TYPO_METRICS, true]
);
// prettier-ignore
font.head.macStyle = accumulateFlags(
[Ot.Head.MacStyle.Bold, isBold],
[Ot.Head.MacStyle.Italic, isItalic || isOblique],
[Ot.Head.MacStyle.Condensed, naming.width < 5],
[Ot.Head.MacStyle.Extended, naming.width > 5]
);
// Panose
font.os2.panose.bFamilyType = 2;
font.os2.panose.bContrast = 3;
font.os2.panose.bXHeight = 4;
// Pitch
if (!isQuasiProportional) {
font.os2.panose.bProportion = 9; // Monospaced
font.post.isFixedPitch = true;
} else {
font.os2.panose.bProportion = 0;
font.post.isFixedPitch = false;
}
// Licensing
if (naming.miscNames) {
nameFont(font, Ot.Name.NameID.Copyright, naming.miscNames.copyright);
nameFont(font, Ot.Name.NameID.Manufacturer, naming.miscNames.manufacturer);
nameFont(font, Ot.Name.NameID.Designer, naming.miscNames.designer);
nameFont(font, Ot.Name.NameID.Description, naming.miscNames.description);
nameFont(font, Ot.Name.NameID.LicenseDescription, naming.miscNames.licence);
}
// Version
nameFont(font, Ot.Name.NameID.VersionString, `Version ${naming.version}`);
const majorVersion = semver.major(naming.version);
const minorVersion = semver.minor(naming.version);
const patchVersion = semver.patch(naming.version);
if (minorVersion > 99 || patchVersion > 99) throw new RangeError("Version number overflow");
font.head.fontRevision = majorVersion + (minorVersion * 10 + patchVersion) / 1000;
// Misc
font.os2.ulCodePageRange1 = 0x2000011f;
font.os2.ulCodePageRange2 = 0xc4000000;
font.head.flags = accumulateFlags(
[Ot.Head.Flags.BaseLineYAt0, true],
[Ot.Head.Flags.LeftSidebearingAtX0, true],
[Ot.Head.Flags.InstructionsMayDependOnPointSize, true],
[Ot.Head.Flags.ForcePpemToBeInteger, true],
[Ot.Head.Flags.InstructionMayAlterAdvanceWidth, true]
);
}
function accumulateFlags(...entries) {
let s = 0;
for (const [flag, cond] of entries) {
if (cond) s |= flag;
}
return s;
}
function getStyleLinkedStyles(weight, width, slope) {
let linkWeight = weight;
let linkSlope = slope;
let nameSuffixWeight = 400;
let nameSuffixWidth = width;
let nameSuffixSlope = "normal";
if (!(linkWeight === 400 || linkWeight == 700)) {
nameSuffixWeight = linkWeight;
linkWeight = 400;
}
if (!(linkSlope === "normal" || linkSlope === "italic")) {
nameSuffixSlope = linkSlope;
linkSlope = "normal";
}
return {
style: getStyle(linkWeight, 5, linkSlope),
familySuffix: getStyle(nameSuffixWeight, nameSuffixWidth, nameSuffixSlope),
familySuffixShort: getShortStyle(nameSuffixWeight, nameSuffixWidth, nameSuffixSlope)
};
}
function nameFont(font, nameID, str) {
// Mac Roman
font.name.records.push({
platformID: 1,
encodingID: 0,
languageID: 0,
nameID,
value: Buffer.from(str, "utf-8")
});
// Windows Unicode English
font.name.records.push({
platformID: 3,
encodingID: 1,
languageID: 1033,
nameID,
value: str
});
}
function isRBIZ(weight, slope) {
return (weight === 400 || weight === 700) && (slope === "normal" || slope === "italic");
}
function getStyle(weight, width, slope) {
const weightPart = weightToMenuStyleMap[weight] ?? "W" + weight;
const widthPart = widthToMenuStyleMap[width] ?? "Wd" + width;
const slopePart = slopeToMenuStyleMap[slope] ?? "";
const rawName = weightPart + " " + widthPart + " " + slopePart;
return rawName.replace(/ +/g, " ").trim() || "Regular";
}
function getShortStyle(weight, width, slope) {
const weightPart = weightToMenuStyleMapShort[weight] ?? "W" + weight;
const widthPart = widthToMenuStyleMapShort[width] ?? "Wd" + width;
const slopePart = slopeToMenuStyleMapShort[slope] ?? "";
const rawName = weightPart + " " + widthPart + " " + slopePart;
return rawName.replace(/ +/g, " ").trim() || "Regular";
}
const weightToMenuStyleMap = {
100: "Thin",
200: "Extralight",
300: "Light",
400: "",
450: "Book",
500: "Medium",
600: "Semibold",
700: "Bold",
800: "Extrabold",
900: "Heavy"
};
const widthToMenuStyleMap = {
1: "Ultra-Condensed",
2: "Extra-Condensed",
3: "Condensed",
4: "Semi-Condensed",
5: "",
6: "Semi-Extended",
7: "Extended",
8: "Extra-Extended",
9: "Ultra-Extended"
};
const slopeToMenuStyleMap = {
normal: "",
italic: "Italic",
oblique: "Oblique"
};
const weightToMenuStyleMapShort = {
100: "Th",
200: "XLt",
300: "Lt",
400: "",
450: "Bk",
500: "Md",
600: "SmBd",
700: "Bd",
800: "XBd",
900: "Hv"
};
const widthToMenuStyleMapShort = {
1: "UltCn",
2: "XCn",
3: "Cn",
4: "SmCn",
5: "",
6: "SmEx",
7: "Ex",
8: "XEx",
9: "UltEx"
};
const slopeToMenuStyleMapShort = {
normal: "",
italic: "It",
oblique: "Obl"
};

View file

@ -9,8 +9,8 @@ glyph-block Symbol-Punctuation-Percentages : begin
glyph-block-import CommonShapes
glyph-block-import Common-Derivatives
define [NarrowUnicode u] : if (para.spacing < 1) u null
define [WideUnicode u] : if (para.spacing >= 1) u null
define NarrowUnicode : NarrowUnicodeT WideWidth1
define WideUnicode : WideUnicodeT WideWidth1
define [PercentBarCor df sw] : HVContrast / [Math.sqrt (1 - [Math.pow ((df.rightSB - df.leftSB - sw) / (CAP - 0)) 2])]
define [PercentBarShape df sw] : begin
@ -108,9 +108,6 @@ glyph-block Symbol-Punctuation-Percentages : begin
create-forked-glyph 'permille.WWID.ringsContinuousSlashAlsoConnected' : composite-proc [ConnnectedBar] [PerMilleProc]
create-forked-glyph 'basepoint.WWID.ringsContinuousSlashAlsoConnected' : composite-proc [ConnnectedBar] [BasePointProc]
select-variant 'permille.WWID' [WideUnicode 0x2030] (follow -- 'permille.WWID')
select-variant 'basepoint.WWID' [WideUnicode 0x2031] (follow -- 'permille.WWID')
create-glyph 'percent.ringsSegmentedSlash' : glyph-proc
set-width Width
local l : SB / 2
@ -191,4 +188,6 @@ glyph-block Symbol-Punctuation-Percentages : begin
select-variant 'percent' '%'
select-variant 'permille.NWID' [NarrowUnicode 0x2030] (follow -- 'permille.NWID')
select-variant 'permille.WWID' [WideUnicode 0x2030] (follow -- 'permille.WWID')
select-variant 'basepoint.NWID' [NarrowUnicode 0x2031] (follow -- 'permille.NWID')
select-variant 'basepoint.WWID' [WideUnicode 0x2031] (follow -- 'permille.WWID')

View file

@ -8,6 +8,7 @@ import { encode } from "@msgpack/msgpack";
import { FontIo } from "ot-builder";
import { buildFont } from "./gen/build-font.mjs";
import { createNamingDictFromArgv } from "./gen/meta/naming.mjs";
import { createGrDisplaySheet } from "./support/gr.mjs";
import { applyLigationData } from "./support/ligation-data.mjs";
import { applyMetricOverride } from "./support/metric-override.mjs";
@ -44,12 +45,8 @@ async function getParameters() {
if (argv.compatibilityLigatures) para.compLig = argv.compatibilityLigatures;
if (argv.metricOverride) applyMetricOverride(para, argv.metricOverride, argv);
para.naming = {
...para.naming,
family: argv.menu.family,
version: argv.menu.version,
weight: argv.menu.weight - 0,
width: argv.menu.width - 0,
slope: argv.menu.slope
miscNames: para.naming,
...createNamingDictFromArgv(argv)
};
return para;
}

View file

@ -131,6 +131,9 @@ export : define [calculateMetrics para] : begin
define WideWidth3 : if (para.spacing >= 3) WideWidth0 Width
define WideWidth4 : if (para.spacing >= 4) WideWidth0 Width
define [NarrowUnicodeT wd] : function [u] : if (wd === Width) u null
define [WideUnicodeT wd] : function [u] : if (wd !== Width) u null
define EssUpper : Stroke * [fallback para.essRatioUpper para.essRatio Contrast]
define EssLower : Stroke * [fallback para.essRatioLower para.essRatio Contrast]
define EssQuestion : Stroke * [fallback para.essRatioQuestion para.essRatio Contrast]
@ -208,11 +211,12 @@ export : define [calculateMetrics para] : begin
AccentClearance AccentHeight CThin CThinB SLAB TailAdjX TailAdjY IBalance IBalance2
JBalance JBalance2 TBalance TBalance2 RBalance RBalance2 FBalance OneBalance WideWidth0
WideWidth1 WideWidth2 WideWidth3 WideWidth4 EssUpper EssLower EssQuestion HalfStroke
RightSB Middle DotRadius PeriodRadius SideJut ArchDepthA ArchDepthB SmallArchDepthA SmallArchDepthB CorrectionOMidX CorrectionOMidS ArchXAdjust compositeBaseAnchors
RightSB Middle DotRadius PeriodRadius SideJut ArchDepthA ArchDepthB SmallArchDepthA
SmallArchDepthB CorrectionOMidX CorrectionOMidS ArchXAdjust compositeBaseAnchors
AdviceStroke AdviceStroke2 OverlayStroke OperatorStroke GeometryStroke ShoulderFine
_SuperXY adviceSSmooth AdviceGlottalStopArchDepth shoulderMidSlope StrokeWidthBlend
ArchDepthAOf ArchDepthBOf SmoothAdjust MidJutSide MidJutCenter YSmoothMidR YSmoothMidL
HSwToV]
HSwToV NarrowUnicodeT WideUnicodeT]
export : define [setFontMetrics para metrics fm] : begin
define [object CAP Descender XH Width SymbolMid] metrics

View file

@ -222,7 +222,7 @@ define-macro glyph-block : syntax-rules
AdviceStroke AdviceStroke2 OverlayStroke OperatorStroke GeometryStroke ShoulderFine
_SuperXY adviceSSmooth AdviceGlottalStopArchDepth shoulderMidSlope StrokeWidthBlend
ArchDepthAOf ArchDepthBOf SmoothAdjust MidJutSide MidJutCenter compositeBaseAnchors
YSmoothMidR YSmoothMidL HSwToV]
YSmoothMidR YSmoothMidL HSwToV NarrowUnicodeT WideUnicodeT]
define spiroFnImports `[g4 g2 corner flat curl close end straight widths
disable-contrast heading unimportant important alsoThru alsoThruThem bezControls
quadControls archv arcvh dispiro spiro-outline]

View file

@ -1,227 +0,0 @@
import semver from 'semver'
import [Ot] from "ot-builder"
extern Buffer
import [fallback] from"../support/utils.mjs"
define COPYRIGHT 0
define FAMILY 1
define STYLE 2
define UNIQUE_NAME 3
define FULL_NAME 4
define VERSION 5
define POSTSCRIPT 6
define TRADEMARK 7
define MANUFACTURER 8
define DESIGNER 9
define DESCRIPTION 10
define LICENCE 13
define PREFERRED_FAMILY 16
define PREFERRED_STYLE 17
define WWS_PREFERRED_FAMILY 21
define WWS_PREFERRED_STYLE 22
define [nameFont font nameid str] : begin
font.name.records.push : object # Mac Roman
platformID 1
encodingID 0
languageID 0
nameID nameid
value : Buffer.from str 'utf-8'
font.name.records.push : object # Windows Unicode English
platformID 3
encodingID 1
languageID 1033
nameID nameid
value str
define weightToMenuStyleMap : object
100 "Thin"
200 "Extralight"
300 "Light"
400 ""
450 "Book"
500 "Medium"
600 "Semibold"
700 "Bold"
800 "Extrabold"
900 "Heavy"
define widthToMenuStyleMap : object
1 "Ultra-Condensed"
2 "Extra-Condensed"
3 "Condensed"
4 "Semi-Condensed"
5 ""
6 "Semi-Extended"
7 "Extended"
8 "Extra-Extended"
9 "Ultra-Extended"
define slopeToMenuStyleMap : object
normal ""
italic "Italic"
oblique "Oblique"
define weightToMenuStyleMapShort : object
100 "Th"
200 "XLt"
300 "Lt"
400 ""
450 "Bk"
500 "Md"
600 "SmBd"
700 "Bd"
800 "XBd"
900 "Hv"
define widthToMenuStyleMapShort : object
1 "UltCn"
2 "XCn"
3 "Cn"
4 "SmCn"
5 ""
6 "SmEx"
7 "Ex"
8 "XEx"
9 "UltEx"
define slopeToMenuStyleMapShort : object
normal ""
italic "It"
oblique "Obl"
define [getStyle weight width slope] : begin
define weightPart : fallback weightToMenuStyleMap.(weight) ('W' + weight)
define widthPart : fallback widthToMenuStyleMap.(width) ("Wd" + width)
define slopePart : fallback slopeToMenuStyleMap.(slope) ''
define rawName : weightPart + ' ' + widthPart + ' ' + slopePart
return : [[rawName.replace [regex ' +' 'g'] ' '].trim] || "Regular"
define [getShortStyle weight width slope] : begin
define weightPart : fallback weightToMenuStyleMapShort.(weight) ('W' + weight)
define widthPart : fallback widthToMenuStyleMapShort.(width) ("Wd" + width)
define slopePart : fallback slopeToMenuStyleMapShort.(slope) ''
define rawName : weightPart + ' ' + widthPart + ' ' + slopePart
return : [rawName.replace [regex ' ' 'g'] ''] || "Regular"
define [isRBIBI weight slope] : (weight == 400 || weight == 700) && (slope == "normal" || slope == "italic")
define [getStyleLinkedStyles weight width slope] : begin
local linkWeight weight
local linkSlope slope
local nameSuffixWeight 400
local nameSuffixWidth width
local nameSuffixSlope "normal"
# Not regular or bold
if (linkWeight != 400 && linkWeight != 700) : begin
nameSuffixWeight = linkWeight
linkWeight = 400
# Not "normal" or italic
if (linkSlope != "normal" && linkSlope != "italic") : begin
nameSuffixSlope = linkSlope
linkSlope = "normal"
return : list
getStyle linkWeight 5 linkSlope
getStyle nameSuffixWeight nameSuffixWidth nameSuffixSlope
getShortStyle nameSuffixWeight nameSuffixWidth nameSuffixSlope
define [accumulate entries] : begin
local s 0
foreach { ev cond } [items-of entries] : begin
if cond : set s : s + ev
return s
export : define [assignFontNames para font] : begin
# Preferred names
define family : para.naming.family.trim
define style : getStyle para.naming.weight para.naming.width para.naming.slope
define version : "Version " + para.naming.version
define isItalic : para.naming.slope == "italic"
define isOblique : para.naming.slope == "oblique"
define isBold : para.naming.weight > 650
nameFont font PREFERRED_FAMILY family # Preferred Family
nameFont font PREFERRED_STYLE style # Preferred Style
nameFont font WWS_PREFERRED_FAMILY family # WWS Preferred Family
nameFont font WWS_PREFERRED_STYLE style # WWS Preferred Style
# Compat names
local {compatStyle compatFamilySuffix shortCompatFamilySuffix} : getStyleLinkedStyles para.naming.weight para.naming.width para.naming.slope
local compatFamily family
if (compatFamilySuffix != "Regular") : set compatFamily : family + ' ' + compatFamilySuffix
if (compatFamily.length >= 31) : set compatFamily : family + ' ' + shortCompatFamilySuffix
nameFont font FAMILY compatFamily # Family
nameFont font STYLE compatStyle # Style
nameFont font UNIQUE_NAME "\(family) \(style) \(version)" # Unique Name
local fontfullName : if (style != 'Regular') (family + ' ' + style) family
nameFont font FULL_NAME fontfullName # Full Name
nameFont font POSTSCRIPT : fontfullName.replace [regex ' ' 'g'] '-' # Postscript
# Misc names
nameFont font COPYRIGHT para.naming.copyright # Copyright
nameFont font MANUFACTURER para.naming.manufacturer # Manufacturer
nameFont font DESIGNER para.naming.designer # Designer
nameFont font DESCRIPTION para.naming.description # Description
nameFont font LICENCE para.naming.licence # Licence
# Weight, width and slope numbers
set font.os2.usWeightClass para.naming.weight
set font.os2.usWidthClass para.naming.width
set font.os2.panose.bWeight : 1 + para.naming.weight / 100
set font.os2.sFamilyClass : 8 * 0x100 + 9
set font.os2.xAvgCharWidth : Math.round para.width
set font.os2.fsSelection : accumulate : list
list Ot.Os2.FsSelection.OBLIQUE isOblique
list Ot.Os2.FsSelection.BOLD isBold
list Ot.Os2.FsSelection.ITALIC (isItalic || isOblique)
list Ot.Os2.FsSelection.REGULAR (!isBold && !isItalic && !isOblique)
list Ot.Os2.FsSelection.USE_TYPO_METRICS true
set font.head.macStyle : accumulate : list
list Ot.Head.MacStyle.Bold isBold
list Ot.Head.MacStyle.Italic (isItalic || isOblique)
list Ot.Head.MacStyle.Condensed (para.naming.width < 5)
list Ot.Head.MacStyle.Extended (para.naming.width > 5)
# Version
nameFont font VERSION version # Version
define majorVersion : semver.major para.naming.version
define minorVersion : semver.minor para.naming.version
define patchVersion : semver.patch para.naming.version
if (minorVersion > 99 || patchVersion > 9) : throw : new Error "Version number overflow"
set font.head.fontRevision : majorVersion + (minorVersion * 10 + patchVersion) / 1000
# Panose
set font.os2.panose.bFamilyType 2
set font.os2.panose.bContrast 3
set font.os2.panose.bXHeight 4
# Pitch
if [not para.isQuasiProportional]
: then : begin
set font.os2.panose.bProportion 9 # Monospaced
set font.post.isFixedPitch true
: else : begin
set font.os2.panose.bProportion 0
set font.post.isFixedPitch false
# Misc
set font.os2.ulCodePageRange1 0x2000011f
set font.os2.ulCodePageRange2 0xc4000000
set font.head.flags : accumulate : list
list Ot.Head.Flags.BaseLineYAt0 true
list Ot.Head.Flags.LeftSidebearingAtX0 true
list Ot.Head.Flags.InstructionsMayDependOnPointSize true
list Ot.Head.Flags.ForcePpemToBeInteger true
list Ot.Head.Flags.InstructionMayAlterAdvanceWidth true
# Enforce the order of NAME table entries
font.name.records.sort : lambda [a b] : begin
if (a.platformID != b.platformID) : return : a.platformID - b.platformID
if (a.encodingID != b.encodingID) : return : a.encodingID - b.encodingID
if (a.languageID != b.languageID) : return : a.languageID - b.languageID
return : a.nameID - b.nameID

View file

@ -21,15 +21,14 @@ define GDEF_MARK 3
define [buildGSUB para glyphStore markGlyphs] : begin
define gsub : CreateEmptyTable
# NWID / WWID
buildGrFeature gsub glyphStore Gr.Nwid
buildGrFeature gsub glyphStore Gr.Wwid
# lnum / onum
buildGrFeature gsub glyphStore Gr.Lnum
buildGrFeature gsub glyphStore Gr.Onum
# NWID / WWID
if (!para.forceMonospace || para.spacing > 0) : begin
buildGrFeature gsub glyphStore Gr.Nwid
buildGrFeature gsub glyphStore Gr.Wwid
# APLF
buildGrFeature gsub glyphStore Gr.AplForm

406
package-lock.json generated
View file

@ -10,6 +10,7 @@
"dependencies": {
"@iarna/toml": "^2.2.5",
"@msgpack/msgpack": "^2.7.2",
"deep-equal": "^2.0.5",
"ot-builder": "^1.5.4",
"otb-ttc-bundle": "^1.5.4",
"semver": "^7.3.7",
@ -789,6 +790,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/available-typed-arrays": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -821,7 +833,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
@ -964,6 +975,31 @@
}
}
},
"node_modules/deep-equal": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.5.tgz",
"integrity": "sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==",
"dependencies": {
"call-bind": "^1.0.0",
"es-get-iterator": "^1.1.1",
"get-intrinsic": "^1.0.1",
"is-arguments": "^1.0.4",
"is-date-object": "^1.0.2",
"is-regex": "^1.1.1",
"isarray": "^2.0.5",
"object-is": "^1.1.4",
"object-keys": "^1.1.1",
"object.assign": "^4.1.2",
"regexp.prototype.flags": "^1.3.0",
"side-channel": "^1.0.3",
"which-boxed-primitive": "^1.0.1",
"which-collection": "^1.0.1",
"which-typed-array": "^1.1.2"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@ -974,7 +1010,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
"integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
"dev": true,
"dependencies": {
"has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1"
@ -1020,7 +1055,6 @@
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz",
"integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
@ -1053,6 +1087,24 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/es-get-iterator": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz",
"integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==",
"dependencies": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.0",
"has-symbols": "^1.0.1",
"is-arguments": "^1.1.0",
"is-map": "^2.0.2",
"is-set": "^2.0.2",
"is-string": "^1.0.5",
"isarray": "^2.0.5"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/es-shim-unscopables": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
@ -1066,7 +1118,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
"dev": true,
"dependencies": {
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
@ -1782,6 +1833,14 @@
"integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==",
"dev": true
},
"node_modules/for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
"dependencies": {
"is-callable": "^1.1.3"
}
},
"node_modules/fs-extra": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
@ -1805,14 +1864,12 @@
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"node_modules/function.prototype.name": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
"integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3",
@ -1836,7 +1893,6 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@ -1854,7 +1910,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
"integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
@ -1868,7 +1923,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
"integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.1"
@ -1963,7 +2017,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1"
},
@ -1975,7 +2028,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
"integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@ -1992,7 +2044,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
"integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
"dev": true,
"dependencies": {
"get-intrinsic": "^1.1.1"
},
@ -2004,7 +2055,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
@ -2016,7 +2066,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"dev": true,
"dependencies": {
"has-symbols": "^1.0.2"
},
@ -2104,7 +2153,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
"integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
"dev": true,
"dependencies": {
"get-intrinsic": "^1.1.0",
"has": "^1.0.3",
@ -2114,11 +2162,25 @@
"node": ">= 0.4"
}
},
"node_modules/is-arguments": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-bigint": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
"integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
"dev": true,
"dependencies": {
"has-bigints": "^1.0.1"
},
@ -2130,7 +2192,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
"integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@ -2146,7 +2207,6 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
"integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
@ -2170,7 +2230,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
"dev": true,
"dependencies": {
"has-tostringtag": "^1.0.0"
},
@ -2211,11 +2270,18 @@
"node": ">=0.10.0"
}
},
"node_modules/is-map": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
"integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-negative-zero": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
"integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
@ -2236,7 +2302,6 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
"integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
"dev": true,
"dependencies": {
"has-tostringtag": "^1.0.0"
},
@ -2251,7 +2316,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@ -2263,11 +2327,18 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-set": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
"integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-shared-array-buffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
"integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2"
},
@ -2279,7 +2350,6 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
"integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
"dev": true,
"dependencies": {
"has-tostringtag": "^1.0.0"
},
@ -2294,7 +2364,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
"integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
"dev": true,
"dependencies": {
"has-symbols": "^1.0.2"
},
@ -2305,11 +2374,36 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-typed-array": {
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz",
"integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==",
"dependencies": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"es-abstract": "^1.20.0",
"for-each": "^0.3.3",
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-weakmap": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
"integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-weakref": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
"integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2"
},
@ -2317,6 +2411,23 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-weakset": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
"integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
"dependencies": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.1"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@ -2486,7 +2597,21 @@
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
"integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object-is": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
"integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@ -2495,7 +2620,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true,
"engines": {
"node": ">= 0.4"
}
@ -2504,7 +2628,6 @@
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz",
"integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.4",
@ -2853,7 +2976,6 @@
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
"integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3",
@ -3060,7 +3182,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
@ -3121,7 +3242,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
"integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.4",
@ -3135,7 +3255,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
"integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.4",
@ -3296,7 +3415,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
"integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-bigints": "^1.0.2",
@ -3425,7 +3543,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
"dev": true,
"dependencies": {
"is-bigint": "^1.0.1",
"is-boolean-object": "^1.1.0",
@ -3437,6 +3554,39 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/which-collection": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
"integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
"dependencies": {
"is-map": "^2.0.1",
"is-set": "^2.0.1",
"is-weakmap": "^2.0.1",
"is-weakset": "^2.0.1"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/which-typed-array": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz",
"integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==",
"dependencies": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"es-abstract": "^1.20.0",
"for-each": "^0.3.3",
"has-tostringtag": "^1.0.0",
"is-typed-array": "^1.1.9"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@ -4233,6 +4383,11 @@
"es-shim-unscopables": "^1.0.0"
}
},
"available-typed-arrays": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="
},
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -4262,7 +4417,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"dev": true,
"requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
@ -4373,6 +4527,28 @@
"ms": "2.1.2"
}
},
"deep-equal": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.5.tgz",
"integrity": "sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==",
"requires": {
"call-bind": "^1.0.0",
"es-get-iterator": "^1.1.1",
"get-intrinsic": "^1.0.1",
"is-arguments": "^1.0.4",
"is-date-object": "^1.0.2",
"is-regex": "^1.1.1",
"isarray": "^2.0.5",
"object-is": "^1.1.4",
"object-keys": "^1.1.1",
"object.assign": "^4.1.2",
"regexp.prototype.flags": "^1.3.0",
"side-channel": "^1.0.3",
"which-boxed-primitive": "^1.0.1",
"which-collection": "^1.0.1",
"which-typed-array": "^1.1.2"
}
},
"deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@ -4383,7 +4559,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
"integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
"dev": true,
"requires": {
"has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1"
@ -4417,7 +4592,6 @@
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz",
"integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
@ -4444,6 +4618,21 @@
"unbox-primitive": "^1.0.2"
}
},
"es-get-iterator": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz",
"integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==",
"requires": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.0",
"has-symbols": "^1.0.1",
"is-arguments": "^1.1.0",
"is-map": "^2.0.2",
"is-set": "^2.0.2",
"is-string": "^1.0.5",
"isarray": "^2.0.5"
}
},
"es-shim-unscopables": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
@ -4457,7 +4646,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
"dev": true,
"requires": {
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
@ -5004,6 +5192,14 @@
"integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==",
"dev": true
},
"for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
"requires": {
"is-callable": "^1.1.3"
}
},
"fs-extra": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
@ -5024,14 +5220,12 @@
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"function.prototype.name": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
"integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3",
@ -5048,8 +5242,7 @@
"functions-have-names": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
"dev": true
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="
},
"get-caller-file": {
"version": "2.0.5",
@ -5061,7 +5254,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
"integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
"dev": true,
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
@ -5072,7 +5264,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
"integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.1"
@ -5140,7 +5331,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"requires": {
"function-bind": "^1.1.1"
}
@ -5148,8 +5338,7 @@
"has-bigints": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
"integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
"dev": true
"integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ=="
},
"has-flag": {
"version": "4.0.0",
@ -5160,7 +5349,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
"integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
"dev": true,
"requires": {
"get-intrinsic": "^1.1.1"
}
@ -5168,14 +5356,12 @@
"has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
},
"has-tostringtag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"dev": true,
"requires": {
"has-symbols": "^1.0.2"
}
@ -5239,18 +5425,25 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
"integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
"dev": true,
"requires": {
"get-intrinsic": "^1.1.0",
"has": "^1.0.3",
"side-channel": "^1.0.4"
}
},
"is-arguments": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
}
},
"is-bigint": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
"integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
"dev": true,
"requires": {
"has-bigints": "^1.0.1"
}
@ -5259,7 +5452,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
"integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@ -5268,8 +5460,7 @@
"is-callable": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
"integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
"dev": true
"integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w=="
},
"is-core-module": {
"version": "2.10.0",
@ -5284,7 +5475,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
"dev": true,
"requires": {
"has-tostringtag": "^1.0.0"
}
@ -5310,11 +5500,15 @@
"is-extglob": "^2.1.1"
}
},
"is-map": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
"integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg=="
},
"is-negative-zero": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
"integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
"dev": true
"integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA=="
},
"is-number": {
"version": "7.0.0",
@ -5326,7 +5520,6 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
"integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
"dev": true,
"requires": {
"has-tostringtag": "^1.0.0"
}
@ -5335,17 +5528,20 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
}
},
"is-set": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
"integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g=="
},
"is-shared-array-buffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
"integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
"dev": true,
"requires": {
"call-bind": "^1.0.2"
}
@ -5354,7 +5550,6 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
"integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
"dev": true,
"requires": {
"has-tostringtag": "^1.0.0"
}
@ -5363,20 +5558,49 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
"integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
"dev": true,
"requires": {
"has-symbols": "^1.0.2"
}
},
"is-typed-array": {
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz",
"integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==",
"requires": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"es-abstract": "^1.20.0",
"for-each": "^0.3.3",
"has-tostringtag": "^1.0.0"
}
},
"is-weakmap": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
"integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA=="
},
"is-weakref": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
"integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
"dev": true,
"requires": {
"call-bind": "^1.0.2"
}
},
"is-weakset": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
"integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
"requires": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.1"
}
},
"isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@ -5516,20 +5740,26 @@
"object-inspect": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
"integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
"dev": true
"integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ=="
},
"object-is": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
"integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
}
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
},
"object.assign": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz",
"integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.4",
@ -5770,7 +6000,6 @@
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
"integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3",
@ -5907,7 +6136,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dev": true,
"requires": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
@ -5956,7 +6184,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
"integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.4",
@ -5967,7 +6194,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
"integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.4",
@ -6086,7 +6312,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
"integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"has-bigints": "^1.0.2",
@ -6186,7 +6411,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
"dev": true,
"requires": {
"is-bigint": "^1.0.1",
"is-boolean-object": "^1.1.0",
@ -6195,6 +6419,30 @@
"is-symbol": "^1.0.3"
}
},
"which-collection": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
"integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
"requires": {
"is-map": "^2.0.1",
"is-set": "^2.0.1",
"is-weakmap": "^2.0.1",
"is-weakset": "^2.0.1"
}
},
"which-typed-array": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz",
"integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==",
"requires": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"es-abstract": "^1.20.0",
"for-each": "^0.3.3",
"has-tostringtag": "^1.0.0",
"is-typed-array": "^1.1.9"
}
},
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",

View file

@ -17,7 +17,8 @@
"toposort": "^2.0.2",
"typo-geom": "^0.12.1",
"uuid": "^8.3.2",
"wawoff2": "^2.0.1"
"wawoff2": "^2.0.1",
"deep-equal": "^2.0.5"
},
"devDependencies": {
"@unicode/unicode-14.0.0": "^1.3.0",

View file

@ -2,6 +2,7 @@ import * as FS from "fs";
import * as Path from "path";
import * as toml from "@iarna/toml";
import deepEqual from "deep-equal";
import semver from "semver";
import * as uuid from "uuid";
import * as Verda from "verda";
@ -148,9 +149,37 @@ const BuildPlans = computed("metadata:build-plans", async target => {
}
returnBuildPlans[prefix] = bp;
}
linkSpacingDerivableBuildPlans(returnBuildPlans);
return { fileNameToBpMap, buildPlans: returnBuildPlans };
});
function linkSpacingDerivableBuildPlans(bps) {
for (const pfxTo in bps) {
const planTo = bps[pfxTo];
const planToVal = rectifyPlanForSpacingDerivation(planTo);
if (!(planTo.spacing === "term" || planTo.spacing === "fixed")) continue;
for (const pfxFrom in bps) {
const planFrom = bps[pfxFrom];
if (!(planFrom.spacing === "normal" || !planFrom.spacing)) continue;
const planFromVal = rectifyPlanForSpacingDerivation(planFrom);
if (!deepEqual(planToVal, planFromVal)) continue;
planTo.spacingDeriveFrom = pfxFrom;
}
}
}
function rectifyPlanForSpacingDerivation(p) {
return {
...p,
family: "#Validation",
desc: "#Validation",
spacing: "#Validation",
snapshotFamily: null,
snapshotFeature: null,
targets: null
};
}
const BuildPlanOf = computed.group("metadata:build-plan-of", async (target, gid) => {
const [{ buildPlans }] = await target.need(BuildPlans);
const plan = buildPlans[gid];
@ -189,6 +218,15 @@ const FontInfoOf = computed.group("metadata:font-info-of", async (target, fileNa
const sfi = sfm[fi0.suffix];
const hintReferenceSuffix = fetchHintReferenceSuffix(sfm);
let spacingDerive = null;
if (bp.spacingDeriveFrom) {
spacingDerive = {
manner: bp.spacing,
prefix: bp.spacingDeriveFrom,
fileName: makeFileName(bp.spacingDeriveFrom, fi0.suffix)
};
}
return {
name: fileName,
variants: bp.variants || null,
@ -230,7 +268,10 @@ const FontInfoOf = computed.group("metadata:font-info-of", async (target, fileNa
: null,
compatibilityLigatures: bp["compatibility-ligatures"] || null,
metricOverride: bp["metric-override"] || null,
excludedCharRanges: bp["exclude-chars"]?.ranges
excludedCharRanges: bp["exclude-chars"]?.ranges,
// Spacing derivation -- creating faster build for spacing variants
spacingDerive
};
});
@ -321,41 +362,59 @@ const ageKey = uuid.v4();
const DistUnhintedTTF = file.make(
(gr, fn) => `${DIST}/${gr}/ttf-unhinted/${fn}.ttf`,
async (target, out, gr, fn) => {
await target.need(Scripts, Parameters, Dependencies, de(`${BUILD}/caches`));
const [compositesFromBuildPlan] = await target.need(CompositesFromBuildPlan);
const charMapDir = `${BUILD}/ttf/${gr}`;
const charMapPath = `${charMapDir}/${fn}.charmap.mpz`;
await target.need(Scripts, Parameters, Dependencies);
const [fi] = await target.need(FontInfoOf(fn), de(out.dir));
const [fi] = await target.need(FontInfoOf(fn), de(out.dir), de(charMapDir));
const cacheFileName =
`${Math.round(1000 * fi.shape.weight)}-${Math.round(1000 * fi.shape.width)}-` +
`${Math.round(3600 * fi.shape.slopeAngle)}-${fi.shape.slope}`;
const cachePath = `${BUILD}/caches/${cacheFileName}.mpz`;
const cacheDiffPath = `${charMapDir}/${fn}.cache.mpz`;
echo.action(echo.hl.command(`Create TTF`), fn, echo.hl.operator("->"), out.full);
const { cacheUpdated } = await silently.node("font-src/index.mjs", {
o: out.full,
oCharMap: charMapPath,
cacheFreshAgeKey: ageKey,
iCache: cachePath,
oCache: cacheDiffPath,
compositesFromBuildPlan,
...fi
});
if (cacheUpdated) {
const lock = build.locks.alloc(cacheFileName);
await lock.acquire();
await silently.node(`font-src/merge-cache.mjs`, {
base: cachePath,
diff: cacheDiffPath,
version: fi.menu.version,
freshAgeKey: ageKey
if (fi.spacingDerive) {
// The font is a spacing variant, and is derivable form an existing
// normally-spaced variant.
const spD = fi.spacingDerive;
const [deriveFrom] = await target.need(DistUnhintedTTF(spD.prefix, spD.fileName));
await silently.node(`font-src/derive-spacing.mjs`, {
i: deriveFrom.full,
o: out.full,
...fi
});
lock.release();
} else {
// Ab-initio build
const charMapDir = `${BUILD}/ttf/${gr}`;
const charMapPath = `${charMapDir}/${fn}.charmap.mpz`;
await target.need(de(charMapDir));
await target.need(de(`${BUILD}/caches`));
const cacheFileName =
`${Math.round(1000 * fi.shape.weight)}-${Math.round(1000 * fi.shape.width)}-` +
`${Math.round(3600 * fi.shape.slopeAngle)}-${fi.shape.slope}`;
const cachePath = `${BUILD}/caches/${cacheFileName}.mpz`;
const cacheDiffPath = `${charMapDir}/${fn}.cache.mpz`;
echo.action(echo.hl.command(`Create TTF`), fn, echo.hl.operator("->"), out.full);
const [compositesFromBuildPlan] = await target.need(CompositesFromBuildPlan);
const { cacheUpdated } = await silently.node("font-src/index.mjs", {
o: out.full,
oCharMap: charMapPath,
cacheFreshAgeKey: ageKey,
iCache: cachePath,
oCache: cacheDiffPath,
compositesFromBuildPlan,
...fi
});
if (cacheUpdated) {
const lock = build.locks.alloc(cacheFileName);
await lock.acquire();
await silently.node(`font-src/merge-cache.mjs`, {
base: cachePath,
diff: cacheDiffPath,
version: fi.menu.version,
freshAgeKey: ageKey
});
lock.release();
}
}
}
);
const BuildCM = file.make(
(gr, f) => `${BUILD}/ttf/${gr}/${f}.charmap.mpz`,
async (target, output, gr, f) => {
@ -363,20 +422,19 @@ const BuildCM = file.make(
}
);
function formatSuffix(fmt, unhinted) {
return fmt + (unhinted ? "-unhinted" : "");
}
const DistHintedTTF = file.make(
(gr, fn) => `${DIST}/${gr}/ttf/${fn}.ttf`,
async (target, out, gr, fn) => {
const [{ hintParams }, hint] = await target.need(FontInfoOf(fn), CheckTtfAutoHintExists);
const [fi, hint] = await target.need(FontInfoOf(fn), CheckTtfAutoHintExists);
const [from] = await target.need(DistUnhintedTTF(gr, fn), de`${out.dir}`);
echo.action(echo.hl.command(`Hint TTF`), from.full, echo.hl.operator("->"), out.full);
await silently.run(hint, hintParams, from.full, out.full);
await silently.run(hint, fi.hintParams, from.full, out.full);
}
);
function formatSuffix(fmt, unhinted) {
return fmt + (unhinted ? "-unhinted" : "");
}
const DistWoff2 = file.make(
(gr, fn, unhinted) => `${DIST}/${gr}/${formatSuffix("woff2", unhinted)}/${fn}.woff2`,
async (target, out, group, f, unhinted) => {