Skip to content

Commit 2e0a96b

Browse files
committed
chore: refresh dependencies and browser test baselines
- bump the package to 5.29.0 and update acad-ts, Playwright, TypeScript, Node types, esbuild, pretext, and the getBoxQuads polyfill - run Chromium test projects through Chrome Canary with experimental web platform features so Element and Text use native getBoxQuads implementations - preserve native box-quad APIs, harden generated binary writes on Windows, and update media, font, form-control, and SVG assertions for current browser behavior - regenerate Chrome Canary and Firefox demo artifacts, writer outputs, assets, and previews Validated with the TypeScript build, production bundle, dependency-tree check, package dry-run, the comprehensive Playwright suite, and focused reruns of all initially failing cases.
1 parent b206a1d commit 2e0a96b

974 files changed

Lines changed: 1859013 additions & 1852774 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENT.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
### Browser Selection
1515
- **Always use Firefox** for finding rendering issues.
16-
- The `getBoxQuads` API is only emulated in Chrome and does not accurately reflect real-world behavior, especially for edge cases.
17-
- Firefox in our tests has enabled native gtBoxQuads API!
16+
- Chrome tests use Chrome Canary with Experimental Web Platform Features enabled, which exposes native `getBoxQuads`.
17+
- Firefox tests also enable the native `getBoxQuads` API.
1818

1919
### Regression Testing
2020
- When testing for new issues, **always verify that no other renderings are broken**.

package-lock.json

Lines changed: 513 additions & 152 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@node-projects/layout2vector",
3-
"version": "5.28.0",
3+
"version": "5.29.0",
44
"description": "DOM → Geometry → DXF/PDF/PNG library",
55
"repository": {
66
"type": "git",
@@ -37,7 +37,7 @@
3737
"bundle": "esbuild ./dist/index.js --format=esm --minify --external:@tarikjabiri/dxf --external:@node-projects/acad-ts --external:@chenglou/pretext --external:fonteditor-core --platform=neutral --bundle --outfile=./dist/index-min.js"
3838
},
3939
"dependencies": {
40-
"@node-projects/acad-ts": "^2.3.0",
40+
"@node-projects/acad-ts": "^3.0.0",
4141
"@tarikjabiri/dxf": "^2.8.9"
4242
},
4343
"peerDependencies": {
@@ -50,11 +50,11 @@
5050
}
5151
},
5252
"devDependencies": {
53-
"@chenglou/pretext": ">=0.0.6",
54-
"@playwright/test": "^1.59.1",
55-
"@types/node": "^25.6.1",
56-
"esbuild": "^0.28.0",
57-
"get-box-quads-polyfill": "^4.43.0",
58-
"typescript": "^6.0.3"
53+
"@chenglou/pretext": ">=0.0.8",
54+
"@playwright/test": "^1.62.1",
55+
"@types/node": "^26.2.0",
56+
"esbuild": "^0.28.2",
57+
"get-box-quads-polyfill": "^4.47.0",
58+
"typescript": "^7.0.2"
5959
}
6060
}

playwright.config.ts

Lines changed: 24 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,70 @@
11
import { defineConfig } from "@playwright/test";
22

3-
const browser = (process.env.BROWSER as "chromium" | "firefox") || "chromium";
3+
const chromeCanary = {
4+
browserName: "chromium" as const,
5+
channel: "chrome-canary",
6+
launchOptions: {
7+
args: ["--enable-experimental-web-platform-features"],
8+
},
9+
};
10+
11+
const firefox = {
12+
browserName: "firefox" as const,
13+
launchOptions: {
14+
firefoxUserPrefs: {
15+
"layout.css.getBoxQuads.enabled": true,
16+
},
17+
},
18+
};
419

520
export default defineConfig({
621
testDir: "./tests",
722
timeout: 30000,
823
retries: 0,
924
use: {
10-
browserName: browser,
1125
headless: true,
1226
},
1327
projects: [
1428
{
1529
name: "unit",
1630
testMatch: "unit/**/*.test.ts",
31+
use: chromeCanary,
1732
},
1833
{
1934
name: "integration",
2035
testMatch: "integration/**/*.test.ts",
36+
use: chromeCanary,
2137
},
2238
{
2339
name: "ui",
2440
testMatch: "ui/**/*.test.ts",
41+
use: chromeCanary,
2542
},
2643
{
2744
name: "demos",
2845
testMatch: "demos/**/*.test.ts",
46+
use: chromeCanary,
2947
},
3048
// Firefox projects — use native getBoxQuads (no polyfill needed)
3149
{
3250
name: "firefox-unit",
3351
testMatch: "unit/**/*.test.ts",
34-
use: {
35-
browserName: "firefox",
36-
launchOptions: {
37-
firefoxUserPrefs: {
38-
"layout.css.getBoxQuads.enabled": true,
39-
},
40-
},
41-
},
52+
use: firefox,
4253
},
4354
{
4455
name: "firefox-integration",
4556
testMatch: "integration/**/*.test.ts",
46-
use: {
47-
browserName: "firefox",
48-
launchOptions: {
49-
firefoxUserPrefs: {
50-
"layout.css.getBoxQuads.enabled": true,
51-
},
52-
},
53-
},
57+
use: firefox,
5458
},
5559
{
5660
name: "firefox-ui",
5761
testMatch: "ui/**/*.test.ts",
58-
use: {
59-
browserName: "firefox",
60-
launchOptions: {
61-
firefoxUserPrefs: {
62-
"layout.css.getBoxQuads.enabled": true,
63-
},
64-
},
65-
},
62+
use: firefox,
6663
},
6764
{
6865
name: "firefox-demos",
6966
testMatch: "demos/**/*.test.ts",
70-
use: {
71-
browserName: "firefox",
72-
launchOptions: {
73-
firefoxUserPrefs: {
74-
"layout.css.getBoxQuads.enabled": true,
75-
},
76-
},
77-
},
67+
use: firefox,
7868
},
7969
],
8070
});

