diff --git a/docs/assets/browser-starter/project.zip b/docs/assets/browser-starter/project.zip index 20d099c..45d32cf 100644 Binary files a/docs/assets/browser-starter/project.zip and b/docs/assets/browser-starter/project.zip differ diff --git a/docs/assets/browser-starter/source.json b/docs/assets/browser-starter/source.json index ba6cf8c..59fb3b3 100644 --- a/docs/assets/browser-starter/source.json +++ b/docs/assets/browser-starter/source.json @@ -1,19 +1,19 @@ { "source_repository": "https://github.com/fullbleed-engine/fullbleed-node", - "source_commit": "7da8faa0dd7e5653c796b2b113ca580bcc25ca3b", + "source_commit": "ae6e301ebc129a15aab89378f44beb81d63d4475", "source_directory": "examples/browser", - "package_version": "0.3.1", - "engine_version": "2.5.10", - "package_integrity": "sha512-95CVTnYKduXD5KcEj9MLfzPsqofahZB2BsJ62Dfg0tOTlPFEHT8vx/T3f8xp4VQYkihOPQdMDiWQzYNHJkLpWA==", - "zip_bytes": 23705, - "zip_sha256": "fec06c1ca935ea71abcf10f7044a5df0e49ff3ffe3e4d77f0bee66969d256ae9", + "package_version": "0.3.2", + "engine_version": "2.5.11", + "package_integrity": "sha512-bzbTUn6Hcxu0YZoP38wkrJ/nZ33+rQfZq5itdpQUl7lIO9mR1m9LC5n/2KLxjj+7dAb8IhpYoVTSmbuhQyA5Vg==", + "zip_bytes": 23698, + "zip_sha256": "4989b21ca73687aa02611437a17c60e567f537e1a127582ffc10362dff8c32bf", "files": { "fullbleed-browser-starter/.gitignore": "c023fec2bf12476cb47709e859f1fbb785aeb1e03281e52141e0bee1ee7dad72", "fullbleed-browser-starter/LICENSE": "36a2115938f6e68cf0d87eccff7a6a3e57c17017e909cbd640d51aff1fa0c5a9", - "fullbleed-browser-starter/README.md": "886bb0ea403780834262b4432a4b866671098fb1f7074524007bc37dccab4a1d", + "fullbleed-browser-starter/README.md": "6b5bec007619b8d1776dc668b4f16d2204e4ad9f92dd9b7e38352e534f1bcd13", "fullbleed-browser-starter/index.html": "79baecb0b24716e78799893fc0076d88b2c026354f9f31acdf799c8f305c954b", - "fullbleed-browser-starter/package-lock.json": "16e4f019872bd1cd5f2a743769f3ec958f9aa78901b6f2f3fd2816e613369346", - "fullbleed-browser-starter/package.json": "36df50538f36f3dc9086e03d0777183c5b2bce508801f0d7c00ef21e23806f6d", + "fullbleed-browser-starter/package-lock.json": "b1f81db73d867f963443fbc2415f352297ee4d9c962f0ba601d9cdc3457e4bd5", + "fullbleed-browser-starter/package.json": "6dbc4b39b8daa889493125b5d1c091941dd8f994a26274153ffc4298e532cd18", "fullbleed-browser-starter/public/favicon.svg": "3eed6dcf1013e48bc64886fed4cf815c609ed06b404742bdacdc44c1df8d3118", "fullbleed-browser-starter/src/invoice.css": "0b310ce0f2964fd6b9b68e4afafa9307b4ff8c6b2f1fc753367dc755620ce427", "fullbleed-browser-starter/src/invoice.html": "1f065ad6694021649e61b3f666cba6dc01aacdcbd8e80e97425b383e60d7d2fe", @@ -23,6 +23,6 @@ "fullbleed-browser-starter/src/style.css": "5005045f66a84a038a0f7a0f7e15b8b5e9eac2489f9717d4a581fec5075bf6f4", "fullbleed-browser-starter/vite.config.js": "ec725922705a3c5ba2df191a564c54c0cac6e8997ecd3d00b8a42c647bec8e74" }, - "local_ui_evidence": "https://github.com/fullbleed-engine/fullbleed-node/blob/7da8faa0dd7e5653c796b2b113ca580bcc25ca3b/verification/starters-031.json", - "source_verification_run": "https://github.com/fullbleed-engine/fullbleed-node/actions/runs/37465413013" + "local_ui_evidence": "https://github.com/fullbleed-engine/fullbleed-node/blob/ae6e301ebc129a15aab89378f44beb81d63d4475/verification/starters-032.json", + "source_verification_run": "https://github.com/fullbleed-engine/fullbleed-node/actions/runs/37569111713" } diff --git a/docs/assets/nextjs/project.zip b/docs/assets/nextjs/project.zip index 5eee59f..b1a54e5 100644 Binary files a/docs/assets/nextjs/project.zip and b/docs/assets/nextjs/project.zip differ diff --git a/docs/assets/nextjs/source.json b/docs/assets/nextjs/source.json index ff6a8c4..7e6b055 100644 --- a/docs/assets/nextjs/source.json +++ b/docs/assets/nextjs/source.json @@ -1,12 +1,12 @@ { "sourceRepository": "https://github.com/fullbleed-engine/fullbleed-node", - "sourceCommit": "7da8faa0dd7e5653c796b2b113ca580bcc25ca3b", + "sourceCommit": "ae6e301ebc129a15aab89378f44beb81d63d4475", "files": 18, "assets": [ { "file": "project.zip", - "sha256": "06d1383ed8a40ab2853e7f9a51a9a7baddb7981b7c02fc0d3772587c8823553f", - "bytes": 104788 + "sha256": "6a4a589bc0153c0ca006a571e576ba8681dac5ae8fa683fc33e2f336322df6d6", + "bytes": 104790 }, { "file": "invoice.pdf", @@ -22,15 +22,15 @@ "fileHashes": { "fullbleed-nextjs/.gitignore": "b4abc38d76926640e3f2cbe3bf25c8f5aec6cc43dd978c48d3ad5cc20d964f66", "fullbleed-nextjs/LICENSE": "36a2115938f6e68cf0d87eccff7a6a3e57c17017e909cbd640d51aff1fa0c5a9", - "fullbleed-nextjs/README.md": "0b47cb42317df65f497447bb1084c888194886f82e5223960ed2ecaa55b22273", + "fullbleed-nextjs/README.md": "96de8ae1580d61c0c34274c3fafe70a81338aa2bd927d22900874c367ae9158c", "fullbleed-nextjs/app/api/invoices/[id]/route.js": "d6348ce64b44feac7010e21fb0f55723e0858c7867222ae831c45d3440a3b052", "fullbleed-nextjs/app/globals.css": "02e0b545a14eaf15e6d3d8fc8c0e8c0f1c5ce5c1b8dc461b4343d330f291233e", "fullbleed-nextjs/app/layout.js": "2df89bff0d2f002b432b3fdb73fd64edf59c57641d9ea6df3f0051cf2329cf27", "fullbleed-nextjs/app/page.js": "24c7996f8172992f925cdb1e47455d0095397d0832f747c90ecb409f2a1d460c", "fullbleed-nextjs/lib/invoice.mjs": "fd87dd082fa19659ec572d97255c1902e1e728e43ebbc3e0ade9891fa7736cf2", "fullbleed-nextjs/next.config.mjs": "e93613419f5aaa6264f0405e5afbb6f5eea4c956e42e7ebf30a6c85a4d9d89b3", - "fullbleed-nextjs/package-lock.json": "57dfea0b9c49f604477b28c88847764bda16c006383df852269bdd2b712daf43", - "fullbleed-nextjs/package.json": "7e52578d679fa9422b15cf5a69fa065d7b6c68d076362ddfc4e885134dfd5766", + "fullbleed-nextjs/package-lock.json": "f5d9b10c7546f8df1c08b0cdb489647289f91b1c89d065c3f1a133478d5fcfbf", + "fullbleed-nextjs/package.json": "e31ff035bd4d340ca73a5ee95319ee85ec4ae1d3651a6193bf2a6f0174a39e9c", "fullbleed-nextjs/public/invoice.png": "72420749ccc3deaa8025daf7baffcdf79be716b6e8e93ed605effebed01e86c7", "fullbleed-nextjs/templates/invoice.css": "cda22b39ab1f7a1eeac7cd76d162b05cd3568c2430c099123ba30a2fbd58a296", "fullbleed-nextjs/templates/invoice.html": "d9a5b1950ddab61f08628b0fcc773cb36f05d9401bb3d87273bca02452b1835e", @@ -39,7 +39,7 @@ "fullbleed-nextjs/tools/start.mjs": "4c185a0801ca4f89a30a0c1e75710f1c22c84463d29477900162b05a8bc52eab", "fullbleed-nextjs/tools/verify.mjs": "54623914ff28a47ea63a553d063ac50a206df0424270dacb3f3a99054982a888" }, - "packageVersion": "0.3.1", - "engineVersion": "2.5.10", - "sourceVerificationRun": "https://github.com/fullbleed-engine/fullbleed-node/actions/runs/37465413382" + "packageVersion": "0.3.2", + "engineVersion": "2.5.11", + "sourceVerificationRun": "https://github.com/fullbleed-engine/fullbleed-node/actions/runs/37569111697" } diff --git a/docs/assets/nextjs/verification.json b/docs/assets/nextjs/verification.json index 0b43859..55146cb 100644 --- a/docs/assets/nextjs/verification.json +++ b/docs/assets/nextjs/verification.json @@ -1,8 +1,8 @@ { "ok": true, - "checkedAt": "2026-10-06T12:49:16.905884+00:00", - "sourceCommit": "7da8faa0dd7e5653c796b2b113ca580bcc25ca3b", - "sourceRun": "https://github.com/fullbleed-engine/fullbleed-node/actions/runs/37465413382", + "checkedAt": "2026-10-07T04:06:45.541502+00:00", + "sourceCommit": "ae6e301ebc129a15aab89378f44beb81d63d4475", + "sourceRun": "https://github.com/fullbleed-engine/fullbleed-node/actions/runs/37569111697", "checks": [ { "name": "standalone artifact is isolated from the source application", @@ -75,14 +75,14 @@ ], "ciResults": [ { - "checkedAt": "2026-10-06T12:44:31.828Z", + "checkedAt": "2026-10-07T03:57:17.033Z", "node": "v22.23.3", "platform": "linux", "next": "16.3.8", - "nodePackage": "0.3.1", - "engineVersion": "2.5.10", + "nodePackage": "0.3.2", + "engineVersion": "2.5.11", "isolation": "process", - "packageLockSha256": "57dfea0b9c49f604477b28c88847764bda16c006383df852269bdd2b712daf43", + "packageLockSha256": "f5d9b10c7546f8df1c08b0cdb489647289f91b1c89d065c3f1a133478d5fcfbf", "pages": 1, "pdfSha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408", "burst": [ @@ -105,14 +105,14 @@ "previewSha256": "72420749ccc3deaa8025daf7baffcdf79be716b6e8e93ed605effebed01e86c7" }, { - "checkedAt": "2026-10-06T12:44:44.228Z", + "checkedAt": "2026-10-07T03:57:25.042Z", "node": "v24.21.0", "platform": "linux", "next": "16.3.8", - "nodePackage": "0.3.1", - "engineVersion": "2.5.10", + "nodePackage": "0.3.2", + "engineVersion": "2.5.11", "isolation": "process", - "packageLockSha256": "57dfea0b9c49f604477b28c88847764bda16c006383df852269bdd2b712daf43", + "packageLockSha256": "f5d9b10c7546f8df1c08b0cdb489647289f91b1c89d065c3f1a133478d5fcfbf", "pages": 1, "pdfSha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408", "burst": [ @@ -135,14 +135,14 @@ "previewSha256": "72420749ccc3deaa8025daf7baffcdf79be716b6e8e93ed605effebed01e86c7" }, { - "checkedAt": "2026-10-06T12:44:58.768Z", + "checkedAt": "2026-10-07T03:57:52.511Z", "node": "v24.21.0", "platform": "win32", "next": "16.3.8", - "nodePackage": "0.3.1", - "engineVersion": "2.5.10", + "nodePackage": "0.3.2", + "engineVersion": "2.5.11", "isolation": "process", - "packageLockSha256": "57dfea0b9c49f604477b28c88847764bda16c006383df852269bdd2b712daf43", + "packageLockSha256": "f5d9b10c7546f8df1c08b0cdb489647289f91b1c89d065c3f1a133478d5fcfbf", "pages": 1, "pdfSha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408", "burst": [ @@ -167,15 +167,15 @@ ], "downloadedStarter": { "ok": true, - "checkedAt": "2026-10-06T12:46:56.297591+00:00", - "sourceCommit": "7da8faa0dd7e5653c796b2b113ca580bcc25ca3b", + "checkedAt": "2026-10-07T04:02:35.480164+00:00", + "sourceCommit": "ae6e301ebc129a15aab89378f44beb81d63d4475", "downloadFiles": 18, - "projectZipSha256": "06d1383ed8a40ab2853e7f9a51a9a7baddb7981b7c02fc0d3772587c8823553f", - "node": "v26.10.0", + "projectZipSha256": "6a4a589bc0153c0ca006a571e576ba8681dac5ae8fa683fc33e2f336322df6d6", + "node": "v22.23.3", "platform": "win32", "next": "16.3.8", - "nodePackage": "0.3.1", - "engineVersion": "2.5.10", + "nodePackage": "0.3.2", + "engineVersion": "2.5.11", "isolation": "process", "commands": [ { @@ -271,29 +271,37 @@ }, "browser": { "ok": true, - "checked_at": "2026-10-06T12:42:59.420658+00:00", + "checkedAt": "2026-10-07T04:04:43.258437+00:00", "browser": "154.0.8037.98", - "checks": [ + "packageVersion": "0.3.2", + "engineVersion": "2.5.11", + "records": [ { "width": 1440, + "download": "invoice-NS-1042.pdf", + "pdfSha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408", "keyboard": false, - "pdf_sha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408", - "page_errors": [] + "horizontalOverflow": false, + "previewLoaded": true }, { "width": 390, - "keyboard": true, - "pdf_sha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408", - "page_errors": [] + "download": "invoice-NS-1042.pdf", + "pdfSha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408", + "keyboard": false, + "horizontalOverflow": false, + "previewLoaded": true }, { "width": 320, - "keyboard": false, - "pdf_sha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408", - "page_errors": [] + "download": "invoice-NS-1042.pdf", + "pdfSha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408", + "keyboard": true, + "horizontalOverflow": false, + "previewLoaded": true } ], - "scope": "Owned anonymous Chrome; production Next.js standalone server; real downloads and responsive layouts." + "pageErrors": [] }, - "scope": "Published npm 0.3.1 / core 2.5.10. Three CI environments and the exact downloadable ZIP pass 17 standalone HTTP checks; their PDFs and previews match. Owned Chrome checks real downloads and narrow layouts. No application authorization, hosting-provider, or standards conformance claim." + "scope": "Public npm 0.3.2; exact starter ZIP; retained isolated-server and real browser download checks. No application-authorization, hosted-capacity, or PDF standards claim." } diff --git a/docs/assets/react-starter/baseline/verification.json b/docs/assets/react-starter/baseline/verification.json index 9d012ea..76bbfde 100644 --- a/docs/assets/react-starter/baseline/verification.json +++ b/docs/assets/react-starter/baseline/verification.json @@ -1,7 +1,7 @@ { - "package": "0.3.1", - "engine": "2.5.10", - "node": "v26.10.0", + "package": "0.3.2", + "engine": "2.5.11", + "node": "v22.23.3", "records": [ { "design": "invoice", diff --git a/docs/assets/react-starter/project.zip b/docs/assets/react-starter/project.zip index a8bf391..2c30e39 100644 Binary files a/docs/assets/react-starter/project.zip and b/docs/assets/react-starter/project.zip differ diff --git a/docs/assets/react-starter/source.json b/docs/assets/react-starter/source.json index cd59a32..57c7fcf 100644 --- a/docs/assets/react-starter/source.json +++ b/docs/assets/react-starter/source.json @@ -1,20 +1,20 @@ { "source_repository": "https://github.com/fullbleed-engine/fullbleed-node", - "source_commit": "7da8faa0dd7e5653c796b2b113ca580bcc25ca3b", + "source_commit": "ae6e301ebc129a15aab89378f44beb81d63d4475", "source_directory": "examples/react", - "package_version": "0.3.1", - "engine_version": "2.5.10", + "package_version": "0.3.2", + "engine_version": "2.5.11", "react_version": "19.3.0", - "package_integrity": "sha512-95CVTnYKduXD5KcEj9MLfzPsqofahZB2BsJ62Dfg0tOTlPFEHT8vx/T3f8xp4VQYkihOPQdMDiWQzYNHJkLpWA==", - "zip_bytes": 29617, - "zip_sha256": "cdb07cbe2fd6a744eb5d49971813f7ab5297f25b31292a35a3f76994492e8264", + "package_integrity": "sha512-bzbTUn6Hcxu0YZoP38wkrJ/nZ33+rQfZq5itdpQUl7lIO9mR1m9LC5n/2KLxjj+7dAb8IhpYoVTSmbuhQyA5Vg==", + "zip_bytes": 29613, + "zip_sha256": "f8c7759e4d321e0c7bc9faab41da345ee9f9638d15e718e8a762c58a3b59d56d", "files": { "fullbleed-react-starter/.gitignore": "25d896ffa2be7ed008ad87c3956a0a88f54167d04a7cef5cf774d6989d3b5a7b", "fullbleed-react-starter/LICENSE": "36a2115938f6e68cf0d87eccff7a6a3e57c17017e909cbd640d51aff1fa0c5a9", - "fullbleed-react-starter/README.md": "098a1ce15c586d7b3d3a5a459ac107230a2cbae3422f55916040a79a027e009f", + "fullbleed-react-starter/README.md": "9b20e8bd9a23d22e4733012b94cc8ab645fa08cb70327aa2ab1027e0b85a4081", "fullbleed-react-starter/index.html": "cadf48a3476088b2efbe9012bb4b2d21fa24f1dd3e99f974f444c88fbf1ee165", - "fullbleed-react-starter/package-lock.json": "e38b0d8775b14bc62ad99cb4b5f518fbf5c797ab208e5cf184d5e4c39a0f0e72", - "fullbleed-react-starter/package.json": "14cb9c05cccdc589f09f8281fdd7b92345aba5e15e0ffbbfa93230deef94861f", + "fullbleed-react-starter/package-lock.json": "c28b7d70a675e27cfcf0c68c06ca1ecc7f640f43f35261f20274f02e48947ce3", + "fullbleed-react-starter/package.json": "ef11b5673e83c8c9222b7b7b6f2ea7c9ca7f0c99e809eb675d7c08cc6173dd14", "fullbleed-react-starter/public/favicon.svg": "3eed6dcf1013e48bc64886fed4cf815c609ed06b404742bdacdc44c1df8d3118", "fullbleed-react-starter/src/App.tsx": "5dbcd45d570a3e4d69f12237d252e30afe71f52cb8411c3ffe094dc72f559b9f", "fullbleed-react-starter/src/invoice.css": "0b310ce0f2964fd6b9b68e4afafa9307b4ff8c6b2f1fc753367dc755620ce427", @@ -28,6 +28,6 @@ "fullbleed-react-starter/vite.config.js": "4b74d0189e7f58a4c75d168367e9b8a53000555dd3de594c497f70fb5e02fff0" }, "verification_workflow": "https://github.com/fullbleed-engine/fullbleed-node/actions/workflows/react-starter.yml", - "source_verification_run": "https://github.com/fullbleed-engine/fullbleed-node/actions/runs/37465413017", - "local_ui_evidence": "https://github.com/fullbleed-engine/fullbleed-node/blob/7da8faa0dd7e5653c796b2b113ca580bcc25ca3b/verification/starters-031.json" + "source_verification_run": "https://github.com/fullbleed-engine/fullbleed-node/actions/runs/37569111695", + "local_ui_evidence": "https://github.com/fullbleed-engine/fullbleed-node/blob/ae6e301ebc129a15aab89378f44beb81d63d4475/verification/starters-032.json" } diff --git a/docs/assets/vue-starter/baseline/verification.json b/docs/assets/vue-starter/baseline/verification.json index 9d012ea..76bbfde 100644 --- a/docs/assets/vue-starter/baseline/verification.json +++ b/docs/assets/vue-starter/baseline/verification.json @@ -1,7 +1,7 @@ { - "package": "0.3.1", - "engine": "2.5.10", - "node": "v26.10.0", + "package": "0.3.2", + "engine": "2.5.11", + "node": "v22.23.3", "records": [ { "design": "invoice", diff --git a/docs/assets/vue-starter/project.zip b/docs/assets/vue-starter/project.zip index 00571c8..9a07610 100644 Binary files a/docs/assets/vue-starter/project.zip and b/docs/assets/vue-starter/project.zip differ diff --git a/docs/assets/vue-starter/source.json b/docs/assets/vue-starter/source.json index 6bc1062..d5e8261 100644 --- a/docs/assets/vue-starter/source.json +++ b/docs/assets/vue-starter/source.json @@ -1,20 +1,20 @@ { "source_repository": "https://github.com/fullbleed-engine/fullbleed-node", - "source_commit": "3e60340b2cb1a4275828ef717a886a93b93c9cc7", + "source_commit": "ae6e301ebc129a15aab89378f44beb81d63d4475", "source_directory": "examples/vue", - "package_version": "0.3.1", - "engine_version": "2.5.10", + "package_version": "0.3.2", + "engine_version": "2.5.11", "vue_version": "3.5.43", - "package_integrity": "sha512-95CVTnYKduXD5KcEj9MLfzPsqofahZB2BsJ62Dfg0tOTlPFEHT8vx/T3f8xp4VQYkihOPQdMDiWQzYNHJkLpWA==", - "zip_bytes": 30301, - "zip_sha256": "0de1074aaed21af1843069e6f811335fe67e638f44b16f8aa27185b50c93bb2b", + "package_integrity": "sha512-bzbTUn6Hcxu0YZoP38wkrJ/nZ33+rQfZq5itdpQUl7lIO9mR1m9LC5n/2KLxjj+7dAb8IhpYoVTSmbuhQyA5Vg==", + "zip_bytes": 30293, + "zip_sha256": "8fd2f6beacc82e1b4baacad6713c8c69b3bc8a035c8e3fc42477a4e41b61d1b6", "files": { "fullbleed-vue-starter/.gitignore": "c023fec2bf12476cb47709e859f1fbb785aeb1e03281e52141e0bee1ee7dad72", "fullbleed-vue-starter/LICENSE": "36a2115938f6e68cf0d87eccff7a6a3e57c17017e909cbd640d51aff1fa0c5a9", - "fullbleed-vue-starter/README.md": "92379177e243f455359ef3f3ddc385701474d859bf23ceabd5d472f4444964c7", + "fullbleed-vue-starter/README.md": "b157b91e6a93417c279b565f2b5ecb96c8299c3e0524b7531704348ba0bbe4e8", "fullbleed-vue-starter/index.html": "30d46eb1b5147bd3d9c580e7adaed5b5202f9b97ab598e189efda7c3d2d405be", - "fullbleed-vue-starter/package-lock.json": "75ce815032cacd7596af9435d1003680967e570fcbc32a398cb041a360febbbc", - "fullbleed-vue-starter/package.json": "470894ba1eb0e0676bc3a38b5fa69aa5cdac752f3c22110d70d54d20e9c97027", + "fullbleed-vue-starter/package-lock.json": "72269d20bb6fabb34779eac61bea9d2b9eaadf5afff09e5e968053c2418fe3c4", + "fullbleed-vue-starter/package.json": "262a2d42ec0067ff76d4c80398b01de7c2fc84c455f66fd7bb62517b30669c90", "fullbleed-vue-starter/public/favicon.svg": "3eed6dcf1013e48bc64886fed4cf815c609ed06b404742bdacdc44c1df8d3118", "fullbleed-vue-starter/src/App.vue": "0afa15196ccedd0b0f91293cc5e362799149a2752c59deaa377f4533825ea2af", "fullbleed-vue-starter/src/DocumentEditor.vue": "a3f3f8096d194e1eed6cd0cf2fb0a0606a04d40823ff7b794b9b1a0dbfd8c28a", @@ -29,5 +29,6 @@ "fullbleed-vue-starter/vite.config.js": "dfcc6c065fb26ada03802def672108735f4c2c35e0f30d11965ddfa796b8a0c0" }, "verification_workflow": "https://github.com/fullbleed-engine/fullbleed-node/actions/workflows/vue-starter.yml", - "local_ui_evidence": "https://github.com/fullbleed-engine/fullbleed-node/blob/3e60340b2cb1a4275828ef717a886a93b93c9cc7/verification/vue-starter.json" + "local_ui_evidence": "https://github.com/fullbleed-engine/fullbleed-node/blob/ae6e301ebc129a15aab89378f44beb81d63d4475/verification/starters-032.json", + "source_verification_run": "https://github.com/fullbleed-engine/fullbleed-node/actions/runs/37569111733" } diff --git a/docs/guides/browser-pdf.md b/docs/guides/browser-pdf.md index 471ee5d..47aedcb 100644 --- a/docs/guides/browser-pdf.md +++ b/docs/guides/browser-pdf.md @@ -18,11 +18,11 @@ Change the customer, reference, and ink color, or open **Edit the HTML & CSS** t paste your own template. Generate a preview, then download the actual PDF. All sample names, organizations, and amounts are fictional. -The downloadable starter uses **npm package 0.3.1**, wrapping **Fullbleed engine 2.5.10**. +The downloadable starter uses **npm package 0.3.2**, wrapping **Fullbleed engine 2.5.11**. The browser and Node entries share the pinned engine and bundled fonts. -For an existing application, **npm package 0.3.2** adds engine **2.5.11** and -fixes blank PNG previews for unembedded Helvetica, Times, and Courier faces. +This version fixes blank PNG previews for unembedded Helvetica, Times, and +Courier faces, including templates pasted into the starter. The [font-preview guide](https://github.com/fullbleed-engine/fullbleed-node/blob/v0.3.2/docs/standard-font-previews.md) explains the substitute designs and upgrade checks. Run the asset-copy command again after upgrading so the browser receives the matching runtime and notices. @@ -131,7 +131,7 @@ completion or cancellation requests worker termination before the promise settle Browsers do not expose a native thread-exit promise. Keep concurrent jobs bounded for the devices you support, especially when generating page previews. -The [0.3.1 release evidence](https://github.com/fullbleed-engine/fullbleed-node/releases/tag/v0.3.1) +The [0.3.2 release evidence](https://github.com/fullbleed-engine/fullbleed-node/releases/tag/v0.3.2) retains checks in Chrome, Firefox, and Playwright WebKit, including PDF/PNG comparison with the installed Node package, independent PDF text checks, cancellation, damaged assets, and recovery. Playwright WebKit is not branded diff --git a/docs/guides/nextjs-pdf.md b/docs/guides/nextjs-pdf.md index 4cedfd9..d7a2a83 100644 --- a/docs/guides/nextjs-pdf.md +++ b/docs/guides/nextjs-pdf.md @@ -34,8 +34,8 @@ Open `http://127.0.0.1:3000` and select **Download sample PDF**. The route `/api/invoices/NS-1042` returns the invoice as an attachment. The browser stays on the starter page. Use `npm run dev` while editing the app. -The lockfile pins Next.js 16.3.8, React 19.3.0 and Fullbleed Node 0.3.1, powered -by engine 2.5.10. Fullbleed is installed from npm. The registry tarball is +The lockfile pins Next.js 16.3.8, React 19.3.0 and Fullbleed Node 0.3.2, powered +by engine 2.5.11. Fullbleed is installed from npm. The registry tarball is byte-identical to the verified GitHub release. For an existing Node application, start with the [Node.js quickstart](../getting-started/node.md). diff --git a/docs/guides/react-pdf.md b/docs/guides/react-pdf.md index 7fe97ce..2f5575a 100644 --- a/docs/guides/react-pdf.md +++ b/docs/guides/react-pdf.md @@ -48,7 +48,7 @@ color and wait for **Ready**. **Download PDF** saves the generated document. Turn off **Update automatically** to generate only when you choose **Generate PDF**. **Cancel** stops a pending preview or active render. -The lockfile pins Fullbleed npm **0.3.1** / engine **2.5.10**, React **19.3.0**, +The lockfile pins Fullbleed npm **0.3.2** / engine **2.5.11**, React **19.3.0**, TypeScript **7.0.2**, and Vite **8.3.2**. The ZIP includes its source and lockfile; the build downloads the published dependencies and copies their verified runtime. @@ -79,7 +79,7 @@ through the SDK's `fonts` and `assets` options. Install the package and copy its runtime into your app's static directory: ```sh -npm install --save-exact fullbleed@0.3.1 +npm install --save-exact fullbleed@0.3.2 npx fullbleed-browser-assets public/fullbleed ``` @@ -146,6 +146,8 @@ independently checks their text and page sizes, and compares the default invoice and report bytes with the installed Node package. It also checks automatic and on-demand modes, fast edits, cancellation, recovery, unmount/remount, URL cleanup, and 1440/390/320px layouts. The docs build installs and checks the exact ZIP. +An edited-template check verifies unembedded Helvetica faces in the PDF and +visible text in its browser preview. These fixtures do not establish compatibility with every browser, device, or hosting policy. WebKit testing is not branded Safari certification. Worker diff --git a/docs/guides/vue-pdf.md b/docs/guides/vue-pdf.md index ec0cccb..38aa05d 100644 --- a/docs/guides/vue-pdf.md +++ b/docs/guides/vue-pdf.md @@ -47,7 +47,7 @@ color and wait for **Ready**, then choose **Download PDF**. Turn off **Update automatically** to generate on demand. **Cancel** stops a pending preview or active render. **Close editor** releases its resources; reopening starts fresh. -The lockfile pins Fullbleed npm **0.3.1** / engine **2.5.10**, Vue **3.5.43**, +The lockfile pins Fullbleed npm **0.3.2** / engine **2.5.11**, Vue **3.5.43**, TypeScript **6.0.3**, and Vite **8.3.2**. The build downloads the published dependencies and copies their verified runtime. TypeScript 6 is pinned for compatibility with the project's `vue-tsc` type checker. @@ -82,7 +82,7 @@ through the SDK's `fonts` and `assets` options. Install the package and copy its runtime into your static directory: ```sh -npm install --save-exact fullbleed@0.3.1 +npm install --save-exact fullbleed@0.3.2 npx fullbleed-browser-assets public/fullbleed ``` @@ -158,6 +158,8 @@ compares default PDF and preview bytes with the installed Node package. It exercises fast edits, both preview modes, cancellation, runtime-outage recovery, template editing, unmount/remount, URL cleanup, and 1440/390/320px layouts. The docs build installs and checks the exact downloadable ZIP. +An edited-template check verifies unembedded Helvetica faces in the PDF and +visible text in its browser preview. These fixtures do not establish compatibility with every device or hosting policy. WebKit testing is not branded Safari certification. Worker counts diff --git a/tools/build_browser_starter.py b/tools/build_browser_starter.py index 9567757..20172ac 100644 --- a/tools/build_browser_starter.py +++ b/tools/build_browser_starter.py @@ -49,7 +49,7 @@ project = workspace / 'fullbleed-browser-starter' package = json.loads((project / 'package.json').read_text()) lock = json.loads((project / 'package-lock.json').read_text()) -assert package['dependencies']['fullbleed'] == manifest['package_version'] == '0.3.1' +assert package['dependencies']['fullbleed'] == manifest['package_version'] == '0.3.2' assert package['devDependencies']['vite'] == '8.3.2' assert lock['packages']['node_modules/fullbleed']['integrity'] == manifest['package_integrity'] assert lock['packages']['node_modules/fullbleed']['resolved'].startswith('https://registry.npmjs.org/') @@ -64,7 +64,7 @@ installed = project / 'node_modules/fullbleed' assert json.loads((installed / 'package.json').read_text())['version'] == manifest['package_version'] runtime = json.loads((project / 'dist/fullbleed/build.json').read_text()) -assert runtime['packageVersion'] == manifest['package_version'] and runtime['engineVersion'] == '2.5.10' +assert runtime['packageVersion'] == manifest['package_version'] and runtime['engineVersion'] == '2.5.11' for name, expected in runtime['files'].items(): value = (project / 'dist/fullbleed' / name).read_bytes() assert len(value) == expected['bytes'] and digest(value) == expected['sha256'] diff --git a/tools/build_react_starter.py b/tools/build_react_starter.py index 4c8d90a..0a3f669 100644 --- a/tools/build_react_starter.py +++ b/tools/build_react_starter.py @@ -49,7 +49,7 @@ project = workspace / 'fullbleed-react-starter' package = json.loads((project / 'package.json').read_text()) lock = json.loads((project / 'package-lock.json').read_text()) -assert package['dependencies']['fullbleed'] == manifest['package_version'] == '0.3.1' +assert package['dependencies']['fullbleed'] == manifest['package_version'] == '0.3.2' assert package['devDependencies']['vite'] == '8.3.2' assert package['dependencies']['react'] == package['dependencies']['react-dom'] == manifest['react_version'] assert lock['packages']['node_modules/fullbleed']['integrity'] == manifest['package_integrity'] @@ -65,7 +65,7 @@ installed = project / 'node_modules/fullbleed' assert json.loads((installed / 'package.json').read_text())['version'] == manifest['package_version'] runtime = json.loads((project / 'dist/fullbleed/build.json').read_text()) -assert runtime['packageVersion'] == manifest['package_version'] and runtime['engineVersion'] == '2.5.10' +assert runtime['packageVersion'] == manifest['package_version'] and runtime['engineVersion'] == '2.5.11' for name, expected in runtime['files'].items(): value = (project / 'dist/fullbleed' / name).read_bytes() assert len(value) == expected['bytes'] and digest(value) == expected['sha256'] diff --git a/tools/build_vue_starter.py b/tools/build_vue_starter.py index 0b269bf..f2b74bd 100644 --- a/tools/build_vue_starter.py +++ b/tools/build_vue_starter.py @@ -49,7 +49,7 @@ project = workspace / 'fullbleed-vue-starter' package = json.loads((project / 'package.json').read_text()) lock = json.loads((project / 'package-lock.json').read_text()) -assert package['dependencies']['fullbleed'] == manifest['package_version'] == '0.3.1' +assert package['dependencies']['fullbleed'] == manifest['package_version'] == '0.3.2' assert package['devDependencies']['vite'] == '8.3.2' assert package['devDependencies']['typescript'] == '6.0.3' assert package['devDependencies']['vue-tsc'] == '3.3.12' @@ -67,7 +67,7 @@ installed = project / 'node_modules/fullbleed' assert json.loads((installed / 'package.json').read_text())['version'] == manifest['package_version'] runtime = json.loads((project / 'dist/fullbleed/build.json').read_text()) -assert runtime['packageVersion'] == manifest['package_version'] and runtime['engineVersion'] == '2.5.10' +assert runtime['packageVersion'] == manifest['package_version'] and runtime['engineVersion'] == '2.5.11' for name, expected in runtime['files'].items(): value = (project / 'dist/fullbleed' / name).read_bytes() assert len(value) == expected['bytes'] and digest(value) == expected['sha256'] diff --git a/tools/check_browser_starter.py b/tools/check_browser_starter.py index 105f784..89f06dd 100644 --- a/tools/check_browser_starter.py +++ b/tools/check_browser_starter.py @@ -11,6 +11,7 @@ from playwright.sync_api import sync_playwright, expect from pypdf import PdfReader +from starter_standard_fonts import verify_edited_preview parser=argparse.ArgumentParser(description=__doc__) parser.add_argument('--dist',type=Path,required=True) @@ -88,11 +89,12 @@ def download(name,pages,text): check('customized bytes differ from the default invoice',documents[-1]['sha256']!=documents[0]['sha256']) page.locator('#template-editor summary').click() page.locator('#html-source').fill('

Edited template

{{customer}} / {{reference}}

') - page.locator('#css-source').fill('@page { size: A5; margin: 15mm } h1 { color: {{ink}}; font-size: 24pt }') + page.locator('#css-source').fill('@page { size: A5; margin: 15mm } body { font-family: Helvetica } h1 { color: {{ink}}; font-size: 24pt }') page.locator('#render-source').click();ready() path=download('edited',1,['Edited template','Birch & ','TEST-2042']) check('edited print CSS changes the PDF page size',abs(float(PdfReader(path).pages[0].mediabox.width)-419.52756)<1) check('document script does not run on the page',page.evaluate('window.documentScriptExecuted !== true')) + verify_edited_preview(page, path, out, check) page.screenshot(path=str(out/'edited-template.png'),full_page=True) page.locator('#kind').select_option('report');page.locator('#generate').click();ready() download('report',3,['COMMON','1,240','420,000.00']) diff --git a/tools/check_react_starter.py b/tools/check_react_starter.py index 7f84434..349b1d6 100644 --- a/tools/check_react_starter.py +++ b/tools/check_react_starter.py @@ -1,6 +1,6 @@ """Check the production React ZIP's PDF downloads and component cleanup. -Adapted from fullbleed-node dc36691c59faa27eedb3c49465e9818c5953abf1. +Adapted from fullbleed-node ae6e301ebc129a15aab89378f44beb81d63d4475. The source repository separately qualifies development StrictMode. """ import argparse @@ -16,6 +16,7 @@ from playwright.sync_api import sync_playwright, expect from pypdf import PdfReader +from starter_standard_fonts import verify_edited_preview parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--dist', type=Path, required=True) @@ -173,11 +174,12 @@ def download(name, count, text): page.locator('#template-editor summary').click() page.locator('#html-source').fill('

React template

{{customer}} / {{reference}}

') - page.locator('#css-source').fill('@page { size: A5; margin: 15mm } h1 { color: {{ink}}; font-size: 24pt }') + page.locator('#css-source').fill('@page { size: A5; margin: 15mm } body { font-family: Helvetica } h1 { color: {{ink}}; font-size: 24pt }') ready() edited = download('edited-template', 1, ['React template', 'Birch & ', 'REACT-2042']) check('edited print CSS changes the page size', abs(float(PdfReader(edited).pages[0].mediabox.width) - 419.52756) < 1) check('document scripts are not executed in the app', page.evaluate('window.documentScriptExecuted !== true')) + verify_edited_preview(page, edited, out, check) page.screenshot(path=str(out / 'edited-template.png'), full_page=True) page.locator('#kind').select_option('report') ready() diff --git a/tools/check_vue_starter.py b/tools/check_vue_starter.py index 2c4bea6..9ce29b0 100644 --- a/tools/check_vue_starter.py +++ b/tools/check_vue_starter.py @@ -1,4 +1,4 @@ -"""Check the exact Vue ZIP; adapted from fullbleed-node 3e60340b2cb1a4275828ef717a886a93b93c9cc7.""" +"""Check the exact Vue ZIP; adapted from fullbleed-node ae6e301ebc129a15aab89378f44beb81d63d4475.""" import argparse from datetime import datetime, timezone import hashlib @@ -12,6 +12,7 @@ from playwright.sync_api import sync_playwright, expect from pypdf import PdfReader +from starter_standard_fonts import verify_edited_preview parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--dist', type=Path, required=True) @@ -184,11 +185,12 @@ def previews_match(name, count): page.locator('#template-editor summary').click() page.locator('#html-source').fill('

Vue template

{{customer}} / {{reference}}

') - page.locator('#css-source').fill('@page { size: A5; margin: 15mm } h1 { color: {{ink}}; font-size: 24pt }') + page.locator('#css-source').fill('@page { size: A5; margin: 15mm } body { font-family: Helvetica } h1 { color: {{ink}}; font-size: 24pt }') ready() edited = download('edited-template', 1, ['Vue template', 'Birch & ', 'VUE-2042']) check('edited print CSS changes the page size', abs(float(PdfReader(edited).pages[0].mediabox.width) - 419.52756) < 1) check('document scripts are not executed in the app', page.evaluate('window.documentScriptExecuted !== true')) + verify_edited_preview(page, edited, out, check) page.screenshot(path=str(out / 'edited-template.png'), full_page=True) page.locator('#kind').select_option('report') ready() diff --git a/tools/starter_standard_fonts.py b/tools/starter_standard_fonts.py new file mode 100644 index 0000000..b56e0dc --- /dev/null +++ b/tools/starter_standard_fonts.py @@ -0,0 +1,37 @@ +"""Check that a pasted Helvetica template has visible browser preview text.""" +import base64 +import hashlib +import json + +from playwright.sync_api import expect +from pypdf import PdfReader + + +def verify_edited_preview(page, pdf_path, out, check): + pdf = PdfReader(pdf_path) + fonts = [item.get_object() for item in pdf.pages[0]['/Resources']['/Font'].values()] + names = sorted(str(font.get('/BaseFont')) for font in fonts) + check('edited template uses unembedded standard Helvetica faces', + bool(fonts) and all(name in ['/Helvetica', '/Helvetica-Bold'] for name in names) + and all('/FontDescriptor' not in font for font in fonts)) + image = page.locator('#preview img') + expect(image).to_have_count(1) + result = image.evaluate('''async image => { + await image.decode(); + const canvas = document.createElement('canvas'); + canvas.width = image.naturalWidth; canvas.height = image.naturalHeight; + const context = canvas.getContext('2d'); context.drawImage(image, 0, 0); + const pixels = context.getImageData(0, 0, canvas.width, canvas.height).data; + let ink = 0; + for (let i = 0; i < pixels.length; i += 4) + if (pixels[i + 3] > 0 && Math.min(pixels[i], pixels[i + 1], pixels[i + 2]) < 245) ink++; + return {width: canvas.width, height: canvas.height, inkPixels: ink, + png: canvas.toDataURL('image/png').split(',')[1]}; + }''') + png = base64.b64decode(result.pop('png')) + (out / 'edited-preview-decoded.png').write_bytes(png) + result.update(fonts=names, pdfSha256=hashlib.sha256(pdf_path.read_bytes()).hexdigest(), + decodedPreviewSha256=hashlib.sha256(png).hexdigest()) + (out / 'edited-preview-verification.json').write_text( + json.dumps(result, indent=2) + '\n', encoding='utf-8', newline='\n') + check('edited standard-font preview contains visible text', result['inkPixels'] > 500)