gutterpress 0.10.0-beta.1 → 0.10.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/dist/api/index.js +2 -2
- package/dist/{audit-85zn35v8.js → audit-cvarpa72.js} +4 -4
- package/dist/{build-1faqmp0y.js → build-6r502chw.js} +4 -4
- package/dist/{cli-7e79d7se.js → cli-149edp6b.js} +1 -1
- package/dist/{cli-v935c2ws.js → cli-cqtggsng.js} +1 -1
- package/dist/{cli-5tffrg48.js → cli-eq5naw4m.js} +136 -122
- package/dist/{cli-afm8pa0h.js → cli-zfcryxg8.js} +2 -2
- package/dist/cli.js +15 -15
- package/dist/{doctor-69v5c9wy.js → doctor-akvxbtjb.js} +2 -2
- package/dist/{engine-nbfdy0pp.js → engine-b159tbns.js} +2 -2
- package/dist/{engine-hrtn0b28.js → engine-ft4cr3ep.js} +1 -1
- package/dist/{gutterpress-viewer-fb6fhwsy.js → gutterpress-viewer-te8g5grx.js} +55 -21
- package/dist/{index-052x5fef.js → index-ge7q9xj3.js} +244 -230
- package/dist/{index-wsydvp08.js → index-wq3r5pj7.js} +1 -1
- package/dist/{index-c2b6gyeg.js → index-ycpvr0am.js} +2 -2
- package/dist/index.js +3 -3
- package/dist/lib/build-staging.d.ts +51 -0
- package/dist/{lint-17404bsx.js → lint-p2sw53d9.js} +4 -4
- package/dist/{new-vsgpxzek.js → new-hvq0x91q.js} +4 -4
- package/dist/{plugin-s4yfpx6p.js → plugin-pssmk0dx.js} +4 -4
- package/dist/{preflight-1h3apvqh.js → preflight-4j00yd0g.js} +4 -4
- package/dist/{preview-cqf383g4.js → preview-d4s6gk6p.js} +4 -4
- package/dist/{preview-interface-hg5eqv88.js → preview-interface-0ssk8bmm.js} +4 -2
- package/dist/{publish-arvycera.js → publish-tkc26en7.js} +4 -4
- package/dist/{repair-vmwh2bhe.js → repair-2va4w12t.js} +4 -4
- package/dist/{validate-ztzq7p35.js → validate-w9vfefrw.js} +4 -4
- package/package.json +1 -1
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
resolveChromiumExecutable,
|
|
18
18
|
run,
|
|
19
19
|
spawnCapture
|
|
20
|
-
} from "./index-
|
|
20
|
+
} from "./index-ycpvr0am.js";
|
|
21
21
|
import {
|
|
22
22
|
gitDirFor,
|
|
23
23
|
gitScopeFor,
|
|
@@ -3950,7 +3950,7 @@ import git from "isomorphic-git";
|
|
|
3950
3950
|
// package.json
|
|
3951
3951
|
var package_default = {
|
|
3952
3952
|
name: "gutterpress",
|
|
3953
|
-
version: "0.10.0
|
|
3953
|
+
version: "0.10.0",
|
|
3954
3954
|
description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
|
|
3955
3955
|
author: "itlackey",
|
|
3956
3956
|
license: "MPL-2.0",
|
|
@@ -4219,183 +4219,6 @@ async function writeBuildFingerprint(input) {
|
|
|
4219
4219
|
return outPath;
|
|
4220
4220
|
}
|
|
4221
4221
|
|
|
4222
|
-
// src/lib/missing-asset-placeholder.ts
|
|
4223
|
-
import { createHash as createHash5 } from "node:crypto";
|
|
4224
|
-
import { deflateSync } from "node:zlib";
|
|
4225
|
-
function placeholderOutputPath(missingOutputPath) {
|
|
4226
|
-
const hash = createHash5("sha256").update(missingOutputPath).digest("hex").slice(0, 16);
|
|
4227
|
-
return `assets/gutterpress-missing/${hash}.png`;
|
|
4228
|
-
}
|
|
4229
|
-
function decodeHtmlAttribute(value) {
|
|
4230
|
-
return value.replace(/"/g, '"').replace(/'|'/g, "'").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
|
|
4231
|
-
}
|
|
4232
|
-
function rewriteMissingImageReferences(html, replacements) {
|
|
4233
|
-
if (replacements.size === 0)
|
|
4234
|
-
return html;
|
|
4235
|
-
const replacementFor = (raw) => replacements.get(raw) ?? replacements.get(decodeHtmlAttribute(raw));
|
|
4236
|
-
const cssUrl = /url\(\s*(?:"([^"]*)"|'([^']*)'|"((?:(?!").)*)"|([^'"()\s]*))\s*\)/giy;
|
|
4237
|
-
const rewriteCssUrls = (css) => {
|
|
4238
|
-
let out2 = "";
|
|
4239
|
-
let copiedThrough = 0;
|
|
4240
|
-
let index = 0;
|
|
4241
|
-
while (index < css.length) {
|
|
4242
|
-
if (css.startsWith("/*", index)) {
|
|
4243
|
-
const end = css.indexOf("*/", index + 2);
|
|
4244
|
-
index = end < 0 ? css.length : end + 2;
|
|
4245
|
-
continue;
|
|
4246
|
-
}
|
|
4247
|
-
const char = css[index];
|
|
4248
|
-
if (char === '"' || char === "'") {
|
|
4249
|
-
const quote = char;
|
|
4250
|
-
index++;
|
|
4251
|
-
while (index < css.length) {
|
|
4252
|
-
if (css[index] === "\\") {
|
|
4253
|
-
index += 2;
|
|
4254
|
-
continue;
|
|
4255
|
-
}
|
|
4256
|
-
const current = css[index++];
|
|
4257
|
-
if (current === quote)
|
|
4258
|
-
break;
|
|
4259
|
-
}
|
|
4260
|
-
continue;
|
|
4261
|
-
}
|
|
4262
|
-
const previous = index > 0 ? css[index - 1] : "";
|
|
4263
|
-
if (!/[a-z0-9_-]/i.test(previous) && css.slice(index, index + 3).toLowerCase() === "url") {
|
|
4264
|
-
cssUrl.lastIndex = index;
|
|
4265
|
-
const match = cssUrl.exec(css);
|
|
4266
|
-
if (match) {
|
|
4267
|
-
const raw = match[1] ?? match[2] ?? match[3] ?? match[4] ?? "";
|
|
4268
|
-
const replacement = replacementFor(raw);
|
|
4269
|
-
if (replacement) {
|
|
4270
|
-
out2 += css.slice(copiedThrough, index);
|
|
4271
|
-
out2 += match[3] !== undefined ? `url("${replacement}")` : `url("${replacement}")`;
|
|
4272
|
-
index = cssUrl.lastIndex;
|
|
4273
|
-
copiedThrough = index;
|
|
4274
|
-
continue;
|
|
4275
|
-
}
|
|
4276
|
-
}
|
|
4277
|
-
}
|
|
4278
|
-
index++;
|
|
4279
|
-
}
|
|
4280
|
-
return copiedThrough === 0 ? css : out2 + css.slice(copiedThrough);
|
|
4281
|
-
};
|
|
4282
|
-
const rewriteTag = (tag) => {
|
|
4283
|
-
let out2 = tag;
|
|
4284
|
-
if (/^<img\b/i.test(tag)) {
|
|
4285
|
-
out2 = out2.replace(/(\s+src\s*=\s*)(?:"([^"]*)"|'([^']*)'|([^\s>]+))/gi, (whole, prefix, double, single, bare) => {
|
|
4286
|
-
const raw = double ?? single ?? bare ?? "";
|
|
4287
|
-
const replacement = replacementFor(raw);
|
|
4288
|
-
if (!replacement)
|
|
4289
|
-
return whole;
|
|
4290
|
-
if (double !== undefined)
|
|
4291
|
-
return `${prefix}"${replacement}"`;
|
|
4292
|
-
if (single !== undefined)
|
|
4293
|
-
return `${prefix}'${replacement}'`;
|
|
4294
|
-
return `${prefix}${replacement}`;
|
|
4295
|
-
});
|
|
4296
|
-
}
|
|
4297
|
-
if (/^<(?:img|source)\b/i.test(tag)) {
|
|
4298
|
-
out2 = out2.replace(/(\s+srcset\s*=\s*)(?:"([^"]*)"|'([^']*)'|([^\s>]+))/gi, (whole, prefix, double, single, bare) => {
|
|
4299
|
-
const value = double ?? single ?? bare ?? "";
|
|
4300
|
-
let rewritten = "";
|
|
4301
|
-
let copiedThrough = 0;
|
|
4302
|
-
let changed = false;
|
|
4303
|
-
for (const candidate of parseSrcsetUrlCandidates(value)) {
|
|
4304
|
-
const replacement = replacementFor(candidate.url);
|
|
4305
|
-
if (!replacement)
|
|
4306
|
-
continue;
|
|
4307
|
-
rewritten += value.slice(copiedThrough, candidate.start) + replacement;
|
|
4308
|
-
copiedThrough = candidate.end;
|
|
4309
|
-
changed = true;
|
|
4310
|
-
}
|
|
4311
|
-
if (!changed)
|
|
4312
|
-
return whole;
|
|
4313
|
-
rewritten += value.slice(copiedThrough);
|
|
4314
|
-
if (double !== undefined)
|
|
4315
|
-
return `${prefix}"${rewritten}"`;
|
|
4316
|
-
if (single !== undefined)
|
|
4317
|
-
return `${prefix}'${rewritten}'`;
|
|
4318
|
-
return `${prefix}${rewritten}`;
|
|
4319
|
-
});
|
|
4320
|
-
}
|
|
4321
|
-
out2 = out2.replace(/(\s+style\s*=\s*)(["'])(.*?)\2/gi, (whole, prefix, quote, value) => {
|
|
4322
|
-
const rewritten = rewriteCssUrls(value);
|
|
4323
|
-
return rewritten === value ? whole : `${prefix}${quote}${rewritten}${quote}`;
|
|
4324
|
-
});
|
|
4325
|
-
return out2;
|
|
4326
|
-
};
|
|
4327
|
-
const rewriteActiveHtml = (active) => active.replace(/<(?:"[^"]*"|'[^']*'|[^'">])*>/g, (tag) => rewriteTag(tag));
|
|
4328
|
-
const protectedRegion = /<!--[\s\S]*?-->|<(script|style|pre|code|textarea)\b[^>]*>[\s\S]*?<\/\1\s*>/gi;
|
|
4329
|
-
let out = "";
|
|
4330
|
-
let last = 0;
|
|
4331
|
-
for (const match of html.matchAll(protectedRegion)) {
|
|
4332
|
-
out += rewriteActiveHtml(html.slice(last, match.index));
|
|
4333
|
-
if (match[1]?.toLowerCase() === "style") {
|
|
4334
|
-
const style = /^(<style\b[^>]*>)([\s\S]*)(<\/style\s*>)$/i.exec(match[0]);
|
|
4335
|
-
out += style ? `${rewriteTag(style[1])}${rewriteCssUrls(style[2])}${style[3]}` : match[0];
|
|
4336
|
-
} else {
|
|
4337
|
-
out += match[0];
|
|
4338
|
-
}
|
|
4339
|
-
last = (match.index ?? 0) + match[0].length;
|
|
4340
|
-
}
|
|
4341
|
-
out += rewriteActiveHtml(html.slice(last));
|
|
4342
|
-
return out;
|
|
4343
|
-
}
|
|
4344
|
-
function crc32(buf) {
|
|
4345
|
-
let c = ~0;
|
|
4346
|
-
for (let i = 0;i < buf.length; i++) {
|
|
4347
|
-
c ^= buf[i];
|
|
4348
|
-
for (let k = 0;k < 8; k++)
|
|
4349
|
-
c = c >>> 1 ^ 3988292384 & -(c & 1);
|
|
4350
|
-
}
|
|
4351
|
-
return ~c >>> 0;
|
|
4352
|
-
}
|
|
4353
|
-
function chunk(type, data) {
|
|
4354
|
-
const out = new Uint8Array(data.length + 12);
|
|
4355
|
-
const view = new DataView(out.buffer);
|
|
4356
|
-
view.setUint32(0, data.length);
|
|
4357
|
-
for (let i = 0;i < 4; i++)
|
|
4358
|
-
out[4 + i] = type.charCodeAt(i);
|
|
4359
|
-
out.set(data, 8);
|
|
4360
|
-
view.setUint32(data.length + 8, crc32(out.subarray(4, data.length + 8)));
|
|
4361
|
-
return out;
|
|
4362
|
-
}
|
|
4363
|
-
function placeholderPng(width = 640, height = 480, cell = 32) {
|
|
4364
|
-
const A = [217, 70, 239];
|
|
4365
|
-
const B = [26, 26, 26];
|
|
4366
|
-
const raw = new Uint8Array(height * (1 + width * 3));
|
|
4367
|
-
let p = 0;
|
|
4368
|
-
for (let y = 0;y < height; y++) {
|
|
4369
|
-
raw[p++] = 0;
|
|
4370
|
-
for (let x = 0;x < width; x++) {
|
|
4371
|
-
const c = ((x / cell | 0) + (y / cell | 0)) % 2 === 0 ? A : B;
|
|
4372
|
-
raw[p++] = c[0];
|
|
4373
|
-
raw[p++] = c[1];
|
|
4374
|
-
raw[p++] = c[2];
|
|
4375
|
-
}
|
|
4376
|
-
}
|
|
4377
|
-
const ihdr = new Uint8Array(13);
|
|
4378
|
-
const hv = new DataView(ihdr.buffer);
|
|
4379
|
-
hv.setUint32(0, width);
|
|
4380
|
-
hv.setUint32(4, height);
|
|
4381
|
-
ihdr[8] = 8;
|
|
4382
|
-
ihdr[9] = 2;
|
|
4383
|
-
const parts = [
|
|
4384
|
-
new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]),
|
|
4385
|
-
chunk("IHDR", ihdr),
|
|
4386
|
-
chunk("IDAT", new Uint8Array(deflateSync(raw))),
|
|
4387
|
-
chunk("IEND", new Uint8Array(0))
|
|
4388
|
-
];
|
|
4389
|
-
const total = parts.reduce((n, x) => n + x.length, 0);
|
|
4390
|
-
const png = new Uint8Array(total);
|
|
4391
|
-
let o = 0;
|
|
4392
|
-
for (const part of parts) {
|
|
4393
|
-
png.set(part, o);
|
|
4394
|
-
o += part.length;
|
|
4395
|
-
}
|
|
4396
|
-
return png;
|
|
4397
|
-
}
|
|
4398
|
-
|
|
4399
4222
|
// src/lib/lint-runner.ts
|
|
4400
4223
|
import { resolve as resolve4 } from "node:path";
|
|
4401
4224
|
import { readFile as readFile8 } from "node:fs/promises";
|
|
@@ -7615,6 +7438,185 @@ function computeGates(format, opts, config) {
|
|
|
7615
7438
|
import path6 from "node:path";
|
|
7616
7439
|
import os from "node:os";
|
|
7617
7440
|
import fsp from "node:fs/promises";
|
|
7441
|
+
|
|
7442
|
+
// src/lib/missing-asset-placeholder.ts
|
|
7443
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
7444
|
+
import { deflateSync } from "node:zlib";
|
|
7445
|
+
function placeholderOutputPath(missingOutputPath) {
|
|
7446
|
+
const hash = createHash5("sha256").update(missingOutputPath).digest("hex").slice(0, 16);
|
|
7447
|
+
return `assets/gutterpress-missing/${hash}.png`;
|
|
7448
|
+
}
|
|
7449
|
+
function decodeHtmlAttribute(value) {
|
|
7450
|
+
return value.replace(/"/g, '"').replace(/'|'/g, "'").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
|
|
7451
|
+
}
|
|
7452
|
+
function rewriteMissingImageReferences(html, replacements) {
|
|
7453
|
+
if (replacements.size === 0)
|
|
7454
|
+
return html;
|
|
7455
|
+
const replacementFor = (raw) => replacements.get(raw) ?? replacements.get(decodeHtmlAttribute(raw));
|
|
7456
|
+
const cssUrl = /url\(\s*(?:"([^"]*)"|'([^']*)'|"((?:(?!").)*)"|([^'"()\s]*))\s*\)/giy;
|
|
7457
|
+
const rewriteCssUrls = (css) => {
|
|
7458
|
+
let out2 = "";
|
|
7459
|
+
let copiedThrough = 0;
|
|
7460
|
+
let index = 0;
|
|
7461
|
+
while (index < css.length) {
|
|
7462
|
+
if (css.startsWith("/*", index)) {
|
|
7463
|
+
const end = css.indexOf("*/", index + 2);
|
|
7464
|
+
index = end < 0 ? css.length : end + 2;
|
|
7465
|
+
continue;
|
|
7466
|
+
}
|
|
7467
|
+
const char = css[index];
|
|
7468
|
+
if (char === '"' || char === "'") {
|
|
7469
|
+
const quote = char;
|
|
7470
|
+
index++;
|
|
7471
|
+
while (index < css.length) {
|
|
7472
|
+
if (css[index] === "\\") {
|
|
7473
|
+
index += 2;
|
|
7474
|
+
continue;
|
|
7475
|
+
}
|
|
7476
|
+
const current = css[index++];
|
|
7477
|
+
if (current === quote)
|
|
7478
|
+
break;
|
|
7479
|
+
}
|
|
7480
|
+
continue;
|
|
7481
|
+
}
|
|
7482
|
+
const previous = index > 0 ? css[index - 1] : "";
|
|
7483
|
+
if (!/[a-z0-9_-]/i.test(previous) && css.slice(index, index + 3).toLowerCase() === "url") {
|
|
7484
|
+
cssUrl.lastIndex = index;
|
|
7485
|
+
const match = cssUrl.exec(css);
|
|
7486
|
+
if (match) {
|
|
7487
|
+
const raw = match[1] ?? match[2] ?? match[3] ?? match[4] ?? "";
|
|
7488
|
+
const replacement = replacementFor(raw);
|
|
7489
|
+
if (replacement) {
|
|
7490
|
+
out2 += css.slice(copiedThrough, index);
|
|
7491
|
+
out2 += match[3] !== undefined ? `url("${replacement}")` : `url("${replacement}")`;
|
|
7492
|
+
index = cssUrl.lastIndex;
|
|
7493
|
+
copiedThrough = index;
|
|
7494
|
+
continue;
|
|
7495
|
+
}
|
|
7496
|
+
}
|
|
7497
|
+
}
|
|
7498
|
+
index++;
|
|
7499
|
+
}
|
|
7500
|
+
return copiedThrough === 0 ? css : out2 + css.slice(copiedThrough);
|
|
7501
|
+
};
|
|
7502
|
+
const rewriteTag = (tag) => {
|
|
7503
|
+
let out2 = tag;
|
|
7504
|
+
if (/^<img\b/i.test(tag)) {
|
|
7505
|
+
out2 = out2.replace(/(\s+src\s*=\s*)(?:"([^"]*)"|'([^']*)'|([^\s>]+))/gi, (whole, prefix, double, single, bare) => {
|
|
7506
|
+
const raw = double ?? single ?? bare ?? "";
|
|
7507
|
+
const replacement = replacementFor(raw);
|
|
7508
|
+
if (!replacement)
|
|
7509
|
+
return whole;
|
|
7510
|
+
if (double !== undefined)
|
|
7511
|
+
return `${prefix}"${replacement}"`;
|
|
7512
|
+
if (single !== undefined)
|
|
7513
|
+
return `${prefix}'${replacement}'`;
|
|
7514
|
+
return `${prefix}${replacement}`;
|
|
7515
|
+
});
|
|
7516
|
+
}
|
|
7517
|
+
if (/^<(?:img|source)\b/i.test(tag)) {
|
|
7518
|
+
out2 = out2.replace(/(\s+srcset\s*=\s*)(?:"([^"]*)"|'([^']*)'|([^\s>]+))/gi, (whole, prefix, double, single, bare) => {
|
|
7519
|
+
const value = double ?? single ?? bare ?? "";
|
|
7520
|
+
let rewritten = "";
|
|
7521
|
+
let copiedThrough = 0;
|
|
7522
|
+
let changed = false;
|
|
7523
|
+
for (const candidate of parseSrcsetUrlCandidates(value)) {
|
|
7524
|
+
const replacement = replacementFor(candidate.url);
|
|
7525
|
+
if (!replacement)
|
|
7526
|
+
continue;
|
|
7527
|
+
rewritten += value.slice(copiedThrough, candidate.start) + replacement;
|
|
7528
|
+
copiedThrough = candidate.end;
|
|
7529
|
+
changed = true;
|
|
7530
|
+
}
|
|
7531
|
+
if (!changed)
|
|
7532
|
+
return whole;
|
|
7533
|
+
rewritten += value.slice(copiedThrough);
|
|
7534
|
+
if (double !== undefined)
|
|
7535
|
+
return `${prefix}"${rewritten}"`;
|
|
7536
|
+
if (single !== undefined)
|
|
7537
|
+
return `${prefix}'${rewritten}'`;
|
|
7538
|
+
return `${prefix}${rewritten}`;
|
|
7539
|
+
});
|
|
7540
|
+
}
|
|
7541
|
+
out2 = out2.replace(/(\s+style\s*=\s*)(["'])(.*?)\2/gi, (whole, prefix, quote, value) => {
|
|
7542
|
+
const rewritten = rewriteCssUrls(value);
|
|
7543
|
+
return rewritten === value ? whole : `${prefix}${quote}${rewritten}${quote}`;
|
|
7544
|
+
});
|
|
7545
|
+
return out2;
|
|
7546
|
+
};
|
|
7547
|
+
const rewriteActiveHtml = (active) => active.replace(/<(?:"[^"]*"|'[^']*'|[^'">])*>/g, (tag) => rewriteTag(tag));
|
|
7548
|
+
const protectedRegion = /<!--[\s\S]*?-->|<(script|style|pre|code|textarea)\b[^>]*>[\s\S]*?<\/\1\s*>/gi;
|
|
7549
|
+
let out = "";
|
|
7550
|
+
let last = 0;
|
|
7551
|
+
for (const match of html.matchAll(protectedRegion)) {
|
|
7552
|
+
out += rewriteActiveHtml(html.slice(last, match.index));
|
|
7553
|
+
if (match[1]?.toLowerCase() === "style") {
|
|
7554
|
+
const style = /^(<style\b[^>]*>)([\s\S]*)(<\/style\s*>)$/i.exec(match[0]);
|
|
7555
|
+
out += style ? `${rewriteTag(style[1])}${rewriteCssUrls(style[2])}${style[3]}` : match[0];
|
|
7556
|
+
} else {
|
|
7557
|
+
out += match[0];
|
|
7558
|
+
}
|
|
7559
|
+
last = (match.index ?? 0) + match[0].length;
|
|
7560
|
+
}
|
|
7561
|
+
out += rewriteActiveHtml(html.slice(last));
|
|
7562
|
+
return out;
|
|
7563
|
+
}
|
|
7564
|
+
function crc32(buf) {
|
|
7565
|
+
let c = ~0;
|
|
7566
|
+
for (let i = 0;i < buf.length; i++) {
|
|
7567
|
+
c ^= buf[i];
|
|
7568
|
+
for (let k = 0;k < 8; k++)
|
|
7569
|
+
c = c >>> 1 ^ 3988292384 & -(c & 1);
|
|
7570
|
+
}
|
|
7571
|
+
return ~c >>> 0;
|
|
7572
|
+
}
|
|
7573
|
+
function chunk(type, data) {
|
|
7574
|
+
const out = new Uint8Array(data.length + 12);
|
|
7575
|
+
const view = new DataView(out.buffer);
|
|
7576
|
+
view.setUint32(0, data.length);
|
|
7577
|
+
for (let i = 0;i < 4; i++)
|
|
7578
|
+
out[4 + i] = type.charCodeAt(i);
|
|
7579
|
+
out.set(data, 8);
|
|
7580
|
+
view.setUint32(data.length + 8, crc32(out.subarray(4, data.length + 8)));
|
|
7581
|
+
return out;
|
|
7582
|
+
}
|
|
7583
|
+
function placeholderPng(width = 640, height = 480, cell = 32) {
|
|
7584
|
+
const A = [217, 70, 239];
|
|
7585
|
+
const B = [26, 26, 26];
|
|
7586
|
+
const raw = new Uint8Array(height * (1 + width * 3));
|
|
7587
|
+
let p = 0;
|
|
7588
|
+
for (let y = 0;y < height; y++) {
|
|
7589
|
+
raw[p++] = 0;
|
|
7590
|
+
for (let x = 0;x < width; x++) {
|
|
7591
|
+
const c = ((x / cell | 0) + (y / cell | 0)) % 2 === 0 ? A : B;
|
|
7592
|
+
raw[p++] = c[0];
|
|
7593
|
+
raw[p++] = c[1];
|
|
7594
|
+
raw[p++] = c[2];
|
|
7595
|
+
}
|
|
7596
|
+
}
|
|
7597
|
+
const ihdr = new Uint8Array(13);
|
|
7598
|
+
const hv = new DataView(ihdr.buffer);
|
|
7599
|
+
hv.setUint32(0, width);
|
|
7600
|
+
hv.setUint32(4, height);
|
|
7601
|
+
ihdr[8] = 8;
|
|
7602
|
+
ihdr[9] = 2;
|
|
7603
|
+
const parts = [
|
|
7604
|
+
new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]),
|
|
7605
|
+
chunk("IHDR", ihdr),
|
|
7606
|
+
chunk("IDAT", new Uint8Array(deflateSync(raw))),
|
|
7607
|
+
chunk("IEND", new Uint8Array(0))
|
|
7608
|
+
];
|
|
7609
|
+
const total = parts.reduce((n, x) => n + x.length, 0);
|
|
7610
|
+
const png = new Uint8Array(total);
|
|
7611
|
+
let o = 0;
|
|
7612
|
+
for (const part of parts) {
|
|
7613
|
+
png.set(part, o);
|
|
7614
|
+
o += part.length;
|
|
7615
|
+
}
|
|
7616
|
+
return png;
|
|
7617
|
+
}
|
|
7618
|
+
|
|
7619
|
+
// src/lib/build-staging.ts
|
|
7618
7620
|
async function shipViewerHtml(htmlFile, outDir) {
|
|
7619
7621
|
await fsp.mkdir(path6.join(outDir, "engine"), { recursive: true });
|
|
7620
7622
|
await fsp.copyFile(await getAssetPath("engine/gutterpress-viewer.js"), path6.join(outDir, "engine/gutterpress-viewer.js"));
|
|
@@ -7623,6 +7625,50 @@ async function shipViewerHtml(htmlFile, outDir) {
|
|
|
7623
7625
|
const html = await fsp.readFile(htmlFile, "utf-8");
|
|
7624
7626
|
await fsp.writeFile(htmlFile, /<\/head>/i.test(html) ? html.replace(/<\/head>/i, tag + "</head>") : tag + html, "utf-8");
|
|
7625
7627
|
}
|
|
7628
|
+
async function stageBookAssets(options) {
|
|
7629
|
+
const { renderDir, outDir, htmlFile, imageRefs, cssAssets, onPlan } = options;
|
|
7630
|
+
const { copies: imageCopies, errors, destinations } = await planImageCopies(renderDir, imageRefs);
|
|
7631
|
+
const copies = [...cssAssets, ...imageCopies];
|
|
7632
|
+
onPlan?.({ unresolved: errors, copyCount: copies.length });
|
|
7633
|
+
const missingPlaceholders = copies.length ? await copyReferencedAssets(copies, outDir) : new Map;
|
|
7634
|
+
let staged = await fsp.readFile(htmlFile, "utf8");
|
|
7635
|
+
if (missingPlaceholders.size > 0) {
|
|
7636
|
+
const rewrites = new Map(missingPlaceholders);
|
|
7637
|
+
for (const [ref, dest] of destinations) {
|
|
7638
|
+
const placeholder = missingPlaceholders.get(dest);
|
|
7639
|
+
if (placeholder)
|
|
7640
|
+
rewrites.set(ref, placeholder);
|
|
7641
|
+
}
|
|
7642
|
+
staged = rewriteMissingImageReferences(staged, rewrites);
|
|
7643
|
+
await fsp.writeFile(htmlFile, staged, "utf8");
|
|
7644
|
+
}
|
|
7645
|
+
if (staged.includes("--gp-shape:")) {
|
|
7646
|
+
await fsp.writeFile(htmlFile, await inlineShapeUrls(staged, outDir), "utf8");
|
|
7647
|
+
}
|
|
7648
|
+
return { missing: [...missingPlaceholders.keys()].sort() };
|
|
7649
|
+
}
|
|
7650
|
+
async function copyReferencedAssets(copies, outDir) {
|
|
7651
|
+
const dirs = new Set(copies.map((c) => path6.dirname(path6.resolve(outDir, c.to))));
|
|
7652
|
+
await Promise.all([...dirs].map((d) => fsp.mkdir(d, { recursive: true })));
|
|
7653
|
+
const missing = new Map;
|
|
7654
|
+
await Promise.all(copies.map(async (c) => {
|
|
7655
|
+
const dest = path6.resolve(outDir, c.to);
|
|
7656
|
+
try {
|
|
7657
|
+
await fsp.copyFile(c.from, dest);
|
|
7658
|
+
} catch (err) {
|
|
7659
|
+
if (err?.code === "ENOENT") {
|
|
7660
|
+
const placeholder = placeholderOutputPath(c.to);
|
|
7661
|
+
const placeholderDest = path6.resolve(outDir, placeholder);
|
|
7662
|
+
await fsp.mkdir(path6.dirname(placeholderDest), { recursive: true });
|
|
7663
|
+
await fsp.writeFile(placeholderDest, placeholderPng());
|
|
7664
|
+
missing.set(c.to, placeholder);
|
|
7665
|
+
return;
|
|
7666
|
+
}
|
|
7667
|
+
throw new BuildError(`Could not copy asset ${c.from} → ${c.to}: ` + (err instanceof Error ? err.message : String(err)), 1);
|
|
7668
|
+
}
|
|
7669
|
+
}));
|
|
7670
|
+
return missing;
|
|
7671
|
+
}
|
|
7626
7672
|
async function createStageRoot() {
|
|
7627
7673
|
return fsp.mkdtemp(path6.join(os.tmpdir(), "gutterpress-stage-"));
|
|
7628
7674
|
}
|
|
@@ -7735,67 +7781,35 @@ async function renderBook(ctx) {
|
|
|
7735
7781
|
}
|
|
7736
7782
|
},
|
|
7737
7783
|
onImageRefs: (refs) => imageRefs.push(...refs),
|
|
7738
|
-
onCssAssets: (
|
|
7784
|
+
onCssAssets: (copies) => cssAssets.push(...copies),
|
|
7739
7785
|
onStyleWarnings: (warnings) => {
|
|
7740
7786
|
for (const w of warnings)
|
|
7741
7787
|
log.warn(` ${w}`);
|
|
7742
7788
|
}
|
|
7743
7789
|
});
|
|
7744
7790
|
log.success(`Wrote ${htmlFile}`);
|
|
7745
|
-
const {
|
|
7746
|
-
|
|
7747
|
-
|
|
7748
|
-
|
|
7791
|
+
const { missing } = await stageBookAssets({
|
|
7792
|
+
renderDir,
|
|
7793
|
+
outDir: workDir,
|
|
7794
|
+
htmlFile,
|
|
7795
|
+
imageRefs,
|
|
7796
|
+
cssAssets,
|
|
7797
|
+
onPlan: ({ unresolved, copyCount }) => {
|
|
7798
|
+
if (unresolved.length > 0) {
|
|
7799
|
+
throw new BuildError(`Cannot resolve ${unresolved.length} image reference(s):
|
|
7800
|
+
` + unresolved.map((e) => ` - ${e}`).join(`
|
|
7749
7801
|
`), 1);
|
|
7750
|
-
}
|
|
7751
|
-
const copies = [...cssAssets, ...imageCopies];
|
|
7752
|
-
let missingPlaceholders = new Map;
|
|
7753
|
-
if (copies.length > 0) {
|
|
7754
|
-
log.info(`Copying ${copies.length} referenced asset(s)`);
|
|
7755
|
-
missingPlaceholders = await copyReferencedAssets(copies, workDir);
|
|
7756
|
-
}
|
|
7757
|
-
let staged = await fsp2.readFile(htmlFile, "utf8");
|
|
7758
|
-
if (missingPlaceholders.size > 0) {
|
|
7759
|
-
const rewrites = new Map(missingPlaceholders);
|
|
7760
|
-
for (const [ref, dest] of destinations) {
|
|
7761
|
-
const placeholder = missingPlaceholders.get(dest);
|
|
7762
|
-
if (placeholder)
|
|
7763
|
-
rewrites.set(ref, placeholder);
|
|
7764
|
-
}
|
|
7765
|
-
staged = rewriteMissingImageReferences(staged, rewrites);
|
|
7766
|
-
await fsp2.writeFile(htmlFile, staged, "utf8");
|
|
7767
|
-
}
|
|
7768
|
-
if (staged.includes("--gp-shape:")) {
|
|
7769
|
-
await fsp2.writeFile(htmlFile, await inlineShapeUrls(staged, workDir), "utf8");
|
|
7770
|
-
}
|
|
7771
|
-
return htmlFile;
|
|
7772
|
-
}
|
|
7773
|
-
async function copyReferencedAssets(copies, outDir) {
|
|
7774
|
-
const dirs = new Set(copies.map((c) => path7.dirname(path7.resolve(outDir, c.to))));
|
|
7775
|
-
await Promise.all([...dirs].map((d) => fsp2.mkdir(d, { recursive: true })));
|
|
7776
|
-
const missing = new Map;
|
|
7777
|
-
await Promise.all(copies.map(async (c) => {
|
|
7778
|
-
const dest = path7.resolve(outDir, c.to);
|
|
7779
|
-
try {
|
|
7780
|
-
await fsp2.copyFile(c.from, dest);
|
|
7781
|
-
} catch (err) {
|
|
7782
|
-
if (err?.code === "ENOENT") {
|
|
7783
|
-
const placeholder = placeholderOutputPath(c.to);
|
|
7784
|
-
const placeholderDest = path7.resolve(outDir, placeholder);
|
|
7785
|
-
await fsp2.mkdir(path7.dirname(placeholderDest), { recursive: true });
|
|
7786
|
-
await fsp2.writeFile(placeholderDest, placeholderPng());
|
|
7787
|
-
missing.set(c.to, placeholder);
|
|
7788
|
-
return;
|
|
7789
7802
|
}
|
|
7790
|
-
|
|
7803
|
+
if (copyCount > 0)
|
|
7804
|
+
log.info(`Copying ${copyCount} referenced asset(s)`);
|
|
7791
7805
|
}
|
|
7792
|
-
})
|
|
7793
|
-
if (missing.
|
|
7794
|
-
log.warn(`${missing.
|
|
7795
|
-
for (const m of
|
|
7806
|
+
});
|
|
7807
|
+
if (missing.length > 0) {
|
|
7808
|
+
log.warn(`${missing.length} referenced image(s) do not exist — a magenta placeholder ` + `was substituted so the build could finish. Each one is a visible hole ` + `in the PDF:`);
|
|
7809
|
+
for (const m of missing)
|
|
7796
7810
|
log.warn(` missing: ${m}`);
|
|
7797
7811
|
}
|
|
7798
|
-
return
|
|
7812
|
+
return htmlFile;
|
|
7799
7813
|
}
|
|
7800
7814
|
async function resolveIccProfile(icc, manifestDir, explicitIccPath) {
|
|
7801
7815
|
const iccCandidates = path7.isAbsolute(icc) ? [icc] : [path7.resolve(manifestDir, icc), path7.resolve(icc)];
|
|
@@ -7893,7 +7907,7 @@ class PdfOutput {
|
|
|
7893
7907
|
const rawPdf = pdfxMode ? path7.join(stage, "raw.pdf") : path7.resolve(pdfFile);
|
|
7894
7908
|
await fsp2.mkdir(path7.dirname(path7.resolve(pdfFile)), { recursive: true });
|
|
7895
7909
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
7896
|
-
const { buildNativePdf } = await import("./engine-
|
|
7910
|
+
const { buildNativePdf } = await import("./engine-b159tbns.js");
|
|
7897
7911
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
7898
7912
|
title: config.title,
|
|
7899
7913
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
@@ -596,7 +596,7 @@ var favicon_default = "./favicon-wkbm9cjn.ico";
|
|
|
596
596
|
var manifest_schema_default = "./manifest.schema-zxgxnbg7.json";
|
|
597
597
|
|
|
598
598
|
// src/assets/preview/scripts/preview-interface.js
|
|
599
|
-
var preview_interface_default = "./preview-interface-
|
|
599
|
+
var preview_interface_default = "./preview-interface-0ssk8bmm.js";
|
|
600
600
|
|
|
601
601
|
// src/assets/preview/scripts/preview-bridge.js
|
|
602
602
|
var preview_bridge_default = "./preview-bridge-fz7vpk8m.js";
|
|
@@ -608,7 +608,7 @@ var preview_shell_default = "./preview-shell-c5mfa3q0.js";
|
|
|
608
608
|
var CGATS21_CRPC1_default = "./CGATS21_CRPC1-g0e3k7kr.icc";
|
|
609
609
|
|
|
610
610
|
// src/assets/engine/gutterpress-viewer.js
|
|
611
|
-
var gutterpress_viewer_default = "./gutterpress-viewer-
|
|
611
|
+
var gutterpress_viewer_default = "./gutterpress-viewer-te8g5grx.js";
|
|
612
612
|
|
|
613
613
|
// src/assets/engine/gutterpress-agent.js
|
|
614
614
|
var gutterpress_agent_default = "./gutterpress-agent-cazqstr1.js";
|
package/dist/index.js
CHANGED
|
@@ -140,15 +140,15 @@ import {
|
|
|
140
140
|
validateProjectPlugins,
|
|
141
141
|
verifyRepoReadable,
|
|
142
142
|
writeAppHeartbeat
|
|
143
|
-
} from "./index-
|
|
143
|
+
} from "./index-ge7q9xj3.js";
|
|
144
144
|
import {
|
|
145
145
|
BUILD_DIAGNOSTIC_CODES
|
|
146
|
-
} from "./index-
|
|
146
|
+
} from "./index-wq3r5pj7.js";
|
|
147
147
|
import {
|
|
148
148
|
BuildError,
|
|
149
149
|
DEFAULT_PRINT_OPTS,
|
|
150
150
|
readyProbeExpr
|
|
151
|
-
} from "./index-
|
|
151
|
+
} from "./index-ycpvr0am.js";
|
|
152
152
|
import {
|
|
153
153
|
AUTO_SNAPSHOT_MESSAGE,
|
|
154
154
|
HISTORY_PAGE_LIMIT,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type AssetCopy } from "./asset-inline";
|
|
1
2
|
/**
|
|
2
3
|
* `--format html`: ship the self-contained `book.html` (already fully
|
|
3
4
|
* inlined — see `lib/asset-inline.ts`) alongside a copy of the native engine's
|
|
@@ -8,6 +9,56 @@
|
|
|
8
9
|
* in the migration plan).
|
|
9
10
|
*/
|
|
10
11
|
export declare function shipViewerHtml(htmlFile: string, outDir: string): Promise<void>;
|
|
12
|
+
/** The copy plan, handed to `onPlan` before a single byte is written. */
|
|
13
|
+
export interface StagingPlan {
|
|
14
|
+
/** Refs that name no in-project file at all (absolute, or outside the book). */
|
|
15
|
+
unresolved: string[];
|
|
16
|
+
/** How many files the staging is about to copy. */
|
|
17
|
+
copyCount: number;
|
|
18
|
+
}
|
|
19
|
+
/** What `stageBookAssets` could not stage, for the caller to report. */
|
|
20
|
+
export interface StagedAssets {
|
|
21
|
+
/** Output-relative paths whose source file does not exist; a placeholder shipped. */
|
|
22
|
+
missing: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Turn a freshly rendered `book.html` plus its reported asset references into a
|
|
26
|
+
* COMPLETE, self-contained staged book in `outDir` — the exact document both
|
|
27
|
+
* renderers must paginate.
|
|
28
|
+
*
|
|
29
|
+
* THE one implementation: `renderBook` (every real build/export) and the
|
|
30
|
+
* preview/print parity gate both call this, so the gate can never measure a
|
|
31
|
+
* document the build would not have produced. It previously hand-rolled a bare
|
|
32
|
+
* `copyFile` loop, which (a) hard-crashed with a raw `ENOENT` on any book
|
|
33
|
+
* carrying a stale image path — i.e. the tool that enforces preview↔print
|
|
34
|
+
* parity could not run on the real books that need it — and (b) skipped
|
|
35
|
+
* `inlineShapeUrls`, so `.gp-shape` wrapping silently differed from the build.
|
|
36
|
+
*
|
|
37
|
+
* A missing image is NOT fatal: the same magenta placeholder the build ships
|
|
38
|
+
* (see missing-asset-placeholder.ts) is substituted and every reference
|
|
39
|
+
* rewritten to it, so the staged layout matches the build's. What could not be
|
|
40
|
+
* staged is returned, never swallowed — callers decide how loud to be.
|
|
41
|
+
*
|
|
42
|
+
* A ref that resolves to no in-project file at all is a different matter, and
|
|
43
|
+
* the two callers disagree about it: a real build refuses to ship (it throws
|
|
44
|
+
* from `onPlan`, before any bytes are copied), while the gate reports it and
|
|
45
|
+
* measures the book anyway. That is why the plan is handed out rather than
|
|
46
|
+
* judged here.
|
|
47
|
+
*/
|
|
48
|
+
export declare function stageBookAssets(options: {
|
|
49
|
+
/** Project dir every image ref resolves against. */
|
|
50
|
+
renderDir: string;
|
|
51
|
+
/** Directory the staged book is being assembled in. */
|
|
52
|
+
outDir: string;
|
|
53
|
+
/** The rendered `book.html`, rewritten in place. */
|
|
54
|
+
htmlFile: string;
|
|
55
|
+
/** Image `src` values the render reported. */
|
|
56
|
+
imageRefs: Iterable<string>;
|
|
57
|
+
/** CSS images too large to inline, already planned by the render. */
|
|
58
|
+
cssAssets: AssetCopy[];
|
|
59
|
+
/** Called once with the copy plan; throw here to abort before copying. */
|
|
60
|
+
onPlan?: (plan: StagingPlan) => void;
|
|
61
|
+
}): Promise<StagedAssets>;
|
|
11
62
|
/**
|
|
12
63
|
* Create a unique scratch directory under the OS temp dir. Used only for
|
|
13
64
|
* PDF/X intermediates (`raw.pdf`, Ghostscript work files) — never for staging
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MANIFEST_FILENAMES,
|
|
3
3
|
runLint
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-eq5naw4m.js";
|
|
5
5
|
import {
|
|
6
6
|
log
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-cqtggsng.js";
|
|
8
8
|
import {
|
|
9
9
|
UsageError,
|
|
10
10
|
rejectExtraPositionals,
|
|
11
11
|
rejectUnknownFlags
|
|
12
|
-
} from "./cli-
|
|
13
|
-
import"./cli-
|
|
12
|
+
} from "./cli-149edp6b.js";
|
|
13
|
+
import"./cli-zfcryxg8.js";
|
|
14
14
|
import"./cli-c41yr7he.js";
|
|
15
15
|
import {
|
|
16
16
|
EXIT_CODES
|
|
@@ -5,16 +5,16 @@ import {
|
|
|
5
5
|
TARGETS,
|
|
6
6
|
TARGET_IDS,
|
|
7
7
|
scaffoldProject
|
|
8
|
-
} from "./cli-
|
|
8
|
+
} from "./cli-eq5naw4m.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveGhostscript
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-cqtggsng.js";
|
|
12
12
|
import {
|
|
13
13
|
UsageError,
|
|
14
14
|
rejectExtraPositionals,
|
|
15
15
|
rejectUnknownFlags
|
|
16
|
-
} from "./cli-
|
|
17
|
-
import"./cli-
|
|
16
|
+
} from "./cli-149edp6b.js";
|
|
17
|
+
import"./cli-zfcryxg8.js";
|
|
18
18
|
import {
|
|
19
19
|
isToolAvailable
|
|
20
20
|
} from "./cli-c41yr7he.js";
|