From 2c5136ee75bccb005ed885ca7e5f81dca231bbad Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Thu, 6 Nov 2025 21:54:10 +0100 Subject: [PATCH 01/12] Replace fontkit with fontkitten --- packages/unpack/package.json | 3 +- packages/unpack/src/index.ts | 40 +++++++++--------- pnpm-lock.yaml | 82 +++--------------------------------- 3 files changed, 28 insertions(+), 97 deletions(-) diff --git a/packages/unpack/package.json b/packages/unpack/package.json index 74f7dab..67cdcb0 100644 --- a/packages/unpack/package.json +++ b/packages/unpack/package.json @@ -46,10 +46,9 @@ "generate": "tsx scripts/generate-weightings" }, "dependencies": { - "fontkit": "^2.0.2" + "fontkitten": "^0.0.10" }, "devDependencies": { - "@types/fontkit": "^2.0.1", "@types/node": "^22.18.8", "fast-xml-parser": "^4.3.2", "sort-keys": "^5.0.0", diff --git a/packages/unpack/src/index.ts b/packages/unpack/src/index.ts index 43ac367..4b26c00 100644 --- a/packages/unpack/src/index.ts +++ b/packages/unpack/src/index.ts @@ -1,5 +1,9 @@ -import * as fontkit from 'fontkit'; -import type { Font as FontKitFont } from 'fontkit'; +import { + create, + type Font as FontKitFont, + type FontCollection, +} from 'fontkitten'; +import { readFile } from 'node:fs/promises'; import weightings from './weightings'; @@ -83,17 +87,14 @@ const unpackMetricsFromFont = (font: FontKitFont) => { export type Font = ReturnType; -const handleCollectionErrors = ({ - font, - postscriptName, - apiName, - apiParamName, -}: { - font: FontKitFont | null; - postscriptName?: string; - apiName: string; - apiParamName: string; -}) => { +function handleCollectionErrors( + font: FontKitFont | FontCollection | null, + { + postscriptName, + apiName, + apiParamName, + }: { postscriptName?: string; apiName: string; apiParamName: string }, +): asserts font is FontKitFont { if (postscriptName && font === null) { throw new Error( [ @@ -126,7 +127,7 @@ const handleCollectionErrors = ({ ].join('\n'), ); } -}; +} interface Options { postscriptName?: string; @@ -135,9 +136,9 @@ interface Options { export const fromFile = (path: string, options?: Options): Promise => { const { postscriptName } = options || {}; - return fontkit.open(path, postscriptName).then((font) => { - handleCollectionErrors({ - font, + return readFile(path).then((buffer) => { + const font = create(buffer, postscriptName); + handleCollectionErrors(font, { postscriptName, apiName: 'fromFile', apiParamName: 'path', @@ -155,10 +156,9 @@ const _fromBuffer = async ( ) => { const { postscriptName } = options || {}; - const fontkitFont = fontkit.create(buffer, postscriptName); + const fontkitFont = create(buffer, postscriptName); - handleCollectionErrors({ - font: fontkitFont, + handleCollectionErrors(fontkitFont, { postscriptName, apiName, apiParamName, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a7c090b..a4b2c87 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -111,13 +111,10 @@ importers: packages/unpack: dependencies: - fontkit: - specifier: ^2.0.2 - version: 2.0.2 + fontkitten: + specifier: ^0.0.10 + version: 0.0.10 devDependencies: - '@types/fontkit': - specifier: ^2.0.1 - version: 2.0.1 '@types/node': specifier: ^22.18.8 version: 22.18.8 @@ -2644,9 +2641,6 @@ packages: '@swc/counter@0.1.2': resolution: {integrity: sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==} - '@swc/helpers@0.4.12': - resolution: {integrity: sha512-R6RmwS9Dld5lNvwKlPn62+piU+WDG1sMfsnfJioXCciyko/gZ0DQ4Mqglhq1iGU1nQ/RcGkAwfMH+elMSkJH3Q==} - '@swc/types@0.1.5': resolution: {integrity: sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==} @@ -2685,9 +2679,6 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - '@types/fontkit@2.0.1': - resolution: {integrity: sha512-B5Jk560iAlWJ56yV1yBUH8Ek9LykCzb3N0FwJHtbH/Vmd/E1QN/Isen4SAtBb2UEWpZid4GjLm1Fih1xM0MbXA==} - '@types/glob@7.2.0': resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} @@ -3414,9 +3405,6 @@ packages: brorand@1.1.0: resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} - brotli@1.3.3: - resolution: {integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==} - browser-assert@1.2.1: resolution: {integrity: sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==} @@ -3697,10 +3685,6 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} - clone@2.1.2: - resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} - engines: {node: '>=0.8'} - co@4.6.0: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -4158,9 +4142,6 @@ packages: resolution: {integrity: sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==} hasBin: true - dfa@1.2.0: - resolution: {integrity: sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==} - diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -4720,8 +4701,9 @@ packages: resolution: {integrity: sha512-a8Ge6cdKh9za/GZR/qtigTAk7SrGore56EFcoMshClsh7FLk1zwszc/ltuMfKhx56qeuyL/jWQ4J4axou0iJ9w==} engines: {node: '>=10'} - fontkit@2.0.2: - resolution: {integrity: sha512-jc4k5Yr8iov8QfS6u8w2CnHWVmbOGtdBtOXMze5Y+QD966Rx6PEVWXSEGwXlsDlKtu1G12cJjcsybnqhSk/+LA==} + fontkitten@0.0.10: + resolution: {integrity: sha512-vRGMicvPSalc2KcNnxXm58jyp3AQNpMaW77GAW34JKm9WQ5Tixb15CvlOcorKMzvWMGYzwvoadgdqdzqepEKZA==} + engines: {node: '>=20'} for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -6643,9 +6625,6 @@ packages: resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} engines: {node: '>=14.16'} - pako@0.2.9: - resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} - pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} @@ -7416,9 +7395,6 @@ packages: resolution: {integrity: sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==} engines: {node: '>=4'} - restructure@3.0.0: - resolution: {integrity: sha512-Xj8/MEIhhfj9X2rmD9iJ4Gga9EFqVlpMj3vfLnV2r/Mh5jRMryNV+6lWh9GdJtDBcBSPIqzRdfBQ3wDtNFv/uw==} - ret@0.1.15: resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} engines: {node: '>=0.12'} @@ -8233,16 +8209,10 @@ packages: resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} engines: {node: '>=4'} - unicode-properties@1.4.1: - resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==} - unicode-property-aliases-ecmascript@2.1.0: resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} - unicode-trie@2.0.0: - resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==} - unified@9.2.0: resolution: {integrity: sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==} @@ -12685,10 +12655,6 @@ snapshots: '@swc/counter@0.1.2': {} - '@swc/helpers@0.4.12': - dependencies: - tslib: 2.6.2 - '@swc/types@0.1.5': {} '@szmarczak/http-timer@1.1.2': @@ -12738,10 +12704,6 @@ snapshots: '@types/estree@1.0.5': {} - '@types/fontkit@2.0.1': - dependencies: - '@types/node': 22.18.8 - '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 @@ -13715,10 +13677,6 @@ snapshots: brorand@1.1.0: {} - brotli@1.3.3: - dependencies: - base64-js: 1.5.1 - browser-assert@1.2.1: {} browser-resolve@2.0.0: @@ -14088,8 +14046,6 @@ snapshots: clone@1.0.4: {} - clone@2.1.2: {} - co@4.6.0: {} collapse-white-space@1.0.6: {} @@ -14572,8 +14528,6 @@ snapshots: transitivePeerDependencies: - supports-color - dfa@1.2.0: {} - diff-sequences@29.6.3: {} diffie-hellman@5.0.3: @@ -15226,17 +15180,9 @@ snapshots: dependencies: tslib: 2.6.2 - fontkit@2.0.2: + fontkitten@0.0.10: dependencies: - '@swc/helpers': 0.4.12 - brotli: 1.3.3 - clone: 2.1.2 - dfa: 1.2.0 - fast-deep-equal: 3.1.3 - restructure: 3.0.0 tiny-inflate: 1.0.3 - unicode-properties: 1.4.1 - unicode-trie: 2.0.0 for-each@0.3.3: dependencies: @@ -17518,8 +17464,6 @@ snapshots: registry-url: 6.0.1 semver: 7.7.2 - pako@0.2.9: {} - pako@1.0.11: {} parallel-transform@1.2.0: @@ -18385,8 +18329,6 @@ snapshots: onetime: 2.0.1 signal-exit: 3.0.7 - restructure@3.0.0: {} - ret@0.1.15: {} reusify@1.0.4: {} @@ -19322,18 +19264,8 @@ snapshots: unicode-match-property-value-ecmascript@2.1.0: {} - unicode-properties@1.4.1: - dependencies: - base64-js: 1.5.1 - unicode-trie: 2.0.0 - unicode-property-aliases-ecmascript@2.1.0: {} - unicode-trie@2.0.0: - dependencies: - pako: 0.2.9 - tiny-inflate: 1.0.3 - unified@9.2.0: dependencies: '@types/unist': 2.0.6 From 2848ae8dd68c2d11a5f3ae0b9a5e694e0f11eb4b Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Thu, 6 Nov 2025 21:55:44 +0100 Subject: [PATCH 02/12] Fix tests --- babel.config.js | 5 ++++- jest.config.js | 1 + package.json | 2 +- packages/unpack/src/__tests__/index.test.ts | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/babel.config.js b/babel.config.js index 859ee2e..78fa68a 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,6 +1,9 @@ module.exports = { presets: [ '@babel/preset-typescript', - ['@babel/preset-env', { bugfixes: true, targets: { node: 'current' } }], + [ + '@babel/preset-env', + { bugfixes: true, targets: { node: 'current' }, modules: false }, + ], ], }; diff --git a/jest.config.js b/jest.config.js index 7951063..f0bd03e 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,3 +1,4 @@ module.exports = { testPathIgnorePatterns: ['node_modules', '/site/.cache'], + extensionsToTreatAsEsm: ['.ts'], }; diff --git a/package.json b/package.json index 3971c78..3bc3a87 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "%packages": "pnpm --filter='@capsizecss/*' --aggregate-output", "%site": "pnpm --filter=./site", "start": "pnpm site:start", - "test": "jest", + "test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" npx jest", "format": "prettier --write .", "lint": "manypkg check && prettier --check . && tsc", "dev": "pnpm unpack:generate && pnpm %packages dev && pnpm metrics:generate", diff --git a/packages/unpack/src/__tests__/index.test.ts b/packages/unpack/src/__tests__/index.test.ts index 8605cc7..10aed62 100644 --- a/packages/unpack/src/__tests__/index.test.ts +++ b/packages/unpack/src/__tests__/index.test.ts @@ -2,6 +2,8 @@ import { readFile } from 'node:fs/promises'; import { fromUrl, fromBlob, fromBuffer } from '../index'; import { join } from 'node:path'; +const __dirname = join(new URL(import.meta.url).pathname, '..'); + const expectedMetrics = { ascent: 1069, capHeight: 714, From 5c9682f5d02da6a11b02fbe9f5479775279d874c Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Thu, 6 Nov 2025 22:02:43 +0100 Subject: [PATCH 03/12] Re-use _fromBuffer in fromFile implementation --- packages/unpack/src/index.ts | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/packages/unpack/src/index.ts b/packages/unpack/src/index.ts index 4b26c00..8995ff2 100644 --- a/packages/unpack/src/index.ts +++ b/packages/unpack/src/index.ts @@ -133,19 +133,12 @@ interface Options { postscriptName?: string; } -export const fromFile = (path: string, options?: Options): Promise => { - const { postscriptName } = options || {}; - - return readFile(path).then((buffer) => { - const font = create(buffer, postscriptName); - handleCollectionErrors(font, { - postscriptName, - apiName: 'fromFile', - apiParamName: 'path', - }); - - return unpackMetricsFromFont(font); - }); +export const fromFile = async ( + path: string, + options?: Options, +): Promise => { + const buffer = await readFile(path); + return _fromBuffer(buffer, 'fromFile', 'path', options); }; const _fromBuffer = async ( From edf0f601344eff456a518ea0e21e2862f5e75719 Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Wed, 12 Nov 2025 00:52:24 +0100 Subject: [PATCH 04/12] Migrate `unpack` package to be ESM-only --- packages/unpack/package.json | 15 ++++++--------- packages/unpack/scripts/generate-weightings.ts | 7 +++++-- packages/unpack/tsdown.config.ts | 5 ++++- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/unpack/package.json b/packages/unpack/package.json index ee1210d..3e765c7 100644 --- a/packages/unpack/package.json +++ b/packages/unpack/package.json @@ -23,17 +23,16 @@ "name": "Michael Taranto", "homepage": "https://github.com/michaeltaranto" }, + "type": "module", "exports": { ".": { "@capsizecss/src": "./src/index.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.cjs" + "default": "./dist/index.mjs" }, "./package.json": "./package.json" }, - "main": "./dist/index.cjs", "module": "./dist/index.mjs", - "types": "./dist/index.d.cts", + "types": "./dist/index.d.mts", "files": [ "dist" ], @@ -56,11 +55,9 @@ }, "publishConfig": { "exports": { - ".": { - "import": "./dist/index.mjs", - "require": "./dist/index.cjs" - }, + ".": "./dist/index.mjs", "./package.json": "./package.json" } - } + }, + "main": "./dist/index.mjs" } diff --git a/packages/unpack/scripts/generate-weightings.ts b/packages/unpack/scripts/generate-weightings.ts index 00721eb..a03b683 100644 --- a/packages/unpack/scripts/generate-weightings.ts +++ b/packages/unpack/scripts/generate-weightings.ts @@ -1,8 +1,11 @@ -import fs from 'fs/promises'; -import path from 'path'; +import fs from 'node:fs/promises'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; import { XMLParser } from 'fast-xml-parser'; import sortKeys from 'sort-keys'; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + type WikiNewsFeed = { feed: { doc: { diff --git a/packages/unpack/tsdown.config.ts b/packages/unpack/tsdown.config.ts index d519593..fabd058 100644 --- a/packages/unpack/tsdown.config.ts +++ b/packages/unpack/tsdown.config.ts @@ -1,4 +1,7 @@ import { defineConfig } from 'tsdown'; import { baseConfig } from '../../tsdown.base.config'; -export default defineConfig(baseConfig); +export default defineConfig({ + ...baseConfig, + format: ['esm'], +}); From aff6773693d80fd8fe0e3276eab4bfec75805a1f Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Wed, 12 Nov 2025 22:11:27 +0100 Subject: [PATCH 05/12] Update `fontkitten` to 0.0.11 --- packages/unpack/package.json | 2 +- pnpm-lock.yaml | 36 ++++++++++++++---------------------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/packages/unpack/package.json b/packages/unpack/package.json index 3e765c7..9843163 100644 --- a/packages/unpack/package.json +++ b/packages/unpack/package.json @@ -41,7 +41,7 @@ "generate": "tsx scripts/generate-weightings" }, "dependencies": { - "fontkitten": "^0.0.10" + "fontkitten": "^0.0.11" }, "devDependencies": { "@types/node": "^22.18.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 65a169a..573355e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -112,8 +112,8 @@ importers: packages/unpack: dependencies: fontkitten: - specifier: ^0.0.10 - version: 0.0.10 + specifier: ^0.0.11 + version: 0.0.11 devDependencies: '@types/node': specifier: ^22.18.8 @@ -314,9 +314,6 @@ packages: engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - peerDependenciesMeta: - '@babel/core': - optional: true '@babel/helper-define-polyfill-provider@0.1.5': resolution: {integrity: sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==} @@ -378,9 +375,6 @@ packages: engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - peerDependenciesMeta: - '@babel/core': - optional: true '@babel/helper-replace-supers@7.22.20': resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==} @@ -4769,8 +4763,8 @@ packages: resolution: {integrity: sha512-a8Ge6cdKh9za/GZR/qtigTAk7SrGore56EFcoMshClsh7FLk1zwszc/ltuMfKhx56qeuyL/jWQ4J4axou0iJ9w==} engines: {node: '>=10'} - fontkitten@0.0.10: - resolution: {integrity: sha512-vRGMicvPSalc2KcNnxXm58jyp3AQNpMaW77GAW34JKm9WQ5Tixb15CvlOcorKMzvWMGYzwvoadgdqdzqepEKZA==} + fontkitten@0.0.11: + resolution: {integrity: sha512-XMiPMBvZrT5tdzNAH/PiSEVTYU+X98rUkaJguPLMPDBCjdvjYUL47/fd78W9bNYyJmw1a2n9iQTRIPGGrh1+Bg==} engines: {node: '>=20'} for-each@0.3.3: @@ -8734,7 +8728,7 @@ snapshots: '@babel/code-frame@7.27.1': dependencies: - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 @@ -8835,11 +8829,10 @@ snapshots: '@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.23.9)': dependencies: + '@babel/core': 7.23.9 '@babel/helper-annotate-as-pure': 7.22.5 regexpu-core: 5.3.2 semver: 6.3.1 - optionalDependencies: - '@babel/core': 7.23.9 '@babel/helper-define-polyfill-provider@0.1.5(@babel/core@7.23.9)': dependencies: @@ -8890,7 +8883,7 @@ snapshots: '@babel/helper-module-imports@7.27.1': dependencies: '@babel/traverse': 7.28.4 - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color @@ -8922,11 +8915,10 @@ snapshots: '@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.23.9)': dependencies: + '@babel/core': 7.23.9 '@babel/helper-annotate-as-pure': 7.22.5 '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-wrap-function': 7.22.20 - optionalDependencies: - '@babel/core': 7.23.9 '@babel/helper-replace-supers@7.22.20(@babel/core@7.23.9)': dependencies: @@ -9689,8 +9681,8 @@ snapshots: '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.4 - '@babel/types': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 '@babel/traverse@7.23.9': dependencies: @@ -9710,11 +9702,11 @@ snapshots: '@babel/traverse@7.28.4': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.3 + '@babel/generator': 7.28.5 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.4 + '@babel/parser': 7.28.5 '@babel/template': 7.27.2 - '@babel/types': 7.28.4 + '@babel/types': 7.28.5 debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -15082,7 +15074,7 @@ snapshots: dependencies: tslib: 2.6.2 - fontkitten@0.0.10: + fontkitten@0.0.11: dependencies: tiny-inflate: 1.0.3 From b98113df3612d94d65bf9aba66b9492d90305187 Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Sat, 15 Nov 2025 12:21:58 +0100 Subject: [PATCH 06/12] Update `fontkitten` to 0.0.13 --- packages/unpack/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/unpack/package.json b/packages/unpack/package.json index 9843163..797ca0b 100644 --- a/packages/unpack/package.json +++ b/packages/unpack/package.json @@ -41,7 +41,7 @@ "generate": "tsx scripts/generate-weightings" }, "dependencies": { - "fontkitten": "^0.0.11" + "fontkitten": "^0.0.13" }, "devDependencies": { "@types/node": "^22.18.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 573355e..593185c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -112,8 +112,8 @@ importers: packages/unpack: dependencies: fontkitten: - specifier: ^0.0.11 - version: 0.0.11 + specifier: ^0.0.13 + version: 0.0.13 devDependencies: '@types/node': specifier: ^22.18.8 @@ -4763,8 +4763,8 @@ packages: resolution: {integrity: sha512-a8Ge6cdKh9za/GZR/qtigTAk7SrGore56EFcoMshClsh7FLk1zwszc/ltuMfKhx56qeuyL/jWQ4J4axou0iJ9w==} engines: {node: '>=10'} - fontkitten@0.0.11: - resolution: {integrity: sha512-XMiPMBvZrT5tdzNAH/PiSEVTYU+X98rUkaJguPLMPDBCjdvjYUL47/fd78W9bNYyJmw1a2n9iQTRIPGGrh1+Bg==} + fontkitten@0.0.13: + resolution: {integrity: sha512-0D6dLEYGTHZT+9CSqnyk0AcbDWH9cs9an9CaUETw647Nl/KlaLNpL1DwVQefmo1B7dzqCignAnp+DHJDl7Lhaw==} engines: {node: '>=20'} for-each@0.3.3: @@ -15074,7 +15074,7 @@ snapshots: dependencies: tslib: 2.6.2 - fontkitten@0.0.11: + fontkitten@0.0.13: dependencies: tiny-inflate: 1.0.3 From bd593a67ef17213cdca7214e5a707996d6e12d86 Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Mon, 17 Nov 2025 16:57:43 +0100 Subject: [PATCH 07/12] Update \`fontkitten\` to 0.0.15 --- packages/unpack/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/unpack/package.json b/packages/unpack/package.json index 797ca0b..a67b723 100644 --- a/packages/unpack/package.json +++ b/packages/unpack/package.json @@ -41,7 +41,7 @@ "generate": "tsx scripts/generate-weightings" }, "dependencies": { - "fontkitten": "^0.0.13" + "fontkitten": "^0.0.15" }, "devDependencies": { "@types/node": "^22.18.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 593185c..1a9d4fc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -112,8 +112,8 @@ importers: packages/unpack: dependencies: fontkitten: - specifier: ^0.0.13 - version: 0.0.13 + specifier: ^0.0.15 + version: 0.0.15 devDependencies: '@types/node': specifier: ^22.18.8 @@ -4763,8 +4763,8 @@ packages: resolution: {integrity: sha512-a8Ge6cdKh9za/GZR/qtigTAk7SrGore56EFcoMshClsh7FLk1zwszc/ltuMfKhx56qeuyL/jWQ4J4axou0iJ9w==} engines: {node: '>=10'} - fontkitten@0.0.13: - resolution: {integrity: sha512-0D6dLEYGTHZT+9CSqnyk0AcbDWH9cs9an9CaUETw647Nl/KlaLNpL1DwVQefmo1B7dzqCignAnp+DHJDl7Lhaw==} + fontkitten@0.0.15: + resolution: {integrity: sha512-lSE5vr++X84COLimYeb78d9TN/MLfnSjm0OXi5d5FDx2uouWqbCexquXaWASnqHZqnFm8eCo1dz0DAd3J6YEOA==} engines: {node: '>=20'} for-each@0.3.3: @@ -15074,7 +15074,7 @@ snapshots: dependencies: tslib: 2.6.2 - fontkitten@0.0.13: + fontkitten@0.0.15: dependencies: tiny-inflate: 1.0.3 From f344887fe2cb695502d7ffde16fcb4e0ad48a607 Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Mon, 17 Nov 2025 17:02:02 +0100 Subject: [PATCH 08/12] Use simpler \`isCollection\` API --- packages/unpack/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/unpack/src/index.ts b/packages/unpack/src/index.ts index 8995ff2..7e2c6ae 100644 --- a/packages/unpack/src/index.ts +++ b/packages/unpack/src/index.ts @@ -109,7 +109,7 @@ function handleCollectionErrors( ); } - if (font !== null && 'fonts' in font && Array.isArray(font.fonts)) { + if (font !== null && font.isCollection) { const availableNames = font.fonts.map((f) => f.postscriptName); throw new Error( [ From 238030197d544c9684ee9e7447b9a22d0c066528 Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Tue, 18 Nov 2025 14:01:24 +0100 Subject: [PATCH 09/12] Update to fontkitten v1 --- packages/unpack/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/unpack/package.json b/packages/unpack/package.json index 797fc86..9bb79e3 100644 --- a/packages/unpack/package.json +++ b/packages/unpack/package.json @@ -41,7 +41,7 @@ "generate": "tsx scripts/generate-weightings" }, "dependencies": { - "fontkitten": "^0.0.15" + "fontkitten": "^1.0.0" }, "devDependencies": { "@types/node": "^22.18.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0b95198..f1a37d0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -103,8 +103,8 @@ importers: packages/unpack: dependencies: fontkitten: - specifier: ^0.0.15 - version: 0.0.15 + specifier: ^1.0.0 + version: 1.0.0 devDependencies: '@types/node': specifier: ^22.18.8 @@ -3095,8 +3095,8 @@ packages: resolution: {integrity: sha512-a8Ge6cdKh9za/GZR/qtigTAk7SrGore56EFcoMshClsh7FLk1zwszc/ltuMfKhx56qeuyL/jWQ4J4axou0iJ9w==} engines: {node: '>=10'} - fontkitten@0.0.15: - resolution: {integrity: sha512-lSE5vr++X84COLimYeb78d9TN/MLfnSjm0OXi5d5FDx2uouWqbCexquXaWASnqHZqnFm8eCo1dz0DAd3J6YEOA==} + fontkitten@1.0.0: + resolution: {integrity: sha512-b0RdzQeztiiUFWEDzq6Ka26qkNVNLCehoRtifOIGNbQ4CfxyYRh73fyWaQX/JshPVcueITOEeoSWPy5XQv8FUg==} engines: {node: '>=20'} for-each@0.3.3: @@ -8341,7 +8341,7 @@ snapshots: dependencies: tslib: 2.8.1 - fontkitten@0.0.15: + fontkitten@1.0.0: dependencies: tiny-inflate: 1.0.3 From c3eac55a386c536d317a3823b4a4e3e6b8ffe92b Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Tue, 18 Nov 2025 14:05:52 +0100 Subject: [PATCH 10/12] Revert change no longer needed after switch to Vitest --- packages/unpack/src/__tests__/index.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/unpack/src/__tests__/index.test.ts b/packages/unpack/src/__tests__/index.test.ts index 9a4a5a6..39f4b7b 100644 --- a/packages/unpack/src/__tests__/index.test.ts +++ b/packages/unpack/src/__tests__/index.test.ts @@ -3,8 +3,6 @@ import { readFile } from 'node:fs/promises'; import { fromUrl, fromBlob, fromBuffer } from '../index'; import { join } from 'node:path'; -const __dirname = join(new URL(import.meta.url).pathname, '..'); - const expectedMetrics = { ascent: 1069, capHeight: 714, From 5517d90f3b4f6fb193f090b15717bbad6f7f4e66 Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Sun, 30 Nov 2025 12:41:09 +0100 Subject: [PATCH 11/12] Add changesets --- .changeset/perfect-islands-type.md | 5 +++++ .changeset/silver-buttons-bake.md | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 .changeset/perfect-islands-type.md create mode 100644 .changeset/silver-buttons-bake.md diff --git a/.changeset/perfect-islands-type.md b/.changeset/perfect-islands-type.md new file mode 100644 index 0000000..10030a2 --- /dev/null +++ b/.changeset/perfect-islands-type.md @@ -0,0 +1,5 @@ +--- +"@capsizecss/unpack": patch +--- + +Reduces `@capsizecss/unpack` install size by using a lighter weight package for extracting font file metrics diff --git a/.changeset/silver-buttons-bake.md b/.changeset/silver-buttons-bake.md new file mode 100644 index 0000000..35bbdd5 --- /dev/null +++ b/.changeset/silver-buttons-bake.md @@ -0,0 +1,15 @@ +--- +"@capsizecss/unpack": major +--- + +This package is now ESM-only. + +In most projects you can continue to use the package as before. CommonJS (CJS) projects using Node.js <20, should update to use a dynamic import: + +```js +// For CJS projects before Node 20 +const { fromBuffer } = await import('@capsizecss/unpack'); + +// For all other projects +import { fromBuffer } from '@capsizecss/unpack'; +``` From b72d8d4d0371c9d36e160a060ffa876a9290e23a Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Sun, 30 Nov 2025 12:46:04 +0100 Subject: [PATCH 12/12] Tweak README mentions of Fontkit --- README.md | 2 +- packages/unpack/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fe40c3d..0ec71ad 100644 --- a/README.md +++ b/README.md @@ -401,7 +401,7 @@ See the [package](packages/unpack/README.md) for documentation. ## Thanks - [Vincent De Oliveira](https://twitter.com/iamvdo) for writing [Deep dive CSS: font metrics, line-height and vertical-align](https://iamvdo.me/en/blog/css-font-metrics-line-height-and-vertical-align), which provided the research needed to build all this. -- [Devon Govett](https://github.com/devongovett) for creating [Fontkit](https://github.com/foliojs/fontkit), which does all the heavy lifting of extracting the font metrics under the covers. +- [Devon Govett](https://github.com/devongovett) for creating [Fontkit](https://github.com/foliojs/fontkit). A [fork of Fontkit](https://github.com/delucis/fontkitten) does all the heavy lifting of extracting the font metrics under the covers. - [SEEK](https://www.seek.com.au) for giving us the space to do interesting work. ## License diff --git a/packages/unpack/README.md b/packages/unpack/README.md index 178f007..3a92c6b 100644 --- a/packages/unpack/README.md +++ b/packages/unpack/README.md @@ -100,7 +100,7 @@ The font metrics object returned contains the following properties: ## Thanks -- [Devon Govett](https://github.com/devongovett) for creating [Fontkit](https://github.com/foliojs/fontkit), which does all the heavy lifting of extracting the font metrics under the covers. +- [Devon Govett](https://github.com/devongovett) for creating [Fontkit](https://github.com/foliojs/fontkit). A [fork of Fontkit](https://github.com/delucis/fontkitten) does all the heavy lifting of extracting the font metrics under the covers. - [SEEK](https://www.seek.com.au) for giving us the space to do interesting work. ## License