From 3a632b710fa18119ad779437e842786746109e72 Mon Sep 17 00:00:00 2001 From: Jacob Bandes-Storch Date: Thu, 19 Dec 2024 14:33:10 -0800 Subject: [PATCH 1/9] Dispatch error events rather than throwing --- .github/dependabot.yml | 12 +++++++++--- src/FontManager.ts | 23 ++++++++++++++++++----- src/LabelPool.ts | 11 ++++++++++- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c2bee98..9926862 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,10 +3,16 @@ version: 2 updates: - - package-ecosystem: "npm" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: weekly + interval: monthly + labels: [] # disable default labels + + - package-ecosystem: npm + directory: / + schedule: + interval: monthly labels: [] # disable default labels # Define groups of dependencies to be updated together diff --git a/src/FontManager.ts b/src/FontManager.ts index 4055c9f..a6c5515 100644 --- a/src/FontManager.ts +++ b/src/FontManager.ts @@ -41,11 +41,16 @@ export type FontManagerOptions = { fontSize?: number; }; +type EventMap = { + atlasChange: object; + error: { error: Error }; +}; + /** * Manages the creation of a Signed Distance Field (SDF) font atlas, and performs text layout to * generate attributes for rendering text using the atlas. */ -export class FontManager extends EventDispatcher<{ atlasChange: object }> { +export class FontManager extends EventDispatcher { private alphabet = ""; atlasData: AtlasData = { data: new Uint8ClampedArray(), @@ -99,9 +104,13 @@ export class FontManager extends EventDispatcher<{ atlasChange: object }> { let maxAscent = 0; for (const char of this.alphabet) { if (charInfo[char] != undefined) { - throw new Error( - `Duplicate character in alphabet: ${char} (${char.codePointAt(0) ?? "undefined"})`, - ); + this.dispatchEvent({ + type: "error", + error: new Error( + `Duplicate character in alphabet: ${char} (${char.codePointAt(0) ?? "undefined"})`, + ), + }); + continue; } const sdf = tinysdf.draw(char); if (x + sdf.width >= atlasWidth) { @@ -110,7 +119,11 @@ export class FontManager extends EventDispatcher<{ atlasChange: object }> { rowHeight = 0; } if (y + sdf.height >= atlasHeight) { - throw new Error(`Unable to fit all ${this.alphabet.length} characters in font atlas`); + this.dispatchEvent({ + type: "error", + error: new Error(`Unable to fit all ${this.alphabet.length} characters in font atlas`), + }); + continue; } rowHeight = Math.max(rowHeight, sdf.height); lineHeight = Math.max(lineHeight, rowHeight); diff --git a/src/LabelPool.ts b/src/LabelPool.ts index ac76546..ae04ed8 100644 --- a/src/LabelPool.ts +++ b/src/LabelPool.ts @@ -362,7 +362,13 @@ export class Label extends THREE.Object3D { } } -export class LabelPool extends EventDispatcher<{ scaleFactorChange: object; atlasChange: object }> { +type EventMap = { + scaleFactorChange: object; + atlasChange: object; + error: { error: Error }; +}; + +export class LabelPool extends EventDispatcher { atlasTexture: THREE.DataTexture; private availableLabels: Label[] = []; @@ -407,6 +413,9 @@ export class LabelPool extends EventDispatcher<{ scaleFactorChange: object; atla THREE.LinearFilter, ); + this.fontManager.addEventListener("error", (event) => { + this.dispatchEvent(event); + }); this.fontManager.addEventListener("atlasChange", () => { this._updateAtlasTexture(); }); From 3b342f734b14a0a2d37460ef2108379a871c0fa1 Mon Sep 17 00:00:00 2001 From: Jacob Bandes-Storch Date: Thu, 19 Dec 2024 14:35:07 -0800 Subject: [PATCH 2/9] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 37b4137..28af706 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@foxglove/three-text", - "version": "0.3.1", + "version": "0.4.0", "description": "Render text in 3D using Signed Distance Fields", "license": "MIT", "repository": { From 201f30fec79257ca0082f4c56ba8138d44498ab9 Mon Sep 17 00:00:00 2001 From: Jacob Bandes-Storch Date: Thu, 19 Dec 2024 14:55:46 -0800 Subject: [PATCH 3/9] error for maximum number of characters --- src/FontManager.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/FontManager.ts b/src/FontManager.ts index a6c5515..25a6f77 100644 --- a/src/FontManager.ts +++ b/src/FontManager.ts @@ -46,6 +46,8 @@ type EventMap = { error: { error: Error }; }; +const MAX_CHARS = 1024; + /** * Manages the creation of a Signed Distance Field (SDF) font atlas, and performs text layout to * generate attributes for rendering text using the atlas. @@ -80,6 +82,15 @@ export class FontManager extends EventDispatcher { needsUpdate = true; } } + if (this.alphabet.length > MAX_CHARS) { + this.dispatchEvent({ + type: "error", + error: new Error( + `Exceeded maximum unique characters: ${this.alphabet.length} > ${MAX_CHARS}`, + ), + }); + return; + } if (!needsUpdate) { return; From f28dee5494623ebfb49d90a4895b8b16f3d183d8 Mon Sep 17 00:00:00 2001 From: Jacob Bandes-Storch Date: Thu, 19 Dec 2024 15:02:10 -0800 Subject: [PATCH 4/9] bump to 2048 --- src/FontManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FontManager.ts b/src/FontManager.ts index 25a6f77..bbde8c2 100644 --- a/src/FontManager.ts +++ b/src/FontManager.ts @@ -46,7 +46,7 @@ type EventMap = { error: { error: Error }; }; -const MAX_CHARS = 1024; +const MAX_CHARS = 2048; /** * Manages the creation of a Signed Distance Field (SDF) font atlas, and performs text layout to From 08f2e3f7c4dd4648b4bfa53225b85ae16863fa07 Mon Sep 17 00:00:00 2001 From: Jacob Bandes-Storch Date: Thu, 19 Dec 2024 15:09:08 -0800 Subject: [PATCH 5/9] bail if alphabet is already longer than max --- src/FontManager.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/FontManager.ts b/src/FontManager.ts index bbde8c2..ed6d3d8 100644 --- a/src/FontManager.ts +++ b/src/FontManager.ts @@ -75,6 +75,10 @@ export class FontManager extends EventDispatcher { } update(newChars: string): void { + if (this.alphabet.length > MAX_CHARS) { + // we would have already reported an error; just bail this time + return; + } let needsUpdate = false; for (const char of newChars) { if (!this.alphabet.includes(char)) { From 6ca874c92bcb96be25b8b2b71c1b6daf54fde2d7 Mon Sep 17 00:00:00 2001 From: Jacob Bandes-Storch Date: Thu, 19 Dec 2024 15:11:32 -0800 Subject: [PATCH 6/9] maybe do report errors again --- src/FontManager.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/FontManager.ts b/src/FontManager.ts index ed6d3d8..50b9d0a 100644 --- a/src/FontManager.ts +++ b/src/FontManager.ts @@ -76,7 +76,12 @@ export class FontManager extends EventDispatcher { update(newChars: string): void { if (this.alphabet.length > MAX_CHARS) { - // we would have already reported an error; just bail this time + this.dispatchEvent({ + type: "error", + error: new Error( + `Exceeded maximum unique characters: ${this.alphabet.length} > ${MAX_CHARS}`, + ), + }); return; } let needsUpdate = false; From 8730521b3bcad5dee087ed6dad5169d26681d791 Mon Sep 17 00:00:00 2001 From: Jacob Bandes-Storch Date: Fri, 10 Jan 2025 16:33:07 -0800 Subject: [PATCH 7/9] feedback and unit tests --- .vscode/settings.json | 3 +- jest.config.js | 8 +- package.json | 6 +- src/FontManager.test.ts | 18 ++ src/FontManager.ts | 20 -- yarn.lock | 463 ++++++++++++++++++++++++++++++++++++++-- 6 files changed, 472 insertions(+), 46 deletions(-) create mode 100644 src/FontManager.test.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 43ed898..fad3f1b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,5 +13,6 @@ "files.trimFinalNewlines": true, "files.trimTrailingWhitespace": true, "prettier.prettierPath": "./node_modules/prettier", - "typescript.tsdk": "node_modules/typescript/lib" + "typescript.tsdk": "node_modules/typescript/lib", + "jest.jestCommandLine": "yarn test" } diff --git a/jest.config.js b/jest.config.js index daef890..bdac7d6 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,4 +1,8 @@ +// eslint-disable-next-line @typescript-eslint/no-require-imports +const { createDefaultEsmPreset } = require("ts-jest"); + +/** @type {import("ts-jest").JestConfigWithTsJest} */ module.exports = { - preset: "ts-jest", - testMatch: ["/src/**/*.test.ts"], + ...createDefaultEsmPreset({}), + setupFiles: ["jest-canvas-mock"], }; diff --git a/package.json b/package.json index 28af706..f6153af 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "build": "tsc -b tsconfig.json tsconfig.cjs.json", "lint": "eslint --fix .", "lint:ci": "eslint .", - "test": "echo 'nothing to test'", + "test": "NODE_OPTIONS=--experimental-vm-modules jest", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build" }, @@ -49,13 +49,15 @@ "eslint-plugin-storybook": "0.11.0", "globals": "15.12.0", "jest": "29.7.0", + "jest-canvas-mock": "2.5.2", + "jest-environment-jsdom": "29.7.0", "prettier": "3.3.3", "react": "18.3.1", "react-dom": "18.3.1", "rimraf": "6.0.1", "storybook": "7.6.16", "three": "0.165.0", - "ts-jest": "29.1.2", + "ts-jest": "29.2.5", "typescript": "5.6.3", "typescript-eslint": "8.13.0" }, diff --git a/src/FontManager.test.ts b/src/FontManager.test.ts new file mode 100644 index 0000000..85bf07c --- /dev/null +++ b/src/FontManager.test.ts @@ -0,0 +1,18 @@ +/** @jest-environment jsdom */ + +import { FontManager } from "./FontManager"; + +describe("FontManager", () => { + it("emits error events", () => { + const fontManager = new FontManager({ fontSize: 500 }); + const errors: Error[] = []; + fontManager.addEventListener("error", (err) => errors.push(err.error)); + for (let i = 0; i < 1000; i++) { + fontManager.update(String.fromCodePoint(i)); + if (errors.length > 0) { + break; + } + } + expect(errors).toEqual([new Error("Unable to fit all 226 characters in font atlas")]); + }); +}); diff --git a/src/FontManager.ts b/src/FontManager.ts index 50b9d0a..a6c5515 100644 --- a/src/FontManager.ts +++ b/src/FontManager.ts @@ -46,8 +46,6 @@ type EventMap = { error: { error: Error }; }; -const MAX_CHARS = 2048; - /** * Manages the creation of a Signed Distance Field (SDF) font atlas, and performs text layout to * generate attributes for rendering text using the atlas. @@ -75,15 +73,6 @@ export class FontManager extends EventDispatcher { } update(newChars: string): void { - if (this.alphabet.length > MAX_CHARS) { - this.dispatchEvent({ - type: "error", - error: new Error( - `Exceeded maximum unique characters: ${this.alphabet.length} > ${MAX_CHARS}`, - ), - }); - return; - } let needsUpdate = false; for (const char of newChars) { if (!this.alphabet.includes(char)) { @@ -91,15 +80,6 @@ export class FontManager extends EventDispatcher { needsUpdate = true; } } - if (this.alphabet.length > MAX_CHARS) { - this.dispatchEvent({ - type: "error", - error: new Error( - `Exceeded maximum unique characters: ${this.alphabet.length} > ${MAX_CHARS}`, - ), - }); - return; - } if (!needsUpdate) { return; diff --git a/yarn.lock b/yarn.lock index f638a0a..8a7bc7c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1896,13 +1896,15 @@ __metadata: eslint-plugin-storybook: "npm:0.11.0" globals: "npm:15.12.0" jest: "npm:29.7.0" + jest-canvas-mock: "npm:2.5.2" + jest-environment-jsdom: "npm:29.7.0" prettier: "npm:3.3.3" react: "npm:18.3.1" react-dom: "npm:18.3.1" rimraf: "npm:6.0.1" storybook: "npm:7.6.16" three: "npm:0.165.0" - ts-jest: "npm:29.1.2" + ts-jest: "npm:29.2.5" typescript: "npm:5.6.3" typescript-eslint: "npm:8.13.0" peerDependencies: @@ -3930,6 +3932,13 @@ __metadata: languageName: node linkType: hard +"@tootallnate/once@npm:2": + version: 2.0.0 + resolution: "@tootallnate/once@npm:2.0.0" + checksum: 073bfa548026b1ebaf1659eb8961e526be22fa77139b10d60e712f46d2f0f05f4e6c8bec62a087d41088ee9e29faa7f54838568e475ab2f776171003c3920858 + languageName: node + linkType: hard + "@tweenjs/tween.js@npm:~23.1.1": version: 23.1.2 resolution: "@tweenjs/tween.js@npm:23.1.2" @@ -4171,6 +4180,17 @@ __metadata: languageName: node linkType: hard +"@types/jsdom@npm:^20.0.0": + version: 20.0.1 + resolution: "@types/jsdom@npm:20.0.1" + dependencies: + "@types/node": "npm:*" + "@types/tough-cookie": "npm:*" + parse5: "npm:^7.0.0" + checksum: 3d4b2a3eab145674ee6da482607c5e48977869109f0f62560bf91ae1a792c9e847ac7c6aaf243ed2e97333cb3c51aef314ffa54a19ef174b8f9592dfcb836b25 + languageName: node + linkType: hard + "@types/json-schema@npm:*, @types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" @@ -4362,6 +4382,13 @@ __metadata: languageName: node linkType: hard +"@types/tough-cookie@npm:*": + version: 4.0.5 + resolution: "@types/tough-cookie@npm:4.0.5" + checksum: 68c6921721a3dcb40451543db2174a145ef915bc8bcbe7ad4e59194a0238e776e782b896c7a59f4b93ac6acefca9161fccb31d1ce3b3445cb6faa467297fb473 + languageName: node + linkType: hard + "@types/unist@npm:^2.0.0": version: 2.0.10 resolution: "@types/unist@npm:2.0.10" @@ -4711,6 +4738,13 @@ __metadata: languageName: node linkType: hard +"abab@npm:^2.0.6": + version: 2.0.6 + resolution: "abab@npm:2.0.6" + checksum: 0b245c3c3ea2598fe0025abf7cc7bb507b06949d51e8edae5d12c1b847a0a0c09639abcb94788332b4e2044ac4491c1e8f571b51c7826fd4b0bda1685ad4a278 + languageName: node + linkType: hard + "abbrev@npm:^2.0.0": version: 2.0.0 resolution: "abbrev@npm:2.0.0" @@ -4728,6 +4762,16 @@ __metadata: languageName: node linkType: hard +"acorn-globals@npm:^7.0.0": + version: 7.0.1 + resolution: "acorn-globals@npm:7.0.1" + dependencies: + acorn: "npm:^8.1.0" + acorn-walk: "npm:^8.0.2" + checksum: 7437f58e92d99292dbebd0e79531af27d706c9f272f31c675d793da6c82d897e75302a8744af13c7f7978a8399840f14a353b60cf21014647f71012982456d2b + languageName: node + linkType: hard + "acorn-import-assertions@npm:^1.9.0": version: 1.9.0 resolution: "acorn-import-assertions@npm:1.9.0" @@ -4753,6 +4797,15 @@ __metadata: languageName: node linkType: hard +"acorn-walk@npm:^8.0.2": + version: 8.3.4 + resolution: "acorn-walk@npm:8.3.4" + dependencies: + acorn: "npm:^8.11.0" + checksum: 76537ac5fb2c37a64560feaf3342023dadc086c46da57da363e64c6148dc21b57d49ace26f949e225063acb6fb441eabffd89f7a3066de5ad37ab3e328927c62 + languageName: node + linkType: hard + "acorn@npm:^7.4.1": version: 7.4.1 resolution: "acorn@npm:7.4.1" @@ -4762,7 +4815,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.11.2, acorn@npm:^8.14.0, acorn@npm:^8.7.1, acorn@npm:^8.8.2": +"acorn@npm:^8.1.0, acorn@npm:^8.11.0, acorn@npm:^8.11.2, acorn@npm:^8.14.0, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2": version: 8.14.0 resolution: "acorn@npm:8.14.0" bin: @@ -4785,6 +4838,15 @@ __metadata: languageName: node linkType: hard +"agent-base@npm:6": + version: 6.0.2 + resolution: "agent-base@npm:6.0.2" + dependencies: + debug: "npm:4" + checksum: dc4f757e40b5f3e3d674bc9beb4f1048f4ee83af189bae39be99f57bf1f48dde166a8b0a5342a84b5944ee8e6ed1e5a9d801858f4ad44764e84957122fe46261 + languageName: node + linkType: hard + "agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": version: 7.1.0 resolution: "agent-base@npm:7.1.0" @@ -5429,7 +5491,7 @@ __metadata: languageName: node linkType: hard -"bs-logger@npm:0.x": +"bs-logger@npm:^0.2.6": version: 0.2.6 resolution: "bs-logger@npm:0.2.6" dependencies: @@ -5786,7 +5848,7 @@ __metadata: languageName: node linkType: hard -"color-name@npm:~1.1.4": +"color-name@npm:^1.1.4, color-name@npm:~1.1.4": version: 1.1.4 resolution: "color-name@npm:1.1.4" checksum: a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 @@ -6056,6 +6118,36 @@ __metadata: languageName: node linkType: hard +"cssfontparser@npm:^1.2.1": + version: 1.2.1 + resolution: "cssfontparser@npm:1.2.1" + checksum: ceb9b2976d503dbff3ac2aff0229b263affb4fb221a6947b357682cd8a952f6995253646ca5f820020d2fe05b5e29b56dbdd2343388c32203e8dd0ed15bdc1ca + languageName: node + linkType: hard + +"cssom@npm:^0.5.0": + version: 0.5.0 + resolution: "cssom@npm:0.5.0" + checksum: 8c4121c243baf0678c65dcac29b201ff0067dfecf978de9d5c83b2ff127a8fdefd2bfd54577f5ad8c80ed7d2c8b489ae01c82023545d010c4ecb87683fb403dd + languageName: node + linkType: hard + +"cssom@npm:~0.3.6": + version: 0.3.8 + resolution: "cssom@npm:0.3.8" + checksum: d74017b209440822f9e24d8782d6d2e808a8fdd58fa626a783337222fe1c87a518ba944d4c88499031b4786e68772c99dfae616638d71906fe9f203aeaf14411 + languageName: node + linkType: hard + +"cssstyle@npm:^2.3.0": + version: 2.3.0 + resolution: "cssstyle@npm:2.3.0" + dependencies: + cssom: "npm:~0.3.6" + checksum: 863400da2a458f73272b9a55ba7ff05de40d850f22eb4f37311abebd7eff801cf1cd2fb04c4c92b8c3daed83fe766e52e4112afb7bc88d86c63a9c2256a7d178 + languageName: node + linkType: hard + "csstype@npm:^3.0.2": version: 3.1.3 resolution: "csstype@npm:3.1.3" @@ -6063,6 +6155,17 @@ __metadata: languageName: node linkType: hard +"data-urls@npm:^3.0.2": + version: 3.0.2 + resolution: "data-urls@npm:3.0.2" + dependencies: + abab: "npm:^2.0.6" + whatwg-mimetype: "npm:^3.0.0" + whatwg-url: "npm:^11.0.0" + checksum: 051c3aaaf3e961904f136aab095fcf6dff4db23a7fc759dd8ba7b3e6ba03fc07ef608086caad8ab910d864bd3b5e57d0d2f544725653d77c96a2c971567045f4 + languageName: node + linkType: hard + "data-view-buffer@npm:^1.0.1": version: 1.0.1 resolution: "data-view-buffer@npm:1.0.1" @@ -6126,6 +6229,13 @@ __metadata: languageName: node linkType: hard +"decimal.js@npm:^10.4.2": + version: 10.4.3 + resolution: "decimal.js@npm:10.4.3" + checksum: 6d60206689ff0911f0ce968d40f163304a6c1bc739927758e6efc7921cfa630130388966f16bf6ef6b838cb33679fbe8e7a78a2f3c478afce841fd55ac8fb8ee + languageName: node + linkType: hard + "dedent@npm:^0.7.0": version: 0.7.0 resolution: "dedent@npm:0.7.0" @@ -6362,6 +6472,15 @@ __metadata: languageName: node linkType: hard +"domexception@npm:^4.0.0": + version: 4.0.0 + resolution: "domexception@npm:4.0.0" + dependencies: + webidl-conversions: "npm:^7.0.0" + checksum: 774277cd9d4df033f852196e3c0077a34dbd15a96baa4d166e0e47138a80f4c0bdf0d94e4703e6ff5883cec56bb821a6fff84402d8a498e31de7c87eb932a294 + languageName: node + linkType: hard + "domhandler@npm:^4.0.0, domhandler@npm:^4.2.0, domhandler@npm:^4.3.1": version: 4.3.1 resolution: "domhandler@npm:4.3.1" @@ -6432,6 +6551,17 @@ __metadata: languageName: node linkType: hard +"ejs@npm:^3.1.10": + version: 3.1.10 + resolution: "ejs@npm:3.1.10" + dependencies: + jake: "npm:^10.8.5" + bin: + ejs: bin/cli.js + checksum: 52eade9e68416ed04f7f92c492183340582a36482836b11eab97b159fcdcfdedc62233a1bf0bf5e5e1851c501f2dca0e2e9afd111db2599e4e7f53ee29429ae1 + languageName: node + linkType: hard + "ejs@npm:^3.1.8": version: 3.1.9 resolution: "ejs@npm:3.1.9" @@ -6531,6 +6661,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:^4.5.0": + version: 4.5.0 + resolution: "entities@npm:4.5.0" + checksum: 5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250 + languageName: node + linkType: hard + "env-paths@npm:^2.2.0": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -6842,7 +6979,7 @@ __metadata: languageName: node linkType: hard -"escodegen@npm:^2.1.0": +"escodegen@npm:^2.0.0, escodegen@npm:^2.1.0": version: 2.1.0 resolution: "escodegen@npm:2.1.0" dependencies: @@ -8118,6 +8255,15 @@ __metadata: languageName: node linkType: hard +"html-encoding-sniffer@npm:^3.0.0": + version: 3.0.0 + resolution: "html-encoding-sniffer@npm:3.0.0" + dependencies: + whatwg-encoding: "npm:^2.0.0" + checksum: b17b3b0fb5d061d8eb15121c3b0b536376c3e295ecaf09ba48dd69c6b6c957839db124fe1e2b3f11329753a4ee01aa7dedf63b7677999e86da17fbbdd82c5386 + languageName: node + linkType: hard + "html-entities@npm:^2.1.0": version: 2.4.0 resolution: "html-entities@npm:2.4.0" @@ -8209,6 +8355,17 @@ __metadata: languageName: node linkType: hard +"http-proxy-agent@npm:^5.0.0": + version: 5.0.0 + resolution: "http-proxy-agent@npm:5.0.0" + dependencies: + "@tootallnate/once": "npm:2" + agent-base: "npm:6" + debug: "npm:4" + checksum: 32a05e413430b2c1e542e5c74b38a9f14865301dd69dff2e53ddb684989440e3d2ce0c4b64d25eb63cf6283e6265ff979a61cf93e3ca3d23047ddfdc8df34a32 + languageName: node + linkType: hard + "http-proxy-agent@npm:^7.0.0": version: 7.0.0 resolution: "http-proxy-agent@npm:7.0.0" @@ -8229,6 +8386,16 @@ __metadata: languageName: node linkType: hard +"https-proxy-agent@npm:^5.0.1": + version: 5.0.1 + resolution: "https-proxy-agent@npm:5.0.1" + dependencies: + agent-base: "npm:6" + debug: "npm:4" + checksum: 6dd639f03434003577c62b27cafdb864784ef19b2de430d8ae2a1d45e31c4fd60719e5637b44db1a88a046934307da7089e03d6089ec3ddacc1189d8de8897d1 + languageName: node + linkType: hard + "https-proxy-agent@npm:^7.0.1": version: 7.0.2 resolution: "https-proxy-agent@npm:7.0.2" @@ -8262,7 +8429,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:^0.6.2": +"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" dependencies: @@ -8641,6 +8808,13 @@ __metadata: languageName: node linkType: hard +"is-potential-custom-element-name@npm:^1.0.1": + version: 1.0.1 + resolution: "is-potential-custom-element-name@npm:1.0.1" + checksum: b73e2f22bc863b0939941d369486d308b43d7aef1f9439705e3582bfccaa4516406865e32c968a35f97a99396dac84e2624e67b0a16b0a15086a785e16ce7db9 + languageName: node + linkType: hard + "is-regex@npm:^1.1.4": version: 1.1.4 resolution: "is-regex@npm:1.1.4" @@ -8899,6 +9073,16 @@ __metadata: languageName: node linkType: hard +"jest-canvas-mock@npm:2.5.2": + version: 2.5.2 + resolution: "jest-canvas-mock@npm:2.5.2" + dependencies: + cssfontparser: "npm:^1.2.1" + moo-color: "npm:^1.0.2" + checksum: 6a4190354b1e9aedcb3045273f13f6f1d2d1efb00cfe6458707fae538a8f91f6afdf72b9e201b653666863054edc783428bdc0c1a2c71d66d9ac364b4893f6d6 + languageName: node + linkType: hard + "jest-changed-files@npm:^29.7.0": version: 29.7.0 resolution: "jest-changed-files@npm:29.7.0" @@ -9036,6 +9220,27 @@ __metadata: languageName: node linkType: hard +"jest-environment-jsdom@npm:29.7.0": + version: 29.7.0 + resolution: "jest-environment-jsdom@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/jsdom": "npm:^20.0.0" + "@types/node": "npm:*" + jest-mock: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jsdom: "npm:^20.0.0" + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + checksum: 139b94e2c8ec1bb5a46ce17df5211da65ce867354b3fd4e00fa6a0d1da95902df4cf7881273fc6ea937e5c325d39d6773f0d41b6c469363334de9d489d2c321f + languageName: node + linkType: hard + "jest-environment-node@npm:^29.7.0": version: 29.7.0 resolution: "jest-environment-node@npm:29.7.0" @@ -9414,6 +9619,45 @@ __metadata: languageName: node linkType: hard +"jsdom@npm:^20.0.0": + version: 20.0.3 + resolution: "jsdom@npm:20.0.3" + dependencies: + abab: "npm:^2.0.6" + acorn: "npm:^8.8.1" + acorn-globals: "npm:^7.0.0" + cssom: "npm:^0.5.0" + cssstyle: "npm:^2.3.0" + data-urls: "npm:^3.0.2" + decimal.js: "npm:^10.4.2" + domexception: "npm:^4.0.0" + escodegen: "npm:^2.0.0" + form-data: "npm:^4.0.0" + html-encoding-sniffer: "npm:^3.0.0" + http-proxy-agent: "npm:^5.0.0" + https-proxy-agent: "npm:^5.0.1" + is-potential-custom-element-name: "npm:^1.0.1" + nwsapi: "npm:^2.2.2" + parse5: "npm:^7.1.1" + saxes: "npm:^6.0.0" + symbol-tree: "npm:^3.2.4" + tough-cookie: "npm:^4.1.2" + w3c-xmlserializer: "npm:^4.0.0" + webidl-conversions: "npm:^7.0.0" + whatwg-encoding: "npm:^2.0.0" + whatwg-mimetype: "npm:^3.0.0" + whatwg-url: "npm:^11.0.0" + ws: "npm:^8.11.0" + xml-name-validator: "npm:^4.0.0" + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + checksum: b109073bb826a966db7828f46cb1d7371abecd30f182b143c52be5fe1ed84513bbbe995eb3d157241681fcd18331381e61e3dc004d4949f3a63bca02f6214902 + languageName: node + linkType: hard + "jsesc@npm:^2.5.1": version: 2.5.2 resolution: "jsesc@npm:2.5.2" @@ -9646,7 +9890,7 @@ __metadata: languageName: node linkType: hard -"lodash.memoize@npm:4.x": +"lodash.memoize@npm:^4.1.2": version: 4.1.2 resolution: "lodash.memoize@npm:4.1.2" checksum: c8713e51eccc650422716a14cece1809cfe34bc5ab5e242b7f8b4e2241c2483697b971a604252807689b9dd69bfe3a98852e19a5b89d506b000b4187a1285df8 @@ -9771,7 +10015,7 @@ __metadata: languageName: node linkType: hard -"make-error@npm:1.x": +"make-error@npm:^1.3.6": version: 1.3.6 resolution: "make-error@npm:1.3.6" checksum: 171e458d86854c6b3fc46610cfacf0b45149ba043782558c6875d9f42f222124384ad0b468c92e996d815a8a2003817a710c0a160e49c1c394626f76fa45396f @@ -10124,6 +10368,15 @@ __metadata: languageName: node linkType: hard +"moo-color@npm:^1.0.2": + version: 1.0.3 + resolution: "moo-color@npm:1.0.3" + dependencies: + color-name: "npm:^1.1.4" + checksum: 778c82f67f638c03a1d0fa78dcd6ea376a9f17b5e78e349c7e34a290b496dbdb43fd0b1c38070e2062d5e784bcf08e57f499015fcbcf52b3a1887d7825ebb80d + languageName: node + linkType: hard + "ms@npm:2.0.0": version: 2.0.0 resolution: "ms@npm:2.0.0" @@ -10313,6 +10566,13 @@ __metadata: languageName: node linkType: hard +"nwsapi@npm:^2.2.2": + version: 2.2.16 + resolution: "nwsapi@npm:2.2.16" + checksum: 0aa0637f4d51043d0183d994e08336bae996b03b42984381bf09ebdf3ff4909c018eda6b2a8aba0a08f3ea8303db8a0dad0608b38dc0bff15fd87017286ae21a + languageName: node + linkType: hard + "nypm@npm:^0.3.3": version: 0.3.6 resolution: "nypm@npm:0.3.6" @@ -10638,6 +10898,15 @@ __metadata: languageName: node linkType: hard +"parse5@npm:^7.0.0, parse5@npm:^7.1.1": + version: 7.2.1 + resolution: "parse5@npm:7.2.1" + dependencies: + entities: "npm:^4.5.0" + checksum: 829d37a0c709215a887e410a7118d754f8e1afd7edb529db95bc7bbf8045fb0266a7b67801331d8e8d9d073ea75793624ec27ce9ff3b96862c3b9008f4d68e80 + languageName: node + linkType: hard + "parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" @@ -11060,6 +11329,15 @@ __metadata: languageName: node linkType: hard +"psl@npm:^1.1.33": + version: 1.15.0 + resolution: "psl@npm:1.15.0" + dependencies: + punycode: "npm:^2.3.1" + checksum: d8d45a99e4ca62ca12ac3c373e63d80d2368d38892daa40cfddaa1eb908be98cd549ac059783ef3a56cfd96d57ae8e2fd9ae53d1378d90d42bc661ff924e102a + languageName: node + linkType: hard + "pump@npm:^2.0.0": version: 2.0.1 resolution: "pump@npm:2.0.1" @@ -11098,7 +11376,7 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^2.1.0": +"punycode@npm:^2.1.0, punycode@npm:^2.1.1, punycode@npm:^2.3.1": version: 2.3.1 resolution: "punycode@npm:2.3.1" checksum: 14f76a8206bc3464f794fb2e3d3cc665ae416c01893ad7a02b23766eb07159144ee612ad67af5e84fa4479ccfe67678c4feb126b0485651b302babf66f04f9e9 @@ -11148,6 +11426,13 @@ __metadata: languageName: node linkType: hard +"querystringify@npm:^2.1.1": + version: 2.2.0 + resolution: "querystringify@npm:2.2.0" + checksum: 3258bc3dbdf322ff2663619afe5947c7926a6ef5fb78ad7d384602974c467fadfc8272af44f5eb8cddd0d011aae8fabf3a929a8eee4b86edcc0a21e6bd10f9aa + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -11561,6 +11846,13 @@ __metadata: languageName: node linkType: hard +"requires-port@npm:^1.0.0": + version: 1.0.0 + resolution: "requires-port@npm:1.0.0" + checksum: b2bfdd09db16c082c4326e573a82c0771daaf7b53b9ce8ad60ea46aa6e30aaf475fe9b164800b89f93b748d2c234d8abff945d2551ba47bf5698e04cd7713267 + languageName: node + linkType: hard + "resolve-cwd@npm:^3.0.0": version: 3.0.0 resolution: "resolve-cwd@npm:3.0.0" @@ -11765,6 +12057,15 @@ __metadata: languageName: node linkType: hard +"saxes@npm:^6.0.0": + version: 6.0.0 + resolution: "saxes@npm:6.0.0" + dependencies: + xmlchars: "npm:^2.2.0" + checksum: 3847b839f060ef3476eb8623d099aa502ad658f5c40fd60c105ebce86d244389b0d76fcae30f4d0c728d7705ceb2f7e9b34bb54717b6a7dbedaf5dad2d9a4b74 + languageName: node + linkType: hard + "scheduler@npm:^0.23.2": version: 0.23.2 resolution: "scheduler@npm:0.23.2" @@ -11815,7 +12116,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": +"semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3": version: 7.6.3 resolution: "semver@npm:7.6.3" bin: @@ -12368,6 +12669,13 @@ __metadata: languageName: node linkType: hard +"symbol-tree@npm:^3.2.4": + version: 3.2.4 + resolution: "symbol-tree@npm:3.2.4" + checksum: dfbe201ae09ac6053d163578778c53aa860a784147ecf95705de0cd23f42c851e1be7889241495e95c37cabb058edb1052f141387bef68f705afc8f9dd358509 + languageName: node + linkType: hard + "synchronous-promise@npm:^2.0.15": version: 2.0.17 resolution: "synchronous-promise@npm:2.0.17" @@ -12584,6 +12892,27 @@ __metadata: languageName: node linkType: hard +"tough-cookie@npm:^4.1.2": + version: 4.1.4 + resolution: "tough-cookie@npm:4.1.4" + dependencies: + psl: "npm:^1.1.33" + punycode: "npm:^2.1.1" + universalify: "npm:^0.2.0" + url-parse: "npm:^1.5.3" + checksum: aca7ff96054f367d53d1e813e62ceb7dd2eda25d7752058a74d64b7266fd07be75908f3753a32ccf866a2f997604b414cfb1916d6e7f69bc64d9d9939b0d6c45 + languageName: node + linkType: hard + +"tr46@npm:^3.0.0": + version: 3.0.0 + resolution: "tr46@npm:3.0.0" + dependencies: + punycode: "npm:^2.1.1" + checksum: cdc47cad3a9d0b6cb293e39ccb1066695ae6fdd39b9e4f351b010835a1f8b4f3a6dc3a55e896b421371187f22b48d7dac1b693de4f6551bdef7b6ab6735dfe3b + languageName: node + linkType: hard + "tr46@npm:~0.0.3": version: 0.0.3 resolution: "tr46@npm:0.0.3" @@ -12607,20 +12936,22 @@ __metadata: languageName: node linkType: hard -"ts-jest@npm:29.1.2": - version: 29.1.2 - resolution: "ts-jest@npm:29.1.2" +"ts-jest@npm:29.2.5": + version: 29.2.5 + resolution: "ts-jest@npm:29.2.5" dependencies: - bs-logger: "npm:0.x" - fast-json-stable-stringify: "npm:2.x" + bs-logger: "npm:^0.2.6" + ejs: "npm:^3.1.10" + fast-json-stable-stringify: "npm:^2.1.0" jest-util: "npm:^29.0.0" json5: "npm:^2.2.3" - lodash.memoize: "npm:4.x" - make-error: "npm:1.x" - semver: "npm:^7.5.3" - yargs-parser: "npm:^21.0.1" + lodash.memoize: "npm:^4.1.2" + make-error: "npm:^1.3.6" + semver: "npm:^7.6.3" + yargs-parser: "npm:^21.1.1" peerDependencies: "@babel/core": ">=7.0.0-beta.0 <8" + "@jest/transform": ^29.0.0 "@jest/types": ^29.0.0 babel-jest: ^29.0.0 jest: ^29.0.0 @@ -12628,6 +12959,8 @@ __metadata: peerDependenciesMeta: "@babel/core": optional: true + "@jest/transform": + optional: true "@jest/types": optional: true babel-jest: @@ -12636,7 +12969,7 @@ __metadata: optional: true bin: ts-jest: cli.js - checksum: c2f51f0241f89d127d41392decbcb83b5dfd5e57ab9d50220aa7b7e2f9b3f3b07ccdbba33311284df1c41941879e4ddfad44b15a9d0da4b74bd1b98702b729df + checksum: acb62d168faec073e64b20873b583974ba8acecdb94681164eb346cef82ade8fb481c5b979363e01a97ce4dd1e793baf64d9efd90720bc941ad7fc1c3d6f3f68 languageName: node linkType: hard @@ -12959,6 +13292,13 @@ __metadata: languageName: node linkType: hard +"universalify@npm:^0.2.0": + version: 0.2.0 + resolution: "universalify@npm:0.2.0" + checksum: cedbe4d4ca3967edf24c0800cfc161c5a15e240dac28e3ce575c689abc11f2c81ccc6532c8752af3b40f9120fb5e454abecd359e164f4f6aa44c29cd37e194fe + languageName: node + linkType: hard + "universalify@npm:^2.0.0": version: 2.0.1 resolution: "universalify@npm:2.0.1" @@ -13015,6 +13355,16 @@ __metadata: languageName: node linkType: hard +"url-parse@npm:^1.5.3": + version: 1.5.10 + resolution: "url-parse@npm:1.5.10" + dependencies: + querystringify: "npm:^2.1.1" + requires-port: "npm:^1.0.0" + checksum: bd5aa9389f896974beb851c112f63b466505a04b4807cea2e5a3b7092f6fbb75316f0491ea84e44f66fed55f1b440df5195d7e3a8203f64fcefa19d182f5be87 + languageName: node + linkType: hard + "url@npm:^0.11.0": version: 0.11.3 resolution: "url@npm:0.11.3" @@ -13139,6 +13489,15 @@ __metadata: languageName: node linkType: hard +"w3c-xmlserializer@npm:^4.0.0": + version: 4.0.0 + resolution: "w3c-xmlserializer@npm:4.0.0" + dependencies: + xml-name-validator: "npm:^4.0.0" + checksum: 02cc66d6efc590bd630086cd88252444120f5feec5c4043932b0d0f74f8b060512f79dc77eb093a7ad04b4f02f39da79ce4af47ceb600f2bf9eacdc83204b1a8 + languageName: node + linkType: hard + "walker@npm:^1.0.8": version: 1.0.8 resolution: "walker@npm:1.0.8" @@ -13174,6 +13533,13 @@ __metadata: languageName: node linkType: hard +"webidl-conversions@npm:^7.0.0": + version: 7.0.0 + resolution: "webidl-conversions@npm:7.0.0" + checksum: 228d8cb6d270c23b0720cb2d95c579202db3aaf8f633b4e9dd94ec2000a04e7e6e43b76a94509cdb30479bd00ae253ab2371a2da9f81446cc313f89a4213a2c4 + languageName: node + linkType: hard + "webpack-dev-middleware@npm:^6.1.1": version: 6.1.1 resolution: "webpack-dev-middleware@npm:6.1.1" @@ -13261,6 +13627,32 @@ __metadata: languageName: node linkType: hard +"whatwg-encoding@npm:^2.0.0": + version: 2.0.0 + resolution: "whatwg-encoding@npm:2.0.0" + dependencies: + iconv-lite: "npm:0.6.3" + checksum: 91b90a49f312dc751496fd23a7e68981e62f33afe938b97281ad766235c4872fc4e66319f925c5e9001502b3040dd25a33b02a9c693b73a4cbbfdc4ad10c3e3e + languageName: node + linkType: hard + +"whatwg-mimetype@npm:^3.0.0": + version: 3.0.0 + resolution: "whatwg-mimetype@npm:3.0.0" + checksum: 323895a1cda29a5fb0b9ca82831d2c316309fede0365047c4c323073e3239067a304a09a1f4b123b9532641ab604203f33a1403b5ca6a62ef405bcd7a204080f + languageName: node + linkType: hard + +"whatwg-url@npm:^11.0.0": + version: 11.0.0 + resolution: "whatwg-url@npm:11.0.0" + dependencies: + tr46: "npm:^3.0.0" + webidl-conversions: "npm:^7.0.0" + checksum: f7ec264976d7c725e0696fcaf9ebe056e14422eacbf92fdbb4462034609cba7d0c85ffa1aab05e9309d42969bcf04632ba5ed3f3882c516d7b093053315bf4c1 + languageName: node + linkType: hard + "whatwg-url@npm:^5.0.0": version: 5.0.0 resolution: "whatwg-url@npm:5.0.0" @@ -13417,6 +13809,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.11.0": + version: 8.18.0 + resolution: "ws@npm:8.18.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 25eb33aff17edcb90721ed6b0eb250976328533ad3cd1a28a274bd263682e7296a6591ff1436d6cbc50fa67463158b062f9d1122013b361cec99a05f84680e06 + languageName: node + linkType: hard + "ws@npm:^8.2.3": version: 8.16.0 resolution: "ws@npm:8.16.0" @@ -13432,6 +13839,20 @@ __metadata: languageName: node linkType: hard +"xml-name-validator@npm:^4.0.0": + version: 4.0.0 + resolution: "xml-name-validator@npm:4.0.0" + checksum: c1bfa219d64e56fee265b2bd31b2fcecefc063ee802da1e73bad1f21d7afd89b943c9e2c97af2942f60b1ad46f915a4c81e00039c7d398b53cf410e29d3c30bd + languageName: node + linkType: hard + +"xmlchars@npm:^2.2.0": + version: 2.2.0 + resolution: "xmlchars@npm:2.2.0" + checksum: b64b535861a6f310c5d9bfa10834cf49127c71922c297da9d4d1b45eeaae40bf9b4363275876088fbe2667e5db028d2cd4f8ee72eed9bede840a67d57dab7593 + languageName: node + linkType: hard + "xtend@npm:~4.0.1": version: 4.0.2 resolution: "xtend@npm:4.0.2" @@ -13467,7 +13888,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^21.0.1, yargs-parser@npm:^21.1.1": +"yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1" checksum: f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 From c1660654f39d583f7c4e538754690e303d8a6dee Mon Sep 17 00:00:00 2001 From: Jacob Bandes-Storch Date: Fri, 10 Jan 2025 16:34:57 -0800 Subject: [PATCH 8/9] node 22 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ee9a4a..f5cc380 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: - run: corepack enable - uses: actions/setup-node@v4 with: - node-version: 20.x + node-version: 22.x registry-url: https://registry.npmjs.org cache: yarn @@ -49,7 +49,7 @@ jobs: - run: corepack enable - uses: actions/setup-node@v4 with: - node-version: 20.x + node-version: 22.x registry-url: https://registry.npmjs.org cache: yarn From e222b196c0c635862d479134e91302702f614cc9 Mon Sep 17 00:00:00 2001 From: Jacob Bandes-Storch Date: Fri, 10 Jan 2025 16:37:24 -0800 Subject: [PATCH 9/9] bring back testMatch --- jest.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/jest.config.js b/jest.config.js index bdac7d6..2006a03 100644 --- a/jest.config.js +++ b/jest.config.js @@ -4,5 +4,6 @@ const { createDefaultEsmPreset } = require("ts-jest"); /** @type {import("ts-jest").JestConfigWithTsJest} */ module.exports = { ...createDefaultEsmPreset({}), + testMatch: ["/src/**/*.test.ts"], setupFiles: ["jest-canvas-mock"], };