gutterpress 0.11.19-alpha.1 → 0.11.19-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 +1 -1
- package/dist/{build-vgz3pr8y.js → build-6631d323.js} +3 -3
- package/dist/checks/source/character-table.d.ts +63 -0
- package/dist/checks/source/characters.d.ts +1 -0
- package/dist/checks/source/index.d.ts +1 -0
- package/dist/{cli-5j0a5hmc.js → cli-1b65ntcd.js} +1 -1
- package/dist/{cli-mkn97gxp.js → cli-4m7sgga3.js} +322 -159
- package/dist/{cli-n3nd3sav.js → cli-zpawttnh.js} +1 -1
- package/dist/cli.js +12 -12
- package/dist/{doctor-gxf8ty3n.js → doctor-vw0a32kd.js} +2 -2
- package/dist/{ext-7j388f5z.js → ext-7t9fgc3x.js} +3 -3
- package/dist/{index-n4ek1358.js → index-bja72kwa.js} +326 -163
- package/dist/index.js +1 -1
- package/dist/{new-0wyn55dn.js → new-b7nz21pm.js} +3 -3
- package/dist/{preflight-re9v4skc.js → preflight-00vckfwg.js} +3 -3
- package/dist/{preview-2x113vyc.js → preview-mjmnnnpp.js} +3 -3
- package/dist/{publish-r379k1hr.js → publish-qkz561hp.js} +3 -3
- package/dist/{validate-fje7ca9g.js → validate-nwet2ksq.js} +6 -5
- package/package.json +1 -1
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
stampCreator,
|
|
15
15
|
stripAnnotations,
|
|
16
16
|
warn
|
|
17
|
-
} from "./cli-
|
|
17
|
+
} from "./cli-1b65ntcd.js";
|
|
18
18
|
import {
|
|
19
19
|
DEBOUNCE,
|
|
20
20
|
UsageError,
|
|
21
21
|
resolvePort
|
|
22
|
-
} from "./cli-
|
|
22
|
+
} from "./cli-zpawttnh.js";
|
|
23
23
|
import {
|
|
24
24
|
blackTextToGray
|
|
25
25
|
} from "./cli-ht1bcqdd.js";
|
|
@@ -8008,11 +8008,174 @@ var check27 = {
|
|
|
8008
8008
|
};
|
|
8009
8009
|
registerCheck(check27);
|
|
8010
8010
|
|
|
8011
|
+
// src/checks/source/characters.ts
|
|
8012
|
+
import { readFile as readFile20 } from "node:fs/promises";
|
|
8013
|
+
|
|
8014
|
+
// src/checks/source/character-table.ts
|
|
8015
|
+
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");
|
|
8016
|
+
var NAMED = {
|
|
8017
|
+
8212: ["Em dash", "typographer", "---"],
|
|
8018
|
+
8211: ["En dash", "typographer", "--"],
|
|
8019
|
+
8220: ["Opening curly quote", "typographer", '"'],
|
|
8020
|
+
8221: ["Closing curly quote", "typographer", '"'],
|
|
8021
|
+
8216: ["Opening curly single quote", "typographer", "'"],
|
|
8022
|
+
8217: ["Curly apostrophe", "typographer", "'"],
|
|
8023
|
+
8230: ["Ellipsis character", "typographer", "..."],
|
|
8024
|
+
700: ["Modifier-letter apostrophe", "lookalike", "'"],
|
|
8025
|
+
180: ["Acute accent", "lookalike", "'"],
|
|
8026
|
+
8242: ["Prime", "lookalike", "'"],
|
|
8027
|
+
8243: ["Double prime", "lookalike", '"'],
|
|
8028
|
+
8219: ["Reversed single quote", "lookalike", "'"],
|
|
8029
|
+
8223: ["Reversed double quote", "lookalike", '"'],
|
|
8030
|
+
65282: ["Full-width quote", "lookalike", '"'],
|
|
8031
|
+
65287: ["Full-width apostrophe", "lookalike", "'"],
|
|
8032
|
+
8208: ["Unicode hyphen", "lookalike", "-"],
|
|
8033
|
+
8209: ["Non-breaking hyphen", "lookalike", "-"],
|
|
8034
|
+
8210: ["Figure dash", "lookalike", "-"],
|
|
8035
|
+
8213: ["Horizontal bar", "lookalike", "---"],
|
|
8036
|
+
8722: ["Minus sign", "lookalike", "-"],
|
|
8037
|
+
8226: ["Bullet", "symbol", "•"],
|
|
8038
|
+
9702: ["White bullet", "symbol", "◦"],
|
|
8039
|
+
9642: ["Small square", "symbol", "▪"],
|
|
8040
|
+
8594: ["Right arrow", "symbol", "→"],
|
|
8041
|
+
8592: ["Left arrow", "symbol", "←"],
|
|
8042
|
+
8596: ["Left-right arrow", "symbol", "↔"],
|
|
8043
|
+
8658: ["Double right arrow", "symbol", "⇒"],
|
|
8044
|
+
10003: ["Check mark", "symbol", "✓"],
|
|
8045
|
+
10004: ["Heavy check mark", "symbol", "✔"],
|
|
8046
|
+
10007: ["Ballot X", "symbol", "✗"],
|
|
8047
|
+
9733: ["Star", "symbol", "★"],
|
|
8048
|
+
8203: ["Zero-width space", "invisible", "​"],
|
|
8049
|
+
8288: ["Word joiner", "invisible", "⁠"],
|
|
8050
|
+
65279: ["Byte-order mark", "invisible"],
|
|
8051
|
+
173: ["Soft hyphen", "invisible", "­"],
|
|
8052
|
+
8204: ["Zero-width non-joiner", "invisible", "‌"],
|
|
8053
|
+
8205: ["Zero-width joiner", "invisible", "‍"],
|
|
8054
|
+
8206: ["Left-to-right mark", "invisible", "‎"],
|
|
8055
|
+
8207: ["Right-to-left mark", "invisible", "‏"],
|
|
8056
|
+
1564: ["Arabic letter mark", "invisible", "؜"],
|
|
8057
|
+
8234: ["Left-to-right embedding", "invisible", "‪"],
|
|
8058
|
+
8235: ["Right-to-left embedding", "invisible", "‫"],
|
|
8059
|
+
8236: ["Pop directional formatting", "invisible", "‬"],
|
|
8060
|
+
8237: ["Left-to-right override", "invisible", "‭"],
|
|
8061
|
+
8238: ["Right-to-left override", "invisible", "‮"],
|
|
8062
|
+
8294: ["Left-to-right isolate", "invisible", "⁦"],
|
|
8063
|
+
8295: ["Right-to-left isolate", "invisible", "⁧"],
|
|
8064
|
+
8296: ["First-strong isolate", "invisible", "⁨"],
|
|
8065
|
+
8297: ["Pop directional isolate", "invisible", "⁩"],
|
|
8066
|
+
8232: ["Line separator", "invisible"],
|
|
8067
|
+
8233: ["Paragraph separator", "invisible"],
|
|
8068
|
+
160: ["Non-breaking space", "whitespace", " "],
|
|
8069
|
+
8192: ["En quad", "whitespace", " "],
|
|
8070
|
+
8193: ["Em quad", "whitespace", " "],
|
|
8071
|
+
8194: ["En space", "whitespace", " "],
|
|
8072
|
+
8195: ["Em space", "whitespace", " "],
|
|
8073
|
+
8196: ["Three-per-em space", "whitespace", " "],
|
|
8074
|
+
8197: ["Four-per-em space", "whitespace", " "],
|
|
8075
|
+
8198: ["Six-per-em space", "whitespace", " "],
|
|
8076
|
+
8199: ["Figure space", "whitespace", " "],
|
|
8077
|
+
8200: ["Punctuation space", "whitespace", " "],
|
|
8078
|
+
8201: ["Thin space", "whitespace", " "],
|
|
8079
|
+
8202: ["Hair space", "whitespace", " "],
|
|
8080
|
+
8239: ["Narrow non-breaking space", "whitespace", " "],
|
|
8081
|
+
8287: ["Medium mathematical space", "whitespace", " "],
|
|
8082
|
+
12288: ["Ideographic space", "whitespace", " "],
|
|
8083
|
+
65533: ["Replacement character", "replacement"]
|
|
8084
|
+
};
|
|
8085
|
+
function fixFor(code, spelling) {
|
|
8086
|
+
switch (code) {
|
|
8087
|
+
case "typographer":
|
|
8088
|
+
return `Type ${spelling} instead; it prints the same.`;
|
|
8089
|
+
case "lookalike":
|
|
8090
|
+
return `Type ${spelling} instead.`;
|
|
8091
|
+
case "whitespace":
|
|
8092
|
+
return `Type a space, or ${spelling} if you meant it.`;
|
|
8093
|
+
case "symbol":
|
|
8094
|
+
case "invisible":
|
|
8095
|
+
return spelling ? `Delete it, or type ${spelling} if you meant it.` : "Delete it.";
|
|
8096
|
+
case "control":
|
|
8097
|
+
return "Delete it; it does not print.";
|
|
8098
|
+
case "replacement":
|
|
8099
|
+
return "Retype the character that was lost here.";
|
|
8100
|
+
case "private-use":
|
|
8101
|
+
return "Replace it with the character you meant; this one only shows in the font it came from.";
|
|
8102
|
+
}
|
|
8103
|
+
}
|
|
8104
|
+
function info2(name, code, spelling) {
|
|
8105
|
+
return { name, code, fix: fixFor(code, spelling) };
|
|
8106
|
+
}
|
|
8107
|
+
function describeCharacter(char) {
|
|
8108
|
+
const cp2 = char.codePointAt(0);
|
|
8109
|
+
const named = NAMED[cp2];
|
|
8110
|
+
if (named)
|
|
8111
|
+
return info2(...named);
|
|
8112
|
+
if (cp2 <= 159)
|
|
8113
|
+
return info2("Control character", "control");
|
|
8114
|
+
if (cp2 >= 57344 && cp2 <= 63743)
|
|
8115
|
+
return info2("Private-use character", "private-use");
|
|
8116
|
+
return info2("Emoji", "symbol", `&#x${cp2.toString(16).toUpperCase()};`);
|
|
8117
|
+
}
|
|
8118
|
+
function codePointLabel(char) {
|
|
8119
|
+
return `U+${char.codePointAt(0).toString(16).toUpperCase().padStart(4, "0")}`;
|
|
8120
|
+
}
|
|
8121
|
+
|
|
8122
|
+
// src/checks/source/characters.ts
|
|
8123
|
+
var PROBE = new RegExp(CHARACTER_PATTERN.source, "u");
|
|
8124
|
+
var check28 = {
|
|
8125
|
+
id: "source.characters",
|
|
8126
|
+
name: "Unusual Characters",
|
|
8127
|
+
description: "Finds invisible and control characters, odd spaces, and pasted typography (em dashes, curly quotes, emoji) in markdown",
|
|
8128
|
+
category: "source",
|
|
8129
|
+
phase: "pre-build",
|
|
8130
|
+
async run(ctx) {
|
|
8131
|
+
const results = [];
|
|
8132
|
+
for (const file of (ctx.markdownFiles ?? []).slice().sort()) {
|
|
8133
|
+
let content;
|
|
8134
|
+
try {
|
|
8135
|
+
content = await readFile20(file, "utf8");
|
|
8136
|
+
} catch {
|
|
8137
|
+
results.push(inspectionFailed(check28.id, `Could not read source file: ${file}`, { file }));
|
|
8138
|
+
continue;
|
|
8139
|
+
}
|
|
8140
|
+
if (!PROBE.test(content))
|
|
8141
|
+
continue;
|
|
8142
|
+
const lines = content.split(`
|
|
8143
|
+
`);
|
|
8144
|
+
let silencedLine = -1;
|
|
8145
|
+
for (let i = 0;i < lines.length; i++) {
|
|
8146
|
+
const line = lines[i];
|
|
8147
|
+
const comment = /^\s*<!--(.*)-->\s*$/.exec(line);
|
|
8148
|
+
if (comment && parseDisableDirective(comment[1])?.includes(check28.id)) {
|
|
8149
|
+
silencedLine = i + 1;
|
|
8150
|
+
continue;
|
|
8151
|
+
}
|
|
8152
|
+
if (i === silencedLine)
|
|
8153
|
+
continue;
|
|
8154
|
+
for (const match of line.matchAll(CHARACTER_PATTERN)) {
|
|
8155
|
+
const char = match[0];
|
|
8156
|
+
const { name, code, fix } = describeCharacter(char);
|
|
8157
|
+
results.push(finding(check28.id, {
|
|
8158
|
+
severity: "warning",
|
|
8159
|
+
code,
|
|
8160
|
+
message: `${name} (${codePointLabel(char)}). ${fix}`,
|
|
8161
|
+
file,
|
|
8162
|
+
line: i + 1,
|
|
8163
|
+
column: match.index + 1,
|
|
8164
|
+
data: { codePoint: char.codePointAt(0) }
|
|
8165
|
+
}));
|
|
8166
|
+
}
|
|
8167
|
+
}
|
|
8168
|
+
}
|
|
8169
|
+
return results;
|
|
8170
|
+
}
|
|
8171
|
+
};
|
|
8172
|
+
registerCheck(check28);
|
|
8173
|
+
|
|
8011
8174
|
// src/checks/asset/image-file-size.ts
|
|
8012
8175
|
import { stat as stat4 } from "node:fs/promises";
|
|
8013
8176
|
|
|
8014
8177
|
// src/lib/image-inspect.ts
|
|
8015
|
-
import { stat as stat3, readFile as
|
|
8178
|
+
import { stat as stat3, readFile as readFile21 } from "node:fs/promises";
|
|
8016
8179
|
var DEFAULT_DPI = 72;
|
|
8017
8180
|
var cache = new Map;
|
|
8018
8181
|
async function inspectImage(path10) {
|
|
@@ -8025,15 +8188,15 @@ async function inspectImage(path10) {
|
|
|
8025
8188
|
const hit = cache.get(path10);
|
|
8026
8189
|
if (hit && hit.mtimeMs === st.mtimeMs && hit.size === st.size)
|
|
8027
8190
|
return hit.info;
|
|
8028
|
-
let
|
|
8191
|
+
let info3 = null;
|
|
8029
8192
|
try {
|
|
8030
|
-
const buf = await
|
|
8031
|
-
|
|
8193
|
+
const buf = await readFile21(path10);
|
|
8194
|
+
info3 = parseImage(buf);
|
|
8032
8195
|
} catch {
|
|
8033
|
-
|
|
8196
|
+
info3 = null;
|
|
8034
8197
|
}
|
|
8035
|
-
cache.set(path10, { mtimeMs: st.mtimeMs, size: st.size, info:
|
|
8036
|
-
return
|
|
8198
|
+
cache.set(path10, { mtimeMs: st.mtimeMs, size: st.size, info: info3 });
|
|
8199
|
+
return info3;
|
|
8037
8200
|
}
|
|
8038
8201
|
function parseImage(b) {
|
|
8039
8202
|
if (b.length > 8 && b[0] === 137 && b[1] === 80 && b[2] === 78 && b[3] === 71) {
|
|
@@ -8232,7 +8395,7 @@ async function collectImageFiles(dirs, exts, ignore2 = ASSET_SCAN_IGNORE_GLOBS)
|
|
|
8232
8395
|
}
|
|
8233
8396
|
|
|
8234
8397
|
// src/checks/asset/image-file-size.ts
|
|
8235
|
-
var
|
|
8398
|
+
var check29 = {
|
|
8236
8399
|
id: "asset.image.file-size",
|
|
8237
8400
|
name: "Image File Size",
|
|
8238
8401
|
description: "Checks that image files do not exceed the maximum size limit",
|
|
@@ -8249,18 +8412,18 @@ var check28 = {
|
|
|
8249
8412
|
const results = [];
|
|
8250
8413
|
for (const file of files) {
|
|
8251
8414
|
try {
|
|
8252
|
-
const
|
|
8253
|
-
if (
|
|
8254
|
-
const sizeMb = (
|
|
8415
|
+
const info3 = await stat4(file);
|
|
8416
|
+
if (info3.size > maxSize) {
|
|
8417
|
+
const sizeMb = (info3.size / 1e6).toFixed(1);
|
|
8255
8418
|
const maxMb = (maxSize / 1e6).toFixed(1);
|
|
8256
|
-
results.push(finding(
|
|
8419
|
+
results.push(finding(check29.id, {
|
|
8257
8420
|
severity: "warning",
|
|
8258
8421
|
message: `Image file too large: ${sizeMb}MB (max ${maxMb}MB)`,
|
|
8259
8422
|
file
|
|
8260
8423
|
}));
|
|
8261
8424
|
}
|
|
8262
8425
|
} catch {
|
|
8263
|
-
results.push(inspectionFailed(
|
|
8426
|
+
results.push(inspectionFailed(check29.id, `Could not stat image file: ${file}`, {
|
|
8264
8427
|
file
|
|
8265
8428
|
}));
|
|
8266
8429
|
}
|
|
@@ -8268,10 +8431,10 @@ var check28 = {
|
|
|
8268
8431
|
return results;
|
|
8269
8432
|
}
|
|
8270
8433
|
};
|
|
8271
|
-
registerCheck(
|
|
8434
|
+
registerCheck(check29);
|
|
8272
8435
|
|
|
8273
8436
|
// src/checks/asset/image-resolution.ts
|
|
8274
|
-
var
|
|
8437
|
+
var check30 = {
|
|
8275
8438
|
id: "asset.image.resolution",
|
|
8276
8439
|
name: "Image Resolution",
|
|
8277
8440
|
description: "Checks source image DPI from embedded density metadata",
|
|
@@ -8287,13 +8450,13 @@ var check29 = {
|
|
|
8287
8450
|
return [];
|
|
8288
8451
|
const results = [];
|
|
8289
8452
|
for (const file of files) {
|
|
8290
|
-
const
|
|
8291
|
-
if (!
|
|
8453
|
+
const info3 = await inspectImage(file);
|
|
8454
|
+
if (!info3)
|
|
8292
8455
|
continue;
|
|
8293
|
-
const { xDpi, yDpi } =
|
|
8456
|
+
const { xDpi, yDpi } = info3;
|
|
8294
8457
|
if (xDpi > 0 && yDpi > 0 && (xDpi < minDpi || yDpi < minDpi)) {
|
|
8295
8458
|
results.push({
|
|
8296
|
-
checkId:
|
|
8459
|
+
checkId: check30.id,
|
|
8297
8460
|
severity: "warning",
|
|
8298
8461
|
message: `Image resolution too low: ${xDpi}x${yDpi} DPI (minimum ${minDpi} DPI)`,
|
|
8299
8462
|
file
|
|
@@ -8303,7 +8466,7 @@ var check29 = {
|
|
|
8303
8466
|
return results;
|
|
8304
8467
|
}
|
|
8305
8468
|
};
|
|
8306
|
-
registerCheck(
|
|
8469
|
+
registerCheck(check30);
|
|
8307
8470
|
|
|
8308
8471
|
// src/checks/asset/image-color-space.ts
|
|
8309
8472
|
var LABEL = {
|
|
@@ -8311,7 +8474,7 @@ var LABEL = {
|
|
|
8311
8474
|
gray: "Gray",
|
|
8312
8475
|
cmyk: "CMYK"
|
|
8313
8476
|
};
|
|
8314
|
-
var
|
|
8477
|
+
var check31 = {
|
|
8315
8478
|
id: "asset.image.color-space",
|
|
8316
8479
|
name: "Image Color Space",
|
|
8317
8480
|
description: "Validates image color spaces against allowed list",
|
|
@@ -8328,11 +8491,11 @@ var check30 = {
|
|
|
8328
8491
|
const allowedLower = new Set(allowed.map((s) => s.toLowerCase()));
|
|
8329
8492
|
const results = [];
|
|
8330
8493
|
for (const file of files) {
|
|
8331
|
-
const
|
|
8332
|
-
const cs =
|
|
8494
|
+
const info3 = await inspectImage(file);
|
|
8495
|
+
const cs = info3?.colorSpace;
|
|
8333
8496
|
if (cs && !allowedLower.has(cs)) {
|
|
8334
8497
|
results.push({
|
|
8335
|
-
checkId:
|
|
8498
|
+
checkId: check31.id,
|
|
8336
8499
|
severity: "warning",
|
|
8337
8500
|
message: `Image uses ${LABEL[cs] ?? cs} color space (allowed: ${allowed.join(", ")})`,
|
|
8338
8501
|
file
|
|
@@ -8342,10 +8505,10 @@ var check30 = {
|
|
|
8342
8505
|
return results;
|
|
8343
8506
|
}
|
|
8344
8507
|
};
|
|
8345
|
-
registerCheck(
|
|
8508
|
+
registerCheck(check31);
|
|
8346
8509
|
|
|
8347
8510
|
// src/checks/asset/image-alpha.ts
|
|
8348
|
-
var
|
|
8511
|
+
var check32 = {
|
|
8349
8512
|
id: "asset.image.alpha-channel",
|
|
8350
8513
|
name: "Image Alpha Channel",
|
|
8351
8514
|
description: "Checks for alpha channels in PNG/TIFF images",
|
|
@@ -8360,10 +8523,10 @@ var check31 = {
|
|
|
8360
8523
|
return [];
|
|
8361
8524
|
const results = [];
|
|
8362
8525
|
for (const file of files) {
|
|
8363
|
-
const
|
|
8364
|
-
if (
|
|
8526
|
+
const info3 = await inspectImage(file);
|
|
8527
|
+
if (info3?.hasAlpha) {
|
|
8365
8528
|
results.push({
|
|
8366
|
-
checkId:
|
|
8529
|
+
checkId: check32.id,
|
|
8367
8530
|
severity: "warning",
|
|
8368
8531
|
message: "Image contains alpha channel, which may cause print issues",
|
|
8369
8532
|
file
|
|
@@ -8373,10 +8536,10 @@ var check31 = {
|
|
|
8373
8536
|
return results;
|
|
8374
8537
|
}
|
|
8375
8538
|
};
|
|
8376
|
-
registerCheck(
|
|
8539
|
+
registerCheck(check32);
|
|
8377
8540
|
|
|
8378
8541
|
// src/checks/asset/image-tac.ts
|
|
8379
|
-
var
|
|
8542
|
+
var check33 = {
|
|
8380
8543
|
id: "asset.image.tac-raster",
|
|
8381
8544
|
name: "Image TAC (Raster)",
|
|
8382
8545
|
description: "Rasterizes and checks TAC per image using Ghostscript",
|
|
@@ -8395,7 +8558,7 @@ var check32 = {
|
|
|
8395
8558
|
const ghostscript = await resolveGhostscript();
|
|
8396
8559
|
if (!ghostscript) {
|
|
8397
8560
|
return [
|
|
8398
|
-
inspectionFailed(
|
|
8561
|
+
inspectionFailed(check33.id, "Could not inspect image ink coverage: Ghostscript executable not found")
|
|
8399
8562
|
];
|
|
8400
8563
|
}
|
|
8401
8564
|
for (const file of files) {
|
|
@@ -8413,7 +8576,7 @@ var check32 = {
|
|
|
8413
8576
|
if (nums.length === 4 && nums.every((n) => Number.isFinite(n))) {
|
|
8414
8577
|
const tac = (nums[0] + nums[1] + nums[2] + nums[3]) * 100;
|
|
8415
8578
|
if (tac > maxTac) {
|
|
8416
|
-
results.push(finding(
|
|
8579
|
+
results.push(finding(check33.id, {
|
|
8417
8580
|
severity: "warning",
|
|
8418
8581
|
message: `Image TAC exceeds limit: ${tac.toFixed(1)}% (max ${maxTac}%)`,
|
|
8419
8582
|
file,
|
|
@@ -8425,16 +8588,16 @@ var check32 = {
|
|
|
8425
8588
|
}
|
|
8426
8589
|
}
|
|
8427
8590
|
} catch {
|
|
8428
|
-
results.push(inspectionFailed(
|
|
8591
|
+
results.push(inspectionFailed(check33.id, `Could not inspect image ink coverage: ${file}`, { file }));
|
|
8429
8592
|
}
|
|
8430
8593
|
}
|
|
8431
8594
|
return results;
|
|
8432
8595
|
}
|
|
8433
8596
|
};
|
|
8434
|
-
registerCheck(
|
|
8597
|
+
registerCheck(check33);
|
|
8435
8598
|
|
|
8436
8599
|
// src/checks/asset/approved-fonts.ts
|
|
8437
|
-
var
|
|
8600
|
+
var check34 = {
|
|
8438
8601
|
id: "asset.font.approved-files",
|
|
8439
8602
|
name: "Approved Font Files",
|
|
8440
8603
|
description: "Checks font files against the approved file patterns",
|
|
@@ -8473,7 +8636,7 @@ var check33 = {
|
|
|
8473
8636
|
for (const font of allFonts) {
|
|
8474
8637
|
if (!approvedFonts.has(font)) {
|
|
8475
8638
|
results.push({
|
|
8476
|
-
checkId:
|
|
8639
|
+
checkId: check34.id,
|
|
8477
8640
|
severity: "warning",
|
|
8478
8641
|
message: "Font file not in approved list",
|
|
8479
8642
|
file: font
|
|
@@ -8483,7 +8646,7 @@ var check33 = {
|
|
|
8483
8646
|
return results;
|
|
8484
8647
|
}
|
|
8485
8648
|
};
|
|
8486
|
-
registerCheck(
|
|
8649
|
+
registerCheck(check34);
|
|
8487
8650
|
|
|
8488
8651
|
// src/checks/asset/font-license.ts
|
|
8489
8652
|
import { existsSync as existsSync10 } from "node:fs";
|
|
@@ -8498,7 +8661,7 @@ var LICENSE_NAMES = [
|
|
|
8498
8661
|
"OFL-1.1.txt",
|
|
8499
8662
|
"COPYING"
|
|
8500
8663
|
];
|
|
8501
|
-
var
|
|
8664
|
+
var check35 = {
|
|
8502
8665
|
id: "asset.font.license",
|
|
8503
8666
|
name: "Font License",
|
|
8504
8667
|
description: "Checks for license files in font directories",
|
|
@@ -8525,7 +8688,7 @@ var check34 = {
|
|
|
8525
8688
|
const hasLicense = LICENSE_NAMES.some((name) => existsSync10(resolve6(fontDir, name)));
|
|
8526
8689
|
if (!hasLicense) {
|
|
8527
8690
|
results.push({
|
|
8528
|
-
checkId:
|
|
8691
|
+
checkId: check35.id,
|
|
8529
8692
|
severity: "warning",
|
|
8530
8693
|
message: `No font license file found in directory`,
|
|
8531
8694
|
file: fontDir
|
|
@@ -8535,10 +8698,10 @@ var check34 = {
|
|
|
8535
8698
|
return results;
|
|
8536
8699
|
}
|
|
8537
8700
|
};
|
|
8538
|
-
registerCheck(
|
|
8701
|
+
registerCheck(check35);
|
|
8539
8702
|
|
|
8540
8703
|
// src/checks/heuristic/text-density.ts
|
|
8541
|
-
var
|
|
8704
|
+
var check36 = {
|
|
8542
8705
|
id: "heuristic.whitespace.text-density",
|
|
8543
8706
|
name: "Text Density",
|
|
8544
8707
|
description: "Checks characters-per-page ratio",
|
|
@@ -8567,7 +8730,7 @@ var check35 = {
|
|
|
8567
8730
|
});
|
|
8568
8731
|
if (lowPages.length > 0) {
|
|
8569
8732
|
results.push({
|
|
8570
|
-
checkId:
|
|
8733
|
+
checkId: check36.id,
|
|
8571
8734
|
severity: "info",
|
|
8572
8735
|
message: `Low text density on pages: ${lowPages.join(", ")} (below ${range.min} chars)`,
|
|
8573
8736
|
file: ctx.pdfPath
|
|
@@ -8575,7 +8738,7 @@ var check35 = {
|
|
|
8575
8738
|
}
|
|
8576
8739
|
if (highPages.length > 0) {
|
|
8577
8740
|
results.push({
|
|
8578
|
-
checkId:
|
|
8741
|
+
checkId: check36.id,
|
|
8579
8742
|
severity: "info",
|
|
8580
8743
|
message: `High text density on pages: ${highPages.join(", ")} (above ${range.max} chars)`,
|
|
8581
8744
|
file: ctx.pdfPath
|
|
@@ -8584,11 +8747,11 @@ var check35 = {
|
|
|
8584
8747
|
return results;
|
|
8585
8748
|
}
|
|
8586
8749
|
};
|
|
8587
|
-
registerCheck(
|
|
8750
|
+
registerCheck(check36);
|
|
8588
8751
|
|
|
8589
8752
|
// src/checks/heuristic/section-density.ts
|
|
8590
|
-
import { readFile as
|
|
8591
|
-
var
|
|
8753
|
+
import { readFile as readFile22 } from "node:fs/promises";
|
|
8754
|
+
var check37 = {
|
|
8592
8755
|
id: "heuristic.chunking.section-density",
|
|
8593
8756
|
name: "Section Density",
|
|
8594
8757
|
description: "Checks heading/paragraph/callout density from source Markdown",
|
|
@@ -8604,7 +8767,7 @@ var check36 = {
|
|
|
8604
8767
|
const results = [];
|
|
8605
8768
|
for (const file of files) {
|
|
8606
8769
|
try {
|
|
8607
|
-
const content = await
|
|
8770
|
+
const content = await readFile22(file, "utf8");
|
|
8608
8771
|
const lines = content.split(`
|
|
8609
8772
|
`);
|
|
8610
8773
|
let currentSectionStart = 0;
|
|
@@ -8614,7 +8777,7 @@ var check36 = {
|
|
|
8614
8777
|
const line = lines[i];
|
|
8615
8778
|
if (/^#{1,6}\s/.test(line)) {
|
|
8616
8779
|
if (paragraphCount > maxParas) {
|
|
8617
|
-
results.push(finding(
|
|
8780
|
+
results.push(finding(check37.id, {
|
|
8618
8781
|
severity: "info",
|
|
8619
8782
|
message: `Section has ${paragraphCount} paragraphs (max recommended: ${maxParas})`,
|
|
8620
8783
|
file,
|
|
@@ -8634,7 +8797,7 @@ var check36 = {
|
|
|
8634
8797
|
}
|
|
8635
8798
|
}
|
|
8636
8799
|
if (paragraphCount > maxParas) {
|
|
8637
|
-
results.push(finding(
|
|
8800
|
+
results.push(finding(check37.id, {
|
|
8638
8801
|
severity: "info",
|
|
8639
8802
|
message: `Section has ${paragraphCount} paragraphs (max recommended: ${maxParas})`,
|
|
8640
8803
|
file,
|
|
@@ -8642,7 +8805,7 @@ var check36 = {
|
|
|
8642
8805
|
}));
|
|
8643
8806
|
}
|
|
8644
8807
|
} catch {
|
|
8645
|
-
results.push(inspectionFailed(
|
|
8808
|
+
results.push(inspectionFailed(check37.id, `Could not read source file: ${file}`, {
|
|
8646
8809
|
file
|
|
8647
8810
|
}));
|
|
8648
8811
|
}
|
|
@@ -8650,10 +8813,10 @@ var check36 = {
|
|
|
8650
8813
|
return results;
|
|
8651
8814
|
}
|
|
8652
8815
|
};
|
|
8653
|
-
registerCheck(
|
|
8816
|
+
registerCheck(check37);
|
|
8654
8817
|
|
|
8655
8818
|
// src/checks/heuristic/layer-count.ts
|
|
8656
|
-
var
|
|
8819
|
+
var check38 = {
|
|
8657
8820
|
id: "heuristic.decoration.layer-count",
|
|
8658
8821
|
name: "Layer Count",
|
|
8659
8822
|
description: "Counts image objects per page",
|
|
@@ -8678,7 +8841,7 @@ var check37 = {
|
|
|
8678
8841
|
heavyPages.sort((a, b) => a - b);
|
|
8679
8842
|
return [
|
|
8680
8843
|
{
|
|
8681
|
-
checkId:
|
|
8844
|
+
checkId: check38.id,
|
|
8682
8845
|
severity: "info",
|
|
8683
8846
|
message: `Pages with many image layers (>${maxLayers}): ${heavyPages.join(", ")}`,
|
|
8684
8847
|
file: ctx.pdfPath
|
|
@@ -8688,10 +8851,10 @@ var check37 = {
|
|
|
8688
8851
|
return [];
|
|
8689
8852
|
}
|
|
8690
8853
|
};
|
|
8691
|
-
registerCheck(
|
|
8854
|
+
registerCheck(check38);
|
|
8692
8855
|
|
|
8693
8856
|
// src/checks/heuristic/placement-variance.ts
|
|
8694
|
-
var
|
|
8857
|
+
var check39 = {
|
|
8695
8858
|
id: "heuristic.layout.placement-variance",
|
|
8696
8859
|
name: "Placement Variance",
|
|
8697
8860
|
description: "Analyzes text baseline coordinates for layout consistency",
|
|
@@ -8709,7 +8872,7 @@ var check38 = {
|
|
|
8709
8872
|
const uniqueX = new Set(positions.map((p) => Math.round(p.x)));
|
|
8710
8873
|
return [
|
|
8711
8874
|
{
|
|
8712
|
-
checkId:
|
|
8875
|
+
checkId: check39.id,
|
|
8713
8876
|
severity: "info",
|
|
8714
8877
|
message: `Layout analysis: ${uniqueX.size} unique horizontal text positions across ${positions.length} text blocks.`,
|
|
8715
8878
|
file: ctx.pdfPath
|
|
@@ -8717,21 +8880,21 @@ var check38 = {
|
|
|
8717
8880
|
];
|
|
8718
8881
|
}
|
|
8719
8882
|
};
|
|
8720
|
-
registerCheck(
|
|
8883
|
+
registerCheck(check39);
|
|
8721
8884
|
|
|
8722
8885
|
// src/checks/tool-check.ts
|
|
8723
8886
|
async function checkToolAvailability(config, opts = {}) {
|
|
8724
8887
|
const { checks: checks2 } = selectChecks(opts, config);
|
|
8725
8888
|
const toolToChecks = new Map;
|
|
8726
|
-
for (const
|
|
8727
|
-
if (!
|
|
8889
|
+
for (const check40 of checks2) {
|
|
8890
|
+
if (!check40.requiredTools?.length)
|
|
8728
8891
|
continue;
|
|
8729
|
-
for (const tool of
|
|
8892
|
+
for (const tool of check40.requiredTools) {
|
|
8730
8893
|
const existing = toolToChecks.get(tool);
|
|
8731
8894
|
if (existing) {
|
|
8732
|
-
existing.push(
|
|
8895
|
+
existing.push(check40.id);
|
|
8733
8896
|
} else {
|
|
8734
|
-
toolToChecks.set(tool, [
|
|
8897
|
+
toolToChecks.set(tool, [check40.id]);
|
|
8735
8898
|
}
|
|
8736
8899
|
}
|
|
8737
8900
|
}
|
|
@@ -8747,11 +8910,11 @@ async function checkToolAvailability(config, opts = {}) {
|
|
|
8747
8910
|
const missing = results.filter((r) => !r.found).map((r) => r.tool);
|
|
8748
8911
|
const missingSet = new Set(missing);
|
|
8749
8912
|
const skippedChecks = [];
|
|
8750
|
-
for (const
|
|
8751
|
-
if (!
|
|
8913
|
+
for (const check40 of checks2) {
|
|
8914
|
+
if (!check40.requiredTools?.length)
|
|
8752
8915
|
continue;
|
|
8753
|
-
if (
|
|
8754
|
-
skippedChecks.push(
|
|
8916
|
+
if (check40.requiredTools.some((t) => missingSet.has(t))) {
|
|
8917
|
+
skippedChecks.push(check40.id);
|
|
8755
8918
|
}
|
|
8756
8919
|
}
|
|
8757
8920
|
return { available, missing, skippedChecks, toolToChecks };
|
|
@@ -8908,7 +9071,7 @@ async function restoreForCommand(dir, options) {
|
|
|
8908
9071
|
}
|
|
8909
9072
|
|
|
8910
9073
|
// src/lib/markdown/index.ts
|
|
8911
|
-
import { readdir as readdir3, readFile as
|
|
9074
|
+
import { readdir as readdir3, readFile as readFile23, writeFile as writeFile2, mkdir as mkdir4 } from "node:fs/promises";
|
|
8912
9075
|
|
|
8913
9076
|
// src/lib/remote-auth/sync-messages.ts
|
|
8914
9077
|
function isOnlineSibling(filepath) {
|
|
@@ -9050,7 +9213,7 @@ ${css.trim()}
|
|
|
9050
9213
|
}
|
|
9051
9214
|
return assembleBookHtml({
|
|
9052
9215
|
files,
|
|
9053
|
-
readText: (relPath) =>
|
|
9216
|
+
readText: (relPath) => readFile23(join2(inputDir, canonicalChapterId(relPath)), "utf-8"),
|
|
9054
9217
|
projectCss: inlined.css,
|
|
9055
9218
|
preloadImages: cssAssetCopies.map((c) => c.to),
|
|
9056
9219
|
title: opts.title,
|
|
@@ -9082,7 +9245,7 @@ async function renderChaptersToFile(inputDir, outDir, opts = {}) {
|
|
|
9082
9245
|
}
|
|
9083
9246
|
|
|
9084
9247
|
// src/lib/markdownlint-fix.ts
|
|
9085
|
-
import { readFile as
|
|
9248
|
+
import { readFile as readFile24, writeFile as writeFile3 } from "node:fs/promises";
|
|
9086
9249
|
import { applyFixes } from "markdownlint";
|
|
9087
9250
|
import { lint as lint2 } from "markdownlint/sync";
|
|
9088
9251
|
async function uncommittedAmong(inputDir, files) {
|
|
@@ -9122,7 +9285,7 @@ async function applyMarkdownlintFixes(ctx) {
|
|
|
9122
9285
|
for (const [file, violations] of Object.entries(results)) {
|
|
9123
9286
|
if (!Array.isArray(violations) || violations.length === 0)
|
|
9124
9287
|
continue;
|
|
9125
|
-
const before = await
|
|
9288
|
+
const before = await readFile24(file, "utf8");
|
|
9126
9289
|
const after = applyFixes(before, violations);
|
|
9127
9290
|
if (after !== before)
|
|
9128
9291
|
pending.push({ file, content: after });
|
|
@@ -9231,16 +9394,16 @@ async function runChecks(ctx, opts = {}) {
|
|
|
9231
9394
|
}
|
|
9232
9395
|
const release = retainPdfCache();
|
|
9233
9396
|
try {
|
|
9234
|
-
for (const
|
|
9397
|
+
for (const check40 of checks2) {
|
|
9235
9398
|
try {
|
|
9236
|
-
let results = await
|
|
9237
|
-
const severityOverride = getCheckSeverityOverride(
|
|
9399
|
+
let results = await check40.run(ctx);
|
|
9400
|
+
const severityOverride = getCheckSeverityOverride(check40.id, ctx.config);
|
|
9238
9401
|
if (severityOverride) {
|
|
9239
9402
|
for (const r of results) {
|
|
9240
9403
|
r.severity = severityOverride;
|
|
9241
9404
|
}
|
|
9242
9405
|
}
|
|
9243
|
-
const lintLevel = ruleLevel(ctx.config.lint.rules,
|
|
9406
|
+
const lintLevel = ruleLevel(ctx.config.lint.rules, check40.id);
|
|
9244
9407
|
if (lintLevel === "off")
|
|
9245
9408
|
results = [];
|
|
9246
9409
|
else if (lintLevel) {
|
|
@@ -9248,15 +9411,15 @@ async function runChecks(ctx, opts = {}) {
|
|
|
9248
9411
|
r.severity = lintLevel === "warn" ? "warning" : "error";
|
|
9249
9412
|
}
|
|
9250
9413
|
if (results.length === 0) {
|
|
9251
|
-
passed.push(
|
|
9414
|
+
passed.push(check40.id);
|
|
9252
9415
|
} else {
|
|
9253
9416
|
allResults.push(...results);
|
|
9254
9417
|
}
|
|
9255
9418
|
} catch (err) {
|
|
9256
9419
|
allResults.push({
|
|
9257
|
-
checkId:
|
|
9420
|
+
checkId: check40.id,
|
|
9258
9421
|
severity: "error",
|
|
9259
|
-
message: `Check "${
|
|
9422
|
+
message: `Check "${check40.id}" threw: ${err instanceof Error ? err.message : String(err)}`
|
|
9260
9423
|
});
|
|
9261
9424
|
}
|
|
9262
9425
|
}
|
|
@@ -9548,7 +9711,7 @@ async function executeValidation(args) {
|
|
|
9548
9711
|
};
|
|
9549
9712
|
if (args.fix) {
|
|
9550
9713
|
const selected = selectChecks(runnerOptions, config).checks;
|
|
9551
|
-
if (selected.some((
|
|
9714
|
+
if (selected.some((check40) => check40.id === MARKDOWNLINT_CHECK_ID)) {
|
|
9552
9715
|
await applyMarkdownlintFixes(context);
|
|
9553
9716
|
} else {
|
|
9554
9717
|
log.warn(`--fix: ${MARKDOWNLINT_CHECK_ID} is not part of this run — no files were fixed.`);
|
|
@@ -9635,7 +9798,7 @@ import { randomBytes } from "node:crypto";
|
|
|
9635
9798
|
|
|
9636
9799
|
// src/lib/build-fingerprint.ts
|
|
9637
9800
|
import * as fs from "node:fs";
|
|
9638
|
-
import { mkdir as mkdir5, readFile as
|
|
9801
|
+
import { mkdir as mkdir5, readFile as readFile25, writeFile as writeFile4 } from "node:fs/promises";
|
|
9639
9802
|
import { createHash as createHash4 } from "node:crypto";
|
|
9640
9803
|
import path12 from "node:path";
|
|
9641
9804
|
import git from "isomorphic-git";
|
|
@@ -9722,8 +9885,8 @@ async function getEngineBundleHash() {
|
|
|
9722
9885
|
getAssetPath("engine/gutterpress-agent.js")
|
|
9723
9886
|
]);
|
|
9724
9887
|
const [viewerBytes, agentBytes] = await Promise.all([
|
|
9725
|
-
|
|
9726
|
-
|
|
9888
|
+
readFile25(viewerPath),
|
|
9889
|
+
readFile25(agentPath)
|
|
9727
9890
|
]);
|
|
9728
9891
|
const hash = createHash4("sha256");
|
|
9729
9892
|
hash.update(viewerBytes);
|
|
@@ -10232,7 +10395,7 @@ function openPath(filePath) {
|
|
|
10232
10395
|
import path16 from "path";
|
|
10233
10396
|
import { tmpdir } from "os";
|
|
10234
10397
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
10235
|
-
import { readdir as readdir4, readFile as
|
|
10398
|
+
import { readdir as readdir4, readFile as readFile26, writeFile as writeFile5 } from "node:fs/promises";
|
|
10236
10399
|
|
|
10237
10400
|
// src/utils/file-utils.ts
|
|
10238
10401
|
import { promises as fs3 } from "fs";
|
|
@@ -10784,7 +10947,7 @@ async function cleanupOrphanTempDirs() {
|
|
|
10784
10947
|
const dir = path16.join(TEMP_DIR_BASE, entry);
|
|
10785
10948
|
const pidFile = path16.join(dir, PID_FILE_NAME);
|
|
10786
10949
|
try {
|
|
10787
|
-
const raw = await
|
|
10950
|
+
const raw = await readFile26(pidFile, "utf8");
|
|
10788
10951
|
const pid = parseInt(raw.trim(), 10);
|
|
10789
10952
|
if (!isProcessAlive(pid)) {
|
|
10790
10953
|
debug(`Removing orphan temp dir ${dir} (pid ${pid} not alive)`);
|
|
@@ -10891,7 +11054,7 @@ function createServerState(inputPath, tempDir, config, options) {
|
|
|
10891
11054
|
import http from "node:http";
|
|
10892
11055
|
import net from "node:net";
|
|
10893
11056
|
import { createHash as createHash5, randomUUID as randomUUID3 } from "node:crypto";
|
|
10894
|
-
import { readFile as
|
|
11057
|
+
import { readFile as readFile27, stat as stat5 } from "node:fs/promises";
|
|
10895
11058
|
import path17 from "path";
|
|
10896
11059
|
import { WebSocket, WebSocketServer } from "ws";
|
|
10897
11060
|
var HMR_PATH = "/__gutterpress-hmr";
|
|
@@ -10960,7 +11123,7 @@ async function serveStatic(absPath, res, cacheControl = "no-store", extraHeaders
|
|
|
10960
11123
|
}
|
|
10961
11124
|
let data;
|
|
10962
11125
|
try {
|
|
10963
|
-
data = await
|
|
11126
|
+
data = await readFile27(filePath);
|
|
10964
11127
|
} catch {
|
|
10965
11128
|
res.writeHead(404);
|
|
10966
11129
|
res.end("Not Found");
|
|
@@ -11009,7 +11172,7 @@ async function serveRevalidatedStatic(req, absPath, res, validators) {
|
|
|
11009
11172
|
let data;
|
|
11010
11173
|
if (!validator || validator.stamp !== stamp) {
|
|
11011
11174
|
try {
|
|
11012
|
-
data = await
|
|
11175
|
+
data = await readFile27(absPath);
|
|
11013
11176
|
} catch {
|
|
11014
11177
|
await serveStatic(absPath, res);
|
|
11015
11178
|
return;
|
|
@@ -11319,7 +11482,7 @@ async function startPreviewServer(options) {
|
|
|
11319
11482
|
}
|
|
11320
11483
|
|
|
11321
11484
|
// src/lib/project-scaffold.ts
|
|
11322
|
-
import { access, copyFile, cp as cp2, mkdir as mkdir7, readdir as readdir5, readFile as
|
|
11485
|
+
import { access, copyFile, cp as cp2, mkdir as mkdir7, readdir as readdir5, readFile as readFile28, stat as stat6, writeFile as writeFile6 } from "node:fs/promises";
|
|
11323
11486
|
import { constants as FS, existsSync as existsSync12 } from "node:fs";
|
|
11324
11487
|
import path18 from "node:path";
|
|
11325
11488
|
|
|
@@ -11518,7 +11681,7 @@ async function scaffoldProject(options) {
|
|
|
11518
11681
|
async function firstSourceFile(manifestPath) {
|
|
11519
11682
|
let text;
|
|
11520
11683
|
try {
|
|
11521
|
-
text = await
|
|
11684
|
+
text = await readFile28(manifestPath, "utf8");
|
|
11522
11685
|
} catch {
|
|
11523
11686
|
return;
|
|
11524
11687
|
}
|
|
@@ -11530,7 +11693,7 @@ async function firstSourceFile(manifestPath) {
|
|
|
11530
11693
|
return m ? m[1].trim() : undefined;
|
|
11531
11694
|
}
|
|
11532
11695
|
async function fillTemplateFile(filePath, substitutions) {
|
|
11533
|
-
let text = await
|
|
11696
|
+
let text = await readFile28(filePath, "utf8");
|
|
11534
11697
|
for (const [token, value] of Object.entries(substitutions)) {
|
|
11535
11698
|
text = text.split(token).join(value);
|
|
11536
11699
|
}
|
|
@@ -11538,7 +11701,7 @@ async function fillTemplateFile(filePath, substitutions) {
|
|
|
11538
11701
|
}
|
|
11539
11702
|
|
|
11540
11703
|
// src/lib/extension-scaffold.ts
|
|
11541
|
-
import { access as access2, mkdir as mkdir8, readFile as
|
|
11704
|
+
import { access as access2, mkdir as mkdir8, readFile as readFile29, writeFile as writeFile7 } from "node:fs/promises";
|
|
11542
11705
|
import { constants as FS2 } from "node:fs";
|
|
11543
11706
|
import path19 from "node:path";
|
|
11544
11707
|
var EXTENSION_KINDS = ["plugin", "theme"];
|
|
@@ -11655,7 +11818,7 @@ async function scaffoldExtension(options) {
|
|
|
11655
11818
|
const src = await getAssetPath(`extension-templates/${kind}/${assetName}`);
|
|
11656
11819
|
const dest = path19.join(extensionDir, relDest);
|
|
11657
11820
|
await mkdir8(path19.dirname(dest), { recursive: true });
|
|
11658
|
-
const text = await
|
|
11821
|
+
const text = await readFile29(src, "utf8");
|
|
11659
11822
|
const table = relDest.endsWith(".json") ? jsonSafe : plain;
|
|
11660
11823
|
await writeFile7(dest, substitute(text, table), "utf8");
|
|
11661
11824
|
written.push(relDest);
|
|
@@ -11700,7 +11863,7 @@ var SKIP_ENTRIES = new Set([
|
|
|
11700
11863
|
|
|
11701
11864
|
// src/lib/extension-import.ts
|
|
11702
11865
|
import { existsSync as existsSync13 } from "node:fs";
|
|
11703
|
-
import { cp as cp3, mkdir as mkdir9, mkdtemp as mkdtemp2, readFile as
|
|
11866
|
+
import { cp as cp3, mkdir as mkdir9, mkdtemp as mkdtemp2, readFile as readFile30, rm as rm4, writeFile as writeFile8 } from "node:fs/promises";
|
|
11704
11867
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
11705
11868
|
import path20 from "node:path";
|
|
11706
11869
|
import { unzipSync } from "fflate";
|
|
@@ -11773,7 +11936,7 @@ async function finalizeExtensionImport(projectDir, sourceDir, relPaths, fallback
|
|
|
11773
11936
|
if (!existsSync13(cssPath)) {
|
|
11774
11937
|
throw new Error("A theme must contain a theme.css file.");
|
|
11775
11938
|
}
|
|
11776
|
-
const css = await
|
|
11939
|
+
const css = await readFile30(cssPath, "utf8");
|
|
11777
11940
|
const { reject, warnings: printFindings } = classifyThemeCssFindings(checkCss(css, "theme.css"));
|
|
11778
11941
|
if (reject) {
|
|
11779
11942
|
throw new Error(`theme.css could not be parsed — ${reject.message}`);
|
|
@@ -11801,7 +11964,7 @@ async function finalizeExtensionImport(projectDir, sourceDir, relPaths, fallback
|
|
|
11801
11964
|
for (let i = 0;i < extraSheets.length; i++) {
|
|
11802
11965
|
const rel = extraSheets[i];
|
|
11803
11966
|
const sheetPath = extraSheetPaths[i];
|
|
11804
|
-
const sheetCss = await
|
|
11967
|
+
const sheetCss = await readFile30(sheetPath, "utf8");
|
|
11805
11968
|
const { reject: sheetReject, warnings: sheetFindings } = classifyThemeCssFindings(checkCss(sheetCss, rel));
|
|
11806
11969
|
if (sheetReject) {
|
|
11807
11970
|
throw new Error(`${rel} could not be parsed — ${sheetReject.message}`);
|
|
@@ -11834,7 +11997,7 @@ async function completeLandedManifest(dest, id, meta, metaExists) {
|
|
|
11834
11997
|
let pkg = {};
|
|
11835
11998
|
if (metaExists) {
|
|
11836
11999
|
try {
|
|
11837
|
-
const parsed = JSON.parse(await
|
|
12000
|
+
const parsed = JSON.parse(await readFile30(file, "utf8"));
|
|
11838
12001
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
11839
12002
|
pkg = parsed;
|
|
11840
12003
|
}
|
|
@@ -11936,11 +12099,11 @@ async function importExtensionFromCssText(projectDir, css, name) {
|
|
|
11936
12099
|
async function importExtensionFromFile(projectDir, filePath) {
|
|
11937
12100
|
const ext = path20.extname(filePath).toLowerCase();
|
|
11938
12101
|
if (ext === ".zip") {
|
|
11939
|
-
const buf = await
|
|
12102
|
+
const buf = await readFile30(filePath);
|
|
11940
12103
|
return importExtensionFromZip(projectDir, new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength));
|
|
11941
12104
|
}
|
|
11942
12105
|
if (ext === ".css") {
|
|
11943
|
-
const css = await
|
|
12106
|
+
const css = await readFile30(filePath, "utf8");
|
|
11944
12107
|
return importExtensionFromCssText(projectDir, css, prettify(path20.basename(filePath, ".css")));
|
|
11945
12108
|
}
|
|
11946
12109
|
throw new Error("Choose a .zip extension package or a .css stylesheet.");
|
|
@@ -12144,13 +12307,13 @@ function publishCredentialKey(host, account) {
|
|
|
12144
12307
|
const a = (account ?? "").trim();
|
|
12145
12308
|
return a ? `${host}#${a}` : host;
|
|
12146
12309
|
}
|
|
12147
|
-
async function resolvePublishCredential(
|
|
12310
|
+
async function resolvePublishCredential(info3, deps, account = deps.credentialAccount) {
|
|
12148
12311
|
const env = deps.env ?? process.env;
|
|
12149
|
-
const fromEnv =
|
|
12312
|
+
const fromEnv = info3.credential.envVar ? env[info3.credential.envVar]?.trim() : undefined;
|
|
12150
12313
|
if (fromEnv) {
|
|
12151
12314
|
return {
|
|
12152
12315
|
credential: {
|
|
12153
|
-
host:
|
|
12316
|
+
host: info3.credential.host,
|
|
12154
12317
|
kind: "token",
|
|
12155
12318
|
token: fromEnv,
|
|
12156
12319
|
createdAt: 0
|
|
@@ -12158,21 +12321,21 @@ async function resolvePublishCredential(info2, deps, account = deps.credentialAc
|
|
|
12158
12321
|
source: "env"
|
|
12159
12322
|
};
|
|
12160
12323
|
}
|
|
12161
|
-
const stored = await deps.tokenStore.get(publishCredentialKey(
|
|
12324
|
+
const stored = await deps.tokenStore.get(publishCredentialKey(info3.credential.host, account));
|
|
12162
12325
|
return stored ? { credential: stored, source: "store" } : null;
|
|
12163
12326
|
}
|
|
12164
|
-
async function publishConnectionStatus(
|
|
12165
|
-
if (!
|
|
12327
|
+
async function publishConnectionStatus(info3, deps, account = deps.credentialAccount) {
|
|
12328
|
+
if (!info3.credential.required)
|
|
12166
12329
|
return { connected: true };
|
|
12167
|
-
const resolved = await resolvePublishCredential(
|
|
12330
|
+
const resolved = await resolvePublishCredential(info3, deps, account);
|
|
12168
12331
|
return resolved ? { connected: true, source: resolved.source } : { connected: false };
|
|
12169
12332
|
}
|
|
12170
|
-
async function listPublishAccounts(
|
|
12171
|
-
const wantHost =
|
|
12333
|
+
async function listPublishAccounts(info3, deps) {
|
|
12334
|
+
const wantHost = info3.credential.host.trim().toLowerCase();
|
|
12172
12335
|
const all = await deps.tokenStore.list();
|
|
12173
12336
|
return all.filter((c) => c.host.trim().toLowerCase() === wantHost).map((c) => ({
|
|
12174
12337
|
account: (c.username ?? "").trim(),
|
|
12175
|
-
label: c.label ?? (c.username ||
|
|
12338
|
+
label: c.label ?? (c.username || info3.label),
|
|
12176
12339
|
createdAt: c.createdAt
|
|
12177
12340
|
}));
|
|
12178
12341
|
}
|
|
@@ -12203,8 +12366,8 @@ async function readGoogleApiError(res) {
|
|
|
12203
12366
|
}
|
|
12204
12367
|
var RATE_LIMIT_REASONS = /^(dailyLimitExceeded|userRateLimitExceeded|rateLimitExceeded|quotaExceeded)$/i;
|
|
12205
12368
|
var PERMISSION_REASONS = /^(insufficientPermissions|insufficientFilePermissions|forbidden|PERMISSION_DENIED)$/i;
|
|
12206
|
-
function hintFor(
|
|
12207
|
-
const reason =
|
|
12369
|
+
function hintFor(info3) {
|
|
12370
|
+
const reason = info3.reason ?? "";
|
|
12208
12371
|
if (/^accessNotConfigured$/i.test(reason)) {
|
|
12209
12372
|
return "Google Drive publishing isn't fully set up on this build: the Google Drive API isn't enabled for the app's Google Cloud project, so a maintainer needs to enable it (the link is in Google's message).";
|
|
12210
12373
|
}
|
|
@@ -12214,18 +12377,18 @@ function hintFor(info2) {
|
|
|
12214
12377
|
if (RATE_LIMIT_REASONS.test(reason)) {
|
|
12215
12378
|
return "Google Drive is rate-limiting requests right now. Wait a minute and try again.";
|
|
12216
12379
|
}
|
|
12217
|
-
if (PERMISSION_REASONS.test(reason) ||
|
|
12380
|
+
if (PERMISSION_REASONS.test(reason) || info3.status === 401) {
|
|
12218
12381
|
return "This Google Drive connection doesn't have permission for that — disconnect and connect Google Drive again to re-approve access.";
|
|
12219
12382
|
}
|
|
12220
12383
|
return;
|
|
12221
12384
|
}
|
|
12222
|
-
function googleApiFailure(what,
|
|
12223
|
-
const parts = [`${what} (HTTP ${
|
|
12224
|
-
const hint = hintFor(
|
|
12385
|
+
function googleApiFailure(what, info3) {
|
|
12386
|
+
const parts = [`${what} (HTTP ${info3.status}${info3.reason ? `, ${info3.reason}` : ""}).`];
|
|
12387
|
+
const hint = hintFor(info3);
|
|
12225
12388
|
if (hint)
|
|
12226
12389
|
parts.push(hint);
|
|
12227
|
-
if (
|
|
12228
|
-
parts.push(`Google said: "${
|
|
12390
|
+
if (info3.message)
|
|
12391
|
+
parts.push(`Google said: "${info3.message}"`);
|
|
12229
12392
|
let text = parts.join(" ");
|
|
12230
12393
|
if (!/\bgoogle\b/i.test(text))
|
|
12231
12394
|
text = `Google Drive: ${text}`;
|
|
@@ -12553,7 +12716,7 @@ async function commandExists(cmd, runCommand = defaultCommandRunner, env) {
|
|
|
12553
12716
|
|
|
12554
12717
|
// src/lib/publish/providers/azure-swa.ts
|
|
12555
12718
|
var AZURE_SWA_HOST = "azure-swa";
|
|
12556
|
-
var
|
|
12719
|
+
var info3 = {
|
|
12557
12720
|
id: "azure-swa",
|
|
12558
12721
|
label: "Azure Static Web Apps",
|
|
12559
12722
|
kind: "api",
|
|
@@ -12578,9 +12741,9 @@ async function resolveSwaCommand(req) {
|
|
|
12578
12741
|
}
|
|
12579
12742
|
var SWA_INSTALL_HINT = "Install the Azure SWA CLI first: `npm install -g @azure/static-web-apps-cli` " + "(needs Node.js), or set SWA_CLI_PATH to the swa binary.";
|
|
12580
12743
|
var azureSwaProvider = {
|
|
12581
|
-
info:
|
|
12744
|
+
info: info3,
|
|
12582
12745
|
async authenticate(req) {
|
|
12583
|
-
const resolved = await resolvePublishCredential(
|
|
12746
|
+
const resolved = await resolvePublishCredential(info3, req.deps);
|
|
12584
12747
|
if (!resolved) {
|
|
12585
12748
|
return {
|
|
12586
12749
|
ok: false,
|
|
@@ -12611,7 +12774,7 @@ var azureSwaProvider = {
|
|
|
12611
12774
|
return issues;
|
|
12612
12775
|
},
|
|
12613
12776
|
async upload(req) {
|
|
12614
|
-
const resolved = await resolvePublishCredential(
|
|
12777
|
+
const resolved = await resolvePublishCredential(info3, req.deps);
|
|
12615
12778
|
if (!resolved) {
|
|
12616
12779
|
throw new Error("No Azure deployment token found. Connect Azure Static Web Apps (or set SWA_CLI_DEPLOYMENT_TOKEN) first.");
|
|
12617
12780
|
}
|
|
@@ -12667,7 +12830,7 @@ async function stageGuidedPackage(req, providerId, listingLines) {
|
|
|
12667
12830
|
|
|
12668
12831
|
// src/lib/publish/providers/drivethrurpg.ts
|
|
12669
12832
|
var PUBLISHER_HUB_URL = "https://www.drivethrurpg.com/publisher_hub";
|
|
12670
|
-
var
|
|
12833
|
+
var info4 = {
|
|
12671
12834
|
id: "drivethrurpg",
|
|
12672
12835
|
label: "DriveThruRPG",
|
|
12673
12836
|
kind: "guided",
|
|
@@ -12683,7 +12846,7 @@ var info3 = {
|
|
|
12683
12846
|
credential: { required: false, host: "drivethrurpg.com" }
|
|
12684
12847
|
};
|
|
12685
12848
|
var drivethrurpgProvider = {
|
|
12686
|
-
info:
|
|
12849
|
+
info: info4,
|
|
12687
12850
|
async authenticate() {
|
|
12688
12851
|
return { ok: true };
|
|
12689
12852
|
},
|
|
@@ -12724,7 +12887,7 @@ var drivethrurpgProvider = {
|
|
|
12724
12887
|
};
|
|
12725
12888
|
|
|
12726
12889
|
// src/lib/publish/providers/gdrive.ts
|
|
12727
|
-
import { mkdtemp as mkdtemp3, readFile as
|
|
12890
|
+
import { mkdtemp as mkdtemp3, readFile as readFile31, readdir as readdir6, rm as rm5, stat as stat7, writeFile as writeFile10 } from "node:fs/promises";
|
|
12728
12891
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
12729
12892
|
import path22 from "node:path";
|
|
12730
12893
|
import { Zip, ZipDeflate } from "fflate";
|
|
@@ -12992,7 +13155,7 @@ async function resumableUpload(fetchImpl, accessToken, opts) {
|
|
|
12992
13155
|
// src/lib/publish/providers/gdrive.ts
|
|
12993
13156
|
var DEFAULT_FOLDER_NAME = "Gutterpress";
|
|
12994
13157
|
var NOT_CONNECTED_MESSAGE = "Google Drive isn't connected. Run `gutterpress publish --provider gdrive --connect` (or set GDRIVE_REFRESH_TOKEN) first.";
|
|
12995
|
-
var
|
|
13158
|
+
var info5 = {
|
|
12996
13159
|
id: "gdrive",
|
|
12997
13160
|
label: "Google Drive",
|
|
12998
13161
|
kind: "api",
|
|
@@ -13031,7 +13194,7 @@ async function mintAccessToken(resolved, fetchImpl) {
|
|
|
13031
13194
|
return accessToken;
|
|
13032
13195
|
}
|
|
13033
13196
|
async function getAccessToken(req) {
|
|
13034
|
-
const resolved = await resolvePublishCredential(
|
|
13197
|
+
const resolved = await resolvePublishCredential(info5, req.deps);
|
|
13035
13198
|
if (!resolved)
|
|
13036
13199
|
throw new Error(NOT_CONNECTED_MESSAGE);
|
|
13037
13200
|
const accessToken = await mintAccessToken(resolved, req.deps.fetch ?? globalThis.fetch);
|
|
@@ -13116,12 +13279,12 @@ async function collectZipEntries(root, dir, out, onWarn) {
|
|
|
13116
13279
|
await collectZipEntries(root, full, out, onWarn);
|
|
13117
13280
|
} else if (entry.isFile()) {
|
|
13118
13281
|
const rel = path22.relative(root, full).split(path22.sep).join("/");
|
|
13119
|
-
out[rel] = await
|
|
13282
|
+
out[rel] = await readFile31(full);
|
|
13120
13283
|
} else if (entry.isSymbolicLink()) {
|
|
13121
13284
|
const resolved = await stat7(full).catch(() => null);
|
|
13122
13285
|
if (resolved?.isFile()) {
|
|
13123
13286
|
const rel = path22.relative(root, full).split(path22.sep).join("/");
|
|
13124
|
-
out[rel] = await
|
|
13287
|
+
out[rel] = await readFile31(full);
|
|
13125
13288
|
} else if (resolved?.isDirectory()) {
|
|
13126
13289
|
await collectZipEntries(root, full, out, onWarn);
|
|
13127
13290
|
} else {
|
|
@@ -13153,9 +13316,9 @@ async function zipHtmlExport(exportDir, title, onWarn, writeArchiveImpl = writeF
|
|
|
13153
13316
|
}
|
|
13154
13317
|
}
|
|
13155
13318
|
var gdriveProvider = {
|
|
13156
|
-
info:
|
|
13319
|
+
info: info5,
|
|
13157
13320
|
async authenticate(req) {
|
|
13158
|
-
const resolved = await resolvePublishCredential(
|
|
13321
|
+
const resolved = await resolvePublishCredential(info5, req.deps);
|
|
13159
13322
|
if (!resolved)
|
|
13160
13323
|
return { ok: false, message: NOT_CONNECTED_MESSAGE };
|
|
13161
13324
|
try {
|
|
@@ -13320,7 +13483,7 @@ async function ensureButler(deps) {
|
|
|
13320
13483
|
var ITCH_HOST = "itch.io";
|
|
13321
13484
|
var TARGET_RE = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
|
|
13322
13485
|
var ITCH_API_TIMEOUT_MS = 15000;
|
|
13323
|
-
var
|
|
13486
|
+
var info6 = {
|
|
13324
13487
|
id: "itch",
|
|
13325
13488
|
label: "itch.io",
|
|
13326
13489
|
kind: "api",
|
|
@@ -13350,9 +13513,9 @@ function itchProjectUrl(target) {
|
|
|
13350
13513
|
return `https://${user}.itch.io/${game}`;
|
|
13351
13514
|
}
|
|
13352
13515
|
var itchProvider = {
|
|
13353
|
-
info:
|
|
13516
|
+
info: info6,
|
|
13354
13517
|
async authenticate(req) {
|
|
13355
|
-
const resolved = await resolvePublishCredential(
|
|
13518
|
+
const resolved = await resolvePublishCredential(info6, req.deps);
|
|
13356
13519
|
if (!resolved) {
|
|
13357
13520
|
return {
|
|
13358
13521
|
ok: false,
|
|
@@ -13420,7 +13583,7 @@ var itchProvider = {
|
|
|
13420
13583
|
},
|
|
13421
13584
|
async upload(req) {
|
|
13422
13585
|
const { target, channel } = readConfig2(req);
|
|
13423
|
-
const resolved = await resolvePublishCredential(
|
|
13586
|
+
const resolved = await resolvePublishCredential(info6, req.deps);
|
|
13424
13587
|
if (!resolved) {
|
|
13425
13588
|
throw new Error("No itch.io API key found. Connect itch.io (or set BUTLER_API_KEY) first.");
|
|
13426
13589
|
}
|
|
@@ -13448,7 +13611,7 @@ ${tail}` : ""}`);
|
|
|
13448
13611
|
|
|
13449
13612
|
// src/lib/publish/providers/kdp.ts
|
|
13450
13613
|
var KDP_URL = "https://kdp.amazon.com/en_US/bookshelf";
|
|
13451
|
-
var
|
|
13614
|
+
var info7 = {
|
|
13452
13615
|
id: "kdp",
|
|
13453
13616
|
label: "Amazon KDP",
|
|
13454
13617
|
kind: "guided",
|
|
@@ -13458,7 +13621,7 @@ var info6 = {
|
|
|
13458
13621
|
credential: { required: false, host: "kdp.amazon.com" }
|
|
13459
13622
|
};
|
|
13460
13623
|
var kdpProvider = {
|
|
13461
|
-
info:
|
|
13624
|
+
info: info7,
|
|
13462
13625
|
async authenticate() {
|
|
13463
13626
|
return { ok: true };
|
|
13464
13627
|
},
|
|
@@ -13503,7 +13666,7 @@ var kdpProvider = {
|
|
|
13503
13666
|
import { cp as cp4, mkdir as mkdir12, stat as stat9 } from "node:fs/promises";
|
|
13504
13667
|
import path24 from "node:path";
|
|
13505
13668
|
var LOCAL_PUBLISH_DEFAULT_DIR = "dist";
|
|
13506
|
-
var
|
|
13669
|
+
var info8 = {
|
|
13507
13670
|
id: "local",
|
|
13508
13671
|
label: "A folder on this computer",
|
|
13509
13672
|
kind: "api",
|
|
@@ -13520,7 +13683,7 @@ function localPublishDir(req) {
|
|
|
13520
13683
|
return path24.resolve(req.project.projectDir, dir);
|
|
13521
13684
|
}
|
|
13522
13685
|
var localFolderProvider = {
|
|
13523
|
-
info:
|
|
13686
|
+
info: info8,
|
|
13524
13687
|
async authenticate() {
|
|
13525
13688
|
return { ok: true };
|
|
13526
13689
|
},
|
|
@@ -13561,7 +13724,7 @@ function requireValidShop(shop) {
|
|
|
13561
13724
|
}
|
|
13562
13725
|
return shop;
|
|
13563
13726
|
}
|
|
13564
|
-
var
|
|
13727
|
+
var info9 = {
|
|
13565
13728
|
id: "shopify",
|
|
13566
13729
|
label: "Shopify",
|
|
13567
13730
|
kind: "api",
|
|
@@ -13595,7 +13758,7 @@ function readConfig3(req) {
|
|
|
13595
13758
|
async function adminGraphQL(req, query, variables = {}) {
|
|
13596
13759
|
const { shop: rawShop, apiVersion } = readConfig3(req);
|
|
13597
13760
|
const shop = requireValidShop(rawShop);
|
|
13598
|
-
const resolved = await resolvePublishCredential(
|
|
13761
|
+
const resolved = await resolvePublishCredential(info9, req.deps);
|
|
13599
13762
|
if (!resolved) {
|
|
13600
13763
|
throw new Error("No Shopify access token found. Connect Shopify (or set SHOPIFY_ADMIN_TOKEN) first.");
|
|
13601
13764
|
}
|
|
@@ -13646,9 +13809,9 @@ function userErrorsToMessage(result) {
|
|
|
13646
13809
|
return errs?.length ? errs[0].message : null;
|
|
13647
13810
|
}
|
|
13648
13811
|
var shopifyProvider = {
|
|
13649
|
-
info:
|
|
13812
|
+
info: info9,
|
|
13650
13813
|
async authenticate(req) {
|
|
13651
|
-
const resolved = await resolvePublishCredential(
|
|
13814
|
+
const resolved = await resolvePublishCredential(info9, req.deps);
|
|
13652
13815
|
if (!resolved) {
|
|
13653
13816
|
return {
|
|
13654
13817
|
ok: false,
|
|
@@ -13784,14 +13947,14 @@ function publishProviderFor(id) {
|
|
|
13784
13947
|
// src/lib/publish/run-publish.ts
|
|
13785
13948
|
import { readdir as readdir7, stat as stat10 } from "node:fs/promises";
|
|
13786
13949
|
import path25 from "node:path";
|
|
13787
|
-
function resolvePublishFormat(
|
|
13788
|
-
if (
|
|
13950
|
+
function resolvePublishFormat(info10, providerConfig) {
|
|
13951
|
+
if (info10.formats && info10.formats.length > 0) {
|
|
13789
13952
|
const configured = typeof providerConfig.format === "string" ? providerConfig.format.trim() : "";
|
|
13790
|
-
if (configured &&
|
|
13953
|
+
if (configured && info10.formats.includes(configured)) {
|
|
13791
13954
|
return configured;
|
|
13792
13955
|
}
|
|
13793
13956
|
}
|
|
13794
|
-
return
|
|
13957
|
+
return info10.format;
|
|
13795
13958
|
}
|
|
13796
13959
|
async function resolvePublishRequest(options, deps) {
|
|
13797
13960
|
const provider = publishProviderFor(options.providerId);
|
|
@@ -13941,17 +14104,17 @@ function overlayStore(inner, key, candidate) {
|
|
|
13941
14104
|
}
|
|
13942
14105
|
async function connectPublishProvider(options, deps) {
|
|
13943
14106
|
const provider = publishProviderFor(options.providerId);
|
|
13944
|
-
const
|
|
13945
|
-
if (!
|
|
13946
|
-
throw new Error(`${
|
|
14107
|
+
const info10 = provider.info;
|
|
14108
|
+
if (!info10.credential.required) {
|
|
14109
|
+
throw new Error(`${info10.label} needs no API key — just publish when you're ready.`);
|
|
13947
14110
|
}
|
|
13948
|
-
if (
|
|
13949
|
-
throw new Error(`${
|
|
14111
|
+
if (info10.credential.connect === "oauth") {
|
|
14112
|
+
throw new Error(`${info10.label} connects through your browser, not a pasted key — run ` + `"gutterpress publish --provider ${info10.id} --connect" or use the desktop app's Connect button.`);
|
|
13950
14113
|
}
|
|
13951
14114
|
const token = options.token.trim();
|
|
13952
14115
|
if (!token)
|
|
13953
14116
|
throw new Error("Paste an API key first.");
|
|
13954
|
-
const host =
|
|
14117
|
+
const host = info10.credential.host;
|
|
13955
14118
|
const account = (options.account ?? "").trim();
|
|
13956
14119
|
const key = publishCredentialKey(host, account);
|
|
13957
14120
|
const candidate = {
|
|
@@ -13959,12 +14122,12 @@ async function connectPublishProvider(options, deps) {
|
|
|
13959
14122
|
kind: "token",
|
|
13960
14123
|
token,
|
|
13961
14124
|
...account ? { username: account } : {},
|
|
13962
|
-
label: account ||
|
|
14125
|
+
label: account || info10.label,
|
|
13963
14126
|
createdAt: Date.now()
|
|
13964
14127
|
};
|
|
13965
14128
|
const req = await resolvePublishRequest({
|
|
13966
14129
|
projectDir: options.projectDir,
|
|
13967
|
-
providerId:
|
|
14130
|
+
providerId: info10.id,
|
|
13968
14131
|
...options.manifestPath ? { manifestPath: options.manifestPath } : {}
|
|
13969
14132
|
}, deps);
|
|
13970
14133
|
const trialDeps = {
|
|
@@ -13975,10 +14138,10 @@ async function connectPublishProvider(options, deps) {
|
|
|
13975
14138
|
};
|
|
13976
14139
|
const auth = await provider.authenticate({ ...req, deps: trialDeps });
|
|
13977
14140
|
if (!auth.ok) {
|
|
13978
|
-
throw new Error(auth.message ?? `${
|
|
14141
|
+
throw new Error(auth.message ?? `${info10.label} didn't accept that key.`);
|
|
13979
14142
|
}
|
|
13980
14143
|
await deps.tokenStore.set(key, candidate);
|
|
13981
|
-
return { connected: true, providerId:
|
|
14144
|
+
return { connected: true, providerId: info10.id };
|
|
13982
14145
|
}
|
|
13983
14146
|
async function disconnectPublishCredential(key, deps, options = {}) {
|
|
13984
14147
|
const existing = await deps.tokenStore.get(key);
|
|
@@ -14108,7 +14271,7 @@ import git8 from "isomorphic-git";
|
|
|
14108
14271
|
// src/lib/remote-auth/scorched-earth.ts
|
|
14109
14272
|
import git9 from "isomorphic-git";
|
|
14110
14273
|
// src/lib/publish/selections.ts
|
|
14111
|
-
import { chmod as chmod2, mkdir as mkdir13, readFile as
|
|
14274
|
+
import { chmod as chmod2, mkdir as mkdir13, readFile as readFile32, writeFile as writeFile12 } from "node:fs/promises";
|
|
14112
14275
|
import path26 from "node:path";
|
|
14113
14276
|
class PublishSelectionsStore {
|
|
14114
14277
|
filePath;
|
|
@@ -14118,7 +14281,7 @@ class PublishSelectionsStore {
|
|
|
14118
14281
|
}
|
|
14119
14282
|
async read() {
|
|
14120
14283
|
try {
|
|
14121
|
-
const raw = await
|
|
14284
|
+
const raw = await readFile32(this.filePath, "utf8");
|
|
14122
14285
|
const parsed = JSON.parse(raw);
|
|
14123
14286
|
if (parsed && typeof parsed === "object") {
|
|
14124
14287
|
return {
|