tests/demos/demo-conversion.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,24 @@ export function ensureDirectory(dirPath: string): void {
7171
}
7272
}
7373

74+
function writeBinaryFile(filePath: string, data: Uint8Array): void {
75+
let lastError: unknown;
76+
for (let attempt = 0; attempt < 10; attempt++) {
77+
try {
78+
fs.writeFileSync(filePath, data);
79+
return;
80+
} catch (error) {
81+
lastError = error;
82+
// Windows scanners and preview handlers can briefly retain generated
83+
// binaries after a previous test has read them.
84+
if ((error as NodeJS.ErrnoException).code !== "UNKNOWN") throw error;
85+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 50);
86+
}
87+
}
88+
89+
throw lastError;
90+
}
91+
7492
ensureDirectory(outputRootDir);
7593

7694
export function getProjectOutputDir(browserName: string): string {
@@ -754,28 +772,28 @@ export async function convertPageToAllWriters(options: ConvertPageToAllWritersOp
754772
expect(emfBytes).toBeInstanceOf(Uint8Array);
755773
expect(emfBytes.length).toBeGreaterThan(80);
756774
const emfPath = path.join(outputDir, `${name}.emf`);
757-
fs.writeFileSync(emfPath, emfBytes);
775+
writeBinaryFile(emfPath, emfBytes);
758776

759777
const emfPlusWriter = new EMFPlusWriter({ width: viewport.width, height: viewport.height });
760778
const emfPlusBytes = await renderIR(fontFallbackIr, emfPlusWriter);
761779
expect(emfPlusBytes).toBeInstanceOf(Uint8Array);
762780
expect(emfPlusBytes.length).toBeGreaterThan(80);
763781
const emfPlusPath = path.join(outputDir, `${name}-emfplus.emf`);
764-
fs.writeFileSync(emfPlusPath, emfPlusBytes);
782+
writeBinaryFile(emfPlusPath, emfPlusBytes);
765783

766784
const dwgWriter = new DWGWriter({ maxY: viewport.height });
767785
const dwgBytes = await renderIR(fontFallbackIr, dwgWriter);
768786
expect(dwgBytes).toBeInstanceOf(Uint8Array);
769787
expect(dwgBytes.length).toBeGreaterThan(100);
770788
const dwgPath = path.join(outputDir, `${name}.dwg`);
771-
fs.writeFileSync(dwgPath, dwgBytes);
789+
writeBinaryFile(dwgPath, dwgBytes);
772790

773791
const acadDxfWriter = new AcadDXFWriter({ maxY: viewport.height });
774792
const acadDxfBytes = await renderIR(fontFallbackIr, acadDxfWriter);
775793
expect(acadDxfBytes).toBeInstanceOf(Uint8Array);
776794
expect(acadDxfBytes.length).toBeGreaterThan(100);
777795
const acadDxfPath = path.join(outputDir, `${name}-acad.dxf`);
778-
fs.writeFileSync(acadDxfPath, acadDxfBytes);
796+
writeBinaryFile(acadDxfPath, acadDxfBytes);
779797

780798
const dxfSize = fs.statSync(dxfPath).size;
781799
const pdfSize = fs.statSync(pdfPath).size;
@@ -813,4 +831,4 @@ export async function convertPageToAllWriters(options: ConvertPageToAllWritersOp
813831
png: pngError,
814832
},
815833
};
816-
}
834+
}

tests/demos/video.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ <h1>First-frame video export</h1>
162162

163163
drawFrame(ctx, "FRAME 1", "#eb3b5a", "#fed330");
164164

165-
const stream = canvas.captureStream(8);
165+
const stream = canvas.captureStream(30);
166166
const recorder = new MediaRecorder(stream, {
167167
mimeType,
168168
videoBitsPerSecond: 300000,
@@ -181,9 +181,9 @@ <h1>First-frame video export</h1>
181181
});
182182

183183
recorder.start();
184-
await delay(180);
184+
await delay(500);
185185
drawFrame(ctx, "FRAME 2", "#2d98da", "#20bf6b");
186-
await delay(180);
186+
await delay(500);
187187
recorder.stop();
188188
await stopped;
189189
stream.getTracks().forEach((track) => track.stop());
@@ -247,4 +247,4 @@ <h1>First-frame video export</h1>
247247
})();
248248
</script>
249249
</body>
250-
</html>
250+
</html>

tests/helpers.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,13 @@ export async function injectLibrary(page: Page): Promise<void> {
127127
* ONLY used in tests — never bundled in production.
128128
*/
129129
export async function injectBoxQuadsPolyfill(page: Page): Promise<void> {
130-
// Firefox has native getBoxQuads — skip the polyfill
131-
const browserName = page.context().browser()?.browserType().name();
132-
if (browserName === "firefox") return;
130+
// Preserve native implementations (Firefox and Chrome Canary with
131+
// Experimental Web Platform Features enabled).
132+
const hasNativeBoxQuads = await page.evaluate(() =>
133+
typeof Element.prototype.getBoxQuads === "function"
134+
&& typeof Text.prototype.getBoxQuads === "function"
135+
);
136+
if (hasNativeBoxQuads) return;
133137

134138
// Read the polyfill source from node_modules
135139
const polyfillPath = path.resolve(

0 commit comments

Comments
 (0)