gutterpress 0.11.20-alpha.2 → 0.11.20-alpha.3
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 +3 -2
- package/dist/{build-qmjg9r2d.js → build-a8ycsg80.js} +5 -4
- package/dist/{cli-zacevwcy.js → cli-9k2tb493.js} +181 -431
- package/dist/{cli-7z29z4wz.js → cli-hn9pk0hp.js} +1 -1
- package/dist/cli-sth219v1.js +418 -0
- package/dist/{cli-j802s31j.js → cli-x4p99w8d.js} +2 -2
- package/dist/{cli-gh0ym80r.js → cli-y9bcya7r.js} +121 -20
- package/dist/cli.js +12 -12
- package/dist/{doctor-fe7tcs4v.js → doctor-wbjkrcpc.js} +2 -2
- package/dist/{engine-yax79k9m.js → engine-fdtv01a2.js} +2 -2
- package/dist/{engine-9xb1ky8d.js → engine-yxnnp3hx.js} +1 -1
- package/dist/{ext-ahwxt6gv.js → ext-pesyrs68.js} +5 -4
- package/dist/{gutterpress-viewer-retj6ym2.js → gutterpress-viewer-1yse8cx3.js} +12 -4
- package/dist/{index-6xwtb7cw.js → index-r87y7wzw.js} +1 -1
- package/dist/index-sth219v1.js +418 -0
- package/dist/{index-razpty47.js → index-tjvrchxj.js} +297 -448
- package/dist/{index-3nr5rzzp.js → index-zagagnwq.js} +2 -2
- package/dist/index.js +4 -3
- package/dist/lib/build-fingerprint.d.ts +8 -0
- package/dist/lib/ghostscript.d.ts +70 -16
- package/dist/lib/pdf-inspect.d.ts +45 -0
- package/dist/{manifest.schema-74s1ykyv.json → manifest.schema-c9x8912a.json} +13 -1
- package/dist/{new-ftd4fec4.js → new-8yah8z91.js} +5 -4
- package/dist/pdf-inspect-zdmy7qca.js +35 -0
- package/dist/{preflight-8sqarcsr.js → preflight-8ccx4kdc.js} +5 -4
- package/dist/{preview-q76xn95h.js → preview-w7v9w36q.js} +5 -4
- package/dist/{publish-7gdy6gbf.js → publish-g5nh5myh.js} +5 -4
- package/dist/schema/manifest.types.d.ts +20 -2
- package/dist/test-helpers/testkit.d.ts +2 -2
- package/dist/{validate-e3ryegce.js → validate-1yh59x0x.js} +5 -4
- package/package.json +1 -1
|
@@ -6,20 +6,22 @@ import {
|
|
|
6
6
|
defaultConfigDir,
|
|
7
7
|
error,
|
|
8
8
|
findPostScriptShadingPages,
|
|
9
|
-
|
|
9
|
+
flattenTransparentPages,
|
|
10
10
|
info,
|
|
11
11
|
log,
|
|
12
|
+
planTransparentPages,
|
|
12
13
|
resolveGhostscript,
|
|
13
14
|
setLogLevel,
|
|
14
15
|
stampCreator,
|
|
15
16
|
stripAnnotations,
|
|
17
|
+
transparentPages,
|
|
16
18
|
warn
|
|
17
|
-
} from "./cli-
|
|
19
|
+
} from "./cli-y9bcya7r.js";
|
|
18
20
|
import {
|
|
19
21
|
DEBOUNCE,
|
|
20
22
|
UsageError,
|
|
21
23
|
resolvePort
|
|
22
|
-
} from "./cli-
|
|
24
|
+
} from "./cli-hn9pk0hp.js";
|
|
23
25
|
import {
|
|
24
26
|
blackTextToGray
|
|
25
27
|
} from "./cli-ht1bcqdd.js";
|
|
@@ -28,11 +30,24 @@ import {
|
|
|
28
30
|
getAssetPath,
|
|
29
31
|
getAssetsDir,
|
|
30
32
|
lastPageMode
|
|
31
|
-
} from "./cli-
|
|
33
|
+
} from "./cli-x4p99w8d.js";
|
|
32
34
|
import {
|
|
33
35
|
BuildError,
|
|
34
36
|
EXIT_CODES
|
|
35
37
|
} from "./cli-46ycxe6r.js";
|
|
38
|
+
import {
|
|
39
|
+
countLinkAnnotations,
|
|
40
|
+
getImageResolutions,
|
|
41
|
+
getOpPass,
|
|
42
|
+
getOutlineCount,
|
|
43
|
+
getPageLabels,
|
|
44
|
+
getPageSize,
|
|
45
|
+
getTextPass,
|
|
46
|
+
isLoadable,
|
|
47
|
+
loadPdf,
|
|
48
|
+
pageHasMarks,
|
|
49
|
+
retainPdfCache
|
|
50
|
+
} from "./cli-sth219v1.js";
|
|
36
51
|
import {
|
|
37
52
|
INSTALL_HINTS,
|
|
38
53
|
execCapture,
|
|
@@ -122,6 +137,8 @@ var DTRPG_PRESET = {
|
|
|
122
137
|
icc: "profiles/CGATS21_CRPC1.icc",
|
|
123
138
|
stripAnnotations: true,
|
|
124
139
|
blackText: "k-only",
|
|
140
|
+
transparency: "flatten-page",
|
|
141
|
+
flattenPages: [],
|
|
125
142
|
rasterDpi: undefined
|
|
126
143
|
},
|
|
127
144
|
page: {
|
|
@@ -207,6 +224,8 @@ var BOOK_PRESET = {
|
|
|
207
224
|
icc: "profiles/CGATS21_CRPC1.icc",
|
|
208
225
|
stripAnnotations: true,
|
|
209
226
|
blackText: "icc",
|
|
227
|
+
transparency: "flatten-page",
|
|
228
|
+
flattenPages: [],
|
|
210
229
|
rasterDpi: undefined
|
|
211
230
|
},
|
|
212
231
|
page: {
|
|
@@ -606,6 +625,14 @@ function resolveWithPreset(cliOverrides, manifest, preset) {
|
|
|
606
625
|
if (lastPage !== undefined && lastPage !== "blank" && lastPage !== "short-by-one") {
|
|
607
626
|
throw new UsageError(`Manifest field \`print.lastPage\` must be "blank" or "short-by-one", got ${JSON.stringify(lastPage)}.`);
|
|
608
627
|
}
|
|
628
|
+
const transparency = c.pdfx?.transparency ?? m.pdfx?.transparency;
|
|
629
|
+
if (transparency !== undefined && transparency !== "flatten-page" && transparency !== "preserve-text") {
|
|
630
|
+
throw new UsageError(`Manifest field \`pdfx.transparency\` must be "flatten-page" or "preserve-text", got ${JSON.stringify(transparency)}.`);
|
|
631
|
+
}
|
|
632
|
+
const flattenPages = c.pdfx?.flattenPages ?? m.pdfx?.flattenPages;
|
|
633
|
+
if (flattenPages !== undefined && !(Array.isArray(flattenPages) && flattenPages.every((n) => Number.isInteger(n) && n >= 1))) {
|
|
634
|
+
throw new UsageError(`Manifest field \`pdfx.flattenPages\` must be a list of page numbers (1, 2, …), got ${JSON.stringify(flattenPages)}.`);
|
|
635
|
+
}
|
|
609
636
|
const rasterDpi = c.pdfx?.rasterDpi ?? m.pdfx?.rasterDpi;
|
|
610
637
|
if (rasterDpi !== undefined && !(Number.isInteger(rasterDpi) && rasterDpi >= 72 && rasterDpi <= 1200)) {
|
|
611
638
|
throw new UsageError(`Manifest field \`pdfx.rasterDpi\` must be a whole number from 72 to 1200, got ${JSON.stringify(rasterDpi)}.`);
|
|
@@ -4899,346 +4926,6 @@ function inspectionFailed(checkId, message, extra = {}) {
|
|
|
4899
4926
|
};
|
|
4900
4927
|
}
|
|
4901
4928
|
|
|
4902
|
-
// src/lib/pdf-inspect.ts
|
|
4903
|
-
import { stat as stat2, readFile as readFile7 } from "node:fs/promises";
|
|
4904
|
-
import { getDocumentProxy } from "unpdf";
|
|
4905
|
-
import * as pdfjs from "unpdf/pdfjs";
|
|
4906
|
-
function getOps(mod) {
|
|
4907
|
-
if ("OPS" in mod && mod.OPS && typeof mod.OPS === "object") {
|
|
4908
|
-
return mod.OPS;
|
|
4909
|
-
}
|
|
4910
|
-
throw new Error("unpdf/pdfjs missing OPS export");
|
|
4911
|
-
}
|
|
4912
|
-
var OPS = getOps(pdfjs);
|
|
4913
|
-
var docCache = new Map;
|
|
4914
|
-
var DOC_CACHE_MAX = 8;
|
|
4915
|
-
function destroyEntry(entry) {
|
|
4916
|
-
entry.doc.then((d) => d.destroy()).catch(() => {});
|
|
4917
|
-
}
|
|
4918
|
-
var EVICT_DESTROY_GRACE_MS = 60000;
|
|
4919
|
-
var gracePending = new Map;
|
|
4920
|
-
function destroyEntryAfterGrace(entry) {
|
|
4921
|
-
const t = setTimeout(() => {
|
|
4922
|
-
gracePending.delete(t);
|
|
4923
|
-
destroyEntry(entry);
|
|
4924
|
-
}, EVICT_DESTROY_GRACE_MS);
|
|
4925
|
-
t.unref?.();
|
|
4926
|
-
gracePending.set(t, entry);
|
|
4927
|
-
}
|
|
4928
|
-
function evictLru() {
|
|
4929
|
-
while (docCache.size > DOC_CACHE_MAX) {
|
|
4930
|
-
const oldestKey = docCache.keys().next().value;
|
|
4931
|
-
if (oldestKey === undefined)
|
|
4932
|
-
break;
|
|
4933
|
-
const evicted = docCache.get(oldestKey);
|
|
4934
|
-
docCache.delete(oldestKey);
|
|
4935
|
-
if (evicted)
|
|
4936
|
-
destroyEntryAfterGrace(evicted);
|
|
4937
|
-
}
|
|
4938
|
-
}
|
|
4939
|
-
async function loadPdf(path6) {
|
|
4940
|
-
let st;
|
|
4941
|
-
try {
|
|
4942
|
-
st = await stat2(path6);
|
|
4943
|
-
} catch {
|
|
4944
|
-
return null;
|
|
4945
|
-
}
|
|
4946
|
-
const hit = docCache.get(path6);
|
|
4947
|
-
if (hit && hit.mtimeMs === st.mtimeMs && hit.size === st.size) {
|
|
4948
|
-
docCache.delete(path6);
|
|
4949
|
-
docCache.set(path6, hit);
|
|
4950
|
-
try {
|
|
4951
|
-
return await hit.doc;
|
|
4952
|
-
} catch {
|
|
4953
|
-
return null;
|
|
4954
|
-
}
|
|
4955
|
-
}
|
|
4956
|
-
if (hit)
|
|
4957
|
-
destroyEntry(hit);
|
|
4958
|
-
const docPromise = readFile7(path6).then((buf) => getDocumentProxy(new Uint8Array(buf)));
|
|
4959
|
-
docCache.delete(path6);
|
|
4960
|
-
docCache.set(path6, { mtimeMs: st.mtimeMs, size: st.size, doc: docPromise });
|
|
4961
|
-
evictLru();
|
|
4962
|
-
try {
|
|
4963
|
-
return await docPromise;
|
|
4964
|
-
} catch {
|
|
4965
|
-
if (docCache.get(path6)?.doc === docPromise)
|
|
4966
|
-
docCache.delete(path6);
|
|
4967
|
-
return null;
|
|
4968
|
-
}
|
|
4969
|
-
}
|
|
4970
|
-
var activeRetains = 0;
|
|
4971
|
-
function retainPdfCache() {
|
|
4972
|
-
activeRetains++;
|
|
4973
|
-
let released = false;
|
|
4974
|
-
return () => {
|
|
4975
|
-
if (released)
|
|
4976
|
-
return;
|
|
4977
|
-
released = true;
|
|
4978
|
-
activeRetains--;
|
|
4979
|
-
if (activeRetains === 0)
|
|
4980
|
-
clearPdfCache();
|
|
4981
|
-
};
|
|
4982
|
-
}
|
|
4983
|
-
function clearPdfCache() {
|
|
4984
|
-
for (const [t, entry] of gracePending) {
|
|
4985
|
-
clearTimeout(t);
|
|
4986
|
-
destroyEntry(entry);
|
|
4987
|
-
}
|
|
4988
|
-
gracePending.clear();
|
|
4989
|
-
for (const entry of docCache.values())
|
|
4990
|
-
destroyEntry(entry);
|
|
4991
|
-
docCache.clear();
|
|
4992
|
-
}
|
|
4993
|
-
function getPageSize(page) {
|
|
4994
|
-
const vp = page.getViewport({ scale: 1 });
|
|
4995
|
-
return { w: vp.width, h: vp.height };
|
|
4996
|
-
}
|
|
4997
|
-
async function getOutlineCount(doc) {
|
|
4998
|
-
try {
|
|
4999
|
-
const outline = await doc.getOutline();
|
|
5000
|
-
return outline ? outline.length : 0;
|
|
5001
|
-
} catch {
|
|
5002
|
-
return 0;
|
|
5003
|
-
}
|
|
5004
|
-
}
|
|
5005
|
-
async function getPageLabels(doc) {
|
|
5006
|
-
try {
|
|
5007
|
-
return await doc.getPageLabels();
|
|
5008
|
-
} catch {
|
|
5009
|
-
return null;
|
|
5010
|
-
}
|
|
5011
|
-
}
|
|
5012
|
-
async function countLinkAnnotations(doc, stopAtFirst = false) {
|
|
5013
|
-
let count = 0;
|
|
5014
|
-
for (let i = 1;i <= doc.numPages; i++) {
|
|
5015
|
-
try {
|
|
5016
|
-
const page = await doc.getPage(i);
|
|
5017
|
-
const annots = await page.getAnnotations();
|
|
5018
|
-
for (const a of annots) {
|
|
5019
|
-
if (a.subtype === "Link") {
|
|
5020
|
-
count++;
|
|
5021
|
-
if (stopAtFirst)
|
|
5022
|
-
return count;
|
|
5023
|
-
}
|
|
5024
|
-
}
|
|
5025
|
-
} catch {}
|
|
5026
|
-
}
|
|
5027
|
-
return count;
|
|
5028
|
-
}
|
|
5029
|
-
var textCache = new WeakMap;
|
|
5030
|
-
function getTextPass(doc) {
|
|
5031
|
-
let p = textCache.get(doc);
|
|
5032
|
-
if (!p) {
|
|
5033
|
-
p = (async () => {
|
|
5034
|
-
const textByPage = [];
|
|
5035
|
-
const positions = [];
|
|
5036
|
-
const runsByPage = [];
|
|
5037
|
-
for (let i = 1;i <= doc.numPages; i++) {
|
|
5038
|
-
try {
|
|
5039
|
-
const page = await doc.getPage(i);
|
|
5040
|
-
const tc = await page.getTextContent();
|
|
5041
|
-
let pageText = "";
|
|
5042
|
-
const runs = [];
|
|
5043
|
-
for (const item of tc.items) {
|
|
5044
|
-
const it = item;
|
|
5045
|
-
if (typeof it.str !== "string")
|
|
5046
|
-
continue;
|
|
5047
|
-
pageText += it.str;
|
|
5048
|
-
if (it.transform && it.str.trim().length > 0) {
|
|
5049
|
-
const x = it.transform[4];
|
|
5050
|
-
const y = it.transform[5];
|
|
5051
|
-
positions.push({ x, y });
|
|
5052
|
-
runs.push({ s: it.str, x, y, w: it.width ?? 0, h: it.height ?? 0 });
|
|
5053
|
-
}
|
|
5054
|
-
}
|
|
5055
|
-
textByPage.push(pageText);
|
|
5056
|
-
runsByPage.push(runs);
|
|
5057
|
-
} catch {
|
|
5058
|
-
textByPage.push("");
|
|
5059
|
-
runsByPage.push([]);
|
|
5060
|
-
}
|
|
5061
|
-
}
|
|
5062
|
-
return { textByPage, positions, runsByPage };
|
|
5063
|
-
})();
|
|
5064
|
-
textCache.set(doc, p);
|
|
5065
|
-
}
|
|
5066
|
-
return p;
|
|
5067
|
-
}
|
|
5068
|
-
var opCache = new WeakMap;
|
|
5069
|
-
function multiply(m1, m2) {
|
|
5070
|
-
return [
|
|
5071
|
-
m1[0] * m2[0] + m1[2] * m2[1],
|
|
5072
|
-
m1[1] * m2[0] + m1[3] * m2[1],
|
|
5073
|
-
m1[0] * m2[2] + m1[2] * m2[3],
|
|
5074
|
-
m1[1] * m2[2] + m1[3] * m2[3],
|
|
5075
|
-
m1[0] * m2[4] + m1[2] * m2[5] + m1[4],
|
|
5076
|
-
m1[1] * m2[4] + m1[3] * m2[5] + m1[5]
|
|
5077
|
-
];
|
|
5078
|
-
}
|
|
5079
|
-
function fontIsEmbedded(f) {
|
|
5080
|
-
if (f.isType3Font)
|
|
5081
|
-
return true;
|
|
5082
|
-
if (f.missingFile === true)
|
|
5083
|
-
return false;
|
|
5084
|
-
if (f.isStandardFont === true)
|
|
5085
|
-
return false;
|
|
5086
|
-
return true;
|
|
5087
|
-
}
|
|
5088
|
-
function getOpPass(doc) {
|
|
5089
|
-
let p = opCache.get(doc);
|
|
5090
|
-
if (!p) {
|
|
5091
|
-
p = (async () => {
|
|
5092
|
-
const imagesByPage = new Map;
|
|
5093
|
-
const fonts = [];
|
|
5094
|
-
const seenFonts = new Set;
|
|
5095
|
-
for (let i = 1;i <= doc.numPages; i++) {
|
|
5096
|
-
let page;
|
|
5097
|
-
try {
|
|
5098
|
-
page = await doc.getPage(i);
|
|
5099
|
-
} catch {
|
|
5100
|
-
continue;
|
|
5101
|
-
}
|
|
5102
|
-
let ops;
|
|
5103
|
-
try {
|
|
5104
|
-
ops = await page.getOperatorList();
|
|
5105
|
-
} catch {
|
|
5106
|
-
continue;
|
|
5107
|
-
}
|
|
5108
|
-
let ctm = [1, 0, 0, 1, 0, 0];
|
|
5109
|
-
const stack = [];
|
|
5110
|
-
const pageImages = [];
|
|
5111
|
-
for (let j = 0;j < ops.fnArray.length; j++) {
|
|
5112
|
-
const fn = ops.fnArray[j];
|
|
5113
|
-
const args = ops.argsArray[j];
|
|
5114
|
-
if (fn === OPS.save) {
|
|
5115
|
-
stack.push(ctm.slice());
|
|
5116
|
-
} else if (fn === OPS.restore) {
|
|
5117
|
-
ctm = stack.pop() ?? ctm;
|
|
5118
|
-
} else if (fn === OPS.transform) {
|
|
5119
|
-
ctm = multiply(ctm, args);
|
|
5120
|
-
} else if (fn === OPS.paintImageXObject || fn === OPS.paintImageXObjectRepeat || fn === OPS.paintInlineImageXObject) {
|
|
5121
|
-
const name = typeof args[0] === "string" ? args[0] : "(inline)";
|
|
5122
|
-
pageImages.push({
|
|
5123
|
-
name,
|
|
5124
|
-
placedW: Math.hypot(ctm[0], ctm[1]),
|
|
5125
|
-
placedH: Math.hypot(ctm[2], ctm[3]),
|
|
5126
|
-
x: ctm[4],
|
|
5127
|
-
y: ctm[5],
|
|
5128
|
-
page: i
|
|
5129
|
-
});
|
|
5130
|
-
} else if (fn === OPS.setFont) {
|
|
5131
|
-
const ref = args[0];
|
|
5132
|
-
if (typeof ref === "string" && !seenFonts.has(ref)) {
|
|
5133
|
-
seenFonts.add(ref);
|
|
5134
|
-
try {
|
|
5135
|
-
if (page.commonObjs.has(ref)) {
|
|
5136
|
-
const f = page.commonObjs.get(ref);
|
|
5137
|
-
fonts.push({
|
|
5138
|
-
name: f?.name ?? ref,
|
|
5139
|
-
embedded: fontIsEmbedded(f ?? {})
|
|
5140
|
-
});
|
|
5141
|
-
}
|
|
5142
|
-
} catch {}
|
|
5143
|
-
}
|
|
5144
|
-
}
|
|
5145
|
-
}
|
|
5146
|
-
if (pageImages.length > 0)
|
|
5147
|
-
imagesByPage.set(i, pageImages);
|
|
5148
|
-
}
|
|
5149
|
-
return { imagesByPage, fonts };
|
|
5150
|
-
})();
|
|
5151
|
-
opCache.set(doc, p);
|
|
5152
|
-
}
|
|
5153
|
-
return p;
|
|
5154
|
-
}
|
|
5155
|
-
function getImagePixelSize(page, name, timeoutMs = 2000) {
|
|
5156
|
-
return new Promise((resolve4) => {
|
|
5157
|
-
let done = false;
|
|
5158
|
-
const finish = (v) => {
|
|
5159
|
-
if (!done) {
|
|
5160
|
-
done = true;
|
|
5161
|
-
resolve4(v);
|
|
5162
|
-
}
|
|
5163
|
-
};
|
|
5164
|
-
const t = setTimeout(() => finish(null), timeoutMs);
|
|
5165
|
-
try {
|
|
5166
|
-
page.objs.get(name, (obj) => {
|
|
5167
|
-
clearTimeout(t);
|
|
5168
|
-
finish(obj && obj.width && obj.height ? { width: obj.width, height: obj.height } : null);
|
|
5169
|
-
});
|
|
5170
|
-
} catch {
|
|
5171
|
-
clearTimeout(t);
|
|
5172
|
-
finish(null);
|
|
5173
|
-
}
|
|
5174
|
-
});
|
|
5175
|
-
}
|
|
5176
|
-
var PAINT_OPS = new Set([
|
|
5177
|
-
"stroke",
|
|
5178
|
-
"closeStroke",
|
|
5179
|
-
"fill",
|
|
5180
|
-
"eoFill",
|
|
5181
|
-
"fillStroke",
|
|
5182
|
-
"eoFillStroke",
|
|
5183
|
-
"closeFillStroke",
|
|
5184
|
-
"closeEOFillStroke",
|
|
5185
|
-
"shadingFill",
|
|
5186
|
-
"paintImageXObject",
|
|
5187
|
-
"paintInlineImageXObject",
|
|
5188
|
-
"paintImageXObjectRepeat",
|
|
5189
|
-
"paintImageMaskXObject",
|
|
5190
|
-
"paintImageMaskXObjectGroup",
|
|
5191
|
-
"paintImageMaskXObjectRepeat",
|
|
5192
|
-
"paintSolidColorImageMask",
|
|
5193
|
-
"showText",
|
|
5194
|
-
"showSpacedText",
|
|
5195
|
-
"nextLineShowText",
|
|
5196
|
-
"nextLineSetSpacingShowText"
|
|
5197
|
-
].map((name) => OPS[name]).filter((op) => op !== undefined));
|
|
5198
|
-
async function pageHasMarks(doc, pageNum) {
|
|
5199
|
-
const ops = await (await doc.getPage(pageNum)).getOperatorList();
|
|
5200
|
-
return ops.fnArray.some((fn, i) => fn === OPS.constructPath ? PAINT_OPS.has(ops.argsArray[i][0]) : PAINT_OPS.has(fn));
|
|
5201
|
-
}
|
|
5202
|
-
async function getImageResolutions(doc) {
|
|
5203
|
-
const { imagesByPage } = await getOpPass(doc);
|
|
5204
|
-
const out = [];
|
|
5205
|
-
for (const [pageNum, imgs] of imagesByPage) {
|
|
5206
|
-
let page;
|
|
5207
|
-
try {
|
|
5208
|
-
page = await doc.getPage(pageNum);
|
|
5209
|
-
} catch {
|
|
5210
|
-
continue;
|
|
5211
|
-
}
|
|
5212
|
-
for (const img of imgs) {
|
|
5213
|
-
if (img.name === "(inline)")
|
|
5214
|
-
continue;
|
|
5215
|
-
const px = await getImagePixelSize(page, img.name);
|
|
5216
|
-
if (!px)
|
|
5217
|
-
continue;
|
|
5218
|
-
const placedWin = img.placedW / 72;
|
|
5219
|
-
const placedHin = img.placedH / 72;
|
|
5220
|
-
if (placedWin <= 0 || placedHin <= 0)
|
|
5221
|
-
continue;
|
|
5222
|
-
out.push({
|
|
5223
|
-
page: pageNum,
|
|
5224
|
-
xDpi: px.width / placedWin,
|
|
5225
|
-
yDpi: px.height / placedHin
|
|
5226
|
-
});
|
|
5227
|
-
}
|
|
5228
|
-
}
|
|
5229
|
-
return out;
|
|
5230
|
-
}
|
|
5231
|
-
async function isLoadable(doc) {
|
|
5232
|
-
try {
|
|
5233
|
-
for (let i = 1;i <= doc.numPages; i++) {
|
|
5234
|
-
await doc.getPage(i);
|
|
5235
|
-
}
|
|
5236
|
-
return true;
|
|
5237
|
-
} catch {
|
|
5238
|
-
return false;
|
|
5239
|
-
}
|
|
5240
|
-
}
|
|
5241
|
-
|
|
5242
4929
|
// src/checks/pdf/qpdf-structure.ts
|
|
5243
4930
|
var check = {
|
|
5244
4931
|
id: "pdf.structure.qpdf",
|
|
@@ -5513,9 +5200,9 @@ var check4 = {
|
|
|
5513
5200
|
registerCheck(check4);
|
|
5514
5201
|
|
|
5515
5202
|
// src/lib/pdf-parse.ts
|
|
5516
|
-
import { readFile as
|
|
5203
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
5517
5204
|
async function readPdfBytes(pdfPath) {
|
|
5518
|
-
return
|
|
5205
|
+
return readFile7(pdfPath, "latin1");
|
|
5519
5206
|
}
|
|
5520
5207
|
function parseInkCov(out) {
|
|
5521
5208
|
const lines = out.split(/\r?\n/).filter((l) => l.includes("CMYK"));
|
|
@@ -5776,7 +5463,7 @@ var check8 = {
|
|
|
5776
5463
|
registerCheck(check8);
|
|
5777
5464
|
|
|
5778
5465
|
// src/checks/pdf/black-text.ts
|
|
5779
|
-
import { readFile as
|
|
5466
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
5780
5467
|
var check9 = {
|
|
5781
5468
|
id: "pdf.print.black-text",
|
|
5782
5469
|
name: "Black Text",
|
|
@@ -5789,7 +5476,7 @@ var check9 = {
|
|
|
5789
5476
|
return [];
|
|
5790
5477
|
try {
|
|
5791
5478
|
const { findRichBlackText, LARGE_TEXT_PT } = await import("./black-text-gray-7dz61456.js");
|
|
5792
|
-
const found = await findRichBlackText(await
|
|
5479
|
+
const found = await findRichBlackText(await readFile8(ctx.pdfPath));
|
|
5793
5480
|
if (found.runs === 0)
|
|
5794
5481
|
return [];
|
|
5795
5482
|
return [
|
|
@@ -6178,7 +5865,7 @@ var check18 = {
|
|
|
6178
5865
|
registerCheck(check18);
|
|
6179
5866
|
|
|
6180
5867
|
// src/checks/source/markdownlint.ts
|
|
6181
|
-
import { readFile as
|
|
5868
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
6182
5869
|
import { lint } from "markdownlint/sync";
|
|
6183
5870
|
import { parse as parseYaml2 } from "yaml";
|
|
6184
5871
|
|
|
@@ -6211,7 +5898,7 @@ function stripJsonComments(s) {
|
|
|
6211
5898
|
return s.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1");
|
|
6212
5899
|
}
|
|
6213
5900
|
async function loadConfig(configPath) {
|
|
6214
|
-
const raw = await
|
|
5901
|
+
const raw = await readFile9(configPath, "utf8");
|
|
6215
5902
|
let parsed;
|
|
6216
5903
|
if (configPath.endsWith(".json")) {
|
|
6217
5904
|
parsed = JSON.parse(raw);
|
|
@@ -6272,7 +5959,7 @@ registerCheck(check19);
|
|
|
6272
5959
|
|
|
6273
5960
|
// src/checks/source/htmlhint.ts
|
|
6274
5961
|
import { existsSync as existsSync7 } from "node:fs";
|
|
6275
|
-
import { readFile as
|
|
5962
|
+
import { readFile as readFile10 } from "node:fs/promises";
|
|
6276
5963
|
import htmlhint from "htmlhint";
|
|
6277
5964
|
var { HTMLHint } = htmlhint;
|
|
6278
5965
|
var CONFIG_NAMES2 = [".htmlhintrc"];
|
|
@@ -6292,8 +5979,8 @@ var check20 = {
|
|
|
6292
5979
|
const resolvedConfig = findConfigFile(ctx.inputDir, CONFIG_NAMES2, configPath);
|
|
6293
5980
|
if (!resolvedConfig && !configPath)
|
|
6294
5981
|
return [];
|
|
6295
|
-
const ruleset = resolvedConfig ? JSON.parse(await
|
|
6296
|
-
const html = await
|
|
5982
|
+
const ruleset = resolvedConfig ? JSON.parse(await readFile10(resolvedConfig, "utf8")) : HTMLHint.defaultRuleset;
|
|
5983
|
+
const html = await readFile10(ctx.htmlPath, "utf8");
|
|
6297
5984
|
const messages = HTMLHint.verify(html, ruleset);
|
|
6298
5985
|
return messages.map((m) => ({
|
|
6299
5986
|
checkId: check20.id,
|
|
@@ -6308,7 +5995,7 @@ var check20 = {
|
|
|
6308
5995
|
registerCheck(check20);
|
|
6309
5996
|
|
|
6310
5997
|
// src/checks/source/stylelint.ts
|
|
6311
|
-
import { readFile as
|
|
5998
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
6312
5999
|
|
|
6313
6000
|
// src/lib/printsafe.ts
|
|
6314
6001
|
import postcss from "postcss";
|
|
@@ -6650,7 +6337,7 @@ function checkCssRaw(css, from) {
|
|
|
6650
6337
|
warnings.push({
|
|
6651
6338
|
rule: ruleRiskyProps,
|
|
6652
6339
|
severity: "warning",
|
|
6653
|
-
message: `"${decl.prop}: ${decl.value}"
|
|
6340
|
+
message: `"${decl.prop}: ${decl.value}" is at risk in PDF/X exports (--format pdfx): Chromium emits repeating-*-gradient() and conic-gradient() in a form Ghostscript has been seen to paint as nothing or as irregular stripes, so it can print blank or distorted, unless the page also uses transparency and Ghostscript flattens the whole page to an image, which keeps the gradient but loses that page's live text. Plain PDF output is unaffected. Use linear-gradient() or radial-gradient() instead; for 0deg/90deg stripes write "linear-gradient(90deg, #b33 0 6px, #c8c5bf 6px 10px)" with "background-size: 10px 100%", and for anything else a small tiled image.`,
|
|
6654
6341
|
...nodeLoc(decl)
|
|
6655
6342
|
});
|
|
6656
6343
|
} else if (isUnpairedFitContentWidth(decl)) {
|
|
@@ -6715,7 +6402,7 @@ var check21 = {
|
|
|
6715
6402
|
for (const file of files) {
|
|
6716
6403
|
let css;
|
|
6717
6404
|
try {
|
|
6718
|
-
css = await
|
|
6405
|
+
css = await readFile11(file, "utf8");
|
|
6719
6406
|
} catch (err) {
|
|
6720
6407
|
results.push({
|
|
6721
6408
|
checkId: check21.id,
|
|
@@ -6742,7 +6429,7 @@ var check21 = {
|
|
|
6742
6429
|
registerCheck(check21);
|
|
6743
6430
|
|
|
6744
6431
|
// src/checks/source/css-ownership.ts
|
|
6745
|
-
import { readFile as
|
|
6432
|
+
import { readFile as readFile12 } from "node:fs/promises";
|
|
6746
6433
|
|
|
6747
6434
|
// src/lib/style-resolver.ts
|
|
6748
6435
|
import { existsSync as existsSync8 } from "node:fs";
|
|
@@ -6810,7 +6497,7 @@ import postcss2 from "postcss";
|
|
|
6810
6497
|
import { parse as parseYaml3 } from "yaml";
|
|
6811
6498
|
var CONFIG_NAMES3 = [".gutterpress/css-contract.yaml", ".gutterpress/css-contract.yml"];
|
|
6812
6499
|
async function loadContract(configPath) {
|
|
6813
|
-
const raw = await
|
|
6500
|
+
const raw = await readFile12(configPath, "utf8");
|
|
6814
6501
|
const parsed = parseYaml3(raw);
|
|
6815
6502
|
if (parsed && typeof parsed === "object")
|
|
6816
6503
|
return parsed;
|
|
@@ -6961,7 +6648,7 @@ var check22 = {
|
|
|
6961
6648
|
continue;
|
|
6962
6649
|
let css;
|
|
6963
6650
|
try {
|
|
6964
|
-
css = await
|
|
6651
|
+
css = await readFile12(absFile, "utf8");
|
|
6965
6652
|
} catch {
|
|
6966
6653
|
continue;
|
|
6967
6654
|
}
|
|
@@ -7008,7 +6695,7 @@ import { dirname as dirname3, resolve as resolve5 } from "node:path";
|
|
|
7008
6695
|
|
|
7009
6696
|
// src/lib/asset-inline.ts
|
|
7010
6697
|
import { createHash as createHash2 } from "node:crypto";
|
|
7011
|
-
import { readFile as
|
|
6698
|
+
import { readFile as readFile13 } from "node:fs/promises";
|
|
7012
6699
|
import path7 from "node:path";
|
|
7013
6700
|
import postcss3 from "postcss";
|
|
7014
6701
|
var FONT_EXTS = new Set([".woff2", ".woff", ".ttf", ".otf"]);
|
|
@@ -7073,7 +6760,7 @@ function mimeFor(ext) {
|
|
|
7073
6760
|
}
|
|
7074
6761
|
async function readOrThrow(absPath, kind, referencedFrom) {
|
|
7075
6762
|
try {
|
|
7076
|
-
return await
|
|
6763
|
+
return await readFile13(absPath);
|
|
7077
6764
|
} catch {
|
|
7078
6765
|
throw new BuildError(`Missing ${kind}: ${absPath}
|
|
7079
6766
|
referenced from ${referencedFrom}
|
|
@@ -7216,7 +6903,7 @@ async function collectStyleDependencies(projectDir, stylePaths) {
|
|
|
7216
6903
|
found.add(abs);
|
|
7217
6904
|
let source;
|
|
7218
6905
|
try {
|
|
7219
|
-
source = await
|
|
6906
|
+
source = await readFile13(abs, "utf-8");
|
|
7220
6907
|
} catch {
|
|
7221
6908
|
return;
|
|
7222
6909
|
}
|
|
@@ -7293,7 +6980,7 @@ async function inlineShapeUrls(html, baseDir) {
|
|
|
7293
6980
|
continue;
|
|
7294
6981
|
let bytes;
|
|
7295
6982
|
try {
|
|
7296
|
-
bytes = await
|
|
6983
|
+
bytes = await readFile13(abs);
|
|
7297
6984
|
} catch {
|
|
7298
6985
|
continue;
|
|
7299
6986
|
}
|
|
@@ -7311,7 +6998,7 @@ async function inlineShapeUrls(html, baseDir) {
|
|
|
7311
6998
|
}
|
|
7312
6999
|
|
|
7313
7000
|
// src/checks/source/local-ref-parser.ts
|
|
7314
|
-
import { readFile as
|
|
7001
|
+
import { readFile as readFile14 } from "node:fs/promises";
|
|
7315
7002
|
function newlineOffsets(content) {
|
|
7316
7003
|
const offsets = [];
|
|
7317
7004
|
for (let i = 0;i < content.length; i++)
|
|
@@ -7380,7 +7067,7 @@ async function* renderedLocalRefs(ctx, checkId, results) {
|
|
|
7380
7067
|
for (const file of files) {
|
|
7381
7068
|
let refs;
|
|
7382
7069
|
try {
|
|
7383
|
-
refs = collectRenderedLocalRefs(await
|
|
7070
|
+
refs = collectRenderedLocalRefs(await readFile14(file, "utf8"));
|
|
7384
7071
|
} catch {
|
|
7385
7072
|
results.push(inspectionFailed(checkId, `Could not read source file: ${file}`, { file }));
|
|
7386
7073
|
continue;
|
|
@@ -7731,7 +7418,7 @@ var check24 = {
|
|
|
7731
7418
|
registerCheck(check24);
|
|
7732
7419
|
|
|
7733
7420
|
// src/checks/source/accessibility-alt-text.ts
|
|
7734
|
-
import { readFile as
|
|
7421
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
7735
7422
|
var check25 = {
|
|
7736
7423
|
id: "source.accessibility.alt-text",
|
|
7737
7424
|
name: "Image Alt Text",
|
|
@@ -7745,7 +7432,7 @@ var check25 = {
|
|
|
7745
7432
|
const results = [];
|
|
7746
7433
|
for (const file of files) {
|
|
7747
7434
|
try {
|
|
7748
|
-
const content = await
|
|
7435
|
+
const content = await readFile15(file, "utf8");
|
|
7749
7436
|
const lines = content.split(`
|
|
7750
7437
|
`);
|
|
7751
7438
|
let inFence = false;
|
|
@@ -7789,7 +7476,7 @@ function extractImageAlts(line) {
|
|
|
7789
7476
|
registerCheck(check25);
|
|
7790
7477
|
|
|
7791
7478
|
// src/checks/source/accessibility-heading-order.ts
|
|
7792
|
-
import { readFile as
|
|
7479
|
+
import { readFile as readFile16 } from "node:fs/promises";
|
|
7793
7480
|
var check26 = {
|
|
7794
7481
|
id: "source.accessibility.heading-order",
|
|
7795
7482
|
name: "Heading Order",
|
|
@@ -7803,7 +7490,7 @@ var check26 = {
|
|
|
7803
7490
|
const results = [];
|
|
7804
7491
|
for (const file of files) {
|
|
7805
7492
|
try {
|
|
7806
|
-
const content = await
|
|
7493
|
+
const content = await readFile16(file, "utf8");
|
|
7807
7494
|
const lines = content.split(`
|
|
7808
7495
|
`);
|
|
7809
7496
|
let inFence = false;
|
|
@@ -7845,7 +7532,7 @@ var check26 = {
|
|
|
7845
7532
|
registerCheck(check26);
|
|
7846
7533
|
|
|
7847
7534
|
// src/checks/source/layout-markers.ts
|
|
7848
|
-
import { readFile as
|
|
7535
|
+
import { readFile as readFile17 } from "node:fs/promises";
|
|
7849
7536
|
|
|
7850
7537
|
// src/lib/unknown-classes.ts
|
|
7851
7538
|
import postcss4 from "postcss";
|
|
@@ -7948,7 +7635,7 @@ async function collectKnownClasses(ctx, plugins) {
|
|
|
7948
7635
|
const sheets = (await collectStyleDependencies(ctx.inputDir, roots)).filter((f) => /\.css$/i.test(f));
|
|
7949
7636
|
for (const sheet of sheets) {
|
|
7950
7637
|
try {
|
|
7951
|
-
addCssClasses(await
|
|
7638
|
+
addCssClasses(await readFile17(sheet, "utf8"), names);
|
|
7952
7639
|
} catch {}
|
|
7953
7640
|
}
|
|
7954
7641
|
return names;
|
|
@@ -7972,7 +7659,7 @@ var check27 = {
|
|
|
7972
7659
|
const knownClasses = () => known ??= collectKnownClasses(ctx, plugins);
|
|
7973
7660
|
for (const file of files) {
|
|
7974
7661
|
try {
|
|
7975
|
-
const content = await
|
|
7662
|
+
const content = await readFile17(file, "utf8");
|
|
7976
7663
|
const env = {};
|
|
7977
7664
|
const tokens = md.parse(content, env);
|
|
7978
7665
|
md.renderer.render(tokens, md.options, env);
|
|
@@ -8012,7 +7699,7 @@ var check27 = {
|
|
|
8012
7699
|
registerCheck(check27);
|
|
8013
7700
|
|
|
8014
7701
|
// src/checks/source/merge-markers.ts
|
|
8015
|
-
import { readFile as
|
|
7702
|
+
import { readFile as readFile18 } from "node:fs/promises";
|
|
8016
7703
|
import path9 from "node:path";
|
|
8017
7704
|
|
|
8018
7705
|
// src/checks/asset/extensions.ts
|
|
@@ -8054,7 +7741,7 @@ var check28 = {
|
|
|
8054
7741
|
for (const file of textFiles) {
|
|
8055
7742
|
let content;
|
|
8056
7743
|
try {
|
|
8057
|
-
content = await
|
|
7744
|
+
content = await readFile18(file, "utf8");
|
|
8058
7745
|
} catch {
|
|
8059
7746
|
results.push(inspectionFailed(check28.id, `Could not read source file: ${file}`, { file }));
|
|
8060
7747
|
continue;
|
|
@@ -8114,7 +7801,7 @@ var check28 = {
|
|
|
8114
7801
|
registerCheck(check28);
|
|
8115
7802
|
|
|
8116
7803
|
// src/checks/source/characters.ts
|
|
8117
|
-
import { readFile as
|
|
7804
|
+
import { readFile as readFile19 } from "node:fs/promises";
|
|
8118
7805
|
|
|
8119
7806
|
// src/checks/source/character-table.ts
|
|
8120
7807
|
var CHARACTER_PATTERN = new RegExp("[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u00A0\\u00AD\\u00B4\\u02BC" + "\\u061C\\u2000-\\u2015\\u2018\\u2019\\u201B-\\u201D\\u201F\\u2022\\u2026" + "\\u2028-\\u202F\\u2032\\u2033\\u205F\\u2060\\u2066-\\u2069\\u2190\\u2192" + "\\u2194\\u21D2\\u2212\\u25AA\\u25E6\\u2605\\u2713\\u2714\\u2717\\u3000" + "\\uE000-\\uF8FF\\uFEFF\\uFF02\\uFF07\\uFFFD]" + "|\\p{Emoji_Presentation}|\\p{Extended_Pictographic}(?=\\uFE0F)", "gu");
|
|
@@ -8237,7 +7924,7 @@ var check29 = {
|
|
|
8237
7924
|
for (const file of (ctx.markdownFiles ?? []).slice().sort()) {
|
|
8238
7925
|
let content;
|
|
8239
7926
|
try {
|
|
8240
|
-
content = await
|
|
7927
|
+
content = await readFile19(file, "utf8");
|
|
8241
7928
|
} catch {
|
|
8242
7929
|
results.push(inspectionFailed(check29.id, `Could not read source file: ${file}`, { file }));
|
|
8243
7930
|
continue;
|
|
@@ -8277,16 +7964,16 @@ var check29 = {
|
|
|
8277
7964
|
registerCheck(check29);
|
|
8278
7965
|
|
|
8279
7966
|
// src/checks/asset/image-file-size.ts
|
|
8280
|
-
import { stat as
|
|
7967
|
+
import { stat as stat3 } from "node:fs/promises";
|
|
8281
7968
|
|
|
8282
7969
|
// src/lib/image-inspect.ts
|
|
8283
|
-
import { stat as
|
|
7970
|
+
import { stat as stat2, readFile as readFile20 } from "node:fs/promises";
|
|
8284
7971
|
var DEFAULT_DPI = 72;
|
|
8285
7972
|
var cache = new Map;
|
|
8286
7973
|
async function inspectImage(path10) {
|
|
8287
7974
|
let st;
|
|
8288
7975
|
try {
|
|
8289
|
-
st = await
|
|
7976
|
+
st = await stat2(path10);
|
|
8290
7977
|
} catch {
|
|
8291
7978
|
return null;
|
|
8292
7979
|
}
|
|
@@ -8295,7 +7982,7 @@ async function inspectImage(path10) {
|
|
|
8295
7982
|
return hit.info;
|
|
8296
7983
|
let info3 = null;
|
|
8297
7984
|
try {
|
|
8298
|
-
const buf = await
|
|
7985
|
+
const buf = await readFile20(path10);
|
|
8299
7986
|
info3 = parseImage(buf);
|
|
8300
7987
|
} catch {
|
|
8301
7988
|
info3 = null;
|
|
@@ -8517,7 +8204,7 @@ var check30 = {
|
|
|
8517
8204
|
const results = [];
|
|
8518
8205
|
for (const file of files) {
|
|
8519
8206
|
try {
|
|
8520
|
-
const info3 = await
|
|
8207
|
+
const info3 = await stat3(file);
|
|
8521
8208
|
if (info3.size > maxSize) {
|
|
8522
8209
|
const sizeMb = (info3.size / 1e6).toFixed(1);
|
|
8523
8210
|
const maxMb = (maxSize / 1e6).toFixed(1);
|
|
@@ -8855,7 +8542,7 @@ var check37 = {
|
|
|
8855
8542
|
registerCheck(check37);
|
|
8856
8543
|
|
|
8857
8544
|
// src/checks/heuristic/section-density.ts
|
|
8858
|
-
import { readFile as
|
|
8545
|
+
import { readFile as readFile21 } from "node:fs/promises";
|
|
8859
8546
|
var check38 = {
|
|
8860
8547
|
id: "heuristic.chunking.section-density",
|
|
8861
8548
|
name: "Section Density",
|
|
@@ -8872,7 +8559,7 @@ var check38 = {
|
|
|
8872
8559
|
const results = [];
|
|
8873
8560
|
for (const file of files) {
|
|
8874
8561
|
try {
|
|
8875
|
-
const content = await
|
|
8562
|
+
const content = await readFile21(file, "utf8");
|
|
8876
8563
|
const lines = content.split(`
|
|
8877
8564
|
`);
|
|
8878
8565
|
let currentSectionStart = 0;
|
|
@@ -9176,7 +8863,7 @@ async function restoreForCommand(dir, options) {
|
|
|
9176
8863
|
}
|
|
9177
8864
|
|
|
9178
8865
|
// src/lib/markdown/index.ts
|
|
9179
|
-
import { readdir as readdir3, readFile as
|
|
8866
|
+
import { readdir as readdir3, readFile as readFile22, writeFile as writeFile2, mkdir as mkdir4 } from "node:fs/promises";
|
|
9180
8867
|
|
|
9181
8868
|
// src/lib/remote-auth/sync-messages.ts
|
|
9182
8869
|
function isOnlineSibling(filepath) {
|
|
@@ -9318,7 +9005,7 @@ ${css.trim()}
|
|
|
9318
9005
|
}
|
|
9319
9006
|
return assembleBookHtml({
|
|
9320
9007
|
files,
|
|
9321
|
-
readText: (relPath) =>
|
|
9008
|
+
readText: (relPath) => readFile22(join2(inputDir, canonicalChapterId(relPath)), "utf-8"),
|
|
9322
9009
|
projectCss: inlined.css,
|
|
9323
9010
|
preloadImages: cssAssetCopies.map((c) => c.to),
|
|
9324
9011
|
title: opts.title,
|
|
@@ -9350,7 +9037,7 @@ async function renderChaptersToFile(inputDir, outDir, opts = {}) {
|
|
|
9350
9037
|
}
|
|
9351
9038
|
|
|
9352
9039
|
// src/lib/markdownlint-fix.ts
|
|
9353
|
-
import { readFile as
|
|
9040
|
+
import { readFile as readFile23, writeFile as writeFile3 } from "node:fs/promises";
|
|
9354
9041
|
import { applyFixes } from "markdownlint";
|
|
9355
9042
|
import { lint as lint2 } from "markdownlint/sync";
|
|
9356
9043
|
async function uncommittedAmong(inputDir, files) {
|
|
@@ -9390,7 +9077,7 @@ async function applyMarkdownlintFixes(ctx) {
|
|
|
9390
9077
|
for (const [file, violations] of Object.entries(results)) {
|
|
9391
9078
|
if (!Array.isArray(violations) || violations.length === 0)
|
|
9392
9079
|
continue;
|
|
9393
|
-
const before = await
|
|
9080
|
+
const before = await readFile23(file, "utf8");
|
|
9394
9081
|
const after = applyFixes(before, violations);
|
|
9395
9082
|
if (after !== before)
|
|
9396
9083
|
pending.push({ file, content: after });
|
|
@@ -9903,7 +9590,7 @@ import { randomBytes } from "node:crypto";
|
|
|
9903
9590
|
|
|
9904
9591
|
// src/lib/build-fingerprint.ts
|
|
9905
9592
|
import * as fs from "node:fs";
|
|
9906
|
-
import { mkdir as mkdir5, readFile as
|
|
9593
|
+
import { mkdir as mkdir5, readFile as readFile24, writeFile as writeFile4 } from "node:fs/promises";
|
|
9907
9594
|
import { createHash as createHash4 } from "node:crypto";
|
|
9908
9595
|
import path12 from "node:path";
|
|
9909
9596
|
import git from "isomorphic-git";
|
|
@@ -9990,8 +9677,8 @@ async function getEngineBundleHash() {
|
|
|
9990
9677
|
getAssetPath("engine/gutterpress-agent.js")
|
|
9991
9678
|
]);
|
|
9992
9679
|
const [viewerBytes, agentBytes] = await Promise.all([
|
|
9993
|
-
|
|
9994
|
-
|
|
9680
|
+
readFile24(viewerPath),
|
|
9681
|
+
readFile24(agentPath)
|
|
9995
9682
|
]);
|
|
9996
9683
|
const hash = createHash4("sha256");
|
|
9997
9684
|
hash.update(viewerBytes);
|
|
@@ -10054,7 +9741,10 @@ async function writeBuildFingerprint(input) {
|
|
|
10054
9741
|
resolvedFlavor: input.pdfx.resolvedFlavor,
|
|
10055
9742
|
iccPath: input.pdfx.iccPath,
|
|
10056
9743
|
stripAnnotations: input.pdfx.stripAnnotations,
|
|
10057
|
-
blackText: input.pdfx.blackText ?? null
|
|
9744
|
+
blackText: input.pdfx.blackText ?? null,
|
|
9745
|
+
transparency: input.pdfx.transparency ?? null,
|
|
9746
|
+
flattenPages: input.pdfx.flattenPages ?? null,
|
|
9747
|
+
rasterDpi: input.pdfx.rasterDpi ?? null
|
|
10058
9748
|
},
|
|
10059
9749
|
outputDir: input.recordedOutputDir ? path12.resolve(input.recordedOutputDir) : outputDir
|
|
10060
9750
|
},
|
|
@@ -10361,7 +10051,7 @@ class PdfOutput {
|
|
|
10361
10051
|
const rawPdf = pdfxMode ? path13.join(stage, "raw.pdf") : path13.resolve(pdfFile);
|
|
10362
10052
|
await fsp2.mkdir(path13.dirname(path13.resolve(pdfFile)), { recursive: true });
|
|
10363
10053
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
10364
|
-
const { buildNativePdf } = await import("./engine-
|
|
10054
|
+
const { buildNativePdf } = await import("./engine-yxnnp3hx.js");
|
|
10365
10055
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
10366
10056
|
title: config.title,
|
|
10367
10057
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
@@ -10383,12 +10073,40 @@ class PdfOutput {
|
|
|
10383
10073
|
if (pdfxMode) {
|
|
10384
10074
|
const icc = opts.iccPath ?? config.pdfx.icc;
|
|
10385
10075
|
effectiveIccPath = await resolveIccProfile(icc, manifestDir, opts.iccPath);
|
|
10386
|
-
|
|
10387
|
-
|
|
10076
|
+
const rawBytes = await fsp2.readFile(rawPdf);
|
|
10077
|
+
const transparent = await transparentPages(rawBytes);
|
|
10078
|
+
const blankGradientPages = await findPostScriptShadingPages(rawBytes);
|
|
10079
|
+
const flattenedGradientPages = blankGradientPages.filter((n) => transparent.includes(n));
|
|
10080
|
+
const vectorGradientPages = blankGradientPages.filter((n) => !transparent.includes(n));
|
|
10081
|
+
const GRADIENT_FIX = "Replace it with a plain linear-gradient() or radial-gradient(), or a small tiled image. For 0deg/90deg stripes, `linear-gradient(90deg, #b33 0 6px, #c8c5bf 6px 10px)` with `background-size: 10px 100%` converts correctly.";
|
|
10082
|
+
const pageList = (pages) => `Page${pages.length === 1 ? "" : "s"} ${pages.join(", ")}`;
|
|
10083
|
+
if (vectorGradientPages.length > 0) {
|
|
10084
|
+
log.warn(`${pageList(vectorGradientPages)}: a repeating-*-gradient() or conic-gradient() ` + "can print blank or distorted — " + `Ghostscript has been seen to paint nothing, or irregular stripes, for it when converting to PDF/X; check the page visually. ${GRADIENT_FIX}`);
|
|
10085
|
+
}
|
|
10086
|
+
if (flattenedGradientPages.length > 0 && config.pdfx.transparency !== "preserve-text") {
|
|
10087
|
+
log.warn(`${pageList(flattenedGradientPages)}: a repeating-*-gradient() or conic-gradient() is painted only as part of the one raster image Ghostscript makes of the whole page, so the page loses its embedded fonts and searchable text. Check the page visually. ${GRADIENT_FIX}`);
|
|
10088
|
+
}
|
|
10089
|
+
const flattenPages = config.pdfx.flattenPages;
|
|
10090
|
+
if (transparent.length > 0 && config.pdfx.transparency === "preserve-text") {
|
|
10091
|
+
const { unsplittableTextReasons } = await import("./pdf-inspect-zdmy7qca.js");
|
|
10092
|
+
const reasons = await unsplittableTextReasons(rawBytes, transparent).catch((err) => {
|
|
10093
|
+
log.warn(`pdfx.transparency: preserve-text could not inspect this PDF's text (${err instanceof Error ? err.message : String(err)}), so every page that uses transparency is flattened whole, as with flatten-page.`);
|
|
10094
|
+
return null;
|
|
10095
|
+
});
|
|
10096
|
+
if (reasons) {
|
|
10097
|
+
const plan = planTransparentPages(transparent, reasons, flattenPages, blankGradientPages);
|
|
10098
|
+
await flattenTransparentPages(rawPdf, plan.split, stage, config.pdfx.rasterDpi);
|
|
10099
|
+
reportTransparentPlan(plan, pdfxMode, config.pdfx.rasterDpi ?? 300, pageList);
|
|
10100
|
+
}
|
|
10101
|
+
}
|
|
10102
|
+
const unused = flattenPages.filter((n) => !transparent.includes(n));
|
|
10103
|
+
if (flattenPages.length > 0 && config.pdfx.transparency !== "preserve-text") {
|
|
10104
|
+
log.warn("pdfx.flattenPages has no effect without pdfx.transparency: preserve-text.");
|
|
10105
|
+
} else if (unused.length > 0) {
|
|
10106
|
+
log.warn(`pdfx.flattenPages lists ${pageList(unused).toLowerCase()}, which ${unused.length === 1 ? "has" : "have"} no transparency (or do not exist): nothing to flatten there.`);
|
|
10388
10107
|
}
|
|
10389
|
-
|
|
10390
|
-
|
|
10391
|
-
log.warn(`Page${blankGradientPages.length === 1 ? "" : "s"} ${blankGradientPages.join(", ")}: ` + "a repeating-*-gradient() or conic-gradient() will print blank — " + "Ghostscript cannot convert it to PDF/X. Replace it with a plain linear-gradient() or radial-gradient(), or a small tiled image. For 0deg/90deg stripes, `linear-gradient(90deg, #b33 0 6px, #c8c5bf 6px 10px)` with `background-size: 10px 100%` converts correctly.");
|
|
10108
|
+
if (transparent.length > 0 && config.pdfx.transparency !== "preserve-text") {
|
|
10109
|
+
log.warn("This book uses transparency — an image with an alpha channel, or a CSS " + `rule like \`opacity\` or \`mix-blend-mode\`. PDF/${pdfxMode === "x1a" ? "X-1a" : "X-3"} has no way to represent that (both are based on PDF 1.3, which predates PDF transparency), so Ghostscript will flatten every page that uses it into a single raster ` + "image — that page loses its embedded fonts and searchable text in the " + "PDF/X output. To keep vector text, remove the `opacity`/blend rule and flatten any alpha-channel image against its intended background before including it (export it with no alpha channel), or build --format pdf instead of pdfx if this book doesn't need print-ready CMYK. Or set `pdfx.transparency: preserve-text` to keep the text live on the pages where that is possible. `pdfx.rasterDpi` sets the resolution of those page images (default 720).");
|
|
10392
10110
|
}
|
|
10393
10111
|
const shouldStrip = opts.stripAnnotations ?? config.pdfx.stripAnnotations;
|
|
10394
10112
|
shouldStripAnnotations = shouldStrip;
|
|
@@ -10431,7 +10149,10 @@ class PdfOutput {
|
|
|
10431
10149
|
resolvedFlavor: config.pdfx.flavor,
|
|
10432
10150
|
iccPath: effectiveIccPath,
|
|
10433
10151
|
stripAnnotations: shouldStripAnnotations,
|
|
10434
|
-
blackText: pdfxMode ? config.pdfx.blackText : null
|
|
10152
|
+
blackText: pdfxMode ? config.pdfx.blackText : null,
|
|
10153
|
+
transparency: pdfxMode ? config.pdfx.transparency : null,
|
|
10154
|
+
flattenPages: pdfxMode ? config.pdfx.flattenPages : null,
|
|
10155
|
+
rasterDpi: pdfxMode ? config.pdfx.rasterDpi ?? null : null
|
|
10435
10156
|
}
|
|
10436
10157
|
}, `Wrote: ${reportedPdf}`, { htmlPath: htmlFile, pdfPath: reportedPdf }, pdfName, engineDiagnostics);
|
|
10437
10158
|
} finally {
|
|
@@ -10468,6 +10189,35 @@ async function runBuild(opts) {
|
|
|
10468
10189
|
await fsp2.rm(ctx.workDir, { recursive: true, force: true });
|
|
10469
10190
|
}
|
|
10470
10191
|
}
|
|
10192
|
+
var FALLBACK_CAUSE = {
|
|
10193
|
+
listed: "listed in pdfx.flattenPages",
|
|
10194
|
+
"text-transparency": "text drawn with transparency or blending (opacity, mix-blend-mode, a soft mask, a translucent text-shadow); keep that text opaque",
|
|
10195
|
+
"type3-font": "text in a Type 3 font: for a synthetic bold (a weight the font has no face for), use a face with that weight or set the font's own weight; for -webkit-text-stroke, remove the stroke or accept this fallback",
|
|
10196
|
+
"text-pattern-or-clip": 'text filled with a pattern or used as a clip (SVG fill="url(#…)", gradient text, background-clip: text)',
|
|
10197
|
+
gradient: "a repeating or conic gradient; use a linear or radial gradient, or a small tiled image"
|
|
10198
|
+
};
|
|
10199
|
+
function reportTransparentPlan({ split, artOnly, kept }, pdfxMode, dpi, pageList) {
|
|
10200
|
+
const one = (pages, singular, plural) => pages.length === 1 ? singular : plural;
|
|
10201
|
+
if (split.length > 0) {
|
|
10202
|
+
log.warn(`${pageList(split)} ${one(split, "uses", "use")} transparency, which PDF/${pdfxMode === "x1a" ? "X-1a" : "X-3"} (PDF 1.3) cannot represent. Each was flattened to a ${dpi} DPI picture with its text kept live on top (pdfx.transparency: preserve-text), so fonts and searchable text survive. On those pages, rules, backgrounds and shapes are raster, and text always sits above the artwork: text another element covers shows through. List a page in pdfx.flattenPages to flatten it whole instead.`);
|
|
10203
|
+
}
|
|
10204
|
+
if (artOnly.length > 0) {
|
|
10205
|
+
log.info(`${pageList(artOnly)} ${one(artOnly, "uses", "use")} transparency but ${one(artOnly, "shows", "show")} no text, so there is no text to keep: Ghostscript flattens ${one(artOnly, "it", "each")} whole (resolution: pdfx.rasterDpi).`);
|
|
10206
|
+
}
|
|
10207
|
+
if (kept.size > 0) {
|
|
10208
|
+
const pages = [...kept.keys()];
|
|
10209
|
+
const byCause = new Map;
|
|
10210
|
+
for (const [n, cause] of kept)
|
|
10211
|
+
byCause.set(cause, [...byCause.get(cause) ?? [], n]);
|
|
10212
|
+
const lines = [...byCause].map(([cause, ns]) => ` - ${one(ns, "page", "pages")} ${ns.join(", ")}: ${FALLBACK_CAUSE[cause]}`);
|
|
10213
|
+
log.warn(`${pageList(pages)} could not keep ${one(pages, "its", "their")} text live; Ghostscript will flatten ${one(pages, "that page", "each of those pages")} into one raster image, losing its embedded fonts and searchable text. Each page lists the first cause found; fixing it can reveal another:
|
|
10214
|
+
` + lines.join(`
|
|
10215
|
+
`));
|
|
10216
|
+
}
|
|
10217
|
+
if (split.length === 0 && [...kept.values()].some((cause) => cause !== "listed")) {
|
|
10218
|
+
log.warn("pdfx.transparency: preserve-text kept no page's text live in this book: every page with transparency and text falls back (see above).");
|
|
10219
|
+
}
|
|
10220
|
+
}
|
|
10471
10221
|
|
|
10472
10222
|
// src/lib/open-path.ts
|
|
10473
10223
|
import { spawn } from "node:child_process";
|
|
@@ -10501,7 +10251,7 @@ function openPath(filePath) {
|
|
|
10501
10251
|
import path16 from "path";
|
|
10502
10252
|
import { tmpdir } from "os";
|
|
10503
10253
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
10504
|
-
import { readdir as readdir4, readFile as
|
|
10254
|
+
import { readdir as readdir4, readFile as readFile25, writeFile as writeFile5 } from "node:fs/promises";
|
|
10505
10255
|
|
|
10506
10256
|
// src/utils/file-utils.ts
|
|
10507
10257
|
import { promises as fs3 } from "fs";
|
|
@@ -11062,7 +10812,7 @@ async function cleanupOrphanTempDirs() {
|
|
|
11062
10812
|
const dir = path16.join(TEMP_DIR_BASE, entry);
|
|
11063
10813
|
const pidFile = path16.join(dir, PID_FILE_NAME);
|
|
11064
10814
|
try {
|
|
11065
|
-
const raw = await
|
|
10815
|
+
const raw = await readFile25(pidFile, "utf8");
|
|
11066
10816
|
const pid = parseInt(raw.trim(), 10);
|
|
11067
10817
|
if (!isProcessAlive(pid)) {
|
|
11068
10818
|
debug(`Removing orphan temp dir ${dir} (pid ${pid} not alive)`);
|
|
@@ -11169,7 +10919,7 @@ function createServerState(inputPath, tempDir, config, options) {
|
|
|
11169
10919
|
import http from "node:http";
|
|
11170
10920
|
import net from "node:net";
|
|
11171
10921
|
import { createHash as createHash5, randomUUID as randomUUID3 } from "node:crypto";
|
|
11172
|
-
import { readFile as
|
|
10922
|
+
import { readFile as readFile26, stat as stat4 } from "node:fs/promises";
|
|
11173
10923
|
import path17 from "path";
|
|
11174
10924
|
import { WebSocket, WebSocketServer } from "ws";
|
|
11175
10925
|
var HMR_PATH = "/__gutterpress-hmr";
|
|
@@ -11228,7 +10978,7 @@ async function findAvailablePort(startPort, host = "127.0.0.1") {
|
|
|
11228
10978
|
async function serveStatic(absPath, res, cacheControl = "no-store", extraHeaders = {}) {
|
|
11229
10979
|
let filePath = absPath;
|
|
11230
10980
|
try {
|
|
11231
|
-
const s = await
|
|
10981
|
+
const s = await stat4(filePath);
|
|
11232
10982
|
if (s.isDirectory())
|
|
11233
10983
|
filePath = path17.join(filePath, "index.html");
|
|
11234
10984
|
} catch {
|
|
@@ -11238,7 +10988,7 @@ async function serveStatic(absPath, res, cacheControl = "no-store", extraHeaders
|
|
|
11238
10988
|
}
|
|
11239
10989
|
let data;
|
|
11240
10990
|
try {
|
|
11241
|
-
data = await
|
|
10991
|
+
data = await readFile26(filePath);
|
|
11242
10992
|
} catch {
|
|
11243
10993
|
res.writeHead(404);
|
|
11244
10994
|
res.end("Not Found");
|
|
@@ -11267,7 +11017,7 @@ async function serveRevalidatedStatic(req, absPath, res, validators) {
|
|
|
11267
11017
|
}
|
|
11268
11018
|
let fileStat;
|
|
11269
11019
|
try {
|
|
11270
|
-
fileStat = await
|
|
11020
|
+
fileStat = await stat4(absPath, { bigint: true });
|
|
11271
11021
|
} catch {
|
|
11272
11022
|
await serveStatic(absPath, res);
|
|
11273
11023
|
return;
|
|
@@ -11287,7 +11037,7 @@ async function serveRevalidatedStatic(req, absPath, res, validators) {
|
|
|
11287
11037
|
let data;
|
|
11288
11038
|
if (!validator || validator.stamp !== stamp) {
|
|
11289
11039
|
try {
|
|
11290
|
-
data = await
|
|
11040
|
+
data = await readFile26(absPath);
|
|
11291
11041
|
} catch {
|
|
11292
11042
|
await serveStatic(absPath, res);
|
|
11293
11043
|
return;
|
|
@@ -11315,7 +11065,7 @@ async function isMissingReferencedImage(pathname, absPath, refs) {
|
|
|
11315
11065
|
if (!refs.has(imageRefKey(pathname)))
|
|
11316
11066
|
return false;
|
|
11317
11067
|
try {
|
|
11318
|
-
await
|
|
11068
|
+
await stat4(absPath);
|
|
11319
11069
|
return false;
|
|
11320
11070
|
} catch (err) {
|
|
11321
11071
|
return err?.code === "ENOENT";
|
|
@@ -11597,7 +11347,7 @@ async function startPreviewServer(options) {
|
|
|
11597
11347
|
}
|
|
11598
11348
|
|
|
11599
11349
|
// src/lib/project-scaffold.ts
|
|
11600
|
-
import { access, copyFile, cp as cp2, mkdir as mkdir7, readdir as readdir5, readFile as
|
|
11350
|
+
import { access, copyFile, cp as cp2, mkdir as mkdir7, readdir as readdir5, readFile as readFile27, stat as stat5, writeFile as writeFile6 } from "node:fs/promises";
|
|
11601
11351
|
import { constants as FS, existsSync as existsSync12 } from "node:fs";
|
|
11602
11352
|
import path18 from "node:path";
|
|
11603
11353
|
|
|
@@ -11796,7 +11546,7 @@ async function scaffoldProject(options) {
|
|
|
11796
11546
|
async function firstSourceFile(manifestPath) {
|
|
11797
11547
|
let text;
|
|
11798
11548
|
try {
|
|
11799
|
-
text = await
|
|
11549
|
+
text = await readFile27(manifestPath, "utf8");
|
|
11800
11550
|
} catch {
|
|
11801
11551
|
return;
|
|
11802
11552
|
}
|
|
@@ -11808,7 +11558,7 @@ async function firstSourceFile(manifestPath) {
|
|
|
11808
11558
|
return m ? m[1].trim() : undefined;
|
|
11809
11559
|
}
|
|
11810
11560
|
async function fillTemplateFile(filePath, substitutions) {
|
|
11811
|
-
let text = await
|
|
11561
|
+
let text = await readFile27(filePath, "utf8");
|
|
11812
11562
|
for (const [token, value] of Object.entries(substitutions)) {
|
|
11813
11563
|
text = text.split(token).join(value);
|
|
11814
11564
|
}
|
|
@@ -11816,7 +11566,7 @@ async function fillTemplateFile(filePath, substitutions) {
|
|
|
11816
11566
|
}
|
|
11817
11567
|
|
|
11818
11568
|
// src/lib/extension-scaffold.ts
|
|
11819
|
-
import { access as access2, mkdir as mkdir8, readFile as
|
|
11569
|
+
import { access as access2, mkdir as mkdir8, readFile as readFile28, writeFile as writeFile7 } from "node:fs/promises";
|
|
11820
11570
|
import { constants as FS2 } from "node:fs";
|
|
11821
11571
|
import path19 from "node:path";
|
|
11822
11572
|
var EXTENSION_KINDS = ["plugin", "theme"];
|
|
@@ -11933,7 +11683,7 @@ async function scaffoldExtension(options) {
|
|
|
11933
11683
|
const src = await getAssetPath(`extension-templates/${kind}/${assetName}`);
|
|
11934
11684
|
const dest = path19.join(extensionDir, relDest);
|
|
11935
11685
|
await mkdir8(path19.dirname(dest), { recursive: true });
|
|
11936
|
-
const text = await
|
|
11686
|
+
const text = await readFile28(src, "utf8");
|
|
11937
11687
|
const table = relDest.endsWith(".json") ? jsonSafe : plain;
|
|
11938
11688
|
await writeFile7(dest, substitute(text, table), "utf8");
|
|
11939
11689
|
written.push(relDest);
|
|
@@ -11978,7 +11728,7 @@ var SKIP_ENTRIES = new Set([
|
|
|
11978
11728
|
|
|
11979
11729
|
// src/lib/extension-import.ts
|
|
11980
11730
|
import { existsSync as existsSync13 } from "node:fs";
|
|
11981
|
-
import { cp as cp3, mkdir as mkdir9, mkdtemp as mkdtemp2, readFile as
|
|
11731
|
+
import { cp as cp3, mkdir as mkdir9, mkdtemp as mkdtemp2, readFile as readFile29, rm as rm4, writeFile as writeFile8 } from "node:fs/promises";
|
|
11982
11732
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
11983
11733
|
import path20 from "node:path";
|
|
11984
11734
|
import { unzipSync } from "fflate";
|
|
@@ -12051,7 +11801,7 @@ async function finalizeExtensionImport(projectDir, sourceDir, relPaths, fallback
|
|
|
12051
11801
|
if (!existsSync13(cssPath)) {
|
|
12052
11802
|
throw new Error("A theme must contain a theme.css file.");
|
|
12053
11803
|
}
|
|
12054
|
-
const css = await
|
|
11804
|
+
const css = await readFile29(cssPath, "utf8");
|
|
12055
11805
|
const { reject, warnings: printFindings } = classifyThemeCssFindings(checkCss(css, "theme.css"));
|
|
12056
11806
|
if (reject) {
|
|
12057
11807
|
throw new Error(`theme.css could not be parsed — ${reject.message}`);
|
|
@@ -12079,7 +11829,7 @@ async function finalizeExtensionImport(projectDir, sourceDir, relPaths, fallback
|
|
|
12079
11829
|
for (let i = 0;i < extraSheets.length; i++) {
|
|
12080
11830
|
const rel = extraSheets[i];
|
|
12081
11831
|
const sheetPath = extraSheetPaths[i];
|
|
12082
|
-
const sheetCss = await
|
|
11832
|
+
const sheetCss = await readFile29(sheetPath, "utf8");
|
|
12083
11833
|
const { reject: sheetReject, warnings: sheetFindings } = classifyThemeCssFindings(checkCss(sheetCss, rel));
|
|
12084
11834
|
if (sheetReject) {
|
|
12085
11835
|
throw new Error(`${rel} could not be parsed — ${sheetReject.message}`);
|
|
@@ -12112,7 +11862,7 @@ async function completeLandedManifest(dest, id, meta, metaExists) {
|
|
|
12112
11862
|
let pkg = {};
|
|
12113
11863
|
if (metaExists) {
|
|
12114
11864
|
try {
|
|
12115
|
-
const parsed = JSON.parse(await
|
|
11865
|
+
const parsed = JSON.parse(await readFile29(file, "utf8"));
|
|
12116
11866
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
12117
11867
|
pkg = parsed;
|
|
12118
11868
|
}
|
|
@@ -12214,11 +11964,11 @@ async function importExtensionFromCssText(projectDir, css, name) {
|
|
|
12214
11964
|
async function importExtensionFromFile(projectDir, filePath) {
|
|
12215
11965
|
const ext = path20.extname(filePath).toLowerCase();
|
|
12216
11966
|
if (ext === ".zip") {
|
|
12217
|
-
const buf = await
|
|
11967
|
+
const buf = await readFile29(filePath);
|
|
12218
11968
|
return importExtensionFromZip(projectDir, new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength));
|
|
12219
11969
|
}
|
|
12220
11970
|
if (ext === ".css") {
|
|
12221
|
-
const css = await
|
|
11971
|
+
const css = await readFile29(filePath, "utf8");
|
|
12222
11972
|
return importExtensionFromCssText(projectDir, css, prettify(path20.basename(filePath, ".css")));
|
|
12223
11973
|
}
|
|
12224
11974
|
throw new Error("Choose a .zip extension package or a .css stylesheet.");
|
|
@@ -13002,7 +12752,7 @@ var drivethrurpgProvider = {
|
|
|
13002
12752
|
};
|
|
13003
12753
|
|
|
13004
12754
|
// src/lib/publish/providers/gdrive.ts
|
|
13005
|
-
import { mkdtemp as mkdtemp3, readFile as
|
|
12755
|
+
import { mkdtemp as mkdtemp3, readFile as readFile30, readdir as readdir6, rm as rm5, stat as stat6, writeFile as writeFile10 } from "node:fs/promises";
|
|
13006
12756
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
13007
12757
|
import path22 from "node:path";
|
|
13008
12758
|
import { Zip, ZipDeflate } from "fflate";
|
|
@@ -13394,12 +13144,12 @@ async function collectZipEntries(root, dir, out, onWarn) {
|
|
|
13394
13144
|
await collectZipEntries(root, full, out, onWarn);
|
|
13395
13145
|
} else if (entry.isFile()) {
|
|
13396
13146
|
const rel = path22.relative(root, full).split(path22.sep).join("/");
|
|
13397
|
-
out[rel] = await
|
|
13147
|
+
out[rel] = await readFile30(full);
|
|
13398
13148
|
} else if (entry.isSymbolicLink()) {
|
|
13399
|
-
const resolved = await
|
|
13149
|
+
const resolved = await stat6(full).catch(() => null);
|
|
13400
13150
|
if (resolved?.isFile()) {
|
|
13401
13151
|
const rel = path22.relative(root, full).split(path22.sep).join("/");
|
|
13402
|
-
out[rel] = await
|
|
13152
|
+
out[rel] = await readFile30(full);
|
|
13403
13153
|
} else if (resolved?.isDirectory()) {
|
|
13404
13154
|
await collectZipEntries(root, full, out, onWarn);
|
|
13405
13155
|
} else {
|
|
@@ -13469,7 +13219,7 @@ var gdriveProvider = {
|
|
|
13469
13219
|
cleanup: async () => {}
|
|
13470
13220
|
};
|
|
13471
13221
|
try {
|
|
13472
|
-
const artifactStat = await
|
|
13222
|
+
const artifactStat = await stat6(source.filePath);
|
|
13473
13223
|
const about = await driveAbout(fetchImpl, accessToken);
|
|
13474
13224
|
if (about.quota.limitBytes != null && about.quota.freeBytes != null) {
|
|
13475
13225
|
if (artifactStat.size > about.quota.freeBytes) {
|
|
@@ -13514,7 +13264,7 @@ var gdriveProvider = {
|
|
|
13514
13264
|
};
|
|
13515
13265
|
|
|
13516
13266
|
// src/lib/publish/butler.ts
|
|
13517
|
-
import { chmod, mkdir as mkdir11, stat as
|
|
13267
|
+
import { chmod, mkdir as mkdir11, stat as stat7, writeFile as writeFile11 } from "node:fs/promises";
|
|
13518
13268
|
import path23 from "node:path";
|
|
13519
13269
|
import { unzipSync as unzipSync2 } from "fflate";
|
|
13520
13270
|
var BUTLER_DOWNLOAD_TIMEOUT_MS = 300000;
|
|
@@ -13535,7 +13285,7 @@ function butlerBinaryName(platform = process.platform) {
|
|
|
13535
13285
|
}
|
|
13536
13286
|
async function fileExists2(p) {
|
|
13537
13287
|
try {
|
|
13538
|
-
return (await
|
|
13288
|
+
return (await stat7(p)).isFile();
|
|
13539
13289
|
} catch {
|
|
13540
13290
|
return false;
|
|
13541
13291
|
}
|
|
@@ -13778,7 +13528,7 @@ var kdpProvider = {
|
|
|
13778
13528
|
};
|
|
13779
13529
|
|
|
13780
13530
|
// src/lib/publish/providers/local-folder.ts
|
|
13781
|
-
import { cp as cp4, mkdir as mkdir12, stat as
|
|
13531
|
+
import { cp as cp4, mkdir as mkdir12, stat as stat8 } from "node:fs/promises";
|
|
13782
13532
|
import path24 from "node:path";
|
|
13783
13533
|
var LOCAL_PUBLISH_DEFAULT_DIR = "dist";
|
|
13784
13534
|
var info8 = {
|
|
@@ -13805,7 +13555,7 @@ var localFolderProvider = {
|
|
|
13805
13555
|
async preflight(req) {
|
|
13806
13556
|
const dir = localPublishDir(req);
|
|
13807
13557
|
try {
|
|
13808
|
-
const s = await
|
|
13558
|
+
const s = await stat8(dir);
|
|
13809
13559
|
if (!s.isDirectory()) {
|
|
13810
13560
|
return [
|
|
13811
13561
|
{ severity: "error", id: "local/not-a-folder", message: `${dir} exists but is not a folder.` }
|
|
@@ -14060,7 +13810,7 @@ function publishProviderFor(id) {
|
|
|
14060
13810
|
}
|
|
14061
13811
|
|
|
14062
13812
|
// src/lib/publish/run-publish.ts
|
|
14063
|
-
import { readdir as readdir7, stat as
|
|
13813
|
+
import { readdir as readdir7, stat as stat9 } from "node:fs/promises";
|
|
14064
13814
|
import path25 from "node:path";
|
|
14065
13815
|
function resolvePublishFormat(info10, providerConfig) {
|
|
14066
13816
|
if (info10.formats && info10.formats.length > 0) {
|
|
@@ -14102,7 +13852,7 @@ var PDF_HINT = "Build the PDF first (gutterpress build, or export it from the ap
|
|
|
14102
13852
|
var HTML_HINT = "Build the website export first (gutterpress build --format html).";
|
|
14103
13853
|
async function artifactIssues(artifact) {
|
|
14104
13854
|
try {
|
|
14105
|
-
const s = await
|
|
13855
|
+
const s = await stat9(artifact.path);
|
|
14106
13856
|
if (artifact.format === "pdf" && !s.isFile()) {
|
|
14107
13857
|
return [
|
|
14108
13858
|
{
|
|
@@ -14148,7 +13898,7 @@ async function artifactIssues(artifact) {
|
|
|
14148
13898
|
var BUILD_FINGERPRINT_FILENAME = "build-fingerprint.json";
|
|
14149
13899
|
async function htmlDirIssues(dir) {
|
|
14150
13900
|
const issues = [];
|
|
14151
|
-
const isThere = async (rel) =>
|
|
13901
|
+
const isThere = async (rel) => stat9(path25.join(dir, rel)).then(() => true, () => false);
|
|
14152
13902
|
if (!await isThere(BOOK_HTML)) {
|
|
14153
13903
|
issues.push({
|
|
14154
13904
|
severity: "error",
|
|
@@ -14386,7 +14136,7 @@ import git8 from "isomorphic-git";
|
|
|
14386
14136
|
// src/lib/remote-auth/scorched-earth.ts
|
|
14387
14137
|
import git9 from "isomorphic-git";
|
|
14388
14138
|
// src/lib/publish/selections.ts
|
|
14389
|
-
import { chmod as chmod2, mkdir as mkdir13, readFile as
|
|
14139
|
+
import { chmod as chmod2, mkdir as mkdir13, readFile as readFile31, writeFile as writeFile12 } from "node:fs/promises";
|
|
14390
14140
|
import path26 from "node:path";
|
|
14391
14141
|
class PublishSelectionsStore {
|
|
14392
14142
|
filePath;
|
|
@@ -14396,7 +14146,7 @@ class PublishSelectionsStore {
|
|
|
14396
14146
|
}
|
|
14397
14147
|
async read() {
|
|
14398
14148
|
try {
|
|
14399
|
-
const raw = await
|
|
14149
|
+
const raw = await readFile31(this.filePath, "utf8");
|
|
14400
14150
|
const parsed = JSON.parse(raw);
|
|
14401
14151
|
if (parsed && typeof parsed === "object") {
|
|
14402
14152
|
return {
|