gutterpress 0.11.20-alpha.1 → 0.11.20-alpha.2
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-cmf4nbpm.js → build-qmjg9r2d.js} +4 -4
- package/dist/checks/pdf/index.d.ts +1 -0
- package/dist/checks/pdf/safe-margins.d.ts +3 -0
- package/dist/{cli-7shp2kmj.js → cli-7z29z4wz.js} +1 -1
- package/dist/{cli-mmm22cza.js → cli-gh0ym80r.js} +1 -1
- package/dist/{cli-rtpm04dv.js → cli-j802s31j.js} +5 -5
- package/dist/{cli-x1nfhaf1.js → cli-zacevwcy.js} +284 -180
- package/dist/cli.js +12 -12
- package/dist/{doctor-0d6esj02.js → doctor-fe7tcs4v.js} +2 -2
- package/dist/{engine-1v8kmv3a.js → engine-9xb1ky8d.js} +1 -1
- package/dist/{engine-adxptzf0.js → engine-yax79k9m.js} +2 -2
- package/dist/{ext-65nfh7st.js → ext-ahwxt6gv.js} +4 -4
- package/dist/{gutterpress-viewer-0r4rt4de.js → gutterpress-viewer-retj6ym2.js} +343 -98
- package/dist/{index-pnvzgftg.js → index-3nr5rzzp.js} +5 -5
- package/dist/{index-cngw658w.js → index-6xwtb7cw.js} +1 -1
- package/dist/{index-1y885h1j.js → index-razpty47.js} +282 -178
- package/dist/index.js +3 -3
- package/dist/lib/presets.d.ts +3 -1
- package/dist/{manifest.schema-nrykd2c6.json → manifest.schema-74s1ykyv.json} +8 -2
- package/dist/{new-y4a2xz3g.js → new-ftd4fec4.js} +4 -4
- package/dist/{preflight-kt7wfgbd.js → preflight-8sqarcsr.js} +4 -4
- package/dist/preview/file-watcher.d.ts +7 -1
- package/dist/{preview-bridge-evecsh4w.js → preview-bridge-8wjcjec3.js} +3 -2
- package/dist/{preview-interface-k2mj5kvq.js → preview-interface-nnmrxyqm.js} +37 -41
- package/dist/{preview-5ze728kp.js → preview-q76xn95h.js} +4 -4
- package/dist/{preview-shell-7jfe6vsc.js → preview-shell-wk9k3gcd.js} +18 -6
- package/dist/{publish-5tpcyysh.js → publish-7gdy6gbf.js} +4 -4
- package/dist/schema/manifest.types.d.ts +27 -6
- package/dist/{validate-p0hkqkfe.js → validate-e3ryegce.js} +4 -4
- package/package.json +1 -1
|
@@ -2101,41 +2101,79 @@
|
|
|
2101
2101
|
const h = area.height * scale;
|
|
2102
2102
|
const b = Math.max(0, area.bleed) * scale;
|
|
2103
2103
|
const s = Math.max(0, area.safe) * scale;
|
|
2104
|
+
const a = Math.max(0, area.artSafe) * scale;
|
|
2105
|
+
const [left, right] = side === "verso" ? [a, s] : [s, a];
|
|
2104
2106
|
const trim = { x: side === "verso" ? b : 0, y: b, w: Math.max(0, w - b), h: Math.max(0, h - 2 * b) };
|
|
2105
2107
|
return {
|
|
2106
2108
|
sheet: { x: 0, y: 0, w, h },
|
|
2107
2109
|
trim,
|
|
2108
2110
|
safe: { x: trim.x + s, y: trim.y + s, w: Math.max(0, trim.w - 2 * s), h: Math.max(0, trim.h - 2 * s) },
|
|
2111
|
+
safeArt: {
|
|
2112
|
+
x: trim.x + left,
|
|
2113
|
+
y: trim.y + a,
|
|
2114
|
+
w: Math.max(0, trim.w - left - right),
|
|
2115
|
+
h: Math.max(0, trim.h - 2 * a)
|
|
2116
|
+
},
|
|
2109
2117
|
bleed: b
|
|
2110
2118
|
};
|
|
2111
2119
|
}
|
|
2112
2120
|
var SEVERITY = { inside: 0, unsafe: 1, bleed: 2, "off-page": 3 };
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2121
|
+
function classifyRect(r, boxes, rule, tol = 0) {
|
|
2122
|
+
const { sheet, trim } = boxes;
|
|
2123
|
+
const safe = rule === "art" ? boxes.safeArt : boxes.safe;
|
|
2124
|
+
const sides = [
|
|
2125
|
+
[-r.x, -safe.x, -trim.x, -sheet.x],
|
|
2126
|
+
[r.x + r.w, safe.x + safe.w, trim.x + trim.w, sheet.x + sheet.w],
|
|
2127
|
+
[-r.y, -safe.y, -trim.y, -sheet.y],
|
|
2128
|
+
[r.y + r.h, safe.y + safe.h, trim.y + trim.h, sheet.y + sheet.h]
|
|
2129
|
+
];
|
|
2130
|
+
let worst = { kind: "inside", gap: 0, need: 0 };
|
|
2131
|
+
let beyond = 0;
|
|
2132
|
+
for (const [ink, limit, edge, sheetEdge] of sides) {
|
|
2133
|
+
const past = ink - limit;
|
|
2134
|
+
if (past <= tol || rule === "art" && ink >= sheetEdge - tol)
|
|
2135
|
+
continue;
|
|
2136
|
+
const kind = ink > sheetEdge + tol ? "off-page" : ink > edge + tol ? "bleed" : "unsafe";
|
|
2137
|
+
if (SEVERITY[kind] > SEVERITY[worst.kind] || kind === worst.kind && past > beyond) {
|
|
2138
|
+
worst = { kind, gap: edge - ink, need: edge - limit };
|
|
2139
|
+
beyond = past;
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
return worst;
|
|
2125
2143
|
}
|
|
2126
2144
|
var INTENT_SELECTOR = ".gp-bleed, .gp-pin, .gp-flush, .gp-behind, .gp-page-full-bleed";
|
|
2145
|
+
var OVERLAY_LAYERS = ["bleed", "safe", "art", "margins"];
|
|
2146
|
+
function layersFrom(state) {
|
|
2147
|
+
const named = state && typeof state === "object" ? state : null;
|
|
2148
|
+
const on = (layer) => named ? named[layer] === true : !!state;
|
|
2149
|
+
return { bleed: on("bleed"), safe: on("safe"), art: on("art"), margins: on("margins") };
|
|
2150
|
+
}
|
|
2127
2151
|
var OVERLAY_STRENGTHS = ["subtle", "normal", "strong"];
|
|
2128
2152
|
var HEX_COLOR = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
|
|
2129
2153
|
function sanitizeOverlayStyle(style) {
|
|
2130
2154
|
const s = style && typeof style === "object" ? style : {};
|
|
2155
|
+
const given = s.colors && typeof s.colors === "object" ? s.colors : {};
|
|
2156
|
+
const hex = (v) => typeof v === "string" && HEX_COLOR.test(v.trim()) ? v.trim() : undefined;
|
|
2131
2157
|
const out = {};
|
|
2132
|
-
|
|
2133
|
-
|
|
2158
|
+
for (const layer of OVERLAY_LAYERS) {
|
|
2159
|
+
const color = hex(given[layer]) ?? (layer === "safe" ? hex(s.color) : undefined);
|
|
2160
|
+
if (color)
|
|
2161
|
+
(out.colors ??= {})[layer] = color;
|
|
2162
|
+
}
|
|
2134
2163
|
if (OVERLAY_STRENGTHS.includes(s.strength))
|
|
2135
2164
|
out.strength = s.strength;
|
|
2136
2165
|
return out;
|
|
2137
2166
|
}
|
|
2138
|
-
var OVERLAY_OFF = {
|
|
2167
|
+
var OVERLAY_OFF = {
|
|
2168
|
+
on: false,
|
|
2169
|
+
layers: { bleed: false, safe: false, art: false, margins: false },
|
|
2170
|
+
issues: 0,
|
|
2171
|
+
intended: 0,
|
|
2172
|
+
bleedPt: 0,
|
|
2173
|
+
safePt: 0,
|
|
2174
|
+
artSafePt: 0,
|
|
2175
|
+
counts: { text: 0, art: 0, bleed: 0, offPage: 0, intended: 0 }
|
|
2176
|
+
};
|
|
2139
2177
|
function printAreaFromMeta() {
|
|
2140
2178
|
const raw = document.querySelector('meta[name="gp-print-area"]')?.getAttribute("content");
|
|
2141
2179
|
if (!raw)
|
|
@@ -2145,24 +2183,37 @@
|
|
|
2145
2183
|
const n = (x) => typeof x === "number" && Number.isFinite(x) && x > 0 ? x : 0;
|
|
2146
2184
|
if (!n(v.width) || !n(v.height))
|
|
2147
2185
|
return null;
|
|
2148
|
-
|
|
2186
|
+
const safe = n(v.safe);
|
|
2187
|
+
const spec = v.spec && typeof v.spec.label === "string" && typeof v.spec.url === "string" && /^https?:\/\//i.test(v.spec.url) ? v.spec : undefined;
|
|
2188
|
+
return {
|
|
2189
|
+
width: n(v.width),
|
|
2190
|
+
height: n(v.height),
|
|
2191
|
+
bleed: n(v.bleed),
|
|
2192
|
+
safe,
|
|
2193
|
+
artSafe: typeof v.artSafe === "number" ? n(v.artSafe) : safe,
|
|
2194
|
+
preset: typeof v.preset === "string" ? v.preset : undefined,
|
|
2195
|
+
spec
|
|
2196
|
+
};
|
|
2149
2197
|
} catch {
|
|
2150
2198
|
return null;
|
|
2151
2199
|
}
|
|
2152
2200
|
}
|
|
2153
2201
|
function sheetArea(sheet) {
|
|
2154
2202
|
const px = (name) => parseFloat(sheet.style.getPropertyValue(name)) || 0;
|
|
2155
|
-
return { width: px("--gp-page-w") / PX_PER_PT, height: px("--gp-page-h") / PX_PER_PT, bleed: 0, safe: 0 };
|
|
2203
|
+
return { width: px("--gp-page-w") / PX_PER_PT, height: px("--gp-page-h") / PX_PER_PT, bleed: 0, safe: 0, artSafe: 0 };
|
|
2156
2204
|
}
|
|
2157
2205
|
var OVERLAY_CSS = `
|
|
2158
2206
|
.root {
|
|
2159
|
-
--gp-ov-color: #2f80ed; /* safe
|
|
2207
|
+
--gp-ov-color: #2f80ed; /* safe layer: the text line + the tint outside it */
|
|
2160
2208
|
--gp-ov-width: 2px; /* line width as seen on screen, at any zoom */
|
|
2161
|
-
--gp-ov-style: dashed; /* safe
|
|
2162
|
-
--gp-ov-
|
|
2163
|
-
--gp-ov-
|
|
2209
|
+
--gp-ov-style: dashed; /* text safe line style */
|
|
2210
|
+
--gp-ov-art-style: dotted; /* art safe line style */
|
|
2211
|
+
--gp-ov-tint: 0.1; /* opacity of the tint between the text line and the trim */
|
|
2212
|
+
--gp-ov-bleed-color: #e5484d; /* bleed layer: the band, and (darker) the trim line */
|
|
2164
2213
|
--gp-ov-bleed-alpha: 0.45; /* opacity of the bleed band */
|
|
2165
|
-
--gp-ov-trim-color: #
|
|
2214
|
+
--gp-ov-trim-color: color-mix(in srgb, var(--gp-ov-bleed-color) 60%, #000); /* darker than the band so it reads as an edge */
|
|
2215
|
+
--gp-ov-art-color: #00b4d8; /* art layer: the art line (dotted, a second cue) */
|
|
2216
|
+
--gp-ov-margins-color: #1a9c6b; /* margins layer: the page's own content box */
|
|
2166
2217
|
--gp-ov-flag-width: 2px; /* overflow flag outline */
|
|
2167
2218
|
--gp-ov-warn: #f59e0b; /* leaves the safe area */
|
|
2168
2219
|
--gp-ov-error: #e5484d; /* crosses the trim / leaves the sheet */
|
|
@@ -2171,10 +2222,18 @@
|
|
|
2171
2222
|
zoom; dividing by it keeps lines the same width on screen at every zoom. */
|
|
2172
2223
|
--gp-ov-w: calc(var(--gp-ov-width) / var(--gp-ov-z, 1));
|
|
2173
2224
|
--gp-ov-flag-w: calc(var(--gp-ov-flag-width) / var(--gp-ov-z, 1));
|
|
2225
|
+
--gp-ov-margins-w: calc(1px / var(--gp-ov-z, 1)); /* thin, whatever the strength */
|
|
2174
2226
|
position: absolute;
|
|
2175
2227
|
inset: 0;
|
|
2176
2228
|
pointer-events: none;
|
|
2177
2229
|
}
|
|
2230
|
+
/* the stage's zoomed copy, holding the pages' boxes; the legend sits beside it, not in it */
|
|
2231
|
+
.gp-ov-canvas {
|
|
2232
|
+
position: absolute;
|
|
2233
|
+
left: 0;
|
|
2234
|
+
top: 0;
|
|
2235
|
+
transform-origin: 0 0;
|
|
2236
|
+
}
|
|
2178
2237
|
.root[data-strength="subtle"] {
|
|
2179
2238
|
--gp-ov-width: 1px;
|
|
2180
2239
|
--gp-ov-tint: 0.05;
|
|
@@ -2186,11 +2245,11 @@
|
|
|
2186
2245
|
--gp-ov-bleed-alpha: 0.65;
|
|
2187
2246
|
--gp-ov-flag-width: 3px;
|
|
2188
2247
|
}
|
|
2189
|
-
.gp-ov-page, .gp-ov-tint, .gp-ov-safe, .gp-ov-bleed, .gp-ov-trim, .gp-ov-flag {
|
|
2248
|
+
.gp-ov-page, .gp-ov-tint, .gp-ov-safe, .gp-ov-art, .gp-ov-bleed, .gp-ov-trim, .gp-ov-margins, .gp-ov-flag {
|
|
2190
2249
|
position: absolute;
|
|
2191
2250
|
box-sizing: border-box;
|
|
2192
2251
|
}
|
|
2193
|
-
/* the band between the
|
|
2252
|
+
/* the band between the text line and the trim, as a REGION (clip-path, set in
|
|
2194
2253
|
overlay.ts), so it reads as an area, not a hairline */
|
|
2195
2254
|
.gp-ov-tint {
|
|
2196
2255
|
background: color-mix(in srgb, var(--gp-ov-color) calc(var(--gp-ov-tint) * 100%), transparent);
|
|
@@ -2198,6 +2257,9 @@
|
|
|
2198
2257
|
.gp-ov-safe {
|
|
2199
2258
|
border: var(--gp-ov-w) var(--gp-ov-style) var(--gp-ov-color);
|
|
2200
2259
|
}
|
|
2260
|
+
.gp-ov-art {
|
|
2261
|
+
border: var(--gp-ov-w) var(--gp-ov-art-style) var(--gp-ov-art-color);
|
|
2262
|
+
}
|
|
2201
2263
|
/* bleed: a translucent band between the trim and the sheet edge (its width is the border) */
|
|
2202
2264
|
.gp-ov-bleed {
|
|
2203
2265
|
border-style: solid;
|
|
@@ -2208,6 +2270,10 @@
|
|
|
2208
2270
|
outline: var(--gp-ov-w) solid var(--gp-ov-trim-color);
|
|
2209
2271
|
outline-offset: calc(-1 * var(--gp-ov-w));
|
|
2210
2272
|
}
|
|
2273
|
+
/* margins: the page's own content box, a thin solid line */
|
|
2274
|
+
.gp-ov-margins {
|
|
2275
|
+
border: var(--gp-ov-margins-w) solid var(--gp-ov-margins-color);
|
|
2276
|
+
}
|
|
2211
2277
|
/* overflow flags: outline + faint tint, never a box change */
|
|
2212
2278
|
.gp-ov-flag[data-kind="unsafe"] {
|
|
2213
2279
|
outline: var(--gp-ov-flag-w) solid var(--gp-ov-warn);
|
|
@@ -2221,6 +2287,38 @@
|
|
|
2221
2287
|
.gp-ov-flag[data-kind="intended"] {
|
|
2222
2288
|
outline: var(--gp-ov-flag-w) dotted var(--gp-ov-intent);
|
|
2223
2289
|
}
|
|
2290
|
+
/* the legend: small, fixed in a corner of the viewport, and the one part that takes the pointer (its link) */
|
|
2291
|
+
.gp-ov-legend {
|
|
2292
|
+
position: fixed;
|
|
2293
|
+
right: 12px;
|
|
2294
|
+
bottom: 12px;
|
|
2295
|
+
box-sizing: border-box;
|
|
2296
|
+
max-width: min(420px, calc(100vw - 24px));
|
|
2297
|
+
padding: 8px 10px;
|
|
2298
|
+
border-radius: 8px;
|
|
2299
|
+
background: rgba(20, 20, 24, 0.92);
|
|
2300
|
+
color: #fff;
|
|
2301
|
+
font: 11px/1.45 ui-sans-serif, system-ui, sans-serif;
|
|
2302
|
+
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.4);
|
|
2303
|
+
pointer-events: auto;
|
|
2304
|
+
}
|
|
2305
|
+
.gp-ov-legend > div + div { margin-top: 3px; }
|
|
2306
|
+
.gp-ov-legend a { color: #9cc2ff; }
|
|
2307
|
+
.gp-ov-row { display: flex; align-items: flex-start; gap: 6px; }
|
|
2308
|
+
.gp-ov-swatch {
|
|
2309
|
+
flex: none;
|
|
2310
|
+
box-sizing: border-box;
|
|
2311
|
+
width: 10px;
|
|
2312
|
+
height: 10px;
|
|
2313
|
+
margin-top: 3px;
|
|
2314
|
+
border: 1px solid rgba(255, 255, 255, 0.7);
|
|
2315
|
+
border-radius: 2px;
|
|
2316
|
+
}
|
|
2317
|
+
.gp-ov-swatch[data-layer="bleed"] { background: var(--gp-ov-bleed-color); }
|
|
2318
|
+
.gp-ov-swatch[data-layer="safe"] { background: var(--gp-ov-color); }
|
|
2319
|
+
.gp-ov-swatch[data-layer="art"] { background: var(--gp-ov-art-color); }
|
|
2320
|
+
.gp-ov-swatch[data-layer="margins"] { background: var(--gp-ov-margins-color); }
|
|
2321
|
+
.gp-ov-note { opacity: 0.75; }
|
|
2224
2322
|
@media print {
|
|
2225
2323
|
.root { display: none; }
|
|
2226
2324
|
}
|
|
@@ -2244,24 +2342,33 @@
|
|
|
2244
2342
|
"mask: none",
|
|
2245
2343
|
"z-index: 2147483647",
|
|
2246
2344
|
"pointer-events: none",
|
|
2247
|
-
"transform-origin: 0 0",
|
|
2248
2345
|
"contain: style"
|
|
2249
2346
|
].map((d) => `${d} !important`).join("; ");
|
|
2250
2347
|
var OVERLAY_TAG = "gp-overlay";
|
|
2251
2348
|
var host = null;
|
|
2252
2349
|
var root = null;
|
|
2350
|
+
var canvas = null;
|
|
2253
2351
|
var observer = null;
|
|
2254
2352
|
var currentStyle = {};
|
|
2353
|
+
var COLOR_TOKEN = {
|
|
2354
|
+
bleed: "--gp-ov-bleed-color",
|
|
2355
|
+
safe: "--gp-ov-color",
|
|
2356
|
+
art: "--gp-ov-art-color",
|
|
2357
|
+
margins: "--gp-ov-margins-color"
|
|
2358
|
+
};
|
|
2255
2359
|
function applyStyle() {
|
|
2256
2360
|
if (!root)
|
|
2257
2361
|
return;
|
|
2258
2362
|
if (currentStyle.strength)
|
|
2259
2363
|
root.dataset.strength = currentStyle.strength;
|
|
2260
|
-
|
|
2261
|
-
|
|
2364
|
+
for (const layer of OVERLAY_LAYERS) {
|
|
2365
|
+
const color = currentStyle.colors?.[layer];
|
|
2366
|
+
if (color)
|
|
2367
|
+
root.style.setProperty(COLOR_TOKEN[layer], color);
|
|
2368
|
+
}
|
|
2262
2369
|
}
|
|
2263
2370
|
function setOverlayStyle(style) {
|
|
2264
|
-
currentStyle = { ...currentStyle, ...style };
|
|
2371
|
+
currentStyle = { ...currentStyle, ...style, colors: { ...currentStyle.colors, ...style.colors } };
|
|
2265
2372
|
applyStyle();
|
|
2266
2373
|
}
|
|
2267
2374
|
function stageFrame() {
|
|
@@ -2271,32 +2378,33 @@
|
|
|
2271
2378
|
return { left: r.left, top: r.top, zoom: zoom || 1 };
|
|
2272
2379
|
}
|
|
2273
2380
|
function syncToStage() {
|
|
2274
|
-
if (!
|
|
2381
|
+
if (!root || !canvas)
|
|
2275
2382
|
return;
|
|
2276
2383
|
const { left, top, zoom } = stageFrame();
|
|
2277
|
-
|
|
2384
|
+
canvas.style.transform = `translate(${left + window.scrollX}px, ${top + window.scrollY}px) scale(${zoom})`;
|
|
2278
2385
|
root.style.setProperty("--gp-ov-z", String(zoom));
|
|
2279
2386
|
}
|
|
2280
2387
|
function ensureRoot() {
|
|
2281
|
-
if (host && root && host.isConnected) {
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2388
|
+
if (!(host && root && host.isConnected)) {
|
|
2389
|
+
host = document.createElement(OVERLAY_TAG);
|
|
2390
|
+
host.setAttribute("style", HOST_STYLE);
|
|
2391
|
+
const shadow = host.attachShadow({ mode: "open" });
|
|
2392
|
+
const sheet = document.createElement("style");
|
|
2393
|
+
sheet.textContent = OVERLAY_CSS;
|
|
2394
|
+
root = document.createElement("div");
|
|
2395
|
+
root.className = "root";
|
|
2396
|
+
shadow.append(sheet, root);
|
|
2397
|
+
document.documentElement.appendChild(host);
|
|
2398
|
+
applyStyle();
|
|
2399
|
+
observer = new MutationObserver(syncToStage);
|
|
2400
|
+
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["style"] });
|
|
2401
|
+
observer.observe(document.body, { attributes: true, attributeFilter: ["style"] });
|
|
2402
|
+
}
|
|
2403
|
+
root.textContent = "";
|
|
2404
|
+
canvas = div("gp-ov-canvas");
|
|
2405
|
+
canvas.setAttribute("aria-hidden", "true");
|
|
2406
|
+
root.appendChild(canvas);
|
|
2407
|
+
return canvas;
|
|
2300
2408
|
}
|
|
2301
2409
|
function clearOverlay() {
|
|
2302
2410
|
observer?.disconnect();
|
|
@@ -2304,6 +2412,7 @@
|
|
|
2304
2412
|
host?.remove();
|
|
2305
2413
|
host = null;
|
|
2306
2414
|
root = null;
|
|
2415
|
+
canvas = null;
|
|
2307
2416
|
}
|
|
2308
2417
|
function div(cls, box) {
|
|
2309
2418
|
const el = document.createElement("div");
|
|
@@ -2325,9 +2434,86 @@
|
|
|
2325
2434
|
el.style.clipPath = `polygon(evenodd, ${t.x}px ${t.y}px, ${t.x + t.w}px ${t.y}px, ${t.x + t.w}px ${t.y + t.h}px, ${t.x}px ${t.y + t.h}px, ${t.x}px ${t.y}px, ` + `${s.x}px ${s.y}px, ${s.x}px ${s.y + s.h}px, ${s.x + s.w}px ${s.y + s.h}px, ${s.x + s.w}px ${s.y}px, ${s.x}px ${s.y}px)`;
|
|
2326
2435
|
return el;
|
|
2327
2436
|
}
|
|
2437
|
+
function marginsBox(p, side) {
|
|
2438
|
+
const { width, height, margin } = p.strip.geometry;
|
|
2439
|
+
const shift = side === "verso" ? p.strip.versoShift : 0;
|
|
2440
|
+
const left = margin.left - shift;
|
|
2441
|
+
const right = margin.right + shift;
|
|
2442
|
+
return {
|
|
2443
|
+
x: left * PX_PER_PT,
|
|
2444
|
+
y: margin.top * PX_PER_PT,
|
|
2445
|
+
w: Math.max(0, width - left - right) * PX_PER_PT,
|
|
2446
|
+
h: Math.max(0, height - margin.top - margin.bottom) * PX_PER_PT
|
|
2447
|
+
};
|
|
2448
|
+
}
|
|
2328
2449
|
var TOL_PX = 1;
|
|
2329
2450
|
var SKIP = new Set(["SCRIPT", "STYLE", "LINK", "TEMPLATE", "BR", "WBR", "SOURCE", "TRACK", "META"]);
|
|
2330
|
-
|
|
2451
|
+
var ART_TAGS = new Set(["img", "svg", "video", "canvas"]);
|
|
2452
|
+
var inches = (px) => +(Math.abs(px) / 96).toFixed(2);
|
|
2453
|
+
var ptIn = (pt2) => `${+(pt2 / 72).toFixed(3)}in`;
|
|
2454
|
+
function legend(layers, area, summary) {
|
|
2455
|
+
const el = div("gp-ov-legend");
|
|
2456
|
+
const add = (cls, ...content) => {
|
|
2457
|
+
const line = div(cls);
|
|
2458
|
+
line.append(...content);
|
|
2459
|
+
el.appendChild(line);
|
|
2460
|
+
};
|
|
2461
|
+
const row = (layer, name, text) => {
|
|
2462
|
+
const swatch = div("gp-ov-swatch");
|
|
2463
|
+
swatch.dataset.layer = layer;
|
|
2464
|
+
const bold = document.createElement("b");
|
|
2465
|
+
bold.textContent = name;
|
|
2466
|
+
const label = document.createElement("span");
|
|
2467
|
+
label.append(bold, text);
|
|
2468
|
+
add("gp-ov-row", swatch, label);
|
|
2469
|
+
};
|
|
2470
|
+
const { bleedPt, safePt, artSafePt, counts } = summary;
|
|
2471
|
+
if (layers.bleed) {
|
|
2472
|
+
row("bleed", "Bleed", bleedPt > 0 ? ` ${ptIn(bleedPt)} — top, bottom, outside; none at the binding` : " — none set (page.bleed in manifest.yaml)");
|
|
2473
|
+
}
|
|
2474
|
+
if (layers.safe) {
|
|
2475
|
+
row("safe", "Safe area: text", safePt > 0 ? ` — ${ptIn(safePt)}, every edge` : " — none set (page.safe in manifest.yaml)");
|
|
2476
|
+
}
|
|
2477
|
+
if (layers.art) {
|
|
2478
|
+
row("art", "Safe area: art", safePt <= 0 && artSafePt <= 0 ? " — none set (page.artSafe in manifest.yaml)" : artSafePt === safePt ? ` — ${ptIn(artSafePt)}, every edge` : ` — ${ptIn(artSafePt)} top, bottom, outside; ${ptIn(safePt)} at the binding`);
|
|
2479
|
+
}
|
|
2480
|
+
if (layers.margins)
|
|
2481
|
+
row("margins", "Page margins", " — your stylesheet's @page margins");
|
|
2482
|
+
if (area && (layers.bleed || layers.safe || layers.art)) {
|
|
2483
|
+
if (area.spec) {
|
|
2484
|
+
const link = document.createElement("a");
|
|
2485
|
+
link.href = area.spec.url;
|
|
2486
|
+
link.target = "_blank";
|
|
2487
|
+
link.rel = "noopener";
|
|
2488
|
+
link.textContent = area.spec.label;
|
|
2489
|
+
add("gp-ov-note", "from ", link);
|
|
2490
|
+
} else {
|
|
2491
|
+
add("gp-ov-note", `from manifest.yaml${area.preset ? ` (preset ${area.preset})` : ""}`);
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
if (layers.safe || layers.art) {
|
|
2495
|
+
const found = [];
|
|
2496
|
+
if (counts.text)
|
|
2497
|
+
found.push(`${counts.text} text outside the safe area`);
|
|
2498
|
+
if (counts.art)
|
|
2499
|
+
found.push(`${counts.art} art outside${counts.text ? "" : " the safe area"}`);
|
|
2500
|
+
if (counts.bleed)
|
|
2501
|
+
found.push(`${counts.bleed} in the bleed band`);
|
|
2502
|
+
if (counts.offPage)
|
|
2503
|
+
found.push(`${counts.offPage} off the page`);
|
|
2504
|
+
if (!found.length) {
|
|
2505
|
+
found.push(`${layers.safe && layers.art ? "everything" : layers.safe ? "all text" : "all art"} inside the safe area`);
|
|
2506
|
+
}
|
|
2507
|
+
if (counts.intended)
|
|
2508
|
+
found.push(`${counts.intended} placed on purpose`);
|
|
2509
|
+
add("gp-ov-found", found.join(" · "));
|
|
2510
|
+
}
|
|
2511
|
+
const key = document.documentElement.dataset.overlayKey;
|
|
2512
|
+
if (key)
|
|
2513
|
+
add("gp-ov-note", `${key} hides`);
|
|
2514
|
+
return el;
|
|
2515
|
+
}
|
|
2516
|
+
function paintOverlay(pages, strips, area, layers) {
|
|
2331
2517
|
const layer = ensureRoot();
|
|
2332
2518
|
syncToStage();
|
|
2333
2519
|
const stage = stageFrame();
|
|
@@ -2343,7 +2529,7 @@
|
|
|
2343
2529
|
h: boxes.sheet.h
|
|
2344
2530
|
});
|
|
2345
2531
|
host2.dataset.page = String(p.index + 1);
|
|
2346
|
-
if (boxes.bleed > 0) {
|
|
2532
|
+
if (layers.bleed && boxes.bleed > 0) {
|
|
2347
2533
|
const sh = boxes.sheet;
|
|
2348
2534
|
const t = boxes.trim;
|
|
2349
2535
|
const band = div("gp-ov-bleed", sh);
|
|
@@ -2351,68 +2537,115 @@
|
|
|
2351
2537
|
host2.appendChild(band);
|
|
2352
2538
|
host2.appendChild(div("gp-ov-trim", t));
|
|
2353
2539
|
}
|
|
2354
|
-
if (area && area.safe > 0) {
|
|
2540
|
+
if (layers.safe && area && area.safe > 0) {
|
|
2355
2541
|
host2.appendChild(unsafeTint(boxes));
|
|
2356
2542
|
host2.appendChild(div("gp-ov-safe", boxes.safe));
|
|
2357
2543
|
}
|
|
2544
|
+
if (layers.art && area && area.artSafe > 0)
|
|
2545
|
+
host2.appendChild(div("gp-ov-art", boxes.safeArt));
|
|
2546
|
+
if (layers.margins && !p.padded)
|
|
2547
|
+
host2.appendChild(div("gp-ov-margins", marginsBox(p, side)));
|
|
2358
2548
|
layer.appendChild(host2);
|
|
2359
2549
|
painted.set(p.index, { host: host2, boxes, sheet: p.sheet, rect });
|
|
2360
2550
|
}
|
|
2361
2551
|
const flags = [];
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
const kinds = [];
|
|
2372
|
-
const found = [];
|
|
2373
|
-
for (const r of Array.from(el.getClientRects())) {
|
|
2552
|
+
const counts = { text: 0, art: 0, bleed: 0, offPage: 0, intended: 0 };
|
|
2553
|
+
const seen = new Set;
|
|
2554
|
+
const range = document.createRange();
|
|
2555
|
+
const source = area?.spec?.label ?? "the safe area";
|
|
2556
|
+
const inspect = (root2, pageOf2, zoom) => {
|
|
2557
|
+
if (!layers.safe && !layers.art)
|
|
2558
|
+
return;
|
|
2559
|
+
const judge = (el, rule, rects) => {
|
|
2560
|
+
for (const r of rects) {
|
|
2374
2561
|
if (r.width <= 0 && r.height <= 0)
|
|
2375
2562
|
continue;
|
|
2376
|
-
const
|
|
2377
|
-
const ay = r.top + Math.min(r.height, colH || r.height) / 2;
|
|
2378
|
-
const target = painted.get(strip.offset + indexInStrip(ax, ay, strip));
|
|
2563
|
+
const target = pageOf2(r);
|
|
2379
2564
|
if (!target)
|
|
2380
2565
|
continue;
|
|
2381
2566
|
target.rect ??= target.sheet.getBoundingClientRect();
|
|
2382
|
-
const
|
|
2567
|
+
const box = {
|
|
2383
2568
|
x: (r.left - target.rect.left) / zoom,
|
|
2384
2569
|
y: (r.top - target.rect.top) / zoom,
|
|
2385
2570
|
w: r.width / zoom,
|
|
2386
2571
|
h: r.height / zoom
|
|
2387
2572
|
};
|
|
2388
|
-
const kind = classifyRect(
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2573
|
+
const { kind, gap, need } = classifyRect(box, target.boxes, rule, TOL_PX);
|
|
2574
|
+
if (kind === "inside")
|
|
2575
|
+
continue;
|
|
2576
|
+
const key = `${target.host.dataset.page} ${box.x} ${box.y} ${box.w} ${box.h}`;
|
|
2577
|
+
if (seen.has(key))
|
|
2578
|
+
continue;
|
|
2579
|
+
seen.add(key);
|
|
2580
|
+
const placed = el.closest(INTENT_SELECTOR) !== null;
|
|
2581
|
+
const bucket = placed ? "intended" : kind === "unsafe" ? rule : kind === "bleed" ? "bleed" : "offPage";
|
|
2582
|
+
counts[bucket]++;
|
|
2583
|
+
const title = `${rule} ${inches(gap)}in ${gap < 0 ? "past" : "from"} the trim; ${source} needs ${inches(need)}in`;
|
|
2584
|
+
flags.push({
|
|
2585
|
+
host: target.host,
|
|
2586
|
+
kind: placed ? "intended" : kind,
|
|
2587
|
+
rule,
|
|
2588
|
+
box,
|
|
2589
|
+
title: placed ? `${title} (placed on purpose)` : title
|
|
2590
|
+
});
|
|
2392
2591
|
}
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
if (
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
for (const f of found)
|
|
2401
|
-
flags.push(isIntended ? { ...f, kind: "intended" } : f);
|
|
2592
|
+
};
|
|
2593
|
+
const visit = (node) => {
|
|
2594
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
2595
|
+
if (!layers.safe || !node.nodeValue?.trim())
|
|
2596
|
+
return;
|
|
2597
|
+
range.selectNodeContents(node);
|
|
2598
|
+
judge(node.parentElement, "text", range.getClientRects());
|
|
2402
2599
|
return;
|
|
2403
2600
|
}
|
|
2404
|
-
|
|
2601
|
+
if (!(node instanceof Element) || SKIP.has(node.tagName) || node.classList.contains("gp-wrap-spacer"))
|
|
2602
|
+
return;
|
|
2603
|
+
if (layers.art) {
|
|
2604
|
+
const cs = getComputedStyle(node);
|
|
2605
|
+
if (ART_TAGS.has(node.localName) || cs.backgroundImage !== "none" || !/^rgba\(.*, 0\)$/.test(cs.backgroundColor) || parseFloat(cs.borderTopWidth) > 0 || parseFloat(cs.borderRightWidth) > 0 || parseFloat(cs.borderBottomWidth) > 0 || parseFloat(cs.borderLeftWidth) > 0) {
|
|
2606
|
+
judge(node, "art", node.getClientRects());
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
for (const child of node.childNodes)
|
|
2405
2610
|
visit(child);
|
|
2406
2611
|
};
|
|
2407
|
-
|
|
2408
|
-
|
|
2612
|
+
visit(root2);
|
|
2613
|
+
};
|
|
2614
|
+
for (const strip of strips) {
|
|
2615
|
+
const zoom = cssZoomOf(strip.el);
|
|
2616
|
+
const colW = (parseFloat(strip.el.style.getPropertyValue("--gp-content-w")) || 0) * zoom;
|
|
2617
|
+
const colH = (parseFloat(strip.el.style.getPropertyValue("--gp-content-h")) || 0) * zoom;
|
|
2618
|
+
const pageOf2 = (r) => {
|
|
2619
|
+
const ax = r.left + Math.min(r.width, colW || r.width) / 2;
|
|
2620
|
+
const ay = r.top + Math.min(r.height, colH || r.height) / 2;
|
|
2621
|
+
return painted.get(strip.offset + indexInStrip(ax, ay, strip));
|
|
2622
|
+
};
|
|
2623
|
+
for (const child of strip.el.childNodes)
|
|
2624
|
+
inspect(child, pageOf2, zoom);
|
|
2625
|
+
}
|
|
2626
|
+
for (const target of painted.values()) {
|
|
2627
|
+
for (const furniture of target.sheet.querySelectorAll(".gp-marginbox"))
|
|
2628
|
+
inspect(furniture, () => target, stage.zoom);
|
|
2409
2629
|
}
|
|
2410
2630
|
for (const f of flags) {
|
|
2411
2631
|
const el = div("gp-ov-flag", f.box);
|
|
2412
2632
|
el.dataset.kind = f.kind;
|
|
2633
|
+
el.dataset.rule = f.rule;
|
|
2634
|
+
el.title = f.title;
|
|
2413
2635
|
f.host.appendChild(el);
|
|
2414
2636
|
}
|
|
2415
|
-
|
|
2637
|
+
const summary = {
|
|
2638
|
+
on: true,
|
|
2639
|
+
layers,
|
|
2640
|
+
issues: counts.text + counts.art + counts.bleed + counts.offPage,
|
|
2641
|
+
intended: counts.intended,
|
|
2642
|
+
bleedPt: area?.bleed ?? 0,
|
|
2643
|
+
safePt: area?.safe ?? 0,
|
|
2644
|
+
artSafePt: area?.artSafe ?? 0,
|
|
2645
|
+
counts
|
|
2646
|
+
};
|
|
2647
|
+
root?.appendChild(legend(layers, area, summary));
|
|
2648
|
+
return summary;
|
|
2416
2649
|
}
|
|
2417
2650
|
|
|
2418
2651
|
// src/engine/viewer/decorate.ts
|
|
@@ -2444,10 +2677,11 @@
|
|
|
2444
2677
|
let paddedPages = new Set;
|
|
2445
2678
|
const warnings = [];
|
|
2446
2679
|
let overlayOn = false;
|
|
2680
|
+
let overlayLayers = OVERLAY_OFF.layers;
|
|
2447
2681
|
let overlayPages = [];
|
|
2448
2682
|
let overlaySummary = OVERLAY_OFF;
|
|
2449
2683
|
const paintOverlayNow = () => {
|
|
2450
|
-
overlaySummary = paintOverlay(overlayPages, layout.strips, printAreaFromMeta());
|
|
2684
|
+
overlaySummary = paintOverlay(overlayPages, layout.strips, printAreaFromMeta(), overlayLayers);
|
|
2451
2685
|
window.dispatchEvent(new CustomEvent("gp:overlay", { detail: overlaySummary }));
|
|
2452
2686
|
};
|
|
2453
2687
|
const api = {
|
|
@@ -2460,20 +2694,31 @@
|
|
|
2460
2694
|
setDesigner(on) {
|
|
2461
2695
|
document.body.dataset.designer = on ? "on" : "off";
|
|
2462
2696
|
},
|
|
2463
|
-
setOverlay(
|
|
2697
|
+
setOverlay(state, style) {
|
|
2464
2698
|
if (style) {
|
|
2465
2699
|
const clean = sanitizeOverlayStyle(style);
|
|
2466
2700
|
setOverlayStyle(clean);
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2701
|
+
const { strength, colors } = clean;
|
|
2702
|
+
if (strength)
|
|
2703
|
+
document.body.dataset.overlayStrength = strength;
|
|
2704
|
+
if (colors?.safe)
|
|
2705
|
+
document.body.dataset.overlayColor = colors.safe;
|
|
2706
|
+
if (colors?.art)
|
|
2707
|
+
document.body.dataset.overlayArtColor = colors.art;
|
|
2708
|
+
if (colors?.bleed)
|
|
2709
|
+
document.body.dataset.overlayBleedColor = colors.bleed;
|
|
2710
|
+
if (colors?.margins)
|
|
2711
|
+
document.body.dataset.overlayMarginsColor = colors.margins;
|
|
2471
2712
|
}
|
|
2472
2713
|
const wasOn = overlayOn;
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2714
|
+
const next = layersFrom(state);
|
|
2715
|
+
const sameLayers = OVERLAY_LAYERS.every((layer) => next[layer] === overlayLayers[layer]);
|
|
2716
|
+
overlayLayers = next;
|
|
2717
|
+
overlayOn = OVERLAY_LAYERS.some((layer) => next[layer]);
|
|
2718
|
+
document.body.dataset.overlay = overlayOn ? "on" : "off";
|
|
2719
|
+
if (overlayOn) {
|
|
2720
|
+
document.body.dataset.overlayLayers = OVERLAY_LAYERS.filter((layer) => next[layer]).join(",");
|
|
2721
|
+
if (!(wasOn && sameLayers && style))
|
|
2477
2722
|
paintOverlayNow();
|
|
2478
2723
|
} else {
|
|
2479
2724
|
clearOverlay();
|
|
@@ -2617,8 +2862,8 @@
|
|
|
2617
2862
|
}
|
|
2618
2863
|
if (!marked.length)
|
|
2619
2864
|
return;
|
|
2620
|
-
const
|
|
2621
|
-
const cx =
|
|
2865
|
+
const canvas2 = document.createElement("canvas");
|
|
2866
|
+
const cx = canvas2.getContext("2d");
|
|
2622
2867
|
for (const m of marked)
|
|
2623
2868
|
m.el.setAttribute(m.attr, m.raw.replace(LEADER_RE, ""));
|
|
2624
2869
|
document.body.offsetHeight;
|
|
@@ -2682,7 +2927,7 @@
|
|
|
2682
2927
|
drawMarginBoxes(sheet, ctx, layout.totalPages - paddedPages.size);
|
|
2683
2928
|
drawGuides(sheet, ctx);
|
|
2684
2929
|
drawCropMarks(sheet, ctx);
|
|
2685
|
-
overlayPages.push({ index: bookIndex, sheet, strip });
|
|
2930
|
+
overlayPages.push({ index: bookIndex, sheet, strip, padded: ctx.padded });
|
|
2686
2931
|
}
|
|
2687
2932
|
const rows = Math.max(1, Math.ceil((strip.pages + shift) / perRow));
|
|
2688
2933
|
run.style.height = `${rowStride * (rows - 1) + PX_PER_PT * g.height}px`;
|