gutterpress 0.11.18-alpha.5 → 0.11.18-alpha.7
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/{build-hc743bws.js → build-3hanyyeb.js} +4 -4
- package/dist/{cli-q90qmcvp.js → cli-kp2djrbt.js} +1 -1
- package/dist/{cli-dm3pa0cw.js → cli-ptez7zcc.js} +50 -2
- package/dist/{cli-dxs69beq.js → cli-srf2kxcm.js} +4 -19
- package/dist/{cli-bx24fj78.js → cli-z2bf2sry.js} +1 -1
- package/dist/cli.js +12 -12
- package/dist/{doctor-vq5xetqk.js → doctor-6zrg2xj3.js} +2 -2
- package/dist/engine/compiler/build.d.ts +1 -1
- package/dist/{engine-vvtkew4q.js → engine-wtnakejg.js} +1 -1
- package/dist/{engine-wjz5yhmp.js → engine-zy6fzs5a.js} +2 -2
- package/dist/{ext-zspsqk4y.js → ext-ym0ceb5j.js} +4 -4
- package/dist/{index-r2ry6j3x.js → index-dqy53qmn.js} +3 -18
- package/dist/{index-pb4fj8m2.js → index-jt552wtf.js} +2 -2
- package/dist/{index-89zg3jtk.js → index-n8vs6pss.js} +51 -2
- package/dist/index.js +3 -3
- package/dist/lib/printsafe.d.ts +0 -1
- package/dist/{manifest.schema-nc30dyfs.json → manifest.schema-5pzhscqh.json} +1 -1
- package/dist/{new-zrvm9vpe.js → new-xqpywrgr.js} +4 -4
- package/dist/{preflight-h003cdh9.js → preflight-1b5d4g0b.js} +4 -4
- package/dist/{preview-xd02xc2h.js → preview-akf5jcbj.js} +4 -4
- package/dist/{publish-1yzay4z4.js → publish-91p3wt6w.js} +4 -4
- package/dist/{theme-5729pyq1.css → theme-j2bagrfx.css} +1 -4
- package/dist/{validate-gmma4d2t.js → validate-xk731cjw.js} +4 -4
- package/package.json +1 -1
package/dist/api/index.js
CHANGED
|
@@ -136,11 +136,11 @@ import {
|
|
|
136
136
|
testRemoteAccess,
|
|
137
137
|
updateExtensions,
|
|
138
138
|
validateProjectExtensions
|
|
139
|
-
} from "../index-
|
|
139
|
+
} from "../index-dqy53qmn.js";
|
|
140
140
|
import"../index-ht1bcqdd.js";
|
|
141
141
|
import {
|
|
142
142
|
BuildError
|
|
143
|
-
} from "../index-
|
|
143
|
+
} from "../index-jt552wtf.js";
|
|
144
144
|
import {
|
|
145
145
|
DEFAULT_PRINT_OPTS,
|
|
146
146
|
assertMilestone,
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runBuild,
|
|
3
3
|
splitOutPath
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-srf2kxcm.js";
|
|
5
5
|
import {
|
|
6
6
|
log
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-z2bf2sry.js";
|
|
8
8
|
import {
|
|
9
9
|
UsageError,
|
|
10
10
|
parseFormat,
|
|
11
11
|
parsePdfxFlavor,
|
|
12
12
|
rejectExtraPositionals,
|
|
13
13
|
rejectUnknownFlags
|
|
14
|
-
} from "./cli-
|
|
14
|
+
} from "./cli-kp2djrbt.js";
|
|
15
15
|
import"./cli-ht1bcqdd.js";
|
|
16
|
-
import"./cli-
|
|
16
|
+
import"./cli-ptez7zcc.js";
|
|
17
17
|
import {
|
|
18
18
|
BuildError
|
|
19
19
|
} from "./cli-46ycxe6r.js";
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
// package.json
|
|
5
5
|
var package_default = {
|
|
6
6
|
name: "gutterpress",
|
|
7
|
-
version: "0.11.18-alpha.
|
|
7
|
+
version: "0.11.18-alpha.7",
|
|
8
8
|
description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
|
|
9
9
|
author: "itlackey",
|
|
10
10
|
license: "MPL-2.0",
|
|
@@ -1116,7 +1116,7 @@ import { fileURLToPath } from "node:url";
|
|
|
1116
1116
|
var favicon_default = "./favicon-272ga6y0.ico";
|
|
1117
1117
|
|
|
1118
1118
|
// src/assets/manifest.schema.json
|
|
1119
|
-
var manifest_schema_default = "./manifest.schema-
|
|
1119
|
+
var manifest_schema_default = "./manifest.schema-5pzhscqh.json";
|
|
1120
1120
|
|
|
1121
1121
|
// src/assets/preview/scripts/preview-interface.js
|
|
1122
1122
|
var preview_interface_default = "./preview-interface-2n1d9pbf.js";
|
|
@@ -1209,7 +1209,7 @@ var page_rules_default = "./page-rules-nsj3aw42.css";
|
|
|
1209
1209
|
var book_default = "./book-ted3tzrp.css";
|
|
1210
1210
|
|
|
1211
1211
|
// src/assets/themes/clean-book/theme.css
|
|
1212
|
-
var theme_default = "./theme-
|
|
1212
|
+
var theme_default = "./theme-j2bagrfx.css";
|
|
1213
1213
|
|
|
1214
1214
|
// src/assets/themes/clean-book/package.json
|
|
1215
1215
|
var package_default3 = "./package-97gm31sg.json";
|
|
@@ -2230,6 +2230,54 @@ ${mapCss}`;
|
|
|
2230
2230
|
if (multicol.length)
|
|
2231
2231
|
log(`audit: ${multicol.length} fragmenting multicol warning(s)`);
|
|
2232
2232
|
}
|
|
2233
|
+
{
|
|
2234
|
+
const missing = JSON.parse(await page.evaluate(`(() => {
|
|
2235
|
+
const words = new Map();
|
|
2236
|
+
const styled = new Map();
|
|
2237
|
+
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
|
|
2238
|
+
for (let n = walker.nextNode(); n; n = walker.nextNode()) {
|
|
2239
|
+
const found = n.data.match(/\\p{L}{7,}/gu);
|
|
2240
|
+
const el = n.parentElement;
|
|
2241
|
+
if (!found || !el) continue;
|
|
2242
|
+
if (!styled.has(el)) styled.set(el, getComputedStyle(el).hyphens === "auto");
|
|
2243
|
+
if (!styled.get(el)) continue;
|
|
2244
|
+
const host = el.closest("[lang]");
|
|
2245
|
+
const lang = host ? host.getAttribute("lang") : null;
|
|
2246
|
+
if (!words.has(lang)) words.set(lang, new Set());
|
|
2247
|
+
const set = words.get(lang);
|
|
2248
|
+
for (const w of found) if (set.size < 200) set.add(w);
|
|
2249
|
+
}
|
|
2250
|
+
if (!words.size) return "[]";
|
|
2251
|
+
const box = document.createElement("div");
|
|
2252
|
+
box.style.cssText = "position:absolute;left:-10000px;top:0;visibility:hidden";
|
|
2253
|
+
const probes = [];
|
|
2254
|
+
for (const [lang, set] of words) {
|
|
2255
|
+
for (const w of [...set].sort((a, b) => b.length - a.length).slice(0, 8)) {
|
|
2256
|
+
const pair = ["auto", "manual"].map((h) => {
|
|
2257
|
+
const d = document.createElement("div");
|
|
2258
|
+
if (lang !== null) d.setAttribute("lang", lang);
|
|
2259
|
+
d.style.cssText = "width:1px;font:16px/16px serif;word-break:normal;overflow-wrap:normal;hyphens:" + h;
|
|
2260
|
+
d.textContent = w;
|
|
2261
|
+
box.appendChild(d);
|
|
2262
|
+
return d;
|
|
2263
|
+
});
|
|
2264
|
+
probes.push({ lang, pair });
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
document.body.appendChild(box);
|
|
2268
|
+
const hyphenates = new Set();
|
|
2269
|
+
for (const { lang, pair } of probes)
|
|
2270
|
+
if (pair[0].offsetHeight > pair[1].offsetHeight) hyphenates.add(lang);
|
|
2271
|
+
box.remove();
|
|
2272
|
+
const ua = navigator.userAgent;
|
|
2273
|
+
const browser = (/Electron\\/[\\d.]+/.exec(ua) || /(?:HeadlessChrome|Chrome)\\/[\\d.]+/.exec(ua) || [ua])[0];
|
|
2274
|
+
return JSON.stringify([...words.keys()].filter((l) => !hyphenates.has(l)).map((lang) => ({ lang, browser })));
|
|
2275
|
+
})()`));
|
|
2276
|
+
for (const { lang, browser: browser2 } of missing)
|
|
2277
|
+
diagnose("engine.hyphenation.unsupported", `Your stylesheets set hyphens: auto, but the browser making this PDF (${browser2}) has no hyphenation dictionary for ${lang ? `"${lang}"` : "the document's language"}, so no word is hyphenated automatically and lines (and pages) break differently than in a browser that has one. Build in a browser that hyphenates, such as Chrome (which the gutterpress CLI uses), or add soft hyphens (­) where a word may break.`);
|
|
2278
|
+
if (missing.length)
|
|
2279
|
+
log(`audit: hyphenation unavailable for ${missing.length} language(s)`);
|
|
2280
|
+
}
|
|
2233
2281
|
if (bytes === undefined) {
|
|
2234
2282
|
prints++;
|
|
2235
2283
|
bytes = await printPdf(page);
|
|
@@ -13,12 +13,12 @@ import {
|
|
|
13
13
|
stampCreator,
|
|
14
14
|
stripAnnotations,
|
|
15
15
|
warn
|
|
16
|
-
} from "./cli-
|
|
16
|
+
} from "./cli-z2bf2sry.js";
|
|
17
17
|
import {
|
|
18
18
|
DEBOUNCE,
|
|
19
19
|
UsageError,
|
|
20
20
|
resolvePort
|
|
21
|
-
} from "./cli-
|
|
21
|
+
} from "./cli-kp2djrbt.js";
|
|
22
22
|
import {
|
|
23
23
|
blackTextToGray
|
|
24
24
|
} from "./cli-ht1bcqdd.js";
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
getAssetPath,
|
|
28
28
|
getAssetsDir,
|
|
29
29
|
lastPageMode
|
|
30
|
-
} from "./cli-
|
|
30
|
+
} from "./cli-ptez7zcc.js";
|
|
31
31
|
import {
|
|
32
32
|
BuildError,
|
|
33
33
|
EXIT_CODES
|
|
@@ -6351,7 +6351,6 @@ var ruleRiskyProps = "printsafe/no-risky-print-effects";
|
|
|
6351
6351
|
var ruleSyntax = "printsafe/syntax-error";
|
|
6352
6352
|
var rulePageContainment = "printsafe/page-containment";
|
|
6353
6353
|
var rulePreviewCannotFollow = "printsafe/preview-cannot-follow";
|
|
6354
|
-
var ruleEngineHyphenation = "printsafe/engine-hyphenation";
|
|
6355
6354
|
function extractUrls(value) {
|
|
6356
6355
|
const urls = [];
|
|
6357
6356
|
const re = /url\(\s*(['"]?)(.*?)\1\s*\)/gi;
|
|
@@ -6553,10 +6552,6 @@ function previewBlindSpot(decl) {
|
|
|
6553
6552
|
}
|
|
6554
6553
|
return null;
|
|
6555
6554
|
}
|
|
6556
|
-
function isAutoHyphenation(decl) {
|
|
6557
|
-
const prop = decl.prop.toLowerCase();
|
|
6558
|
-
return (prop === "hyphens" || prop === "-webkit-hyphens") && decl.value.trim().toLowerCase() === "auto";
|
|
6559
|
-
}
|
|
6560
6555
|
function nodeLoc(node) {
|
|
6561
6556
|
return {
|
|
6562
6557
|
line: node.source?.start?.line ?? 1,
|
|
@@ -6675,16 +6670,6 @@ function checkCssRaw(css, from) {
|
|
|
6675
6670
|
warnings.push({ rule: rulePreviewCannotFollow, severity: "warning", message, ...nodeLoc(decl) });
|
|
6676
6671
|
}
|
|
6677
6672
|
});
|
|
6678
|
-
root.walkDecls((decl) => {
|
|
6679
|
-
if (!isAutoHyphenation(decl))
|
|
6680
|
-
return;
|
|
6681
|
-
warnings.push({
|
|
6682
|
-
rule: ruleEngineHyphenation,
|
|
6683
|
-
severity: "warning",
|
|
6684
|
-
message: `"${decl.prop}: auto" depends on the browser's hyphenation dictionaries, so the desktop app and the CLI (and different operating systems) can break lines and pages differently. Use "hyphens: manual" with soft hyphens (­) for identical pages everywhere.`,
|
|
6685
|
-
...nodeLoc(decl)
|
|
6686
|
-
});
|
|
6687
|
-
});
|
|
6688
6673
|
root.walkRules((rule) => {
|
|
6689
6674
|
if (rule.parent?.type === "atrule") {
|
|
6690
6675
|
const at = rule.parent.name.toLowerCase();
|
|
@@ -10097,7 +10082,7 @@ class PdfOutput {
|
|
|
10097
10082
|
const rawPdf = pdfxMode ? path13.join(stage, "raw.pdf") : path13.resolve(pdfFile);
|
|
10098
10083
|
await fsp2.mkdir(path13.dirname(path13.resolve(pdfFile)), { recursive: true });
|
|
10099
10084
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
10100
|
-
const { buildNativePdf } = await import("./engine-
|
|
10085
|
+
const { buildNativePdf } = await import("./engine-wtnakejg.js");
|
|
10101
10086
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
10102
10087
|
title: config.title,
|
|
10103
10088
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
package/dist/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
UsageError,
|
|
7
7
|
package_default,
|
|
8
8
|
rejectUnknownFlags
|
|
9
|
-
} from "./cli-
|
|
9
|
+
} from "./cli-kp2djrbt.js";
|
|
10
10
|
import {
|
|
11
11
|
EXIT_CODES
|
|
12
12
|
} from "./cli-46ycxe6r.js";
|
|
@@ -18,14 +18,14 @@ import {
|
|
|
18
18
|
import { defineCommand, parseArgs, runMain } from "citty";
|
|
19
19
|
import { statSync } from "node:fs";
|
|
20
20
|
var SUBCOMMANDS = {
|
|
21
|
-
new: () => import("./new-
|
|
22
|
-
preview: () => import("./preview-
|
|
23
|
-
build: () => import("./build-
|
|
24
|
-
publish: () => import("./publish-
|
|
25
|
-
validate: () => import("./validate-
|
|
26
|
-
preflight: () => import("./preflight-
|
|
27
|
-
doctor: () => import("./doctor-
|
|
28
|
-
ext: () => import("./ext-
|
|
21
|
+
new: () => import("./new-xqpywrgr.js").then((m) => m.default),
|
|
22
|
+
preview: () => import("./preview-akf5jcbj.js").then((m) => m.default),
|
|
23
|
+
build: () => import("./build-3hanyyeb.js").then((m) => m.default),
|
|
24
|
+
publish: () => import("./publish-91p3wt6w.js").then((m) => m.default),
|
|
25
|
+
validate: () => import("./validate-xk731cjw.js").then((m) => m.default),
|
|
26
|
+
preflight: () => import("./preflight-1b5d4g0b.js").then((m) => m.default),
|
|
27
|
+
doctor: () => import("./doctor-6zrg2xj3.js").then((m) => m.default),
|
|
28
|
+
ext: () => import("./ext-ym0ceb5j.js").then((m) => m.default)
|
|
29
29
|
};
|
|
30
30
|
var VERSION = package_default.version;
|
|
31
31
|
var main = defineCommand({
|
|
@@ -50,7 +50,7 @@ async function preflightRequiredInvocations(rawArgs) {
|
|
|
50
50
|
const [command, ...commandArgs] = rawArgs;
|
|
51
51
|
try {
|
|
52
52
|
if (command === "new") {
|
|
53
|
-
const { newArgs } = await import("./new-
|
|
53
|
+
const { newArgs } = await import("./new-xqpywrgr.js");
|
|
54
54
|
rejectUnknownFlags(commandArgs, newArgs, "new");
|
|
55
55
|
const parsed = parseArgs(commandArgs, {
|
|
56
56
|
...newArgs,
|
|
@@ -62,7 +62,7 @@ async function preflightRequiredInvocations(rawArgs) {
|
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
64
|
if (command === "preflight") {
|
|
65
|
-
const { preflightArgs } = await import("./preflight-
|
|
65
|
+
const { preflightArgs } = await import("./preflight-1b5d4g0b.js");
|
|
66
66
|
rejectUnknownFlags(commandArgs, preflightArgs, "preflight");
|
|
67
67
|
const parsed = parseArgs(commandArgs, {
|
|
68
68
|
...preflightArgs,
|
|
@@ -82,7 +82,7 @@ async function preflightRequiredInvocations(rawArgs) {
|
|
|
82
82
|
}
|
|
83
83
|
if (subcommand.startsWith("-"))
|
|
84
84
|
return;
|
|
85
|
-
const { EXT_SUBCOMMANDS, extAddArgs, extRemoveArgs, extEnableArgs, extDisableArgs } = await import("./ext-
|
|
85
|
+
const { EXT_SUBCOMMANDS, extAddArgs, extRemoveArgs, extEnableArgs, extDisableArgs } = await import("./ext-ym0ceb5j.js");
|
|
86
86
|
if (!EXT_SUBCOMMANDS.includes(subcommand)) {
|
|
87
87
|
throw new UsageError(`gutterpress ext: unknown command "${subcommand}"`);
|
|
88
88
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getSystemDiagnostics,
|
|
3
3
|
log
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-z2bf2sry.js";
|
|
5
5
|
import {
|
|
6
6
|
UsageError,
|
|
7
7
|
rejectExtraPositionals,
|
|
8
8
|
rejectUnknownFlags
|
|
9
|
-
} from "./cli-
|
|
9
|
+
} from "./cli-kp2djrbt.js";
|
|
10
10
|
import"./cli-46ycxe6r.js";
|
|
11
11
|
import"./cli-7fkhgtfn.js";
|
|
12
12
|
import"./cli-37x76zdn.js";
|
|
@@ -8,7 +8,7 @@ import { type PostprocessResult } from "./postprocess.ts";
|
|
|
8
8
|
* set is closed here so a surface's label table can be asserted complete
|
|
9
9
|
* against it rather than drifting silently as checks are added.
|
|
10
10
|
*/
|
|
11
|
-
export type BuildDiagnosticCode = "engine.width.overflow" | "engine.width.intrinsic" | "engine.xref.broken" | "engine.abspos.leak" | "engine.layer.trapped" | "engine.multicol.dead-column" | "engine.content.overheight" | "engine.image.low-dpi" | "engine.flush.margin-box" | "engine.page-background.unreferenced";
|
|
11
|
+
export type BuildDiagnosticCode = "engine.width.overflow" | "engine.width.intrinsic" | "engine.xref.broken" | "engine.abspos.leak" | "engine.layer.trapped" | "engine.multicol.dead-column" | "engine.content.overheight" | "engine.image.low-dpi" | "engine.flush.margin-box" | "engine.page-background.unreferenced" | "engine.hyphenation.unsupported";
|
|
12
12
|
export declare const BUILD_DIAGNOSTIC_CODES: readonly BuildDiagnosticCode[];
|
|
13
13
|
export interface BuildDiagnostic {
|
|
14
14
|
code: BuildDiagnosticCode;
|
|
@@ -12,17 +12,17 @@ import {
|
|
|
12
12
|
searchNpmExtensions,
|
|
13
13
|
setExtensionEnabled,
|
|
14
14
|
updateExtensions
|
|
15
|
-
} from "./cli-
|
|
16
|
-
import"./cli-
|
|
15
|
+
} from "./cli-srf2kxcm.js";
|
|
16
|
+
import"./cli-z2bf2sry.js";
|
|
17
17
|
import {
|
|
18
18
|
UsageError,
|
|
19
19
|
exitForUsage,
|
|
20
20
|
rejectExtraPositionals,
|
|
21
21
|
rejectUnknownFlags,
|
|
22
22
|
resolveProjectDir
|
|
23
|
-
} from "./cli-
|
|
23
|
+
} from "./cli-kp2djrbt.js";
|
|
24
24
|
import"./cli-ht1bcqdd.js";
|
|
25
|
-
import"./cli-
|
|
25
|
+
import"./cli-ptez7zcc.js";
|
|
26
26
|
import {
|
|
27
27
|
EXIT_CODES
|
|
28
28
|
} from "./cli-46ycxe6r.js";
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
getAssetsDir,
|
|
10
10
|
lastPageMode,
|
|
11
11
|
parseSize
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-jt552wtf.js";
|
|
13
13
|
import {
|
|
14
14
|
INSTALL_HINTS,
|
|
15
15
|
execCapture,
|
|
@@ -5916,7 +5916,7 @@ import git from "isomorphic-git";
|
|
|
5916
5916
|
// package.json
|
|
5917
5917
|
var package_default = {
|
|
5918
5918
|
name: "gutterpress",
|
|
5919
|
-
version: "0.11.18-alpha.
|
|
5919
|
+
version: "0.11.18-alpha.7",
|
|
5920
5920
|
description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
|
|
5921
5921
|
author: "itlackey",
|
|
5922
5922
|
license: "MPL-2.0",
|
|
@@ -7787,7 +7787,6 @@ var ruleRiskyProps = "printsafe/no-risky-print-effects";
|
|
|
7787
7787
|
var ruleSyntax = "printsafe/syntax-error";
|
|
7788
7788
|
var rulePageContainment = "printsafe/page-containment";
|
|
7789
7789
|
var rulePreviewCannotFollow = "printsafe/preview-cannot-follow";
|
|
7790
|
-
var ruleEngineHyphenation = "printsafe/engine-hyphenation";
|
|
7791
7790
|
function extractUrls(value) {
|
|
7792
7791
|
const urls = [];
|
|
7793
7792
|
const re = /url\(\s*(['"]?)(.*?)\1\s*\)/gi;
|
|
@@ -7989,10 +7988,6 @@ function previewBlindSpot(decl) {
|
|
|
7989
7988
|
}
|
|
7990
7989
|
return null;
|
|
7991
7990
|
}
|
|
7992
|
-
function isAutoHyphenation(decl) {
|
|
7993
|
-
const prop = decl.prop.toLowerCase();
|
|
7994
|
-
return (prop === "hyphens" || prop === "-webkit-hyphens") && decl.value.trim().toLowerCase() === "auto";
|
|
7995
|
-
}
|
|
7996
7991
|
function nodeLoc(node) {
|
|
7997
7992
|
return {
|
|
7998
7993
|
line: node.source?.start?.line ?? 1,
|
|
@@ -8111,16 +8106,6 @@ function checkCssRaw(css, from) {
|
|
|
8111
8106
|
warnings.push({ rule: rulePreviewCannotFollow, severity: "warning", message, ...nodeLoc(decl) });
|
|
8112
8107
|
}
|
|
8113
8108
|
});
|
|
8114
|
-
root.walkDecls((decl) => {
|
|
8115
|
-
if (!isAutoHyphenation(decl))
|
|
8116
|
-
return;
|
|
8117
|
-
warnings.push({
|
|
8118
|
-
rule: ruleEngineHyphenation,
|
|
8119
|
-
severity: "warning",
|
|
8120
|
-
message: `"${decl.prop}: auto" depends on the browser's hyphenation dictionaries, so the desktop app and the CLI (and different operating systems) can break lines and pages differently. Use "hyphens: manual" with soft hyphens (­) for identical pages everywhere.`,
|
|
8121
|
-
...nodeLoc(decl)
|
|
8122
|
-
});
|
|
8123
|
-
});
|
|
8124
8109
|
root.walkRules((rule) => {
|
|
8125
8110
|
if (rule.parent?.type === "atrule") {
|
|
8126
8111
|
const at = rule.parent.name.toLowerCase();
|
|
@@ -10677,7 +10662,7 @@ class PdfOutput {
|
|
|
10677
10662
|
const rawPdf = pdfxMode ? path13.join(stage, "raw.pdf") : path13.resolve(pdfFile);
|
|
10678
10663
|
await fsp2.mkdir(path13.dirname(path13.resolve(pdfFile)), { recursive: true });
|
|
10679
10664
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
10680
|
-
const { buildNativePdf } = await import("./engine-
|
|
10665
|
+
const { buildNativePdf } = await import("./engine-zy6fzs5a.js");
|
|
10681
10666
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
10682
10667
|
title: config.title,
|
|
10683
10668
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
@@ -148,7 +148,7 @@ import { fileURLToPath } from "node:url";
|
|
|
148
148
|
var favicon_default = "./favicon-272ga6y0.ico";
|
|
149
149
|
|
|
150
150
|
// src/assets/manifest.schema.json
|
|
151
|
-
var manifest_schema_default = "./manifest.schema-
|
|
151
|
+
var manifest_schema_default = "./manifest.schema-5pzhscqh.json";
|
|
152
152
|
|
|
153
153
|
// src/assets/preview/scripts/preview-interface.js
|
|
154
154
|
var preview_interface_default = "./preview-interface-2n1d9pbf.js";
|
|
@@ -241,7 +241,7 @@ var page_rules_default = "./page-rules-nsj3aw42.css";
|
|
|
241
241
|
var book_default = "./book-ted3tzrp.css";
|
|
242
242
|
|
|
243
243
|
// src/assets/themes/clean-book/theme.css
|
|
244
|
-
var theme_default = "./theme-
|
|
244
|
+
var theme_default = "./theme-j2bagrfx.css";
|
|
245
245
|
|
|
246
246
|
// src/assets/themes/clean-book/package.json
|
|
247
247
|
var package_default3 = "./package-97gm31sg.json";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
stringValueAt,
|
|
20
20
|
toFolioPage,
|
|
21
21
|
wantsRecto
|
|
22
|
-
} from "./index-
|
|
22
|
+
} from "./index-jt552wtf.js";
|
|
23
23
|
import {
|
|
24
24
|
launchChromium
|
|
25
25
|
} from "./index-rzm1phg0.js";
|
|
@@ -724,7 +724,8 @@ var BUILD_DIAGNOSTIC_CODES = [
|
|
|
724
724
|
"engine.content.overheight",
|
|
725
725
|
"engine.image.low-dpi",
|
|
726
726
|
"engine.flush.margin-box",
|
|
727
|
-
"engine.page-background.unreferenced"
|
|
727
|
+
"engine.page-background.unreferenced",
|
|
728
|
+
"engine.hyphenation.unsupported"
|
|
728
729
|
];
|
|
729
730
|
async function build(opts) {
|
|
730
731
|
const log = opts.onProgress ?? (() => {});
|
|
@@ -1333,6 +1334,54 @@ ${mapCss}`;
|
|
|
1333
1334
|
if (multicol.length)
|
|
1334
1335
|
log(`audit: ${multicol.length} fragmenting multicol warning(s)`);
|
|
1335
1336
|
}
|
|
1337
|
+
{
|
|
1338
|
+
const missing = JSON.parse(await page.evaluate(`(() => {
|
|
1339
|
+
const words = new Map();
|
|
1340
|
+
const styled = new Map();
|
|
1341
|
+
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
|
|
1342
|
+
for (let n = walker.nextNode(); n; n = walker.nextNode()) {
|
|
1343
|
+
const found = n.data.match(/\\p{L}{7,}/gu);
|
|
1344
|
+
const el = n.parentElement;
|
|
1345
|
+
if (!found || !el) continue;
|
|
1346
|
+
if (!styled.has(el)) styled.set(el, getComputedStyle(el).hyphens === "auto");
|
|
1347
|
+
if (!styled.get(el)) continue;
|
|
1348
|
+
const host = el.closest("[lang]");
|
|
1349
|
+
const lang = host ? host.getAttribute("lang") : null;
|
|
1350
|
+
if (!words.has(lang)) words.set(lang, new Set());
|
|
1351
|
+
const set = words.get(lang);
|
|
1352
|
+
for (const w of found) if (set.size < 200) set.add(w);
|
|
1353
|
+
}
|
|
1354
|
+
if (!words.size) return "[]";
|
|
1355
|
+
const box = document.createElement("div");
|
|
1356
|
+
box.style.cssText = "position:absolute;left:-10000px;top:0;visibility:hidden";
|
|
1357
|
+
const probes = [];
|
|
1358
|
+
for (const [lang, set] of words) {
|
|
1359
|
+
for (const w of [...set].sort((a, b) => b.length - a.length).slice(0, 8)) {
|
|
1360
|
+
const pair = ["auto", "manual"].map((h) => {
|
|
1361
|
+
const d = document.createElement("div");
|
|
1362
|
+
if (lang !== null) d.setAttribute("lang", lang);
|
|
1363
|
+
d.style.cssText = "width:1px;font:16px/16px serif;word-break:normal;overflow-wrap:normal;hyphens:" + h;
|
|
1364
|
+
d.textContent = w;
|
|
1365
|
+
box.appendChild(d);
|
|
1366
|
+
return d;
|
|
1367
|
+
});
|
|
1368
|
+
probes.push({ lang, pair });
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
document.body.appendChild(box);
|
|
1372
|
+
const hyphenates = new Set();
|
|
1373
|
+
for (const { lang, pair } of probes)
|
|
1374
|
+
if (pair[0].offsetHeight > pair[1].offsetHeight) hyphenates.add(lang);
|
|
1375
|
+
box.remove();
|
|
1376
|
+
const ua = navigator.userAgent;
|
|
1377
|
+
const browser = (/Electron\\/[\\d.]+/.exec(ua) || /(?:HeadlessChrome|Chrome)\\/[\\d.]+/.exec(ua) || [ua])[0];
|
|
1378
|
+
return JSON.stringify([...words.keys()].filter((l) => !hyphenates.has(l)).map((lang) => ({ lang, browser })));
|
|
1379
|
+
})()`));
|
|
1380
|
+
for (const { lang, browser: browser2 } of missing)
|
|
1381
|
+
diagnose("engine.hyphenation.unsupported", `Your stylesheets set hyphens: auto, but the browser making this PDF (${browser2}) has no hyphenation dictionary for ${lang ? `"${lang}"` : "the document's language"}, so no word is hyphenated automatically and lines (and pages) break differently than in a browser that has one. Build in a browser that hyphenates, such as Chrome (which the gutterpress CLI uses), or add soft hyphens (­) where a word may break.`);
|
|
1382
|
+
if (missing.length)
|
|
1383
|
+
log(`audit: hyphenation unavailable for ${missing.length} language(s)`);
|
|
1384
|
+
}
|
|
1336
1385
|
if (bytes === undefined) {
|
|
1337
1386
|
prints++;
|
|
1338
1387
|
bytes = await printPdf(page);
|
package/dist/index.js
CHANGED
|
@@ -153,14 +153,14 @@ import {
|
|
|
153
153
|
testRemoteAccess,
|
|
154
154
|
updateExtensions,
|
|
155
155
|
validateProjectExtensions
|
|
156
|
-
} from "./index-
|
|
156
|
+
} from "./index-dqy53qmn.js";
|
|
157
157
|
import"./index-ht1bcqdd.js";
|
|
158
158
|
import {
|
|
159
159
|
BUILD_DIAGNOSTIC_CODES
|
|
160
|
-
} from "./index-
|
|
160
|
+
} from "./index-n8vs6pss.js";
|
|
161
161
|
import {
|
|
162
162
|
BuildError
|
|
163
|
-
} from "./index-
|
|
163
|
+
} from "./index-jt552wtf.js";
|
|
164
164
|
import {
|
|
165
165
|
DEFAULT_PRINT_OPTS,
|
|
166
166
|
assertMilestone,
|
package/dist/lib/printsafe.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ export declare const ruleRiskyProps = "printsafe/no-risky-print-effects";
|
|
|
3
3
|
export declare const ruleSyntax = "printsafe/syntax-error";
|
|
4
4
|
export declare const rulePageContainment = "printsafe/page-containment";
|
|
5
5
|
export declare const rulePreviewCannotFollow = "printsafe/preview-cannot-follow";
|
|
6
|
-
export declare const ruleEngineHyphenation = "printsafe/engine-hyphenation";
|
|
7
6
|
export interface PrintSafeWarning {
|
|
8
7
|
rule: string;
|
|
9
8
|
severity: "error" | "warning";
|
|
@@ -243,7 +243,7 @@
|
|
|
243
243
|
},
|
|
244
244
|
"rules": {
|
|
245
245
|
"type": "object",
|
|
246
|
-
"description": "Per-rule level overrides, keyed by rule id: a printsafe rule (printsafe/no-risky-print-effects, printsafe/page-containment, printsafe/preview-cannot-follow, printsafe/
|
|
246
|
+
"description": "Per-rule level overrides, keyed by rule id: a printsafe rule (printsafe/no-risky-print-effects, printsafe/page-containment, printsafe/preview-cannot-follow, printsafe/no-remote-urls) or a check id such as source.accessibility.heading-order. \"off\" silences the rule; \"warn\" / \"error\" set its severity. An id that matches no rule is ignored. To silence one site instead, put a `gutterpress-disable-next-line <rule-id> -- reason` comment (CSS `/* */` or markdown `<!-- -->`) on the line above it.",
|
|
247
247
|
"additionalProperties": { "enum": ["off", "warn", "error"] },
|
|
248
248
|
"examples": [{ "printsafe/no-risky-print-effects": "off" }]
|
|
249
249
|
}
|
|
@@ -7,17 +7,17 @@ import {
|
|
|
7
7
|
TARGET_IDS,
|
|
8
8
|
scaffoldExtension,
|
|
9
9
|
scaffoldProject
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-srf2kxcm.js";
|
|
11
11
|
import {
|
|
12
12
|
resolveGhostscript
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-z2bf2sry.js";
|
|
14
14
|
import {
|
|
15
15
|
UsageError,
|
|
16
16
|
rejectExtraPositionals,
|
|
17
17
|
rejectUnknownFlags
|
|
18
|
-
} from "./cli-
|
|
18
|
+
} from "./cli-kp2djrbt.js";
|
|
19
19
|
import"./cli-ht1bcqdd.js";
|
|
20
|
-
import"./cli-
|
|
20
|
+
import"./cli-ptez7zcc.js";
|
|
21
21
|
import {
|
|
22
22
|
EXIT_CODES
|
|
23
23
|
} from "./cli-46ycxe6r.js";
|
|
@@ -2,17 +2,17 @@ import {
|
|
|
2
2
|
executeValidation,
|
|
3
3
|
publishTargetFor,
|
|
4
4
|
reportMissingTools
|
|
5
|
-
} from "./cli-
|
|
5
|
+
} from "./cli-srf2kxcm.js";
|
|
6
6
|
import {
|
|
7
7
|
log
|
|
8
|
-
} from "./cli-
|
|
8
|
+
} from "./cli-z2bf2sry.js";
|
|
9
9
|
import {
|
|
10
10
|
UsageError,
|
|
11
11
|
rejectExtraPositionals,
|
|
12
12
|
rejectUnknownFlags
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-kp2djrbt.js";
|
|
14
14
|
import"./cli-ht1bcqdd.js";
|
|
15
|
-
import"./cli-
|
|
15
|
+
import"./cli-ptez7zcc.js";
|
|
16
16
|
import {
|
|
17
17
|
BuildError,
|
|
18
18
|
EXIT_CODES
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
runBuild,
|
|
8
8
|
splitOutPath,
|
|
9
9
|
startPreviewServer
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-srf2kxcm.js";
|
|
11
11
|
import {
|
|
12
12
|
log
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-z2bf2sry.js";
|
|
14
14
|
import {
|
|
15
15
|
UsageError,
|
|
16
16
|
parseFormat,
|
|
@@ -18,9 +18,9 @@ import {
|
|
|
18
18
|
rejectExtraPositionals,
|
|
19
19
|
rejectUnknownFlags,
|
|
20
20
|
resolvePort
|
|
21
|
-
} from "./cli-
|
|
21
|
+
} from "./cli-kp2djrbt.js";
|
|
22
22
|
import"./cli-ht1bcqdd.js";
|
|
23
|
-
import"./cli-
|
|
23
|
+
import"./cli-ptez7zcc.js";
|
|
24
24
|
import {
|
|
25
25
|
BuildError
|
|
26
26
|
} from "./cli-46ycxe6r.js";
|
|
@@ -11,18 +11,18 @@ import {
|
|
|
11
11
|
publishProviderFor,
|
|
12
12
|
resolvePublishFormat,
|
|
13
13
|
runPublish
|
|
14
|
-
} from "./cli-
|
|
14
|
+
} from "./cli-srf2kxcm.js";
|
|
15
15
|
import {
|
|
16
16
|
FileTokenStore,
|
|
17
17
|
log
|
|
18
|
-
} from "./cli-
|
|
18
|
+
} from "./cli-z2bf2sry.js";
|
|
19
19
|
import {
|
|
20
20
|
UsageError,
|
|
21
21
|
rejectExtraPositionals,
|
|
22
22
|
rejectUnknownFlags
|
|
23
|
-
} from "./cli-
|
|
23
|
+
} from "./cli-kp2djrbt.js";
|
|
24
24
|
import"./cli-ht1bcqdd.js";
|
|
25
|
-
import"./cli-
|
|
25
|
+
import"./cli-ptez7zcc.js";
|
|
26
26
|
import {
|
|
27
27
|
EXIT_CODES
|
|
28
28
|
} from "./cli-46ycxe6r.js";
|
|
@@ -44,10 +44,7 @@ h1 { font-size: var(--fs-h1); margin: 0 0 0.6em; }
|
|
|
44
44
|
h2 { font-size: var(--fs-h2); margin: 1.4em 0 0.4em; }
|
|
45
45
|
h3 { font-size: var(--fs-h3); margin: 1.2em 0 0.3em; }
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
ships dictionaries (desktop app and CLI differ), which changes the page count.
|
|
49
|
-
Authors add soft hyphens (­) where they want a break. */
|
|
50
|
-
p { margin: 0 0 0.8em; text-align: justify; hyphens: manual; }
|
|
47
|
+
p { margin: 0 0 0.8em; text-align: justify; hyphens: auto; }
|
|
51
48
|
|
|
52
49
|
a { color: var(--color-accent); text-decoration: none; }
|
|
53
50
|
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
executeAndReport
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-srf2kxcm.js";
|
|
4
4
|
import {
|
|
5
5
|
log
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-z2bf2sry.js";
|
|
7
7
|
import {
|
|
8
8
|
UsageError,
|
|
9
9
|
rejectExtraPositionals,
|
|
10
10
|
rejectUnknownFlags
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-kp2djrbt.js";
|
|
12
12
|
import"./cli-ht1bcqdd.js";
|
|
13
|
-
import"./cli-
|
|
13
|
+
import"./cli-ptez7zcc.js";
|
|
14
14
|
import {
|
|
15
15
|
BuildError,
|
|
16
16
|
EXIT_CODES
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gutterpress",
|
|
3
|
-
"version": "0.11.18-alpha.
|
|
3
|
+
"version": "0.11.18-alpha.7",
|
|
4
4
|
"description": "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
|
|
5
5
|
"author": "itlackey",
|
|
6
6
|
"license": "MPL-2.0",
|