fullbleed 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -4
- package/dist/THIRD_PARTY_NOTICES.txt +7 -7
- package/dist/browser/asset-manifest.json +11 -8
- package/dist/browser/client.js +11 -7
- package/dist/browser/worker.js +3 -3
- package/dist/build.json +15 -12
- package/dist/engine.wasm +0 -0
- package/dist/index.d.cts +2 -0
- package/package.json +2 -2
- package/src/browser.d.ts +2 -0
- package/src/browser.js +1 -1
- package/src/copy-browser-assets.cjs +1 -1
- package/src/index.cjs +3 -3
- package/src/index.d.ts +2 -0
- package/src/render-input.cjs +9 -4
package/README.md
CHANGED
|
@@ -14,8 +14,8 @@ also includes a ZIP for local development.
|
|
|
14
14
|
Using Vue? The [Vue and TypeScript starter](examples/vue) includes editable
|
|
15
15
|
templates, automatic previews, downloads, and a reusable `usePdfPreview` composable.
|
|
16
16
|
|
|
17
|
-
This is an optional integration around the published **Fullbleed 2.5.
|
|
18
|
-
The package has its own version, **0.
|
|
17
|
+
This is an optional integration around the published **Fullbleed 2.5.22** engine.
|
|
18
|
+
The package has its own version, **0.5.0**. Node applications can use a shared
|
|
19
19
|
render queue to bound active renders and waiting requests, include queue time in
|
|
20
20
|
deadlines, cancel waiting jobs, and stop rendering cleanly during shutdown.
|
|
21
21
|
The browser entry renders in a Web Worker, and the Node API supports worker and
|
|
@@ -25,6 +25,16 @@ process isolation. See the [browser guide](docs/browser.md),
|
|
|
25
25
|
[font-family checks](https://github.com/fullbleed-engine/fullbleed-node/blob/main/docs/font-families.md), and
|
|
26
26
|
[embedded-font checks](https://github.com/fullbleed-engine/fullbleed-node/blob/main/docs/font-subsets.md) for the retained fixtures.
|
|
27
27
|
|
|
28
|
+
Version 0.5.0 adds `defaultStyles: false` to both JavaScript entries. Use it to
|
|
29
|
+
preserve a template's original CSS, including font inheritance from `html`,
|
|
30
|
+
low-specificity selectors, and cascade layers. Existing calls keep the Inter
|
|
31
|
+
body rule. [Retained styling checks](docs/default-styles.md) cover both choices.
|
|
32
|
+
|
|
33
|
+
Version 0.4.1 brought the engine's recent layout fixes to both JavaScript entries.
|
|
34
|
+
The [engine update checks](https://github.com/fullbleed-engine/fullbleed-node/blob/main/docs/engine-2.5.22.md)
|
|
35
|
+
cover nested counters, clipped effects, border-image tiling, and floated initials
|
|
36
|
+
with independent text, color, and Chrome print expectations.
|
|
37
|
+
|
|
28
38
|
## Install and render
|
|
29
39
|
|
|
30
40
|
Use Node.js 22 or newer. Install the [npm package](https://www.npmjs.com/package/fullbleed):
|
|
@@ -33,7 +43,7 @@ Use Node.js 22 or newer. Install the [npm package](https://www.npmjs.com/package
|
|
|
33
43
|
npm install fullbleed
|
|
34
44
|
```
|
|
35
45
|
|
|
36
|
-
For a version-pinned installation, use `npm install --save-exact fullbleed@0.
|
|
46
|
+
For a version-pinned installation, use `npm install --save-exact fullbleed@0.5.0`.
|
|
37
47
|
Package archives and retained PDF/PNG evidence are attached to each
|
|
38
48
|
[GitHub release](https://github.com/fullbleed-engine/fullbleed-node/releases).
|
|
39
49
|
The [installation verification records](https://github.com/fullbleed-engine/fullbleed-node/tree/main/verification)
|
|
@@ -203,7 +213,8 @@ native engine.
|
|
|
203
213
|
| Option | Behavior |
|
|
204
214
|
| --- | --- |
|
|
205
215
|
| `html` | Required nonempty HTML string. |
|
|
206
|
-
| `css` | CSS string; defaults to empty.
|
|
216
|
+
| `css` | CSS string; defaults to empty. |
|
|
217
|
+
| `defaultStyles` | Default `true`: prepend `body { font-family: Inter; }`. Set `false` to pass CSS unchanged; bundled fonts remain available. |
|
|
207
218
|
| `fonts` | Additional TrueType font bytes as `Uint8Array[]` or `Buffer[]`. |
|
|
208
219
|
| `assets` | Map relative asset names to nonempty byte arrays. |
|
|
209
220
|
| `previewDpi` | `0` disables previews; otherwise an integer from 36 to 300. |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
fullbleed 2.5.
|
|
1
|
+
fullbleed 2.5.22 / LICENSE
|
|
2
2
|
|
|
3
3
|
MIT License
|
|
4
4
|
|
|
@@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
23
23
|
SOFTWARE.
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
fullbleed 2.5.
|
|
26
|
+
fullbleed 2.5.22 / THIRD_PARTY_LICENSES.md
|
|
27
27
|
|
|
28
28
|
<!-- SPDX-License-Identifier: MIT -->
|
|
29
29
|
# Third-Party Licenses
|
|
@@ -826,7 +826,7 @@ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
826
826
|
DEALINGS IN THE SOFTWARE.
|
|
827
827
|
|
|
828
828
|
|
|
829
|
-
fullbleed 2.5.
|
|
829
|
+
fullbleed 2.5.22 / src/preview_fonts/LICENSE-Liberation.txt
|
|
830
830
|
|
|
831
831
|
Digitized data copyright (c) 2010 Google Corporation
|
|
832
832
|
with Reserved Font Arimo, Tinos and Cousine.
|
|
@@ -932,7 +932,7 @@ DEALINGS IN THE FONT SOFTWARE.
|
|
|
932
932
|
|
|
933
933
|
|
|
934
934
|
|
|
935
|
-
fullbleed 2.5.
|
|
935
|
+
fullbleed 2.5.22 / src/preview_fonts/LICENSE-NotoSans.txt
|
|
936
936
|
|
|
937
937
|
Copyright 2022 The Noto Project Authors (https://github.com/notofonts/latin-greek-cyrillic)
|
|
938
938
|
|
|
@@ -1031,7 +1031,7 @@ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
|
1031
1031
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
1032
1032
|
|
|
1033
1033
|
|
|
1034
|
-
fullbleed 2.5.
|
|
1034
|
+
fullbleed 2.5.22 / src/preview_fonts/LICENSE-NotoSansMath.txt
|
|
1035
1035
|
|
|
1036
1036
|
Copyright 2018 Google LLC. All Rights Reserved.
|
|
1037
1037
|
|
|
@@ -1130,7 +1130,7 @@ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
|
1130
1130
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
1131
1131
|
|
|
1132
1132
|
|
|
1133
|
-
fullbleed 2.5.
|
|
1133
|
+
fullbleed 2.5.22 / src/preview_fonts/LICENSE-NotoSansSymbols.txt
|
|
1134
1134
|
|
|
1135
1135
|
Copyright 2016 Google LLC. All Rights Reserved.
|
|
1136
1136
|
|
|
@@ -1229,7 +1229,7 @@ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
|
1229
1229
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
1230
1230
|
|
|
1231
1231
|
|
|
1232
|
-
fullbleed 2.5.
|
|
1232
|
+
fullbleed 2.5.22 / src/preview_fonts/LICENSE-NotoSansSymbols2.txt
|
|
1233
1233
|
|
|
1234
1234
|
Copyright 2017 Google Inc. All Rights Reserved.
|
|
1235
1235
|
|
|
@@ -1,27 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "fullbleed.browser-assets.v1",
|
|
3
|
-
"packageVersion": "0.
|
|
4
|
-
"engineVersion": "2.5.
|
|
3
|
+
"packageVersion": "0.5.0",
|
|
4
|
+
"engineVersion": "2.5.22",
|
|
5
|
+
"engineFeatures": [
|
|
6
|
+
"svg_raster"
|
|
7
|
+
],
|
|
5
8
|
"files": {
|
|
6
9
|
"client.js": {
|
|
7
10
|
"source": "dist/browser/client.js",
|
|
8
|
-
"bytes":
|
|
9
|
-
"sha256": "
|
|
11
|
+
"bytes": 12323,
|
|
12
|
+
"sha256": "9a6287ef90efea5efd08f8c7ce5a068eddf612a55fb22d3602d0d12c1a33f65d"
|
|
10
13
|
},
|
|
11
14
|
"worker.js": {
|
|
12
15
|
"source": "dist/browser/worker.js",
|
|
13
16
|
"bytes": 52109,
|
|
14
|
-
"sha256": "
|
|
17
|
+
"sha256": "7ff41b156cb8b21c66719ab86691e0f31c7e95fd3ca11922e5ee0692b2dcc8b0"
|
|
15
18
|
},
|
|
16
19
|
"engine.wasm": {
|
|
17
20
|
"source": "dist/engine.wasm",
|
|
18
|
-
"bytes":
|
|
19
|
-
"sha256": "
|
|
21
|
+
"bytes": 5640040,
|
|
22
|
+
"sha256": "a739438e01e9b52db48e47f1a604b700d98119b40db41361cc1563da059d1cbf"
|
|
20
23
|
},
|
|
21
24
|
"THIRD_PARTY_NOTICES.txt": {
|
|
22
25
|
"source": "dist/THIRD_PARTY_NOTICES.txt",
|
|
23
26
|
"bytes": 81572,
|
|
24
|
-
"sha256": "
|
|
27
|
+
"sha256": "b8e9cf0c642fb3790a77654d514dd8a1c37fb1edb2e92a6fffdeb62de0efb43d"
|
|
25
28
|
},
|
|
26
29
|
"LICENSE.txt": {
|
|
27
30
|
"source": "LICENSE",
|
package/dist/browser/client.js
CHANGED
|
@@ -68,12 +68,13 @@ var require_render_input = __commonJS({
|
|
|
68
68
|
var assetLimit = 64 * 1024 * 1024;
|
|
69
69
|
function normalize(options, { browser = false } = {}) {
|
|
70
70
|
if (!options || typeof options !== "object" || Array.isArray(options)) invalid2("Pass an options object with an html string.");
|
|
71
|
-
const supported = /* @__PURE__ */ new Set(["html", "css", "fonts", "assets", "previewDpi", "timeoutMs", "maxPages", "allowMissingGlyphs", "signal"]);
|
|
71
|
+
const supported = /* @__PURE__ */ new Set(["html", "css", "defaultStyles", "fonts", "assets", "previewDpi", "timeoutMs", "maxPages", "allowMissingGlyphs", "signal"]);
|
|
72
72
|
if (!browser) supported.add("isolation");
|
|
73
73
|
for (const key of Object.keys(options)) if (!supported.has(key)) invalid2(`Unknown option: ${key}`);
|
|
74
|
-
const { html, css = "", fonts = [], assets = {}, previewDpi = 0, timeoutMs = 3e4, maxPages = 1e3, allowMissingGlyphs = false, signal, isolation = "worker" } = options;
|
|
74
|
+
const { html, css = "", defaultStyles = true, fonts = [], assets = {}, previewDpi = 0, timeoutMs = 3e4, maxPages = 1e3, allowMissingGlyphs = false, signal, isolation = "worker" } = options;
|
|
75
75
|
if (typeof html !== "string" || !html.trim()) invalid2("html must be a nonempty string.");
|
|
76
76
|
if (typeof css !== "string") invalid2("css must be a string.");
|
|
77
|
+
if (typeof defaultStyles !== "boolean") invalid2("defaultStyles must be a boolean.");
|
|
77
78
|
if (new TextEncoder().encode(html).byteLength + new TextEncoder().encode(css).byteLength > sourceLimit) invalid2("HTML and CSS together must not exceed 4,000,000 UTF-8 bytes.");
|
|
78
79
|
if (!Number.isInteger(previewDpi) || previewDpi !== 0 && (previewDpi < 36 || previewDpi > 300)) invalid2("previewDpi must be 0 (disabled) or an integer from 36 to 300.");
|
|
79
80
|
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 2147483647) invalid2("timeoutMs must be a positive integer no greater than 2147483647.");
|
|
@@ -99,9 +100,12 @@ var require_render_input = __commonJS({
|
|
|
99
100
|
for (let i = 1; i < segments.length; i++) if (fileNames.has(segments.slice(0, i).join("/"))) invalid2(`Asset is both a file and a directory: ${name}`);
|
|
100
101
|
return { name: "assets/" + name, data: bytes(assets[name], `assets[${name}]`) };
|
|
101
102
|
});
|
|
102
|
-
return { html, css, customFonts, assetFiles, previewDpi, timeoutMs, maxPages, allowMissingGlyphs, signal, isolation };
|
|
103
|
+
return { html, css, defaultStyles, customFonts, assetFiles, previewDpi, timeoutMs, maxPages, allowMissingGlyphs, signal, isolation };
|
|
103
104
|
}
|
|
104
|
-
|
|
105
|
+
function stylesheet(job) {
|
|
106
|
+
return (job.defaultStyles ? "body { font-family: Inter; }\n" : "") + job.css;
|
|
107
|
+
}
|
|
108
|
+
module.exports = { FullbleedError: FullbleedError2, normalize, stylesheet };
|
|
105
109
|
}
|
|
106
110
|
});
|
|
107
111
|
|
|
@@ -109,8 +113,8 @@ var require_render_input = __commonJS({
|
|
|
109
113
|
init_define_FULLBLEED_FONT_NAMES();
|
|
110
114
|
init_define_FULLBLEED_RUNTIME_FILES();
|
|
111
115
|
var import_render_input = __toESM(require_render_input(), 1);
|
|
112
|
-
var version = "0.
|
|
113
|
-
var engineVersion = "2.5.
|
|
116
|
+
var version = "0.5.0";
|
|
117
|
+
var engineVersion = "2.5.22";
|
|
114
118
|
var FullbleedError = import_render_input.default.FullbleedError;
|
|
115
119
|
var invalid = (message) => {
|
|
116
120
|
throw new FullbleedError("INVALID_INPUT", message);
|
|
@@ -183,7 +187,7 @@ function createRenderer(options) {
|
|
|
183
187
|
try {
|
|
184
188
|
worker.postMessage({ type: "render", job: {
|
|
185
189
|
html: job.html,
|
|
186
|
-
css:
|
|
190
|
+
css: import_render_input.default.stylesheet(job),
|
|
187
191
|
fonts: job.customFonts,
|
|
188
192
|
assets: job.assetFiles,
|
|
189
193
|
previewDpi: job.previewDpi,
|
package/dist/browser/worker.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
var define_FULLBLEED_FONT_NAMES_default = ["Inter-Variable.ttf", "DMSerifDisplay-Regular.ttf", "DMSerifDisplay-Italic.ttf", "BebasNeue-Regular.ttf"];
|
|
3
3
|
|
|
4
4
|
// <define:__FULLBLEED_RUNTIME_FILES__>
|
|
5
|
-
var define_FULLBLEED_RUNTIME_FILES_default = { "engine.wasm": { bytes:
|
|
5
|
+
var define_FULLBLEED_RUNTIME_FILES_default = { "engine.wasm": { bytes: 5640040, sha256: "a739438e01e9b52db48e47f1a604b700d98119b40db41361cc1563da059d1cbf" }, "fonts/Inter-Variable.ttf": { bytes: 876576, sha256: "29160a80ff49ddcab2c97711247e08b1fab27a484a329ce8b813d820dc559031" }, "fonts/DMSerifDisplay-Regular.ttf": { bytes: 76580, sha256: "8cc3643535edf039aa5d95440a8542735e9197e4f4b8d9303e980fefbf5ab616" }, "fonts/DMSerifDisplay-Italic.ttf": { bytes: 71208, sha256: "df74c0ac387baeaeb0fe4f2324e1668e6a3ed8c09cd9796fe162c71753e19e45" }, "fonts/BebasNeue-Regular.ttf": { bytes: 61400, sha256: "08e4623805102d819f58601e46e345648846075e363b2ceb23313c2d1c83ec73" } };
|
|
6
6
|
|
|
7
7
|
// node_modules/@bjorn3/browser_wasi_shim/dist/wasi_defs.js
|
|
8
8
|
var CLOCKID_REALTIME = 0;
|
|
@@ -1438,8 +1438,8 @@ async function runEngine(job) {
|
|
|
1438
1438
|
}
|
|
1439
1439
|
|
|
1440
1440
|
// src/browser-worker.js
|
|
1441
|
-
var version = "0.
|
|
1442
|
-
var engineVersion = "2.5.
|
|
1441
|
+
var version = "0.5.0";
|
|
1442
|
+
var engineVersion = "2.5.22";
|
|
1443
1443
|
var files = define_FULLBLEED_RUNTIME_FILES_default;
|
|
1444
1444
|
var fontNames = define_FULLBLEED_FONT_NAMES_default;
|
|
1445
1445
|
var hex = (bytes) => Array.from(new Uint8Array(bytes), (value) => value.toString(16).padStart(2, "0")).join("");
|
package/dist/build.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"packageVersion": "0.
|
|
3
|
-
"engineVersion": "2.5.
|
|
4
|
-
"engineSource": "https://crates.io/crates/fullbleed/2.5.
|
|
2
|
+
"packageVersion": "0.5.0",
|
|
3
|
+
"engineVersion": "2.5.22",
|
|
4
|
+
"engineSource": "https://crates.io/crates/fullbleed/2.5.22",
|
|
5
|
+
"engineFeatures": [
|
|
6
|
+
"svg_raster"
|
|
7
|
+
],
|
|
5
8
|
"target": "wasm32-wasip1",
|
|
6
9
|
"memoryMaximumBytes": 536870912,
|
|
7
10
|
"fonts": [
|
|
@@ -13,7 +16,7 @@
|
|
|
13
16
|
"dependencies": [
|
|
14
17
|
{
|
|
15
18
|
"name": "fullbleed",
|
|
16
|
-
"version": "2.5.
|
|
19
|
+
"version": "2.5.22",
|
|
17
20
|
"source": "registry+https://github.com/rust-lang/crates.io-index",
|
|
18
21
|
"license": "MIT"
|
|
19
22
|
},
|
|
@@ -44,12 +47,12 @@
|
|
|
44
47
|
],
|
|
45
48
|
"files": {
|
|
46
49
|
"dist/engine.wasm": {
|
|
47
|
-
"bytes":
|
|
48
|
-
"sha256": "
|
|
50
|
+
"bytes": 5640040,
|
|
51
|
+
"sha256": "a739438e01e9b52db48e47f1a604b700d98119b40db41361cc1563da059d1cbf"
|
|
49
52
|
},
|
|
50
53
|
"dist/THIRD_PARTY_NOTICES.txt": {
|
|
51
54
|
"bytes": 81572,
|
|
52
|
-
"sha256": "
|
|
55
|
+
"sha256": "b8e9cf0c642fb3790a77654d514dd8a1c37fb1edb2e92a6fffdeb62de0efb43d"
|
|
53
56
|
},
|
|
54
57
|
"dist/preview-font-notices/LICENSE-Liberation.txt": {
|
|
55
58
|
"bytes": 4414,
|
|
@@ -100,16 +103,16 @@
|
|
|
100
103
|
"sha256": "29160a80ff49ddcab2c97711247e08b1fab27a484a329ce8b813d820dc559031"
|
|
101
104
|
},
|
|
102
105
|
"dist/browser/client.js": {
|
|
103
|
-
"bytes":
|
|
104
|
-
"sha256": "
|
|
106
|
+
"bytes": 12323,
|
|
107
|
+
"sha256": "9a6287ef90efea5efd08f8c7ce5a068eddf612a55fb22d3602d0d12c1a33f65d"
|
|
105
108
|
},
|
|
106
109
|
"dist/browser/worker.js": {
|
|
107
110
|
"bytes": 52109,
|
|
108
|
-
"sha256": "
|
|
111
|
+
"sha256": "7ff41b156cb8b21c66719ab86691e0f31c7e95fd3ca11922e5ee0692b2dcc8b0"
|
|
109
112
|
},
|
|
110
113
|
"dist/browser/asset-manifest.json": {
|
|
111
|
-
"bytes":
|
|
112
|
-
"sha256": "
|
|
114
|
+
"bytes": 2443,
|
|
115
|
+
"sha256": "8eeccbcac3bc80594f9cbae279c9ad710dc34baaac5996f47ddf36eb93a4d967"
|
|
113
116
|
}
|
|
114
117
|
}
|
|
115
118
|
}
|
package/dist/engine.wasm
CHANGED
|
Binary file
|
package/dist/index.d.cts
CHANGED
|
@@ -4,6 +4,8 @@ import type { Buffer } from 'node:buffer';
|
|
|
4
4
|
export interface RenderOptions {
|
|
5
5
|
html: string;
|
|
6
6
|
css?: string;
|
|
7
|
+
/** Default true: prepend the package's Inter body rule. False passes CSS unchanged. */
|
|
8
|
+
defaultStyles?: boolean;
|
|
7
9
|
/** Additional TrueType font files, as bytes. Use their family names in CSS. */
|
|
8
10
|
fonts?: readonly Uint8Array[];
|
|
9
11
|
/** Relative asset names; reference them as assets/name.svg in HTML/CSS. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fullbleed",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Generate PDFs from HTML and CSS in Node.js or a browser worker with the Fullbleed Rust engine, bundled fonts, and optional PNG previews.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.cjs",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"access": "public"
|
|
78
78
|
},
|
|
79
79
|
"fullbleed": {
|
|
80
|
-
"engineVersion": "2.5.
|
|
80
|
+
"engineVersion": "2.5.22"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@types/node": "22.20.5",
|
package/src/browser.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export interface BrowserRendererOptions {
|
|
|
6
6
|
export interface BrowserRenderOptions {
|
|
7
7
|
html: string;
|
|
8
8
|
css?: string;
|
|
9
|
+
/** Default true: prepend the package's Inter body rule. False passes CSS unchanged. */
|
|
10
|
+
defaultStyles?: boolean;
|
|
9
11
|
/** Additional TrueType font bytes; use the font family names in CSS. */
|
|
10
12
|
fonts?: readonly Uint8Array[];
|
|
11
13
|
/** Relative names referenced as assets/name.svg in document HTML/CSS. */
|
package/src/browser.js
CHANGED
|
@@ -66,7 +66,7 @@ export function createRenderer(options) {
|
|
|
66
66
|
ready = true;
|
|
67
67
|
try {
|
|
68
68
|
worker.postMessage({ type: 'render', job: {
|
|
69
|
-
html: job.html, css:
|
|
69
|
+
html: job.html, css: input.stylesheet(job),
|
|
70
70
|
fonts: job.customFonts, assets: job.assetFiles, previewDpi: job.previewDpi,
|
|
71
71
|
maxPages: job.maxPages, allowMissingGlyphs: job.allowMissingGlyphs,
|
|
72
72
|
} });
|
|
@@ -35,7 +35,7 @@ async function main() {
|
|
|
35
35
|
await writeFile(path, file.data);
|
|
36
36
|
}
|
|
37
37
|
await writeFile(join(destination, 'build.json'), JSON.stringify({ schema: manifest.schema,
|
|
38
|
-
packageVersion: pkg.version, engineVersion: manifest.engineVersion,
|
|
38
|
+
packageVersion: pkg.version, engineVersion: manifest.engineVersion, engineFeatures: manifest.engineFeatures,
|
|
39
39
|
files: Object.fromEntries(files.map(({ name, bytes, sha256 }) => [name, { bytes, sha256 }])) }, null, 2) + '\n');
|
|
40
40
|
console.log(JSON.stringify({ ok: true, directory: destination, packageVersion: pkg.version,
|
|
41
41
|
engineVersion: manifest.engineVersion, files: files.length + 1, bytes: files.reduce((sum, file) => sum + file.bytes, 0) }));
|
package/src/index.cjs
CHANGED
|
@@ -8,7 +8,7 @@ const { fork } = require('node:child_process');
|
|
|
8
8
|
const { pathToFileURL } = require('node:url');
|
|
9
9
|
const pkg = require('../package.json');
|
|
10
10
|
|
|
11
|
-
const { FullbleedError, normalize } = require('./render-input.cjs');
|
|
11
|
+
const { FullbleedError, normalize, stylesheet } = require('./render-input.cjs');
|
|
12
12
|
const { createQueue } = require('./render-queue.cjs');
|
|
13
13
|
const hash = bytes => createHash('sha256').update(bytes).digest('hex');
|
|
14
14
|
const root = join(__dirname, '..');
|
|
@@ -136,7 +136,7 @@ function renderProcess(job, remaining) {
|
|
|
136
136
|
child.send({ type: 'render', options: {
|
|
137
137
|
html: job.html, css: job.css, fonts: job.customFonts.map(font => font.data),
|
|
138
138
|
assets: Object.fromEntries(job.assetFiles.map(file => [file.name.slice('assets/'.length), file.data])),
|
|
139
|
-
previewDpi: job.previewDpi, maxPages: job.maxPages, allowMissingGlyphs: job.allowMissingGlyphs,
|
|
139
|
+
previewDpi: job.previewDpi, maxPages: job.maxPages, allowMissingGlyphs: job.allowMissingGlyphs, defaultStyles: job.defaultStyles,
|
|
140
140
|
timeoutMs: remaining,
|
|
141
141
|
} }, error => {
|
|
142
142
|
if (error) stop(new FullbleedError('PROCESS_FAILED', 'Could not send the rendering request.', { cause: error }));
|
|
@@ -198,7 +198,7 @@ async function renderJob(job, start) {
|
|
|
198
198
|
eval: true,
|
|
199
199
|
workerData: {
|
|
200
200
|
module: loaded.module, fonts: [...loaded.fonts, ...job.customFonts], assets: job.assetFiles,
|
|
201
|
-
html: job.html, css:
|
|
201
|
+
html: job.html, css: stylesheet(job), previewDpi: job.previewDpi, maxPages: job.maxPages,
|
|
202
202
|
allowMissingGlyphs: job.allowMissingGlyphs,
|
|
203
203
|
},
|
|
204
204
|
});
|
package/src/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ import type { Buffer } from 'node:buffer';
|
|
|
4
4
|
export interface RenderOptions {
|
|
5
5
|
html: string;
|
|
6
6
|
css?: string;
|
|
7
|
+
/** Default true: prepend the package's Inter body rule. False passes CSS unchanged. */
|
|
8
|
+
defaultStyles?: boolean;
|
|
7
9
|
/** Additional TrueType font files, as bytes. Use their family names in CSS. */
|
|
8
10
|
fonts?: readonly Uint8Array[];
|
|
9
11
|
/** Relative asset names; reference them as assets/name.svg in HTML/CSS. */
|
package/src/render-input.cjs
CHANGED
|
@@ -14,12 +14,13 @@ const assetLimit = 64 * 1024 * 1024;
|
|
|
14
14
|
|
|
15
15
|
function normalize(options, { browser = false } = {}) {
|
|
16
16
|
if (!options || typeof options !== 'object' || Array.isArray(options)) invalid('Pass an options object with an html string.');
|
|
17
|
-
const supported = new Set(['html', 'css', 'fonts', 'assets', 'previewDpi', 'timeoutMs', 'maxPages', 'allowMissingGlyphs', 'signal']);
|
|
17
|
+
const supported = new Set(['html', 'css', 'defaultStyles', 'fonts', 'assets', 'previewDpi', 'timeoutMs', 'maxPages', 'allowMissingGlyphs', 'signal']);
|
|
18
18
|
if (!browser) supported.add('isolation');
|
|
19
19
|
for (const key of Object.keys(options)) if (!supported.has(key)) invalid(`Unknown option: ${key}`);
|
|
20
|
-
const { html, css = '', fonts = [], assets = {}, previewDpi = 0, timeoutMs = 30000, maxPages = 1000, allowMissingGlyphs = false, signal, isolation = 'worker' } = options;
|
|
20
|
+
const { html, css = '', defaultStyles = true, fonts = [], assets = {}, previewDpi = 0, timeoutMs = 30000, maxPages = 1000, allowMissingGlyphs = false, signal, isolation = 'worker' } = options;
|
|
21
21
|
if (typeof html !== 'string' || !html.trim()) invalid('html must be a nonempty string.');
|
|
22
22
|
if (typeof css !== 'string') invalid('css must be a string.');
|
|
23
|
+
if (typeof defaultStyles !== 'boolean') invalid('defaultStyles must be a boolean.');
|
|
23
24
|
if (new TextEncoder().encode(html).byteLength + new TextEncoder().encode(css).byteLength > sourceLimit) invalid('HTML and CSS together must not exceed 4,000,000 UTF-8 bytes.');
|
|
24
25
|
if (!Number.isInteger(previewDpi) || (previewDpi !== 0 && (previewDpi < 36 || previewDpi > 300))) invalid('previewDpi must be 0 (disabled) or an integer from 36 to 300.');
|
|
25
26
|
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 2147483647) invalid('timeoutMs must be a positive integer no greater than 2147483647.');
|
|
@@ -45,7 +46,11 @@ function normalize(options, { browser = false } = {}) {
|
|
|
45
46
|
for (let i = 1; i < segments.length; i++) if (fileNames.has(segments.slice(0, i).join('/'))) invalid(`Asset is both a file and a directory: ${name}`);
|
|
46
47
|
return { name: 'assets/' + name, data: bytes(assets[name], `assets[${name}]`) };
|
|
47
48
|
});
|
|
48
|
-
return { html, css, customFonts, assetFiles, previewDpi, timeoutMs, maxPages, allowMissingGlyphs, signal, isolation };
|
|
49
|
+
return { html, css, defaultStyles, customFonts, assetFiles, previewDpi, timeoutMs, maxPages, allowMissingGlyphs, signal, isolation };
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
function stylesheet(job) {
|
|
53
|
+
return (job.defaultStyles ? 'body { font-family: Inter; }\n' : '') + job.css;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = { FullbleedError, normalize, stylesheet };
|