diff --git a/packages/font-glyphs/src/letter/latin/c.ptl b/packages/font-glyphs/src/letter/latin/c.ptl index df5585160..a1e3bdbad 100644 --- a/packages/font-glyphs/src/letter/latin/c.ptl +++ b/packages/font-glyphs/src/letter/latin/c.ptl @@ -12,7 +12,8 @@ glyph-block Letter-Latin-C : begin glyph-block-import Mark-Shared-Metrics : markStroke glyph-block-import Letter-Shared : CreateDependentComposite CreateTurnedLetter glyph-block-import Letter-Shared-Shapes : SerifFrame CurlyTail DToothlessRise - glyph-block-import Letter-Shared-Shapes : SerifedArcStart SerifedArcEnd InwardSlabArcStart + glyph-block-import Letter-Shared-Shapes : SerifedArcStart SerifedArcEnd + glyph-block-import Letter-Shared-Shapes : InwardSlabArcStart InwardSlabArcEnd glyph-block-import Letter-Shared-Shapes : ArcStartSerif ArcEndSerif glyph-block-import Letter-Shared-Shapes : LetterBarOverlay PalatalHook RetroflexHook TopHook glyph-block-import Letter-Shared-Shapes : ArcStartSerifWidth ArcStartSerifDepth @@ -28,10 +29,7 @@ glyph-block Letter-Latin-C : begin widths.lhs sw match st [Just SLAB-CLASSICAL] : SerifedArcStart.RtlLhs (df.rightSB - offset) df.middle top sw [fallback hook Hook] origBar - [Just SLAB-INWARD] : list - g4 (df.rightSB - offset) (top - DToothlessRise) - g4 (df.middle - CorrectionOMidX * sw) (top - O - offset) - archv + [Just SLAB-INWARD] : InwardSlabArcStart.RtlLhs (df.rightSB - offset) df.middle top sw [Just FLAT-CONNECTION] : list flat (df.width - offset) (top - offset) curl (df.middle - CorrectionOMidX * sw) (top - offset) @@ -45,10 +43,7 @@ glyph-block Letter-Latin-C : begin match sb [Just SLAB-CLASSICAL] : SerifedArcEnd.LtrLhs (df.rightSB - offset) df.middle bot sw [fallback hook Hook] origBar - [Just SLAB-INWARD] : list - arcvh - g4 (df.middle + CorrectionOMidX * sw) (bot + O + offset) - g4 (df.rightSB - offset) (bot + DToothlessRise) + [Just SLAB-INWARD] : InwardSlabArcEnd.LtrLhs (df.rightSB - offset) df.middle bot sw [Just FLAT-CONNECTION] : list arcvh flat (df.middle + CorrectionOMidX * sw) (bot + O + offset) @@ -61,10 +56,7 @@ glyph-block Letter-Latin-C : begin widths.rhs sw match st [Just SLAB-CLASSICAL] : SerifedArcStart.LtrRhs (df.leftSB + offset) df.middle top sw [fallback hook Hook] origBar - [Just SLAB-INWARD] : list - g4 (df.leftSB + offset) (top - DToothlessRise) - g4 (df.middle - CorrectionOMidX * sw) (top - O - offset) - archv + [Just SLAB-INWARD] : InwardSlabArcStart.LtrRhs (df.leftSB + offset) df.middle top sw [Just FLAT-CONNECTION] : list flat (0 + offset) (top - offset) curl (df.middle - CorrectionOMidX * sw) (top - offset) @@ -78,10 +70,7 @@ glyph-block Letter-Latin-C : begin match sb [Just SLAB-CLASSICAL] : SerifedArcEnd.RtlRhs (df.leftSB + offset) df.middle bot sw [fallback hook Hook] - [Just SLAB-INWARD] : list - arcvh - g4 (df.middle + CorrectionOMidX * sw) (bot + O + offset) - g4 (df.leftSB + offset) (bot + DToothlessRise) + [Just SLAB-INWARD] : InwardSlabArcEnd.RtlRhs (df.leftSB + offset) df.middle bot sw [Just FLAT-CONNECTION] : list arcvh flat (df.middle + CorrectionOMidX * sw) (bot + O + offset) diff --git a/packages/font-glyphs/src/letter/latin/lower-a.ptl b/packages/font-glyphs/src/letter/latin/lower-a.ptl index 8c9efa9a6..ec0d5ba90 100644 --- a/packages/font-glyphs/src/letter/latin/lower-a.ptl +++ b/packages/font-glyphs/src/letter/latin/lower-a.ptl @@ -13,7 +13,7 @@ glyph-block Letter-Latin-Lower-A : begin glyph-block-import Letter-Shared : CreateTurnedLetter glyph-block-import Letter-Shared-Shapes : SerifFrame OBarLeft OBarRight ArcStartSerif glyph-block-import Letter-Shared-Shapes : RightwardTailedBar InvRightwardTailedBar - glyph-block-import Letter-Shared-Shapes : DToothlessRise DMBlend RetroflexHook + glyph-block-import Letter-Shared-Shapes : DToothlessRise DMBlend RetroflexHook InwardSlabArcStart glyph-block-export DoubleStorey DoubleStoreyConfig define DoubleStorey : namespace @@ -33,9 +33,7 @@ glyph-block Letter-Latin-Lower-A : begin 1 : list g4 df.leftSB (XH - AHook) hookstart (XH - O) (sw -- stroke) - 2 : list - g4 df.leftSB (XH - DToothlessRise) - g4 (df.middle - CorrectionOMidX * stroke) (XH - O) + 2 : InwardSlabArcStart.LtrRhs df.leftSB df.middle XH stroke flat df.rightSB (XH - [ADoubleStoreySmoothB df]) [if isMask corner curl] df.rightSB y0 [heading Downward] if [not isMask] {} {[corner df.leftSB y0]} diff --git a/packages/font-glyphs/src/letter/latin/lower-m.ptl b/packages/font-glyphs/src/letter/latin/lower-m.ptl index cc0e0b0de..baea88d49 100644 --- a/packages/font-glyphs/src/letter/latin/lower-m.ptl +++ b/packages/font-glyphs/src/letter/latin/lower-m.ptl @@ -153,21 +153,36 @@ glyph-block Letter-Latin-Lower-M : begin define [EarlessCornerDoubleArchSmallMShape df top lbot mbot rbot _mid] : glyph-proc local mid : fallback _mid df.middle - include : dispiro - widths.rhs df.mvs - g4 df.leftSB (top - DToothlessRise) - g4.right.mid [mix df.leftSB (mid + [HSwToV : 0.5 * df.mvs]) 0.5] (top - O) [heading Rightward] - g4 (mid + [HSwToV : 0.5 * df.mvs]) (top - DToothlessRise) - include : dispiro - widths.rhs df.mvs - g4 (mid - [HSwToV : 0.5 * df.mvs]) (top - DToothlessRise) - g4.right.mid [mix df.rightSB (mid - [HSwToV : 0.5 * df.mvs]) 0.5] (top - O) [heading Rightward] - archv - flat df.rightSB (top - [SmallMSmooth df]) [heading Downward] - curl df.rightSB rbot [heading Downward] + + define [leftKnots sink offset] : begin + local xMidBarRightSide : mid + [HSwToV : 0.5 * df.mvs] + local xArchMid : [mix df.leftSB xMidBarRightSide 0.5] - CorrectionOMidX * df.mvs + return : sink + widths.rhs df.mvs + [if (sink == dispiro) g2 corner] (df.leftSB - offset) (top - DToothlessRise) + g2.right.mid (xArchMid - offset) (top - O) + archv + flat (xMidBarRightSide - offset) (top - [SmallMSmooth df]) [heading Downward] + [if (sink == dispiro) curl corner] (xMidBarRightSide - offset) mbot [heading Downward] + if (sink == spiro-outline) { [corner (df.leftSB - offset) 0 ] } { } + + define [rightKnots sink] : begin + local xMidBarLeftSide : mid - [HSwToV : 0.5 * df.mvs] + local xArchMid : [mix df.rightSB xMidBarLeftSide 0.5] - CorrectionOMidX * df.mvs + return : sink + widths.rhs df.mvs + g2 [mix xArchMid xMidBarLeftSide 2] (top - 2 * DToothlessRise) + g2 xMidBarLeftSide (top - DToothlessRise) + g2.right.mid xArchMid (top - O) + archv + flat df.rightSB (top - [SmallMSmooth df]) [heading Downward] + curl df.rightSB rbot [heading Downward] + + include : leftKnots dispiro 0 + include : difference [rightKnots dispiro] [leftKnots spiro-outline 0.1] include : tagged 'barL' : VBar.l df.leftSB lbot (top - DToothlessRise) df.mvs - include : tagged 'barM' : VBar.m mid mbot (top - DToothlessRise) df.mvs + # include : tagged 'barM' : VBar.m mid mbot (top - DToothlessRise) df.mvs define [EarlessRoundedDoubleArchSmallMShape df top lbot mbot rbot _mid] : glyph-proc local mid : fallback _mid df.middle @@ -198,7 +213,7 @@ glyph-block Letter-Latin-Lower-M : begin include : dispiro widths.rhs df.mvs g4 df.leftSB (top - DToothlessRise) - g4 (mid - CorrectionOMidS) (top - O) + g4 (mid - CorrectionOMidX * df.mvs) (top - O) archv flat df.rightSB [Math.max (top - [SmallMSmooth df]) (rbot + 0.1)] curl df.rightSB rbot [heading Downward] diff --git a/packages/font-glyphs/src/letter/latin/s.ptl b/packages/font-glyphs/src/letter/latin/s.ptl index bd7d1e25f..0be8d937a 100644 --- a/packages/font-glyphs/src/letter/latin/s.ptl +++ b/packages/font-glyphs/src/letter/latin/s.ptl @@ -13,6 +13,7 @@ glyph-block Letter-Latin-S : begin glyph-block-import Letter-Shared-Shapes : DToothlessRise FlatHookDepth glyph-block-import Letter-Shared-Shapes : ArcStartSerifWidth ArcStartSerifDepth glyph-block-import Letter-Shared-Shapes : SerifedArcStart SerifedArcEnd + glyph-block-import Letter-Shared-Shapes : InwardSlabArcStart InwardSlabArcEnd glyph-block-import Letter-Shared-Shapes : ArcStartSerif ArcEndSerif glyph-block-import Letter-Shared-Shapes : PalatalHook RetroflexHook CyrDescender CurlyTail @@ -48,10 +49,7 @@ glyph-block Letter-Latin-S : begin return : dispiro match st [Just SLAB-CLASSICAL] : SerifedArcStart.RtlLhs df.rightSB df.middle top stroke Hook - [Just SLAB-INWARD] : list - g4 df.rightSB (top - DToothlessRise) [widths.lhs stroke] - g4 (df.middle - CorrectionOMidX * stroke) (top - O) - archv + [Just SLAB-INWARD] : InwardSlabArcStart.RtlLhs df.rightSB df.middle top stroke Hook __ : list g4 df.rightSB (top - Hook) [widths.lhs stroke] hookstart (top - O) (sw -- stroke) (swItalicAdj -- Stroke) @@ -62,10 +60,7 @@ glyph-block Letter-Latin-S : begin match sb [Just SLAB-CLASSICAL] : SerifedArcEnd.RtlRhs df.leftSB df.middle bot stroke Hook - [Just SLAB-INWARD] : list - arcvh - g4 (df.middle + CorrectionOMidX * stroke) (bot + O) - g4 df.leftSB (bot + DToothlessRise) + [Just SLAB-INWARD] : InwardSlabArcEnd.RtlRhs df.leftSB df.middle bot stroke Hook __ : list hookend (bot + O) (sw -- stroke) (swItalicAdj -- Stroke) g4 (df.leftSB + SOBot) (bot + Hook) @@ -75,10 +70,7 @@ glyph-block Letter-Latin-S : begin return : dispiro match st [Just SLAB-CLASSICAL] : SerifedArcStart.LtrRhs df.leftSB df.middle CAP stroke Hook - [Just SLAB-INWARD] : list - g4 df.leftSB (CAP - DToothlessRise) [widths.rhs stroke] - g4 (df.middle - CorrectionOMidX * stroke) (CAP - O) - archv + [Just SLAB-INWARD] : InwardSlabArcStart.LtrRhs df.leftSB df.middle CAP stroke Hook __ : list g4 df.leftSB (CAP - Hook) [widths.rhs stroke] hookstart (CAP - O) (sw -- stroke) (swItalicAdj -- Stroke) @@ -87,10 +79,7 @@ glyph-block Letter-Latin-S : begin g4 (df.leftSB + SOBot) archDepth [widths.lhs stroke] match sb [Just SLAB-CLASSICAL] : SerifedArcEnd.LtrLhs df.rightSB df.middle 0 stroke Hook - [Just SLAB-INWARD] : list - arcvh - g4 (df.middle + CorrectionOMidX * stroke) O - g4 df.rightSB DToothlessRise + [Just SLAB-INWARD] : InwardSlabArcEnd.LtrLhs df.rightSB df.middle 0 stroke Hook __ : list hookend O (sw -- stroke) (swItalicAdj -- Stroke) g4 (df.rightSB + OX - SOBot) Hook @@ -102,10 +91,7 @@ glyph-block Letter-Latin-S : begin return : dispiro match st [Just SLAB-CLASSICAL] : SerifedArcStart.RtlLhs df.rightSB df.middle XH stroke SHook - [Just SLAB-INWARD] : list - g4 df.rightSB (XH - DToothlessRise) [widths.lhs stroke] - g4 (df.middle - CorrectionOMidX * stroke) (XH - O) - archv + [Just SLAB-INWARD] : InwardSlabArcStart.RtlLhs df.rightSB df.middle XH stroke SHook __ : list g4 (df.rightSB + OX) (XH - SHook) [widths.lhs stroke] hookstart (XH - O) (sw -- stroke) (swItalicAdj -- Stroke) @@ -119,10 +105,7 @@ glyph-block Letter-Latin-S : begin arcvh SCurlyTail df stroke [Just SLAB-CLASSICAL] : SerifedArcEnd.RtlRhs df.leftSB df.middle 0 stroke SHook - [Just SLAB-INWARD] : list - arcvh - g4 (df.middle + CorrectionOMidX * stroke) O - g4 df.leftSB DToothlessRise + [Just SLAB-INWARD] : InwardSlabArcEnd.RtlRhs df.leftSB df.middle 0 stroke SHook __ : list hookend O (sw -- stroke) (swItalicAdj -- Stroke) g4 (df.leftSB - OX + SOBot) SHook @@ -153,10 +136,7 @@ glyph-block Letter-Latin-S : begin return : dispiro match st [Just SLAB-CLASSICAL] : SerifedArcStart.RtlLhs df.rightSB df.middle top stroke Hook - [Just SLAB-INWARD] : list - g4 df.rightSB (top - DToothlessRise) [widths.lhs stroke] - g4 (df.middle - CorrectionOMidX * stroke) (top - O) - archv + [Just SLAB-INWARD] : InwardSlabArcStart.RtlLhs df.rightSB df.middle top stroke Hook __ : list g4 df.rightSB (top - Hook) [widths.lhs stroke] hookstart (top - O) (sw -- stroke) (swItalicAdj -- Stroke) @@ -172,10 +152,7 @@ glyph-block Letter-Latin-S : begin return : dispiro match st [Just SLAB-CLASSICAL] : SerifedArcStart.LtrRhs df.leftSB df.middle XH stroke SHook - [Just SLAB-INWARD] : list - g4 df.leftSB (XH - DToothlessRise) [widths.rhs stroke] - g4 (df.middle - CorrectionOMidX * stroke) (XH - O) - archv + [Just SLAB-INWARD] : InwardSlabArcStart.LtrRhs df.leftSB df.middle XH stroke SHook __ : list g4 (df.leftSB - OX) (XH - SHook) [widths.rhs stroke] hookstart (XH - O) (sw -- stroke) (swItalicAdj -- Stroke) @@ -184,10 +161,7 @@ glyph-block Letter-Latin-S : begin g4 (df.leftSB - OX + SOBot) (archDepth) [widths.lhs stroke] match sb [Just SLAB-CLASSICAL] : SerifedArcEnd.LtrLhs df.rightSB df.middle 0 stroke SHook - [Just SLAB-INWARD] : list - arcvh - g4 (df.middle + CorrectionOMidX * stroke) O - g4 df.rightSB DToothlessRise + [Just SLAB-INWARD] : InwardSlabArcEnd.LtrLhs df.rightSB df.middle 0 stroke SHook __ : list hookend O (sw -- stroke) (swItalicAdj -- Stroke) g4 (df.rightSB + OX - SOBot) SHook diff --git a/packages/font-glyphs/src/letter/shared.ptl b/packages/font-glyphs/src/letter/shared.ptl index 2dffaa442..c98ac464a 100644 --- a/packages/font-glyphs/src/letter/shared.ptl +++ b/packages/font-glyphs/src/letter/shared.ptl @@ -562,30 +562,30 @@ glyph-block Letter-Shared-Shapes : begin glyph-block-export InwardSlabArcStart define InwardSlabArcStart : namespace - export : define [RtlLhs sx cx cy sw hook] : begin + export : define [RtlLhs sx cx cy sw _hook] : begin return : list - g4 sx (cy - DToothlessRise) [widths.lhs sw] - g4 (cx - CorrectionOMidX * sw) (cy - O) + g2 sx (cy - DToothlessRise) [widths.lhs sw] + g2.left.mid (cx - CorrectionOMidX * sw) (cy - O) archv - export : define [LtrRhs sx cx cy sw hook] : begin + export : define [LtrRhs sx cx cy sw _hook] : begin return : list - g4 sx (cy - DToothlessRise) [widths.rhs sw] - g4 (cx - CorrectionOMidX * sw) (cy - O) + g2 sx (cy - DToothlessRise) [widths.rhs sw] + g2.right.mid (cx - CorrectionOMidX * sw) (cy - O) archv glyph-block-export InwardSlabArcEnd define InwardSlabArcEnd : namespace - export : define [RtlRhs sx cx cy sw hook] : begin + export : define [RtlRhs sx cx cy sw _hook] : begin return : list arcvh - g4 (cx + CorrectionOMidX * sw) (cy + O) - g4 sx (cy + DToothlessRise) [widths.rhs sw] - export : define [LtrLhs sx cx cy sw hook] : begin + g2.left.mid (cx + CorrectionOMidX * sw) (cy + O) + g2 sx (cy + DToothlessRise) [widths.rhs sw] + export : define [LtrLhs sx cx cy sw _hook] : begin return : list arcvh - g4 (cx + CorrectionOMidX * sw) (cy + O) - g4 sx (cy + DToothlessRise) [widths.lhs sw] + g2.right.mid (cx + CorrectionOMidX * sw) (cy + O) + g2 sx (cy + DToothlessRise) [widths.lhs sw] glyph-block-export ArcStartSerifWidth define [ArcStartSerifWidth stroke] : clamp (stroke * 0.875) stroke VJutStroke diff --git a/packages/font/src/cleanup/glyphs.mjs b/packages/font/src/cleanup/glyphs.mjs index 913513240..610129fed 100644 --- a/packages/font/src/cleanup/glyphs.mjs +++ b/packages/font/src/cleanup/glyphs.mjs @@ -38,6 +38,6 @@ function flattenSimpleGlyph(cache, skew, g) { g.includeContours(cs); } catch (e) { console.error("Detected broken geometry when processing", g._m_identifier); - throw e; + g.clearGeometry(); } } diff --git a/packages/geometry-cache/src/index.mjs b/packages/geometry-cache/src/index.mjs index 55cc59245..981054a40 100644 --- a/packages/geometry-cache/src/index.mjs +++ b/packages/geometry-cache/src/index.mjs @@ -1,10 +1,11 @@ import fs from "fs"; +import { setTimeout } from "node:timers/promises"; import zlib from "zlib"; import * as CurveUtil from "@iosevka/geometry/curve-util"; import { encode, decode } from "@msgpack/msgpack"; -const Edition = 40; +const Edition = 41; const MAX_AGE = 16; class GfEntry { constructor(age, value) { @@ -78,12 +79,22 @@ class Cache { export async function load(path, version, freshAgeKey) { let cache = new Cache(freshAgeKey); if (path && fs.existsSync(path)) { - try { - const buf = zlib.gunzipSync(await fs.promises.readFile(path)); - cache.loadRep(version, decode(buf)); - } catch (e) { - console.error("Error loading cache. Treat as empty."); - console.error(e); + let loadAttempt = 0; + while (loadAttempt < 3) { + try { + const buf = zlib.gunzipSync(await fs.promises.readFile(path)); + cache.loadRep(version, decode(buf)); + loadAttempt += 1; + break; + } catch (e) { + if (loadAttempt < 2) { + await setTimeout(500); + } else { + console.error("Error loading cache. Treat as empty."); + console.error(e); + } + loadAttempt += 1; + } } } return cache; diff --git a/packages/geometry/src/curve-util.mjs b/packages/geometry/src/curve-util.mjs index 8c5153352..41c8d3954 100644 --- a/packages/geometry/src/curve-util.mjs +++ b/packages/geometry/src/curve-util.mjs @@ -136,17 +136,28 @@ export class BezToContoursSink { this.lastContour = []; } moveTo(x, y) { + if (!isFinite(x) || !isFinite(y)) throw new Error("Invalid coordinates detected in moveTo"); this.endShape(); this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Corner, x, y)); } lineTo(x, y) { + if (!isFinite(x) || !isFinite(y)) throw new Error("Invalid coordinates detected in lineTo"); this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Corner, x, y)); } curveTo(xc, yc, x, y) { + if (!isFinite(xc) || !isFinite(yc) || !isFinite(x) || !isFinite(y)) + throw new Error("Invalid coordinates detected in curveTo"); this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Quadratic, xc, yc)); this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Corner, x, y)); } cubicTo(x1, y1, x2, y2, x, y) { + if (!isFinite(x1) || !isFinite(y1)) + throw new Error("Invalid coordinates detected in cubicTo"); + if (!isFinite(x2) || !isFinite(y2)) + throw new Error("Invalid coordinates detected in cubicTo"); + if (!isFinite(x) || !isFinite(y)) + throw new Error("Invalid coordinates detected in cubicTo"); + this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.CubicStart, x1, y1)); this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.CubicEnd, x2, y2)); this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Corner, x, y)); diff --git a/packages/geometry/src/spiro-to-outline.mjs b/packages/geometry/src/spiro-to-outline.mjs index 5e0016e76..ef24785ee 100644 --- a/packages/geometry/src/spiro-to-outline.mjs +++ b/packages/geometry/src/spiro-to-outline.mjs @@ -50,9 +50,11 @@ class SpiroSimplifier { flushArcs() { if (!this.m_ongoingArcs.length) return; if (this.m_ongoingArcs.length === 1) { - this.combinedArcs.push(this.m_ongoingArcs[0]); + const arc = this.m_ongoingArcs[0]; + if (arc.arcLength > 1e-6) this.combinedArcs.push(arc); } else { - this.combinedArcs.push(new SpiroSequenceArc(this.m_ongoingArcs)); + const combined = new SpiroSequenceArc(this.m_ongoingArcs); + if (combined.totalLength > 1e-6) this.combinedArcs.push(combined); } this.m_ongoingArcs = []; } @@ -60,6 +62,16 @@ class SpiroSimplifier { class SpiroSequenceArc { constructor(segments) { + // Filter out zero-length segments + let rear = 0; + for (let j = 0; j < segments.length; j++) { + if (segments[j].arcLength > 1e-6) { + segments[rear++] = segments[j]; + } + } + segments.length = rear; + + // Compute total length and stops let totalLength = 0; let stops = []; for (let j = 0; j < segments.length; j++) { @@ -69,6 +81,7 @@ class SpiroSequenceArc { for (let j = 0; j < segments.length; j++) { stops[j] = stops[j] / totalLength; } + this.totalLength = totalLength; this.m_segments = segments; this.m_stops = stops; } diff --git a/verdafile.mjs b/verdafile.mjs index 331f6e1fa..2e0cd603c 100644 --- a/verdafile.mjs +++ b/verdafile.mjs @@ -53,7 +53,7 @@ build.setJournal(`${BUILD}/.verda-build-journal`); build.setSelfTracking(); /////////////////////////////////////////////////////////// -////// Oracles ////// +////// Environment ////// /////////////////////////////////////////////////////////// const Version = computed(`env::version`, async target => { @@ -71,16 +71,40 @@ const CheckTtfAutoHintExists = oracle(`oracle:check-ttfautohint-exists`, async t }); const Dependencies = computed("env::dependencies", async target => { - const [pjf] = await target.need(sfu`package.json`); - const pj = JSON.parse(await FS.promises.readFile(pjf.full, "utf-8")); - let subGoals = []; - for (const pkgName in pj.dependencies) { - subGoals.push(InstalledVersion(pkgName, pj.dependencies[pkgName])); + const [packageJsons] = await target.need(AllPackageJsons); + const subGoals = []; + for (const pjf of packageJsons) { + subGoals.push(DependenciesFor(pjf)); } - const [actual] = await target.need(subGoals); - return actual; + return await target.need(subGoals); }); +const AllPackageJsons = computed("env::all-package-jsons", async target => { + const [ppj, tpj] = await target.need(PackagesPackagesJsons, ToolPackagesJsons); + return [`package.json`, ...ppj, ...tpj]; +}); +const PackagesPackagesJsons = computed("env::packages-packages-jsons", target => + FileList({ under: "packages", pattern: "*/package.json" })(target), +); +const ToolPackagesJsons = computed("env::tool-packages-jsons", target => + FileList({ under: "tools", pattern: "*/package.json" })(target), +); + +const DependenciesFor = computed.make( + pakcageJsonPath => `env::dependencies-for::${pakcageJsonPath}`, + async (target, pakcageJsonPath) => { + const [pjf] = await target.need(sfu(pakcageJsonPath)); + const pj = JSON.parse(await FS.promises.readFile(pjf.full, "utf-8")); + let subGoals = []; + for (const pkgName in pj.dependencies) { + if (/^@iosevka/.test(pkgName)) continue; + subGoals.push(InstalledVersion(pkgName, pj.dependencies[pkgName])); + } + const [actual] = await target.need(subGoals); + return actual; + }, +); + const InstalledVersion = computed.make( (pkg, required) => `env::installed-version::${pkg}::${required}`, async (target, pkg, required) => {