gutterpress 0.11.20-alpha.3 → 0.11.20-alpha.4
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-a8ycsg80.js → build-epdcrm2c.js} +4 -4
- package/dist/{cli-9k2tb493.js → cli-0ey902sx.js} +90 -28
- package/dist/{cli-x4p99w8d.js → cli-61vd4ews.js} +83 -41
- package/dist/{cli-hn9pk0hp.js → cli-fmksazej.js} +1 -1
- package/dist/{cli-y9bcya7r.js → cli-h4tfmpg3.js} +2 -2
- package/dist/cli.js +12 -12
- package/dist/{doctor-wbjkrcpc.js → doctor-78es5scm.js} +2 -2
- package/dist/engine/compiler/build.d.ts +1 -1
- package/dist/engine/shared/margin-box-support.d.ts +2 -2
- package/dist/engine/shared/pin-edges.d.ts +127 -0
- package/dist/engine/shared/print-area.d.ts +68 -0
- package/dist/{engine-yxnnp3hx.js → engine-67f68bxs.js} +1 -1
- package/dist/{engine-fdtv01a2.js → engine-7ha27n2b.js} +2 -2
- package/dist/{ext-pesyrs68.js → ext-9mc7sr0d.js} +4 -4
- package/dist/{gutterpress-agent-cazqstr1.js → gutterpress-agent-mrdnwktc.js} +78 -13
- package/dist/{gutterpress-viewer-1yse8cx3.js → gutterpress-viewer-jr30yw8t.js} +143 -52
- package/dist/{index-r87y7wzw.js → index-ad95fws8.js} +82 -40
- package/dist/{index-zagagnwq.js → index-gm5xbx5w.js} +3 -3
- package/dist/{index-tjvrchxj.js → index-t13p8y08.js} +199 -137
- package/dist/index.js +3 -3
- package/dist/lib/extension-manifest.d.ts +13 -0
- package/dist/lib/markdown/assemble.d.ts +12 -2
- package/dist/lib/markdown/gutterpress-css.d.ts +46 -30
- package/dist/lib/markdown/index.d.ts +5 -0
- package/dist/{manifest.schema-c9x8912a.json → manifest.schema-13dfax80.json} +3 -3
- package/dist/{new-8yah8z91.js → new-s4f0tnya.js} +4 -4
- package/dist/{preflight-8ccx4kdc.js → preflight-7ck4rbsq.js} +4 -4
- package/dist/preview/file-watcher.d.ts +4 -10
- package/dist/{preview-w7v9w36q.js → preview-j91sxadd.js} +4 -4
- package/dist/{publish-g5nh5myh.js → publish-f12xaenm.js} +4 -4
- package/dist/render.js +57 -6
- package/dist/schema/manifest.types.d.ts +8 -6
- package/dist/{validate-1yh59x0x.js → validate-pb5gysvr.js} +4 -4
- package/package.json +1 -1
- package/dist/engine/shared/flush.d.ts +0 -59
package/dist/api/index.js
CHANGED
|
@@ -137,11 +137,11 @@ import {
|
|
|
137
137
|
testRemoteAccess,
|
|
138
138
|
updateExtensions,
|
|
139
139
|
validateProjectExtensions
|
|
140
|
-
} from "../index-
|
|
140
|
+
} from "../index-t13p8y08.js";
|
|
141
141
|
import"../index-ht1bcqdd.js";
|
|
142
142
|
import {
|
|
143
143
|
BuildError
|
|
144
|
-
} from "../index-
|
|
144
|
+
} from "../index-gm5xbx5w.js";
|
|
145
145
|
import"../index-sth219v1.js";
|
|
146
146
|
import {
|
|
147
147
|
DEFAULT_PRINT_OPTS,
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runBuild,
|
|
3
3
|
splitOutPath
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-0ey902sx.js";
|
|
5
5
|
import {
|
|
6
6
|
log
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-h4tfmpg3.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-fmksazej.js";
|
|
15
15
|
import"./cli-ht1bcqdd.js";
|
|
16
|
-
import"./cli-
|
|
16
|
+
import"./cli-61vd4ews.js";
|
|
17
17
|
import {
|
|
18
18
|
BuildError
|
|
19
19
|
} from "./cli-46ycxe6r.js";
|
|
@@ -16,12 +16,12 @@ import {
|
|
|
16
16
|
stripAnnotations,
|
|
17
17
|
transparentPages,
|
|
18
18
|
warn
|
|
19
|
-
} from "./cli-
|
|
19
|
+
} from "./cli-h4tfmpg3.js";
|
|
20
20
|
import {
|
|
21
21
|
DEBOUNCE,
|
|
22
22
|
UsageError,
|
|
23
23
|
resolvePort
|
|
24
|
-
} from "./cli-
|
|
24
|
+
} from "./cli-fmksazej.js";
|
|
25
25
|
import {
|
|
26
26
|
blackTextToGray
|
|
27
27
|
} from "./cli-ht1bcqdd.js";
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
getAssetPath,
|
|
31
31
|
getAssetsDir,
|
|
32
32
|
lastPageMode
|
|
33
|
-
} from "./cli-
|
|
33
|
+
} from "./cli-61vd4ews.js";
|
|
34
34
|
import {
|
|
35
35
|
BuildError,
|
|
36
36
|
EXIT_CODES
|
|
@@ -701,6 +701,7 @@ function resolveDeclaredStyles(rawStyles, baseDir, subject) {
|
|
|
701
701
|
// src/lib/extension-manifest.ts
|
|
702
702
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
703
703
|
import path from "node:path";
|
|
704
|
+
import { satisfies, validRange } from "semver";
|
|
704
705
|
var EXTENSION_MANIFEST_FILENAME = "package.json";
|
|
705
706
|
var GUTTERPRESS_KEY = "gutterpress";
|
|
706
707
|
function object(value) {
|
|
@@ -724,6 +725,7 @@ function metaFromPackageJson(raw) {
|
|
|
724
725
|
...str(pkg.description) ? { description: str(pkg.description) } : {},
|
|
725
726
|
...keywords ? { keywords } : {},
|
|
726
727
|
...str(pkg.main) ? { main: str(pkg.main) } : {},
|
|
728
|
+
...str(object(pkg.engines)?.gutterpress) ? { gutterpressRange: str(object(pkg.engines)?.gutterpress) } : {},
|
|
727
729
|
..."preview" in gp ? { preview: str(gp.preview) ?? null } : {},
|
|
728
730
|
...Array.isArray(gp.styles) ? { styles: declaredList(gp.styles) } : {},
|
|
729
731
|
...str(gp.tokensFile) ? { tokensFile: str(gp.tokensFile) } : {},
|
|
@@ -760,6 +762,17 @@ function extensionCarries(meta) {
|
|
|
760
762
|
function pathEscapesFolder(rel) {
|
|
761
763
|
return path.isAbsolute(rel) || rel.split(/[\\/]/).includes("..");
|
|
762
764
|
}
|
|
765
|
+
function assertSupportsThisGutterpress(meta, ref) {
|
|
766
|
+
const range = meta.gutterpressRange;
|
|
767
|
+
if (range === undefined)
|
|
768
|
+
return;
|
|
769
|
+
if (!validRange(range)) {
|
|
770
|
+
throw new Error(`Extension "${ref}" has an invalid engines.gutterpress range "${range}".`);
|
|
771
|
+
}
|
|
772
|
+
if (!satisfies(PACKAGE_VERSION, range, { includePrerelease: true })) {
|
|
773
|
+
throw new Error(`Extension "${ref}" needs Gutterpress ${range} (its package.json engines.gutterpress); ` + `this is Gutterpress ${PACKAGE_VERSION}. Update Gutterpress, or pin an older version of the extension.`);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
763
776
|
function assertExtensionContained(meta) {
|
|
764
777
|
if (meta.engineStyles !== undefined) {
|
|
765
778
|
throw new Error("The extension's metadata declares `engineStyles`, which was removed — " + "move its entries to the end of `styles`.");
|
|
@@ -2031,7 +2044,9 @@ var GUTTERPRESS_CSS = `
|
|
|
2031
2044
|
cap at equal specificity */
|
|
2032
2045
|
.gp-small { width: 25%; max-width: 100%; }
|
|
2033
2046
|
.gp-medium { width: 50%; max-width: 100%; }
|
|
2034
|
-
.gp-large { width:
|
|
2047
|
+
.gp-large { width: 60%; max-width: 100%; }
|
|
2048
|
+
.gp-xl { width: 80%; max-width: 100%; }
|
|
2049
|
+
.gp-xxl { width: 90%; max-width: 100%; }
|
|
2035
2050
|
|
|
2036
2051
|
/* float clearance presets — consumed by var(--gp-gap) in the float rules
|
|
2037
2052
|
above and by .gp-shape's shape-margin below; --gp-gap itself is
|
|
@@ -2089,10 +2104,16 @@ img.gp-shape {
|
|
|
2089
2104
|
}
|
|
2090
2105
|
|
|
2091
2106
|
/* pin — within the nearest positioned ancestor (.page/.spread, rule above).
|
|
2092
|
-
|
|
2107
|
+
The four insets are the pin box: 0 (the text block's edge) unless an
|
|
2108
|
+
engine set --gp-pin-<edge> on the page root for an edge a pin uses (the
|
|
2109
|
+
art-safe line). Non-auto insets and the explicit centers are
|
|
2110
|
+
load-bearing; see doctrine comment. */
|
|
2093
2111
|
.gp-pin {
|
|
2094
2112
|
position: absolute;
|
|
2095
|
-
|
|
2113
|
+
top: var(--gp-pin-top, 0px);
|
|
2114
|
+
right: var(--gp-pin-right, 0px);
|
|
2115
|
+
bottom: var(--gp-pin-bottom, 0px);
|
|
2116
|
+
left: var(--gp-pin-left, 0px);
|
|
2096
2117
|
align-self: center;
|
|
2097
2118
|
justify-self: center;
|
|
2098
2119
|
margin: 0;
|
|
@@ -2107,6 +2128,16 @@ img.gp-shape {
|
|
|
2107
2128
|
.gp-left { justify-self: start; }
|
|
2108
2129
|
.gp-right { justify-self: end; }
|
|
2109
2130
|
|
|
2131
|
+
/* the escape hatch — the paper's edge, past the printer's safe area: the
|
|
2132
|
+
pin box loses its art-safe insets. Set on the pin itself, so it beats the
|
|
2133
|
+
values the page root hands down. */
|
|
2134
|
+
.gp-pin.gp-flush {
|
|
2135
|
+
--gp-pin-top: 0px;
|
|
2136
|
+
--gp-pin-right: 0px;
|
|
2137
|
+
--gp-pin-bottom: 0px;
|
|
2138
|
+
--gp-pin-left: 0px;
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2110
2141
|
/* wrapper-margin neutralization (same pattern and rationale as the
|
|
2111
2142
|
.gp-bleed paragraph-margin note in the doctrine comment; for pin, the
|
|
2112
2143
|
emptied paragraph would otherwise leave a phantom margin gap in flow) */
|
|
@@ -2216,6 +2247,8 @@ var GP_CLASSES = new Set([
|
|
|
2216
2247
|
"gp-small",
|
|
2217
2248
|
"gp-medium",
|
|
2218
2249
|
"gp-large",
|
|
2250
|
+
"gp-xl",
|
|
2251
|
+
"gp-xxl",
|
|
2219
2252
|
"gp-tight",
|
|
2220
2253
|
"gp-loose",
|
|
2221
2254
|
"gp-columns",
|
|
@@ -2232,6 +2265,7 @@ var GP_CLASSES = new Set([
|
|
|
2232
2265
|
"gp-pin",
|
|
2233
2266
|
"gp-top",
|
|
2234
2267
|
"gp-bottom",
|
|
2268
|
+
"gp-flush",
|
|
2235
2269
|
"gp-behind",
|
|
2236
2270
|
"gp-base",
|
|
2237
2271
|
"gp-raised",
|
|
@@ -2245,8 +2279,7 @@ var GP_CLASSES = new Set([
|
|
|
2245
2279
|
"gp-alert-caution",
|
|
2246
2280
|
"gp-page-break",
|
|
2247
2281
|
"gp-column-break",
|
|
2248
|
-
"gp-continued"
|
|
2249
|
-
"gp-flush"
|
|
2282
|
+
"gp-continued"
|
|
2250
2283
|
]);
|
|
2251
2284
|
|
|
2252
2285
|
// src/lib/markdown/gp-pin-scope.js
|
|
@@ -2283,6 +2316,21 @@ function hasPinClass(token) {
|
|
|
2283
2316
|
const cls = token.attrGet && token.attrGet("class");
|
|
2284
2317
|
return typeof cls === "string" && cls.split(/\s+/).includes("gp-pin");
|
|
2285
2318
|
}
|
|
2319
|
+
var PIN_EDGES = ["gp-top", "gp-right", "gp-bottom", "gp-left"];
|
|
2320
|
+
var FLUSH_ART_MSG = "`.gp-flush` puts this image on the paper's edge, past the printer's safe area. Printers trim up to 0.125in there, so keep it for art that is meant to bleed off the page.";
|
|
2321
|
+
function checkFlushArt(token, env, line) {
|
|
2322
|
+
if (token.type !== "image")
|
|
2323
|
+
return;
|
|
2324
|
+
const cls = token.attrGet && token.attrGet("class");
|
|
2325
|
+
if (typeof cls !== "string")
|
|
2326
|
+
return;
|
|
2327
|
+
const classes = cls.split(/\s+/);
|
|
2328
|
+
if (!classes.includes("gp-pin") || !classes.includes("gp-flush"))
|
|
2329
|
+
return;
|
|
2330
|
+
if (!classes.some((c) => PIN_EDGES.includes(c)))
|
|
2331
|
+
return;
|
|
2332
|
+
warn3(env, line, "flush_art", FLUSH_ART_MSG);
|
|
2333
|
+
}
|
|
2286
2334
|
function elementNameFor(token) {
|
|
2287
2335
|
switch (token.type) {
|
|
2288
2336
|
case "layout_chapter_open":
|
|
@@ -2342,6 +2390,7 @@ function gpPinScope(md) {
|
|
|
2342
2390
|
if (token.type === "inline" && token.children) {
|
|
2343
2391
|
for (const child of token.children) {
|
|
2344
2392
|
checkUnknownGpClasses(child, state.env, line);
|
|
2393
|
+
checkFlushArt(child, state.env, line);
|
|
2345
2394
|
}
|
|
2346
2395
|
}
|
|
2347
2396
|
}
|
|
@@ -3369,6 +3418,7 @@ This folder still has a ${stale}. Gutterpress no longer reads it — ` + `descri
|
|
|
3369
3418
|
async function loadExtensionFromDir(extensionDir, config, pluginRef) {
|
|
3370
3419
|
const meta = await readExtensionMeta(extensionDir);
|
|
3371
3420
|
assertExtensionContained(meta);
|
|
3421
|
+
assertSupportsThisGutterpress(meta, pluginRef);
|
|
3372
3422
|
const resolved = resolveExtension(extensionDir, meta, `Plugin "${pluginRef}"`);
|
|
3373
3423
|
const extensionStyles = resolved.styles ?? [];
|
|
3374
3424
|
const name = config.name ?? meta.name ?? pluginRef;
|
|
@@ -3443,6 +3493,7 @@ async function loadPlugin(config, baseDir) {
|
|
|
3443
3493
|
if (loaded.packageDir) {
|
|
3444
3494
|
const meta = await readExtensionMeta(loaded.packageDir);
|
|
3445
3495
|
assertExtensionContained(meta);
|
|
3496
|
+
assertSupportsThisGutterpress(meta, pluginRef);
|
|
3446
3497
|
const resolved = resolveExtension(loaded.packageDir, { ...meta, main: undefined }, `Plugin "${pluginRef}"`);
|
|
3447
3498
|
if (resolved.markdown && loaded.entryPath && resolve3(resolved.markdown) !== resolve3(loaded.entryPath)) {
|
|
3448
3499
|
throw new Error(`its package.json declares gutterpress.markdown "${meta.markdown}" but the package entry is "${relative(loaded.packageDir, loaded.entryPath)}" — an npm extension's ` + "markdown-it plugin is its package entry, so declare that file or drop the field.");
|
|
@@ -3566,7 +3617,7 @@ import path3 from "node:path";
|
|
|
3566
3617
|
import { Transform } from "node:stream";
|
|
3567
3618
|
import { pipeline } from "node:stream/promises";
|
|
3568
3619
|
import { createGunzip } from "node:zlib";
|
|
3569
|
-
import { maxSatisfying, satisfies, validRange } from "semver";
|
|
3620
|
+
import { maxSatisfying, satisfies as satisfies2, validRange as validRange2 } from "semver";
|
|
3570
3621
|
|
|
3571
3622
|
// src/lib/fetch-timeout.ts
|
|
3572
3623
|
class FetchPassthroughError extends Error {
|
|
@@ -3807,7 +3858,7 @@ async function selectPackage(ctx, name, selector) {
|
|
|
3807
3858
|
version = selector;
|
|
3808
3859
|
} else if (typeof tags[selector] === "string") {
|
|
3809
3860
|
version = tags[selector];
|
|
3810
|
-
} else if (
|
|
3861
|
+
} else if (validRange2(selector)) {
|
|
3811
3862
|
version = maxSatisfying(Object.keys(versions), selector) ?? undefined;
|
|
3812
3863
|
}
|
|
3813
3864
|
if (!version || !isExactNpmVersion(version)) {
|
|
@@ -4025,7 +4076,7 @@ async function installPackage(ctx, name, selector, parentPackagePath, ancestors,
|
|
|
4025
4076
|
}
|
|
4026
4077
|
throw error2;
|
|
4027
4078
|
}
|
|
4028
|
-
const ancestor = ancestors.find((candidate) => candidate.name === name && (candidate.version === selected.version || (selector ?
|
|
4079
|
+
const ancestor = ancestors.find((candidate) => candidate.name === name && (candidate.version === selected.version || (selector ? satisfies2(candidate.version, selector) : false)));
|
|
4029
4080
|
if (ancestor)
|
|
4030
4081
|
return { path: ancestor.path };
|
|
4031
4082
|
if (ctx.records.length >= ctx.limits.totalPackages) {
|
|
@@ -8885,6 +8936,20 @@ function canonicalChapterId(p) {
|
|
|
8885
8936
|
return s;
|
|
8886
8937
|
}
|
|
8887
8938
|
|
|
8939
|
+
// src/engine/shared/print-area.ts
|
|
8940
|
+
function printAreaMeta(page) {
|
|
8941
|
+
const area = JSON.stringify({
|
|
8942
|
+
width: page.width,
|
|
8943
|
+
height: page.height,
|
|
8944
|
+
bleed: page.bleed ?? 0,
|
|
8945
|
+
safe: page.safe ?? 0,
|
|
8946
|
+
artSafe: page.artSafe,
|
|
8947
|
+
preset: page.preset,
|
|
8948
|
+
spec: page.spec
|
|
8949
|
+
});
|
|
8950
|
+
return `<meta name="gp-print-area" content='${area.replace(/&/g, "&").replace(/'/g, "'")}'>`;
|
|
8951
|
+
}
|
|
8952
|
+
|
|
8888
8953
|
// src/lib/markdown/assemble.ts
|
|
8889
8954
|
async function assembleBookHtml(opts) {
|
|
8890
8955
|
const title = opts.title ?? "Document";
|
|
@@ -8950,7 +9015,8 @@ ${projectCss.trim()}` : null
|
|
|
8950
9015
|
<html lang="en"${printAttrs}>
|
|
8951
9016
|
<head>
|
|
8952
9017
|
<meta charset="UTF-8">
|
|
8953
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"
|
|
9018
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">${opts.printArea ? `
|
|
9019
|
+
${printAreaMeta(opts.printArea)}` : ""}
|
|
8954
9020
|
<title>${title}</title>${preloadTags}
|
|
8955
9021
|
<style data-project-css>
|
|
8956
9022
|
${inlineCss}
|
|
@@ -9010,6 +9076,7 @@ ${css.trim()}
|
|
|
9010
9076
|
preloadImages: cssAssetCopies.map((c) => c.to),
|
|
9011
9077
|
title: opts.title,
|
|
9012
9078
|
print: opts.print,
|
|
9079
|
+
printArea: opts.printArea,
|
|
9013
9080
|
plugins: opts.plugins,
|
|
9014
9081
|
pluginCss,
|
|
9015
9082
|
annotateSourceChapters: opts.annotateSourceChapters,
|
|
@@ -9022,6 +9089,7 @@ async function renderChaptersToFile(inputDir, outDir, opts = {}) {
|
|
|
9022
9089
|
const html = await renderChapters(inputDir, {
|
|
9023
9090
|
title: opts.title,
|
|
9024
9091
|
print: opts.print,
|
|
9092
|
+
printArea: opts.printArea,
|
|
9025
9093
|
styles: opts.styles,
|
|
9026
9094
|
files: opts.files,
|
|
9027
9095
|
plugins: opts.plugins,
|
|
@@ -9899,6 +9967,7 @@ async function renderBook(ctx) {
|
|
|
9899
9967
|
const htmlFile = await renderChaptersToFile(renderDir, workDir, {
|
|
9900
9968
|
title: config.title,
|
|
9901
9969
|
print: config.print,
|
|
9970
|
+
printArea: { ...config.page, preset: config.preset, spec: config.spec },
|
|
9902
9971
|
styles: config.styles,
|
|
9903
9972
|
files: config.source.files,
|
|
9904
9973
|
plugins,
|
|
@@ -10051,7 +10120,7 @@ class PdfOutput {
|
|
|
10051
10120
|
const rawPdf = pdfxMode ? path13.join(stage, "raw.pdf") : path13.resolve(pdfFile);
|
|
10052
10121
|
await fsp2.mkdir(path13.dirname(path13.resolve(pdfFile)), { recursive: true });
|
|
10053
10122
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
10054
|
-
const { buildNativePdf } = await import("./engine-
|
|
10123
|
+
const { buildNativePdf } = await import("./engine-67f68bxs.js");
|
|
10055
10124
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
10056
10125
|
title: config.title,
|
|
10057
10126
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
@@ -10354,6 +10423,7 @@ async function renderPreviewBook(inputPath, config, opts) {
|
|
|
10354
10423
|
return renderChapters(inputPath, {
|
|
10355
10424
|
title: config.title ?? "Document",
|
|
10356
10425
|
print: config.print,
|
|
10426
|
+
printArea: config.printArea,
|
|
10357
10427
|
styles: config.styles,
|
|
10358
10428
|
files: opts.files,
|
|
10359
10429
|
plugins,
|
|
@@ -10368,19 +10438,8 @@ async function renderPreviewBook(inputPath, config, opts) {
|
|
|
10368
10438
|
}
|
|
10369
10439
|
});
|
|
10370
10440
|
}
|
|
10371
|
-
function injectPreviewScripts(html
|
|
10372
|
-
const
|
|
10373
|
-
width: page.width,
|
|
10374
|
-
height: page.height,
|
|
10375
|
-
bleed: page.bleed ?? 0,
|
|
10376
|
-
safe: page.safe ?? 0,
|
|
10377
|
-
artSafe: page.artSafe,
|
|
10378
|
-
preset: page.preset,
|
|
10379
|
-
spec: page.spec
|
|
10380
|
-
}) : "";
|
|
10381
|
-
const meta = area ? ` <meta name="gp-print-area" content='${area.replace(/&/g, "&").replace(/'/g, "'")}'>
|
|
10382
|
-
` : "";
|
|
10383
|
-
const scripts = meta + ` <script src="/engine/gutterpress-viewer.js"></script>
|
|
10441
|
+
function injectPreviewScripts(html) {
|
|
10442
|
+
const scripts = ` <script src="/engine/gutterpress-viewer.js"></script>
|
|
10384
10443
|
` + `<script src="/preview/scripts/preview-interface.js"></script>
|
|
10385
10444
|
` + `<script src="/preview/scripts/preview-bridge.js"></script>
|
|
10386
10445
|
`;
|
|
@@ -10395,7 +10454,10 @@ async function generateAndWriteHtml(inputPath, tempDir, config, cssAssets, image
|
|
|
10395
10454
|
}
|
|
10396
10455
|
const nextAssets = new Map;
|
|
10397
10456
|
const nextImageRefs = new Set;
|
|
10398
|
-
const html = await renderPreviewBook(inputPath,
|
|
10457
|
+
const html = await renderPreviewBook(inputPath, {
|
|
10458
|
+
...config,
|
|
10459
|
+
printArea: config.page && { ...config.page, preset: config.preset, spec: config.spec }
|
|
10460
|
+
}, {
|
|
10399
10461
|
files: config.source?.files ?? null,
|
|
10400
10462
|
onCssAssets: (copies) => {
|
|
10401
10463
|
for (const copy of copies)
|
|
@@ -10414,7 +10476,7 @@ async function generateAndWriteHtml(inputPath, tempDir, config, cssAssets, image
|
|
|
10414
10476
|
for (const ref of nextImageRefs)
|
|
10415
10477
|
imageRefs.add(ref);
|
|
10416
10478
|
}
|
|
10417
|
-
await fsp3.writeFile(path15.join(tempDir, BOOK_HTML_FILENAME), injectPreviewScripts(html
|
|
10479
|
+
await fsp3.writeFile(path15.join(tempDir, BOOK_HTML_FILENAME), injectPreviewScripts(html), "utf-8");
|
|
10418
10480
|
}
|
|
10419
10481
|
function isDotPathUnderRoot(candidatePath, root) {
|
|
10420
10482
|
const normalizedRoot = root.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
@@ -567,14 +567,15 @@ function specificity(r) {
|
|
|
567
567
|
return (r.name ? 2 : 0) + r.pseudos.length;
|
|
568
568
|
}
|
|
569
569
|
|
|
570
|
-
// src/engine/shared/
|
|
571
|
-
var
|
|
572
|
-
|
|
573
|
-
|
|
570
|
+
// src/engine/shared/pin-edges.ts
|
|
571
|
+
var PIN_EDGES = ["top", "right", "bottom", "left"];
|
|
572
|
+
var EDGE_PIN_SELECTOR = PIN_EDGES.map((edge) => `.gp-pin.gp-${edge}`).join(", ");
|
|
573
|
+
function pinKey(edges) {
|
|
574
|
+
return PIN_EDGES.filter((e) => edges.includes(e)).map((e) => e[0]).join("");
|
|
574
575
|
}
|
|
575
|
-
function
|
|
576
|
+
function pinPageName(authorPage, edges) {
|
|
576
577
|
const safe = authorPage ? authorPage.replace(/[^A-Za-z0-9_-]/g, "_") : "";
|
|
577
|
-
return `gp--
|
|
578
|
+
return `gp--pin${safe ? `-${safe}` : ""}-${pinKey(edges)}`;
|
|
578
579
|
}
|
|
579
580
|
function flushMargins(margin, edges) {
|
|
580
581
|
return {
|
|
@@ -584,6 +585,23 @@ function flushMargins(margin, edges) {
|
|
|
584
585
|
left: edges.includes("left") ? 0 : margin.left
|
|
585
586
|
};
|
|
586
587
|
}
|
|
588
|
+
function pinInsets(area, side, edges) {
|
|
589
|
+
const binding = side === "recto" ? "left" : "right";
|
|
590
|
+
const inset = (edge) => !area || !edges.includes(edge) ? 0 : edge === binding ? area.safe : area.bleed + area.artSafe;
|
|
591
|
+
return { top: inset("top"), right: inset("right"), bottom: inset("bottom"), left: inset("left") };
|
|
592
|
+
}
|
|
593
|
+
var NO_PADDING = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
594
|
+
function pinRootStyle(margin, area, side, edges, padding = NO_PADDING) {
|
|
595
|
+
const px = (pt) => pt * 96 / 72;
|
|
596
|
+
const inset = pinInsets(area, side, edges);
|
|
597
|
+
const style = { "box-decoration-break": "clone" };
|
|
598
|
+
for (const edge of PIN_EDGES)
|
|
599
|
+
if (edges.includes(edge))
|
|
600
|
+
style[`padding-${edge}`] = `${px(margin[edge]) + padding[edge]}px`;
|
|
601
|
+
for (const edge of PIN_EDGES)
|
|
602
|
+
style[`--gp-pin-${edge}`] = `${px(inset[edge])}px`;
|
|
603
|
+
return style;
|
|
604
|
+
}
|
|
587
605
|
function marginBoxesOnEdges(edges) {
|
|
588
606
|
const owners = {
|
|
589
607
|
"top-left-corner": ["top", "left"],
|
|
@@ -1116,7 +1134,7 @@ import { fileURLToPath } from "node:url";
|
|
|
1116
1134
|
var favicon_default = "./favicon-272ga6y0.ico";
|
|
1117
1135
|
|
|
1118
1136
|
// src/assets/manifest.schema.json
|
|
1119
|
-
var manifest_schema_default = "./manifest.schema-
|
|
1137
|
+
var manifest_schema_default = "./manifest.schema-13dfax80.json";
|
|
1120
1138
|
|
|
1121
1139
|
// src/assets/preview/scripts/preview-interface.js
|
|
1122
1140
|
var preview_interface_default = "./preview-interface-nnmrxyqm.js";
|
|
@@ -1131,10 +1149,10 @@ var preview_shell_default = "./preview-shell-wk9k3gcd.js";
|
|
|
1131
1149
|
var CGATS21_CRPC1_default = "./CGATS21_CRPC1-g0e3k7kr.icc";
|
|
1132
1150
|
|
|
1133
1151
|
// src/assets/engine/gutterpress-viewer.js
|
|
1134
|
-
var gutterpress_viewer_default = "./gutterpress-viewer-
|
|
1152
|
+
var gutterpress_viewer_default = "./gutterpress-viewer-jr30yw8t.js";
|
|
1135
1153
|
|
|
1136
1154
|
// src/assets/engine/gutterpress-agent.js
|
|
1137
|
-
var gutterpress_agent_default = "./gutterpress-agent-
|
|
1155
|
+
var gutterpress_agent_default = "./gutterpress-agent-mrdnwktc.js";
|
|
1138
1156
|
|
|
1139
1157
|
// src/assets/templates/book/manifest.yaml
|
|
1140
1158
|
var manifest_default = "./manifest-n1gh3qw5.yaml";
|
|
@@ -1652,25 +1670,31 @@ async function build(opts) {
|
|
|
1652
1670
|
await page.send("Emulation.setDeviceMetricsOverride", sheetViewport);
|
|
1653
1671
|
await page.send("Emulation.setEmulatedMedia", { media: "print" });
|
|
1654
1672
|
log(`print media emulated for audits and measurement`);
|
|
1655
|
-
const
|
|
1656
|
-
const
|
|
1657
|
-
for (const root of
|
|
1658
|
-
if (
|
|
1673
|
+
const pinRoots = await page.evaluate(`window.__gp.pinRoots()`);
|
|
1674
|
+
const pinGroups = new Map;
|
|
1675
|
+
for (const root of pinRoots) {
|
|
1676
|
+
if (pinGroups.has(root.key))
|
|
1659
1677
|
continue;
|
|
1660
1678
|
const authorPage = root.page === "auto" ? undefined : root.page;
|
|
1661
|
-
|
|
1679
|
+
pinGroups.set(root.key, {
|
|
1662
1680
|
authorPage,
|
|
1663
1681
|
edges: root.edges,
|
|
1664
|
-
|
|
1682
|
+
padding: root.padding,
|
|
1683
|
+
genName: pinPageName(authorPage, root.edges),
|
|
1665
1684
|
key: root.key
|
|
1666
1685
|
});
|
|
1667
1686
|
}
|
|
1668
|
-
|
|
1687
|
+
const printArea = pinRoots.length ? await page.evaluate(`window.__gp.printArea()`) : null;
|
|
1688
|
+
const pinStyle = (group, pseudos) => pinRootStyle(resolvePage(model, { name: group.authorPage, pseudos }).geometry.margin, printArea, pseudos.includes("left") ? "verso" : "recto", group.edges, group.padding);
|
|
1689
|
+
if (pinGroups.size) {
|
|
1669
1690
|
const lines = [];
|
|
1670
|
-
|
|
1691
|
+
const aliased = new Set;
|
|
1692
|
+
for (const group of pinGroups.values()) {
|
|
1693
|
+
const alias = !aliased.has(group.genName);
|
|
1694
|
+
aliased.add(group.genName);
|
|
1671
1695
|
const relocated = new Set(marginBoxesOnEdges(group.edges));
|
|
1672
1696
|
const pseudoSets = [[]];
|
|
1673
|
-
if (group.authorPage) {
|
|
1697
|
+
if (alias && group.authorPage) {
|
|
1674
1698
|
for (const rule of model.pageRules) {
|
|
1675
1699
|
if (rule.name !== group.authorPage)
|
|
1676
1700
|
continue;
|
|
@@ -1694,7 +1718,7 @@ ${body.join(`
|
|
|
1694
1718
|
}`);
|
|
1695
1719
|
}
|
|
1696
1720
|
}
|
|
1697
|
-
for (const pseudos of pseudoSets) {
|
|
1721
|
+
for (const pseudos of alias ? pseudoSets : []) {
|
|
1698
1722
|
const pseudo = pseudos.length ? `:${pseudos.join(":")}` : "";
|
|
1699
1723
|
const body = [];
|
|
1700
1724
|
for (const edge of group.edges)
|
|
@@ -1706,14 +1730,15 @@ ${body.join(`
|
|
|
1706
1730
|
`)}
|
|
1707
1731
|
}`);
|
|
1708
1732
|
}
|
|
1709
|
-
|
|
1733
|
+
const recto = Object.entries(pinStyle(group, ["right"])).map(([prop, value]) => ` ${prop}: ${value};`).join("");
|
|
1734
|
+
lines.push(`:where(.page, .spread)[data-gp-pin="${group.key}"][data-gp-pin][data-gp-pin][data-gp-pin] { page: ${group.genName};${recto} }`);
|
|
1710
1735
|
}
|
|
1711
|
-
const
|
|
1736
|
+
const pinCss = lines.join(`
|
|
1712
1737
|
`);
|
|
1713
|
-
await page.evaluate(`window.__gp.addCss("gp-
|
|
1738
|
+
await page.evaluate(`window.__gp.addCss("gp-pin-css", ${JSON.stringify(pinCss)})`);
|
|
1714
1739
|
model = extract(`${cssText}
|
|
1715
|
-
${
|
|
1716
|
-
log(
|
|
1740
|
+
${pinCss}`);
|
|
1741
|
+
log(`pinned art: ${pinRoots.length} page root(s) -> ${pinGroups.size} generated page context(s)`);
|
|
1717
1742
|
}
|
|
1718
1743
|
const { tier3Reasons } = classify(model);
|
|
1719
1744
|
const pseudoContexts = pagePseudoContexts(model);
|
|
@@ -1738,11 +1763,16 @@ ${flushCss}`);
|
|
|
1738
1763
|
return !!c && c !== "none" && c !== "normal";
|
|
1739
1764
|
});
|
|
1740
1765
|
};
|
|
1741
|
-
const furnitureRoots =
|
|
1742
|
-
const group =
|
|
1766
|
+
const furnitureRoots = pinRoots.filter((root) => {
|
|
1767
|
+
const group = pinGroups.get(root.key);
|
|
1743
1768
|
return pseudoContexts.some((pseudos) => relocationBoxes(group, pseudos).length > 0);
|
|
1744
1769
|
});
|
|
1745
|
-
const
|
|
1770
|
+
const relocationDiagnosed = new Set;
|
|
1771
|
+
const sideRoots = pinRoots.filter((root) => {
|
|
1772
|
+
const group = pinGroups.get(root.key);
|
|
1773
|
+
const recto = JSON.stringify(pinStyle(group, ["right"]));
|
|
1774
|
+
return [["left"], ["right", "first"]].some((pseudos) => JSON.stringify(pinStyle(group, pseudos)) !== recto);
|
|
1775
|
+
});
|
|
1746
1776
|
const tier2 = synthesize({
|
|
1747
1777
|
model,
|
|
1748
1778
|
marks: opts.marks,
|
|
@@ -1786,7 +1816,7 @@ ${describe(widthOffenders.intrinsics)}`;
|
|
|
1786
1816
|
log(`WARNING: ${msg}`);
|
|
1787
1817
|
}
|
|
1788
1818
|
const rectoDecls = model.breaks.filter(isRectoVersoBreak);
|
|
1789
|
-
const needsMeasure = tier3Reasons.length > 0 || consumedStrings(model).size > 0 || rectoDecls.length > 0 || model.counterResets.length > 0 || furnitureRoots.length > 0;
|
|
1819
|
+
const needsMeasure = tier3Reasons.length > 0 || consumedStrings(model).size > 0 || rectoDecls.length > 0 || model.counterResets.length > 0 || furnitureRoots.length > 0 || sideRoots.length > 0;
|
|
1790
1820
|
let tier = tier2.geometry.bleed > 0 || tier2.geometry.slug > 0 ? 2 : 1;
|
|
1791
1821
|
let passes = 1;
|
|
1792
1822
|
let pageMap = {};
|
|
@@ -1814,7 +1844,7 @@ ${describe(widthOffenders.intrinsics)}`;
|
|
|
1814
1844
|
targets.add(s.id);
|
|
1815
1845
|
for (const s of resetSites)
|
|
1816
1846
|
targets.add(s.id);
|
|
1817
|
-
for (const r of furnitureRoots)
|
|
1847
|
+
for (const r of [...furnitureRoots, ...sideRoots])
|
|
1818
1848
|
targets.add(r.id);
|
|
1819
1849
|
await page.evaluate(`window.__gp.instrument(${JSON.stringify([...targets])})`);
|
|
1820
1850
|
const targetText = await page.evaluate(`window.__gp.targetTexts(${JSON.stringify([...targets])})`);
|
|
@@ -1900,8 +1930,12 @@ ${describe(widthOffenders.intrinsics)}`;
|
|
|
1900
1930
|
/* Tier 3 */
|
|
1901
1931
|
${mapCss}`;
|
|
1902
1932
|
}
|
|
1933
|
+
const pageAt = (id) => map[id] ?? predictedForResult?.pageMap[id];
|
|
1934
|
+
const pseudosAt = (physical) => [
|
|
1935
|
+
physical % 2 === 1 ? "right" : "left",
|
|
1936
|
+
...physical === 1 ? ["first"] : []
|
|
1937
|
+
];
|
|
1903
1938
|
if (furnitureRoots.length) {
|
|
1904
|
-
const pageAt = (id) => map[id] ?? predictedForResult?.pageMap[id];
|
|
1905
1939
|
const byName = new Map;
|
|
1906
1940
|
for (const s of sources) {
|
|
1907
1941
|
const p = pageAt(s.id);
|
|
@@ -1919,10 +1953,8 @@ ${mapCss}`;
|
|
|
1919
1953
|
const physical = pageAt(root.id);
|
|
1920
1954
|
if (!physical)
|
|
1921
1955
|
continue;
|
|
1922
|
-
const group =
|
|
1923
|
-
const pseudos =
|
|
1924
|
-
if (physical === 1)
|
|
1925
|
-
pseudos.push("first");
|
|
1956
|
+
const group = pinGroups.get(root.key);
|
|
1957
|
+
const pseudos = pseudosAt(physical);
|
|
1926
1958
|
const ctx = resolvePage(model, { name: group.authorPage, pseudos });
|
|
1927
1959
|
const g = ctx.geometry;
|
|
1928
1960
|
const eff = flushMargins(g.margin, group.edges);
|
|
@@ -1938,9 +1970,9 @@ ${mapCss}`;
|
|
|
1938
1970
|
}
|
|
1939
1971
|
});
|
|
1940
1972
|
if (!text) {
|
|
1941
|
-
if (!
|
|
1942
|
-
|
|
1943
|
-
diagnose("engine.
|
|
1973
|
+
if (!relocationDiagnosed.has(name)) {
|
|
1974
|
+
relocationDiagnosed.add(name);
|
|
1975
|
+
diagnose("engine.pin.margin-box", `@${name} sits on an edge a pinned image frees, and its content could not be ` + `re-homed into the page (unsupported content value: ${decls.content}). It will ` + `not print on that page — simplify the box's content, or pin the image to another edge.`);
|
|
1944
1976
|
}
|
|
1945
1977
|
continue;
|
|
1946
1978
|
}
|
|
@@ -1965,7 +1997,17 @@ ${mapCss}`;
|
|
|
1965
1997
|
items.push({ id: root.id, boxes });
|
|
1966
1998
|
}
|
|
1967
1999
|
if (items.length)
|
|
1968
|
-
await page.evaluate(`window.__gp.
|
|
2000
|
+
await page.evaluate(`window.__gp.setPinFurniture(${JSON.stringify(items)})`);
|
|
2001
|
+
}
|
|
2002
|
+
if (sideRoots.length) {
|
|
2003
|
+
const items = sideRoots.flatMap((root) => {
|
|
2004
|
+
const physical = pageAt(root.id);
|
|
2005
|
+
if (!physical)
|
|
2006
|
+
return [];
|
|
2007
|
+
return [{ id: root.id, style: pinStyle(pinGroups.get(root.key), pseudosAt(physical)) }];
|
|
2008
|
+
});
|
|
2009
|
+
if (items.length)
|
|
2010
|
+
await page.evaluate(`window.__gp.setPinGeometry(${JSON.stringify(items)})`);
|
|
1969
2011
|
}
|
|
1970
2012
|
};
|
|
1971
2013
|
const predicted = await predictPageMap(browser, url, AGENT, VIEWER, {
|
|
@@ -2328,12 +2370,12 @@ function shrinkScale(boxes, limitPx) {
|
|
|
2328
2370
|
async function findWidthOffenders(page, model, bleedSlugExtensionPt, restoreViewport) {
|
|
2329
2371
|
const contexts = [
|
|
2330
2372
|
resolvePage(model),
|
|
2331
|
-
...model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--
|
|
2373
|
+
...model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--pin-")).map((n) => resolvePage(model, { name: n }))
|
|
2332
2374
|
];
|
|
2333
2375
|
const contentPxOf = (c) => (c.geometry.width - c.geometry.margin.left - c.geometry.margin.right + bleedSlugExtensionPt) * 96 / 72;
|
|
2334
2376
|
const defaultLimitPx = contentPxOf(contexts[0]);
|
|
2335
2377
|
const namedLimits = {};
|
|
2336
|
-
model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--
|
|
2378
|
+
model.pageNames.filter((n) => !n.startsWith("gp-") || n.startsWith("gp--pin-")).forEach((n) => {
|
|
2337
2379
|
namedLimits[n] = contentPxOf(resolvePage(model, { name: n }));
|
|
2338
2380
|
});
|
|
2339
2381
|
const widths = [...new Set([defaultLimitPx, ...Object.values(namedLimits)])].sort((a, b) => a - b);
|
|
@@ -2520,7 +2562,7 @@ async function predictPageMap(browser, url, agentScript, viewerScript, args, she
|
|
|
2520
2562
|
await page.waitForReady();
|
|
2521
2563
|
await page.evaluate(`window.__GP_MANUAL__ = true;`);
|
|
2522
2564
|
await page.evaluate(viewerScript);
|
|
2523
|
-
await page.evaluate(`window.__gp.
|
|
2565
|
+
await page.evaluate(`window.__gp.pinRoots()`);
|
|
2524
2566
|
await page.evaluate(`window.__gp.stringSources(${JSON.stringify(args.stringSets)})`);
|
|
2525
2567
|
if (args.rectoDecls.length)
|
|
2526
2568
|
await page.evaluate(`window.__gp.forcedBreakSites(${JSON.stringify(args.rectoDecls)})`);
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
// package.json
|
|
5
5
|
var package_default = {
|
|
6
6
|
name: "gutterpress",
|
|
7
|
-
version: "0.11.20-alpha.
|
|
7
|
+
version: "0.11.20-alpha.4",
|
|
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",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
package_default
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-fmksazej.js";
|
|
4
4
|
import {
|
|
5
5
|
enhancedPath,
|
|
6
6
|
execCapture,
|
|
@@ -685,4 +685,4 @@ async function getSystemDiagnostics() {
|
|
|
685
685
|
};
|
|
686
686
|
}
|
|
687
687
|
|
|
688
|
-
export { setLogLevel, debug, info, warn, error, log, resolveGhostscript, transparentPages, findPostScriptShadingPages, stripAnnotations, planTransparentPages, flattenTransparentPages, stampCreator, convertToPdfxCmyk,
|
|
688
|
+
export { setLogLevel, debug, info, warn, error, log, PACKAGE_META, PACKAGE_VERSION, resolveGhostscript, transparentPages, findPostScriptShadingPages, stripAnnotations, planTransparentPages, flattenTransparentPages, stampCreator, convertToPdfxCmyk, defaultConfigDir, FileTokenStore, getSystemDiagnostics };
|