gutterpress 0.10.0-alpha.3 → 0.10.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/api/index.js +2 -2
- package/dist/{audit-xxegv0t0.js → audit-85zn35v8.js} +4 -4
- package/dist/{build-w0vb6mgq.js → build-1faqmp0y.js} +6 -4
- package/dist/{cli-5czby0dd.js → cli-5tffrg48.js} +90 -23
- package/dist/{cli-f4rcbt2t.js → cli-7e79d7se.js} +1 -1
- package/dist/{cli-yp3p0sf2.js → cli-afm8pa0h.js} +327 -24
- package/dist/{cli-gk3wsdpb.js → cli-v935c2ws.js} +1 -1
- package/dist/{cli-revgt4pr.js → cli-yzf38679.js} +1 -0
- package/dist/cli.js +16 -16
- package/dist/{doctor-ctgn1dnt.js → doctor-69v5c9wy.js} +2 -2
- package/dist/engine/compiler/build.d.ts +1 -1
- package/dist/engine/shared/flush.d.ts +59 -0
- package/dist/engine/shared/margin-box-support.d.ts +24 -0
- package/dist/{engine-eng4xh2q.js → engine-hrtn0b28.js} +1 -1
- package/dist/{engine-q5skhgms.js → engine-nbfdy0pp.js} +2 -2
- package/dist/{gutterpress-agent-1ctgfz92.js → gutterpress-agent-cazqstr1.js} +49 -1
- package/dist/{gutterpress-viewer-cem7dmr5.js → gutterpress-viewer-fb6fhwsy.js} +137 -51
- package/dist/{index-s416qpdv.js → index-052x5fef.js} +89 -22
- package/dist/{index-mvehxh0e.js → index-c2b6gyeg.js} +47 -4
- package/dist/{index-a4kr77td.js → index-wsydvp08.js} +287 -23
- package/dist/index.js +3 -3
- package/dist/lib/build-runner.d.ts +7 -0
- package/dist/lib/engine.d.ts +9 -0
- package/dist/lib/markdown/gutterpress-css.d.ts +9 -1
- package/dist/lib/markdown/markers.d.ts +51 -1
- package/dist/{lint-gsh6qwrq.js → lint-17404bsx.js} +4 -4
- package/dist/{new-nkhycqy4.js → new-vsgpxzek.js} +4 -4
- package/dist/{plugin-129wcs93.js → plugin-s4yfpx6p.js} +4 -4
- package/dist/{preflight-41hcejg9.js → preflight-1h3apvqh.js} +4 -4
- package/dist/{preview-pftsvr9z.js → preview-cqf383g4.js} +6 -5
- package/dist/{preview-interface-fnqb2y4v.js → preview-interface-hg5eqv88.js} +193 -4
- package/dist/{publish-dnjvb4jg.js → publish-arvycera.js} +4 -4
- package/dist/render.js +83 -7
- package/dist/{repair-a3enjttn.js → repair-vmwh2bhe.js} +4 -4
- package/dist/{validate-ph1xffqy.js → validate-ztzq7p35.js} +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -190,6 +190,7 @@ gutterpress preview [input-dir] [options]
|
|
|
190
190
|
--skip-lint Skip CSS linting (pdf|pdfx only)
|
|
191
191
|
--skip-pre-validate Skip pre-build validation (pdf|pdfx only)
|
|
192
192
|
--skip-post-validate Skip post-build PDF/X validation (pdfx only)
|
|
193
|
+
--allow-shrink Build anyway when content is wider than the page content box (pdf|pdfx only)
|
|
193
194
|
--engine <name> native (default) | paged (deprecated) [overrides the manifest's engine: field; applies to the live preview AND --format pdf|pdfx]
|
|
194
195
|
```
|
|
195
196
|
|
|
@@ -210,6 +211,7 @@ gutterpress build [input-dir] [options]
|
|
|
210
211
|
--skip-lint Skip the CSS print-safety pass (default: lint runs for pdf/pdfx)
|
|
211
212
|
--skip-pre-validate Skip pre-build validation
|
|
212
213
|
--skip-post-validate Skip post-build PDF/X validation
|
|
214
|
+
--allow-shrink Build anyway when content is wider than the page content box. Chromium then scales the WHOLE book down to fit it — the build reports that whole-document scale (e.g. "about 0.72x its declared size") plus every offender, as warnings.
|
|
213
215
|
--engine <name> native (default) | paged (deprecated) [overrides the manifest's engine: field; native = the Gutterpress engine, native Chromium pagination]
|
|
214
216
|
```
|
|
215
217
|
|
package/dist/api/index.js
CHANGED
|
@@ -122,12 +122,12 @@ import {
|
|
|
122
122
|
validateProjectPlugins,
|
|
123
123
|
verifyRepoReadable,
|
|
124
124
|
writeAppHeartbeat
|
|
125
|
-
} from "../index-
|
|
125
|
+
} from "../index-052x5fef.js";
|
|
126
126
|
import {
|
|
127
127
|
BuildError,
|
|
128
128
|
DEFAULT_PRINT_OPTS,
|
|
129
129
|
readyProbeExpr
|
|
130
|
-
} from "../index-
|
|
130
|
+
} from "../index-c2b6gyeg.js";
|
|
131
131
|
import {
|
|
132
132
|
AUTO_SNAPSHOT_MESSAGE,
|
|
133
133
|
HISTORY_PAGE_LIMIT,
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
executeAndReport
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-5tffrg48.js";
|
|
4
4
|
import {
|
|
5
5
|
log
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-v935c2ws.js";
|
|
7
7
|
import {
|
|
8
8
|
UsageError,
|
|
9
9
|
rejectExtraPositionals,
|
|
10
10
|
rejectUnknownFlags
|
|
11
|
-
} from "./cli-
|
|
12
|
-
import"./cli-
|
|
11
|
+
} from "./cli-7e79d7se.js";
|
|
12
|
+
import"./cli-afm8pa0h.js";
|
|
13
13
|
import"./cli-c41yr7he.js";
|
|
14
14
|
import {
|
|
15
15
|
EXIT_CODES
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runBuild,
|
|
3
3
|
splitOutPath
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-5tffrg48.js";
|
|
5
5
|
import {
|
|
6
6
|
log
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-v935c2ws.js";
|
|
8
8
|
import {
|
|
9
9
|
UsageError,
|
|
10
10
|
parseEngine,
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
parsePdfxFlavor,
|
|
13
13
|
rejectExtraPositionals,
|
|
14
14
|
rejectUnknownFlags
|
|
15
|
-
} from "./cli-
|
|
16
|
-
import"./cli-
|
|
15
|
+
} from "./cli-7e79d7se.js";
|
|
16
|
+
import"./cli-afm8pa0h.js";
|
|
17
17
|
import"./cli-c41yr7he.js";
|
|
18
18
|
import {
|
|
19
19
|
BuildError
|
|
@@ -37,6 +37,7 @@ var commandArgs = {
|
|
|
37
37
|
"skip-lint": { type: "boolean", description: "Skip CSS linting (default: lint runs for pdf/pdfx)" },
|
|
38
38
|
"skip-pre-validate": { type: "boolean", description: "Skip pre-build validation" },
|
|
39
39
|
"skip-post-validate": { type: "boolean", description: "Skip post-build PDF/X validation" },
|
|
40
|
+
"allow-shrink": { type: "boolean", description: "Build anyway when content is wider than the page content box, instead of failing. Chromium then scales the WHOLE book down to fit; each offender is reported as a warning." },
|
|
40
41
|
engine: { type: "string", description: "Pagination engine. Paged.js has been removed; native is the only engine. This flag is accepted but ignored (a warning fires for --engine paged)." }
|
|
41
42
|
};
|
|
42
43
|
var build_default = defineCommand({
|
|
@@ -66,6 +67,7 @@ var build_default = defineCommand({
|
|
|
66
67
|
skipLint: !!args["skip-lint"],
|
|
67
68
|
skipPreValidate: !!args["skip-pre-validate"],
|
|
68
69
|
skipPostValidate: !!args["skip-post-validate"],
|
|
70
|
+
allowShrink: !!args["allow-shrink"],
|
|
69
71
|
engine: parseEngine(args.engine),
|
|
70
72
|
rawArgs: args
|
|
71
73
|
});
|
|
@@ -15,20 +15,21 @@ import {
|
|
|
15
15
|
stampCreator,
|
|
16
16
|
stripAnnotations,
|
|
17
17
|
warn
|
|
18
|
-
} from "./cli-
|
|
18
|
+
} from "./cli-v935c2ws.js";
|
|
19
19
|
import {
|
|
20
20
|
DEBOUNCE,
|
|
21
21
|
UsageError,
|
|
22
22
|
resolvePort
|
|
23
|
-
} from "./cli-
|
|
23
|
+
} from "./cli-7e79d7se.js";
|
|
24
24
|
import {
|
|
25
|
+
MARGIN_BOX_IGNORED_PROPERTIES,
|
|
25
26
|
RENDER_TIMEOUT_MS,
|
|
26
27
|
REQUIRED_MILESTONE,
|
|
27
28
|
closeBrowser,
|
|
28
29
|
getAssetPath,
|
|
29
30
|
getBrowser,
|
|
30
31
|
prewarmBrowser
|
|
31
|
-
} from "./cli-
|
|
32
|
+
} from "./cli-afm8pa0h.js";
|
|
32
33
|
import {
|
|
33
34
|
INSTALL_HINTS,
|
|
34
35
|
execCapture,
|
|
@@ -1089,17 +1090,6 @@ import { readFile as readFile3 } from "node:fs/promises";
|
|
|
1089
1090
|
|
|
1090
1091
|
// src/lib/printsafe.ts
|
|
1091
1092
|
import postcss from "postcss";
|
|
1092
|
-
|
|
1093
|
-
// src/engine/shared/margin-box-support.ts
|
|
1094
|
-
var MARGIN_BOX_IGNORED_PROPERTIES = new Set([
|
|
1095
|
-
"transform",
|
|
1096
|
-
"rotate",
|
|
1097
|
-
"translate",
|
|
1098
|
-
"scale",
|
|
1099
|
-
"box-shadow"
|
|
1100
|
-
]);
|
|
1101
|
-
|
|
1102
|
-
// src/lib/printsafe.ts
|
|
1103
1093
|
var ruleRemoteUrls = "printsafe/no-remote-urls";
|
|
1104
1094
|
var ruleRiskyProps = "printsafe/no-risky-print-effects";
|
|
1105
1095
|
var ruleSyntax = "printsafe/syntax-error";
|
|
@@ -3291,6 +3281,9 @@ function warn2(env, line, type, message, marker) {
|
|
|
3291
3281
|
env.layoutWarnings = [];
|
|
3292
3282
|
env.layoutWarnings.push({ line, type, message, marker });
|
|
3293
3283
|
}
|
|
3284
|
+
function proseEscapeHint(kind) {
|
|
3285
|
+
return ` If this line is prose that happens to begin with "@${kind}" — a wrapped sentence, for` + ` instance — escape it as \\@${kind} or write it as \`@${kind}\` in backticks, and it stays text.`;
|
|
3286
|
+
}
|
|
3294
3287
|
function addClasses(token, baseClass, extraClass) {
|
|
3295
3288
|
const cls = [];
|
|
3296
3289
|
if (baseClass)
|
|
@@ -3352,14 +3345,14 @@ function plugin(md, pluginOptions = {}) {
|
|
|
3352
3345
|
const unknown = parsed.__unknownTokens;
|
|
3353
3346
|
delete parsed.__unknownTokens;
|
|
3354
3347
|
for (const t of unknown) {
|
|
3355
|
-
warn2(state.env, startLine + 1, "unrecognized_marker_token", `@${parsed.kind}: "${t}" is not something a marker understands, so it was kept verbatim as a class name. Write a class as .my-class (or {.my-class}), an id as #my-id, and anything else as key=value
|
|
3348
|
+
warn2(state.env, startLine + 1, "unrecognized_marker_token", `@${parsed.kind}: "${t}" is not something a marker understands, so it was kept verbatim as a class name. Write a class as .my-class (or {.my-class}), an id as #my-id, and anything else as key=value.` + proseEscapeHint(parsed.kind), parsed);
|
|
3356
3349
|
}
|
|
3357
3350
|
}
|
|
3358
3351
|
if (parsed.__extraBareTokens) {
|
|
3359
3352
|
const { tokens, named } = parsed.__extraBareTokens;
|
|
3360
3353
|
delete parsed.__extraBareTokens;
|
|
3361
3354
|
const list = tokens.map((t) => `"${t}"`).join(", ");
|
|
3362
|
-
warn2(state.env, startLine + 1, "extra_bare_marker_token", named ? `@${parsed.kind}: only the first plain word (${list.split(", ")[0]}) is used as the name; the rest (${tokens.slice(1).map((t) => `"${t}"`).join(", ")}) became class names instead. Quote a name that contains spaces ("${tokens.join(" ")}"), or write classes as .${tokens.slice(1).join(" .")}.` : `@${parsed.kind}: ${list} are several plain words, but a marker has only one name slot — so NONE of them was used as the name and they all became class names instead. Quote a name that contains spaces ("${tokens.join(" ")}"), or write classes as .${tokens.join(" .")}
|
|
3355
|
+
warn2(state.env, startLine + 1, "extra_bare_marker_token", named ? `@${parsed.kind}: only the first plain word (${list.split(", ")[0]}) is used as the name; the rest (${tokens.slice(1).map((t) => `"${t}"`).join(", ")}) became class names instead. Quote a name that contains spaces ("${tokens.join(" ")}"), or write classes as .${tokens.slice(1).join(" .")}.` : `@${parsed.kind}: ${list} are several plain words, but a marker has only one name slot — so NONE of them was used as the name and they all became class names instead. Quote a name that contains spaces ("${tokens.join(" ")}"), or write classes as .${tokens.join(" .")}.` + proseEscapeHint(parsed.kind), parsed);
|
|
3363
3356
|
}
|
|
3364
3357
|
state.line = startLine + 1;
|
|
3365
3358
|
return true;
|
|
@@ -3451,7 +3444,12 @@ function plugin(md, pluginOptions = {}) {
|
|
|
3451
3444
|
t.meta = { line: meta.__line };
|
|
3452
3445
|
addClasses(t, "spread", meta.attrs && meta.attrs.class ? meta.attrs.class : "");
|
|
3453
3446
|
attachDataAttrs(t, "spread", meta.name, meta.attrs || {});
|
|
3454
|
-
stack.open({
|
|
3447
|
+
stack.open({
|
|
3448
|
+
kind: "spread",
|
|
3449
|
+
classes: meta.attrs && meta.attrs.class || "",
|
|
3450
|
+
noPagesYet: true,
|
|
3451
|
+
sawAnyPage: false
|
|
3452
|
+
}, t);
|
|
3455
3453
|
}
|
|
3456
3454
|
function openPage(meta) {
|
|
3457
3455
|
const chapter = stack.get("chapter");
|
|
@@ -3466,7 +3464,7 @@ function plugin(md, pluginOptions = {}) {
|
|
|
3466
3464
|
const label = chapter ? chapter.label : "";
|
|
3467
3465
|
if (label)
|
|
3468
3466
|
t.attrSet("data-chapter-label", label);
|
|
3469
|
-
stack.open({ kind: "page" }, t);
|
|
3467
|
+
stack.open({ kind: "page", classes: explicit }, t);
|
|
3470
3468
|
if (label && !chapter.openerEmitted) {
|
|
3471
3469
|
const opener = new state.Token("html_block", "", 0);
|
|
3472
3470
|
opener.content = `<div class="chapter-opener" data-chapter-label="${escapeAttr(label)}">${escapeHtml(label)}</div>
|
|
@@ -3489,13 +3487,51 @@ function plugin(md, pluginOptions = {}) {
|
|
|
3489
3487
|
t.meta = { hasColumnBreak: false, line: meta.__line };
|
|
3490
3488
|
stack.open({
|
|
3491
3489
|
kind: "section",
|
|
3490
|
+
classes: meta.attrs && meta.attrs.class || "",
|
|
3491
|
+
sawContent: false,
|
|
3492
3492
|
meta: { name: meta.name || null, attrs: { ...meta.attrs || {} } },
|
|
3493
3493
|
openToken: t
|
|
3494
3494
|
}, t);
|
|
3495
3495
|
}
|
|
3496
|
+
function breakHost() {
|
|
3497
|
+
return stack.get("section") || stack.get("page") || stack.get("spread");
|
|
3498
|
+
}
|
|
3499
|
+
function gridClassOf(frame) {
|
|
3500
|
+
if (!frame || !frame.classes)
|
|
3501
|
+
return null;
|
|
3502
|
+
return frame.classes.split(/\s+/).find((c) => c.startsWith("gp-grid-")) || null;
|
|
3503
|
+
}
|
|
3504
|
+
function warnBreakInsideGrid(kind, line, meta) {
|
|
3505
|
+
const host = breakHost();
|
|
3506
|
+
const gridClass = gridClassOf(host);
|
|
3507
|
+
if (!gridClass)
|
|
3508
|
+
return;
|
|
3509
|
+
warn2(state.env, line, "break_inside_grid", `@${kind} inside a grid container: the enclosing @${host.kind} carries .${gridClass}, so this break's <div> becomes a grid ITEM — it takes a cell of its own, corrupts the grid's placement, and print and the live preview then disagree about which page the content after it lands on. Move the break outside the grid @${host.kind}, or remove it — grid rows already flow and fragment across pages on their own.`, meta);
|
|
3510
|
+
}
|
|
3511
|
+
function warnIfEmptyDecoratedSection(closingKind, closingLine) {
|
|
3512
|
+
const sec = stack.get("section");
|
|
3513
|
+
if (!sec || sec.sawContent)
|
|
3514
|
+
return;
|
|
3515
|
+
const attrs = sec.meta && sec.meta.attrs || {};
|
|
3516
|
+
const decorations = [];
|
|
3517
|
+
for (const c of (attrs.class || "").split(/\s+/).filter(Boolean))
|
|
3518
|
+
decorations.push(`.${c}`);
|
|
3519
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
3520
|
+
if (k === "class")
|
|
3521
|
+
continue;
|
|
3522
|
+
decorations.push(k === "id" ? `#${v}` : `${k}=${v}`);
|
|
3523
|
+
}
|
|
3524
|
+
if (!decorations.length)
|
|
3525
|
+
return;
|
|
3526
|
+
const openLine = sec.openToken && sec.openToken.meta && Number.isFinite(sec.openToken.meta.line) ? sec.openToken.meta.line : closingLine;
|
|
3527
|
+
warn2(state.env, openLine, "empty_section", `This @section (${decorations.join(" ")}) was closed by the @${closingKind} on line ${closingLine} with no content between the two markers, so its styling applies to an empty element and nothing prints the layout it asked for. Delete one of the two markers, or move the content that belongs inside the section between them.`, null);
|
|
3528
|
+
}
|
|
3496
3529
|
for (let i = 0;i < state.tokens.length; i++) {
|
|
3497
3530
|
const tok = state.tokens[i];
|
|
3498
3531
|
if (tok.type !== "layout_marker") {
|
|
3532
|
+
const openSectionFrame = stack.get("section");
|
|
3533
|
+
if (openSectionFrame)
|
|
3534
|
+
openSectionFrame.sawContent = true;
|
|
3499
3535
|
out.push(tok);
|
|
3500
3536
|
continue;
|
|
3501
3537
|
}
|
|
@@ -3521,6 +3557,7 @@ function plugin(md, pluginOptions = {}) {
|
|
|
3521
3557
|
continue;
|
|
3522
3558
|
}
|
|
3523
3559
|
if (kind === "section") {
|
|
3560
|
+
warnIfEmptyDecoratedSection("section", line);
|
|
3524
3561
|
stack.close("section");
|
|
3525
3562
|
const spread = stack.get("spread");
|
|
3526
3563
|
if (spread && spread.noPagesYet) {
|
|
@@ -3549,6 +3586,7 @@ function plugin(md, pluginOptions = {}) {
|
|
|
3549
3586
|
continue;
|
|
3550
3587
|
}
|
|
3551
3588
|
if (kind === "page-break") {
|
|
3589
|
+
warnBreakInsideGrid("page-break", line, meta);
|
|
3552
3590
|
const t = new state.Token("layout_page_break", "div", 0);
|
|
3553
3591
|
t.meta = { line };
|
|
3554
3592
|
t.attrSet("class", "gp-page-break");
|
|
@@ -3557,6 +3595,7 @@ function plugin(md, pluginOptions = {}) {
|
|
|
3557
3595
|
continue;
|
|
3558
3596
|
}
|
|
3559
3597
|
if (kind === "column-break") {
|
|
3598
|
+
warnBreakInsideGrid("column-break", line, meta);
|
|
3560
3599
|
const openSectionFrame = stack.get("section");
|
|
3561
3600
|
if (openSectionFrame && openSectionFrame.openToken && !openSectionFrame.openToken.meta.hasColumnBreak) {
|
|
3562
3601
|
const sectionCls = openSectionFrame.openToken.attrGet("class") || "";
|
|
@@ -3572,6 +3611,7 @@ function plugin(md, pluginOptions = {}) {
|
|
|
3572
3611
|
continue;
|
|
3573
3612
|
}
|
|
3574
3613
|
if (kind === "end-section") {
|
|
3614
|
+
warnIfEmptyDecoratedSection("end-section", line);
|
|
3575
3615
|
stack.close("section");
|
|
3576
3616
|
continue;
|
|
3577
3617
|
}
|
|
@@ -3659,7 +3699,7 @@ body { margin: 0; }
|
|
|
3659
3699
|
.gp-page-break { break-before: page; }
|
|
3660
3700
|
.page { break-before: page; }
|
|
3661
3701
|
.spread { break-before: page; }
|
|
3662
|
-
:where(.page, .spread) { position: relative; }
|
|
3702
|
+
:where(.page, .spread) { position: relative; display: flow-root; box-sizing: border-box; min-height: calc(var(--gp-content-h, 1px) - 1px); }
|
|
3663
3703
|
.gp-column-break { break-after: column; height: 0; font-size: 0; line-height: 0; visibility: hidden; }
|
|
3664
3704
|
|
|
3665
3705
|
:where(h1,h2,h3,h4,h5,h6) { break-after: avoid; }
|
|
@@ -6006,6 +6046,26 @@ var GUTTERPRESS_CSS = `
|
|
|
6006
6046
|
.gp-columns-2 { columns: 2; column-gap: var(--gp-column-gap, 1.5em); }
|
|
6007
6047
|
.gp-columns-3 { columns: 3; column-gap: var(--gp-column-gap, 1.5em); }
|
|
6008
6048
|
|
|
6049
|
+
/* grid runs — the SLOTTED counterpart to the column runs above. Grid places
|
|
6050
|
+
each child into the next cell, across then down (deterministic slots: card
|
|
6051
|
+
layouts, stat blocks, image-plus-caption pairs); columns FLOW one text run
|
|
6052
|
+
down then across. Same neutral-primitive rationale as .gp-columns-*, and
|
|
6053
|
+
permanent vocabulary for the same reason: standard CSS Grid verbatim, no
|
|
6054
|
+
spec gap to remove later. MEASURED (Chromium 151, gp-grid evidence pack):
|
|
6055
|
+
grid rows fragment across sheets with EXACT print/viewer parity — 2- and
|
|
6056
|
+
3-col, unequal item heights, mid-row cuts, multi-sheet overflow,
|
|
6057
|
+
break-inside:avoid, gap geometry — so a grid taller than the page is safe,
|
|
6058
|
+
no fit-one-page constraint. Two things to know, not fix:
|
|
6059
|
+
- on a min-height page root (MARKER_CSS), default align-content
|
|
6060
|
+
stretches rows apart to fill the page — identically in both engines.
|
|
6061
|
+
Authors wanting packed rows set align-content: start.
|
|
6062
|
+
- a @page-break / @column-break marker DIRECTLY inside a grid container
|
|
6063
|
+
becomes a grid item and corrupts placement (the one measured parity
|
|
6064
|
+
break); markers.js diagnoses it (break_inside_grid).
|
|
6065
|
+
--gp-grid-gap is author-settable. */
|
|
6066
|
+
.gp-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--gp-grid-gap, 1.5em); }
|
|
6067
|
+
.gp-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gp-grid-gap, 1.5em); }
|
|
6068
|
+
|
|
6009
6069
|
/* shape wrap — text follows the image's alpha silhouette instead of its
|
|
6010
6070
|
rectangular box. shape-outside only applies to floats, so this is inert
|
|
6011
6071
|
without .gp-left/.gp-right (and under .gp-pin, which un-floats). The
|
|
@@ -6068,8 +6128,14 @@ img.gp-shape {
|
|
|
6068
6128
|
opacity, filter, transform on it traps the negative layer inside).
|
|
6069
6129
|
Core keeps .page/.spread at 'position: relative; z-index: auto'
|
|
6070
6130
|
precisely so they are not stacking contexts.
|
|
6071
|
-
- a clipping ancestor (overflow other than visible)
|
|
6072
|
-
|
|
6131
|
+
- a clipping ancestor (overflow other than visible) — but only where
|
|
6132
|
+
the art actually overhangs that ancestor's clip box on a clipped
|
|
6133
|
+
axis: the overhang is cut off, the same mechanism that clips a
|
|
6134
|
+
.gp-bleed plate back to the wrapper's width. Clipping never reorders
|
|
6135
|
+
layers — within-bounds art under a clipping .page prints whole and
|
|
6136
|
+
still behind (measured; see the build audit's comment in
|
|
6137
|
+
engine/compiler/build.ts), and a static wrapper's overflow never
|
|
6138
|
+
binds an abspos .gp-pin at all.
|
|
6073
6139
|
The build-time engine.layer.trapped audit reports both against the live
|
|
6074
6140
|
ancestor chain. printsafe/page-containment is only an early source hint for
|
|
6075
6141
|
declarations written directly on .page/.spread. */
|
|
@@ -7363,11 +7429,12 @@ class PdfOutput {
|
|
|
7363
7429
|
const rawPdf = pdfxMode ? path7.join(stage, "raw.pdf") : path7.resolve(pdfFile);
|
|
7364
7430
|
await fsp2.mkdir(path7.dirname(path7.resolve(pdfFile)), { recursive: true });
|
|
7365
7431
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
7366
|
-
const { buildNativePdf } = await import("./engine-
|
|
7432
|
+
const { buildNativePdf } = await import("./engine-hrtn0b28.js");
|
|
7367
7433
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
7368
7434
|
title: config.title,
|
|
7369
7435
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
7370
|
-
signature: config.print.signature
|
|
7436
|
+
signature: config.print.signature,
|
|
7437
|
+
allowShrink: opts.allowShrink
|
|
7371
7438
|
}, opts.engineBrowser);
|
|
7372
7439
|
for (const d of engineDiagnostics)
|
|
7373
7440
|
log.warn(d.message);
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
// package.json
|
|
5
5
|
var package_default = {
|
|
6
6
|
name: "gutterpress",
|
|
7
|
-
version: "0.10.0-
|
|
7
|
+
version: "0.10.0-beta.1",
|
|
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",
|