gutterpress 0.0.0 → 0.9.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +21 -16
  2. package/dist/api/index.d.ts +6 -2
  3. package/dist/api/index.js +15 -3
  4. package/dist/{audit-1jrwwacz.js → audit-nhn2pjz3.js} +5 -5
  5. package/dist/{build-5s92kgpc.js → build-san7fv2z.js} +5 -5
  6. package/dist/checks/types.d.ts +6 -0
  7. package/dist/{cli-hvqjs342.js → cli-e5zhb0xs.js} +2 -2
  8. package/dist/{cli-7ykx7pp0.js → cli-k4bd06sd.js} +982 -331
  9. package/dist/{cli-h7phg3ka.js → cli-najycadg.js} +258 -258
  10. package/dist/{index-1tyj4bk3.js → cli-wchtvxvw.js} +4 -1
  11. package/dist/{cli-5bxx0c4y.js → cli-yzrh708h.js} +2 -2
  12. package/dist/cli.js +15 -15
  13. package/dist/{doctor-25zjt8dz.js → doctor-hrk0kxxz.js} +2 -2
  14. package/dist/{index-3h3fef7r.js → index-bynn850m.js} +1200 -410
  15. package/dist/{cli-1tyj4bk3.js → index-wchtvxvw.js} +4 -1
  16. package/dist/{index-5bxx0c4y.js → index-yzrh708h.js} +2 -2
  17. package/dist/index.js +15 -3
  18. package/dist/lib/asset-inline.d.ts +19 -0
  19. package/dist/lib/build-error.d.ts +0 -1
  20. package/dist/lib/build-fingerprint.d.ts +14 -0
  21. package/dist/lib/build-runner.d.ts +21 -1
  22. package/dist/lib/ghostscript.d.ts +0 -9
  23. package/dist/lib/manifest-config.d.ts +7 -0
  24. package/dist/lib/manifest.d.ts +8 -0
  25. package/dist/lib/markdown/assemble.d.ts +4 -6
  26. package/dist/lib/markdown/chapter-id.d.ts +1 -1
  27. package/dist/lib/markdown/index.d.ts +1 -2
  28. package/dist/lib/npm-plugin-installer.d.ts +1 -1
  29. package/dist/lib/output-paths.d.ts +0 -1
  30. package/dist/lib/pagination.d.ts +0 -20
  31. package/dist/lib/pdf-inspect.d.ts +2 -2
  32. package/dist/lib/pdf-parse.d.ts +2 -1
  33. package/dist/lib/plugin-manager.d.ts +0 -2
  34. package/dist/lib/presets.d.ts +36 -7
  35. package/dist/lib/project-scaffold.d.ts +39 -2
  36. package/dist/lib/project-source.d.ts +11 -9
  37. package/dist/lib/project-templates.d.ts +45 -7
  38. package/dist/lib/publish/providers/azure-swa.d.ts +0 -1
  39. package/dist/lib/publish/providers/itch.d.ts +0 -1
  40. package/dist/lib/publish/providers/shopify.d.ts +0 -1
  41. package/dist/lib/remote-auth/github-repos.d.ts +0 -2
  42. package/dist/lib/remote-auth/recovery/dispatch.d.ts +0 -5
  43. package/dist/lib/remote-auth/recovery/outcome-mapping.d.ts +3 -2
  44. package/dist/lib/remote-auth/recovery/recover-stale-lock.d.ts +0 -8
  45. package/dist/lib/remote-auth/sync.d.ts +2 -10
  46. package/dist/lib/remote-auth/test-access.d.ts +0 -2
  47. package/dist/lib/remote-auth/test-support/git-http-server.d.ts +0 -37
  48. package/dist/lib/source-provider.d.ts +0 -14
  49. package/dist/lib/static-serve.d.ts +39 -0
  50. package/dist/lib/style-resolver.d.ts +10 -1
  51. package/dist/lib/targets.d.ts +84 -0
  52. package/dist/lib/theme-import.d.ts +0 -2
  53. package/dist/lib/theme-manager.d.ts +1 -1
  54. package/dist/lib/validation-exec.d.ts +4 -3
  55. package/dist/{lint-f63nxjfj.js → lint-96j9hrj4.js} +5 -5
  56. package/dist/{manifest.schema-rn1dpdpn.json → manifest.schema-z61rzw44.json} +12 -6
  57. package/dist/new-8p38wavc.js +185 -0
  58. package/dist/{pagedjs-interface-80g3xa8p.js → pagedjs-interface-qxvzgwd7.js} +92 -33
  59. package/dist/{plugin-wf2cbmwc.js → plugin-ees6nhkc.js} +5 -5
  60. package/dist/{preflight-tg4mpz1h.js → preflight-1q6c2edh.js} +24 -29
  61. package/dist/preview/file-watcher.d.ts +48 -39
  62. package/dist/preview/http-server.d.ts +5 -2
  63. package/dist/preview/server-context.d.ts +24 -0
  64. package/dist/preview-shell-6dqexx1m.js +581 -0
  65. package/dist/{preview-h2bwbb2x.js → preview-y5a2zen1.js} +5 -5
  66. package/dist/{project-source-0tg0r6vm.js → project-source-p0gn1wd5.js} +3 -3
  67. package/dist/{publish-ztaet53r.js → publish-rm9yb3wh.js} +5 -5
  68. package/dist/render.js +10 -19
  69. package/dist/{repair-jkp4n3j8.js → repair-zgq7q2g6.js} +5 -5
  70. package/dist/schema/manifest.types.d.ts +14 -3
  71. package/dist/server.d.ts +2 -0
  72. package/dist/{source-provider-hp96b5jf.js → source-provider-c1rjm2c0.js} +2 -8
  73. package/dist/types.d.ts +0 -1
  74. package/dist/{validate-k2drs19j.js → validate-nr0xa6sa.js} +8 -8
  75. package/package.json +2 -2
  76. package/dist/chapter-01-jj8ftn4c.md +0 -29
  77. package/dist/lib/validation-profile.d.ts +0 -18
  78. package/dist/manifest-ryyg71nf.yaml +0 -9
  79. package/dist/new-7b08a42h.js +0 -105
  80. package/dist/preview-shell-rghtfmc8.js +0 -155
  81. package/dist/theme-0yzvthe8.css +0 -65
  82. package/dist/theme-6a2fngc8.json +0 -6
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "./cli-hvqjs342.js";
3
+ } from "./cli-e5zhb0xs.js";
4
4
  import {
5
5
  __require
6
6
  } from "./cli-37x76zdn.js";
@@ -67,156 +67,6 @@ var log = {
67
67
  }
68
68
  };
69
69
 
70
- // src/lib/remote-auth/token-store.ts
71
- import { chmod, mkdir, readFile, rename, writeFile } from "node:fs/promises";
72
- import os from "node:os";
73
- import path from "node:path";
74
- function credentialHostKey(hostOrUrl) {
75
- const trimmed = String(hostOrUrl ?? "").trim();
76
- if (!trimmed)
77
- return "";
78
- const scp = /^[\w.-]+@([\w.][\w.-]*):/.exec(trimmed);
79
- if (scp)
80
- return stripWww(scp[1].toLowerCase());
81
- const candidate = /^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
82
- try {
83
- const url = new URL(candidate);
84
- if (!url.hostname)
85
- return "";
86
- const host = url.port ? `${url.hostname}:${url.port}`.toLowerCase() : url.hostname.toLowerCase();
87
- return stripWww(host);
88
- } catch {
89
- return "";
90
- }
91
- }
92
- function stripWww(host) {
93
- return host.startsWith("www.") && host.length > 4 ? host.slice(4) : host;
94
- }
95
- function defaultConfigDir() {
96
- const override = process.env.GUTTERPRESS_CONFIG_DIR?.trim();
97
- if (override)
98
- return override;
99
- if (process.platform === "win32" && process.env.APPDATA) {
100
- return path.join(process.env.APPDATA, "gutterpress");
101
- }
102
- const xdg = process.env.XDG_CONFIG_HOME?.trim();
103
- return path.join(xdg || path.join(os.homedir(), ".config"), "gutterpress");
104
- }
105
-
106
- class FileTokenStore {
107
- filePath;
108
- queue = Promise.resolve();
109
- constructor(filePath) {
110
- this.filePath = filePath ?? path.join(defaultConfigDir(), "credentials.json");
111
- }
112
- async read() {
113
- let raw;
114
- try {
115
- raw = await readFile(this.filePath, "utf8");
116
- } catch (e) {
117
- if (e?.code === "ENOENT") {
118
- return { version: 1, credentials: {} };
119
- }
120
- throw e;
121
- }
122
- try {
123
- const parsed = JSON.parse(raw);
124
- if (parsed && typeof parsed === "object" && parsed.credentials)
125
- return parsed;
126
- } catch {
127
- await writeFile(`${this.filePath}.corrupt`, raw, {
128
- encoding: "utf8",
129
- mode: 384
130
- }).catch(() => {});
131
- }
132
- return { version: 1, credentials: {} };
133
- }
134
- async write(data) {
135
- await mkdir(path.dirname(this.filePath), { recursive: true });
136
- const tmpPath = `${this.filePath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
137
- await writeFile(tmpPath, JSON.stringify(data, null, 2), {
138
- encoding: "utf8",
139
- mode: 384
140
- });
141
- await rename(tmpPath, this.filePath);
142
- await chmod(this.filePath, 384);
143
- }
144
- enqueue(fn) {
145
- const run = this.queue.then(fn, fn);
146
- this.queue = run.catch(() => {
147
- return;
148
- });
149
- return run;
150
- }
151
- get(host) {
152
- return this.enqueue(async () => {
153
- try {
154
- const data = await this.read();
155
- return data.credentials[normalizeHost(host)] ?? null;
156
- } catch {
157
- return null;
158
- }
159
- });
160
- }
161
- set(host, credential) {
162
- return this.enqueue(async () => {
163
- const data = await this.read();
164
- data.credentials[normalizeHost(host)] = credential;
165
- await this.write(data);
166
- });
167
- }
168
- delete(host) {
169
- return this.enqueue(async () => {
170
- const data = await this.read();
171
- delete data.credentials[normalizeHost(host)];
172
- await this.write(data);
173
- });
174
- }
175
- list() {
176
- return this.enqueue(async () => {
177
- try {
178
- const data = await this.read();
179
- return Object.values(data.credentials);
180
- } catch {
181
- return [];
182
- }
183
- });
184
- }
185
- }
186
- function normalizeHost(host) {
187
- return host.trim().toLowerCase();
188
- }
189
- function extractUrlCredential(url) {
190
- let parsed;
191
- try {
192
- parsed = new URL(url);
193
- } catch {
194
- return { cleanUrl: url };
195
- }
196
- if (!/^https?:$/.test(parsed.protocol))
197
- return { cleanUrl: url };
198
- if (!parsed.username && !parsed.password)
199
- return { cleanUrl: url };
200
- const token = parsed.password ? decodeURIComponent(parsed.password) : decodeURIComponent(parsed.username);
201
- const username = parsed.password ? decodeURIComponent(parsed.username) : undefined;
202
- parsed.username = "";
203
- parsed.password = "";
204
- const credential = {
205
- host: credentialHostKey(parsed.toString()),
206
- kind: "token",
207
- token,
208
- ...username ? { username } : {},
209
- createdAt: Date.now()
210
- };
211
- return { cleanUrl: parsed.toString(), credential };
212
- }
213
-
214
- // src/lib/diagnostics.ts
215
- import { platform as platform2, arch, release } from "node:os";
216
-
217
- // src/lib/chromium.ts
218
- import { existsSync } from "node:fs";
219
-
220
70
  // src/lib/tool-probe.ts
221
71
  import { platform } from "node:os";
222
72
 
@@ -356,107 +206,9 @@ async function findTool(tool) {
356
206
  }
357
207
  }
358
208
 
359
- // src/lib/install-hints.ts
360
- var INSTALL_HINTS = {
361
- chromium: {
362
- label: "Google Chrome, Chromium, or Microsoft Edge",
363
- body: ` macOS: brew install --cask google-chrome
364
- ` + ` Ubuntu: sudo apt install -y chromium-browser
365
- ` + " Windows: https://www.google.com/chrome/ (Edge is auto-detected if pre-installed)"
366
- },
367
- gs: {
368
- label: "Ghostscript",
369
- body: ` macOS: brew install ghostscript
370
- ` + ` Ubuntu: sudo apt install -y ghostscript
371
- ` + " Windows: https://www.ghostscript.com/releases/gsdnld.html (standard installs are auto-detected; or: choco install ghostscript)"
372
- },
373
- qpdf: {
374
- label: "qpdf",
375
- body: ` macOS: brew install qpdf
376
- ` + ` Ubuntu: sudo apt install -y qpdf
377
- ` + " Windows: choco install qpdf (or: https://github.com/qpdf/qpdf/releases)"
378
- }
379
- };
380
- function fullInstallHint(tool) {
381
- const hint = INSTALL_HINTS[tool];
382
- return `Install ${hint.label}:
383
- ${hint.body}`;
384
- }
385
-
386
- // src/lib/chromium.ts
387
- var SYSTEM_PATHS = [
388
- process.env.CHROMIUM_PATH,
389
- process.env.PUPPETEER_EXECUTABLE_PATH,
390
- "/usr/bin/google-chrome",
391
- "/usr/bin/google-chrome-stable",
392
- "/usr/bin/chromium",
393
- "/usr/bin/chromium-browser",
394
- "/snap/bin/chromium",
395
- "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
396
- "/Applications/Chromium.app/Contents/MacOS/Chromium",
397
- "/opt/homebrew/bin/chromium",
398
- "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
399
- "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
400
- "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
401
- "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
402
- process.env.LOCALAPPDATA ? `${process.env.LOCALAPPDATA}\\Google\\Chrome\\Application\\chrome.exe` : undefined,
403
- "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
404
- "C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe",
405
- process.env.LOCALAPPDATA ? `${process.env.LOCALAPPDATA}\\Microsoft\\Edge\\Application\\msedge.exe` : undefined,
406
- process.env.LOCALAPPDATA ? `${process.env.LOCALAPPDATA}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe` : undefined
407
- ].filter(Boolean);
408
- var PATH_CANDIDATES = [
409
- "google-chrome",
410
- "google-chrome-stable",
411
- "chromium",
412
- "chromium-browser",
413
- "chrome",
414
- "chrome.exe",
415
- "msedge",
416
- "msedge.exe",
417
- "brave",
418
- "brave-browser",
419
- "brave.exe",
420
- "vivaldi",
421
- "vivaldi-stable",
422
- "vivaldi.exe",
423
- "opera",
424
- "opera-stable",
425
- "opera.exe"
426
- ];
427
- async function resolveChromiumExecutable() {
428
- for (const candidate of SYSTEM_PATHS) {
429
- if (existsSync(candidate))
430
- return candidate;
431
- }
432
- for (const candidate of PATH_CANDIDATES) {
433
- const found = await findTool(candidate);
434
- if (found)
435
- return found;
436
- }
437
- return;
438
- }
439
- async function requireChromiumExecutable() {
440
- const found = await resolveChromiumExecutable();
441
- if (found)
442
- return found;
443
- throw new Error([
444
- "No Chrome / Chromium / Edge binary found. Gutterpress needs a Chromium-based browser to render PDFs.",
445
- "",
446
- "Install one of:",
447
- INSTALL_HINTS.chromium.body,
448
- "",
449
- "Or point to an existing install:",
450
- " CHROMIUM_PATH=/path/to/chrome gutterpress build ...",
451
- "",
452
- "The Gutterpress desktop app includes its own browser and needs no separate browser installation."
453
- ].join(`
454
- `));
455
- }
456
-
457
209
  // src/lib/ghostscript.ts
458
- import { existsSync as existsSync2 } from "node:fs";
459
- import { readFile as readFile2, writeFile as writeFile2, unlink, rename as rename2, readdir } from "node:fs/promises";
210
+ import { existsSync } from "node:fs";
211
+ import { readFile, writeFile, unlink, rename, readdir } from "node:fs/promises";
460
212
  import { join as join2, basename, resolve } from "node:path";
461
213
  var WINDOWS_GHOSTSCRIPT_NAMES = ["gswin64c", "gswin32c", "gs"];
462
214
  var POSIX_GHOSTSCRIPT_NAMES = ["gs"];
@@ -490,7 +242,7 @@ async function findWindowsGhostscriptInstall(env) {
490
242
  for (const version of versions) {
491
243
  for (const executable of ["gswin64c.exe", "gswin32c.exe"]) {
492
244
  const candidate = join2(installRoot, version.name, "bin", executable);
493
- if (existsSync2(candidate))
245
+ if (existsSync(candidate))
494
246
  return candidate;
495
247
  }
496
248
  }
@@ -499,7 +251,7 @@ async function findWindowsGhostscriptInstall(env) {
499
251
  }
500
252
  async function resolveGhostscript(targetPlatform = process.platform, env = process.env) {
501
253
  const override = envValue(env, "GHOSTSCRIPT_PATH");
502
- if (override && existsSync2(override))
254
+ if (override && existsSync(override))
503
255
  return override;
504
256
  const names = targetPlatform === "win32" ? WINDOWS_GHOSTSCRIPT_NAMES : POSIX_GHOSTSCRIPT_NAMES;
505
257
  for (const name of names) {
@@ -513,7 +265,7 @@ async function stripAnnotations(pdfPath, stagingDir) {
513
265
  const tmp = join2(stagingDir, "annotations-stripped.pdf");
514
266
  try {
515
267
  await run("qpdf", [pdfPath, tmp, "--flatten-annotations=all"]);
516
- await rename2(tmp, pdfPath);
268
+ await rename(tmp, pdfPath);
517
269
  } finally {
518
270
  await unlink(tmp).catch(() => {});
519
271
  }
@@ -585,11 +337,11 @@ ${docInfoConformance}/DOCINFO pdfmark
585
337
  }
586
338
  async function stampCreator(pdfPath) {
587
339
  const { PDFDocument } = await import("pdf-lib");
588
- const bytes = await readFile2(pdfPath);
340
+ const bytes = await readFile(pdfPath);
589
341
  const doc = await PDFDocument.load(bytes, { updateMetadata: false });
590
342
  doc.setCreator("gutterpress");
591
343
  const out = await doc.save();
592
- await writeFile2(pdfPath, out);
344
+ await writeFile(pdfPath, out);
593
345
  }
594
346
  async function convertToPdfxCmyk(inputPdf, outPdf, config) {
595
347
  const iccPath = resolve(config.iccPath);
@@ -618,7 +370,7 @@ async function convertToPdfxCmyk(inputPdf, outPdf, config) {
618
370
  inputPdf
619
371
  ];
620
372
  try {
621
- await writeFile2(tmpDef, makePdfxDefPs({
373
+ await writeFile(tmpDef, makePdfxDefPs({
622
374
  iccPath,
623
375
  pdfx: config.pdfx,
624
376
  title: config.title ?? basename(outPdf),
@@ -634,6 +386,254 @@ async function convertToPdfxCmyk(inputPdf, outPdf, config) {
634
386
  }
635
387
  }
636
388
 
389
+ // src/lib/remote-auth/token-store.ts
390
+ import { chmod, mkdir, readFile as readFile2, rename as rename2, writeFile as writeFile2 } from "node:fs/promises";
391
+ import os from "node:os";
392
+ import path from "node:path";
393
+ function credentialHostKey(hostOrUrl) {
394
+ const trimmed = String(hostOrUrl ?? "").trim();
395
+ if (!trimmed)
396
+ return "";
397
+ const scp = /^[\w.-]+@([\w.][\w.-]*):/.exec(trimmed);
398
+ if (scp)
399
+ return stripWww(scp[1].toLowerCase());
400
+ const candidate = /^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
401
+ try {
402
+ const url = new URL(candidate);
403
+ if (!url.hostname)
404
+ return "";
405
+ const host = url.port ? `${url.hostname}:${url.port}`.toLowerCase() : url.hostname.toLowerCase();
406
+ return stripWww(host);
407
+ } catch {
408
+ return "";
409
+ }
410
+ }
411
+ function stripWww(host) {
412
+ return host.startsWith("www.") && host.length > 4 ? host.slice(4) : host;
413
+ }
414
+ function defaultConfigDir() {
415
+ const override = process.env.GUTTERPRESS_CONFIG_DIR?.trim();
416
+ if (override)
417
+ return override;
418
+ if (process.platform === "win32" && process.env.APPDATA) {
419
+ return path.join(process.env.APPDATA, "gutterpress");
420
+ }
421
+ const xdg = process.env.XDG_CONFIG_HOME?.trim();
422
+ return path.join(xdg || path.join(os.homedir(), ".config"), "gutterpress");
423
+ }
424
+
425
+ class FileTokenStore {
426
+ filePath;
427
+ queue = Promise.resolve();
428
+ constructor(filePath) {
429
+ this.filePath = filePath ?? path.join(defaultConfigDir(), "credentials.json");
430
+ }
431
+ async read() {
432
+ let raw;
433
+ try {
434
+ raw = await readFile2(this.filePath, "utf8");
435
+ } catch (e) {
436
+ if (e?.code === "ENOENT") {
437
+ return { version: 1, credentials: {} };
438
+ }
439
+ throw e;
440
+ }
441
+ try {
442
+ const parsed = JSON.parse(raw);
443
+ if (parsed && typeof parsed === "object" && parsed.credentials)
444
+ return parsed;
445
+ } catch {
446
+ await writeFile2(`${this.filePath}.corrupt`, raw, {
447
+ encoding: "utf8",
448
+ mode: 384
449
+ }).catch(() => {});
450
+ }
451
+ return { version: 1, credentials: {} };
452
+ }
453
+ async write(data) {
454
+ await mkdir(path.dirname(this.filePath), { recursive: true });
455
+ const tmpPath = `${this.filePath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
456
+ await writeFile2(tmpPath, JSON.stringify(data, null, 2), {
457
+ encoding: "utf8",
458
+ mode: 384
459
+ });
460
+ await rename2(tmpPath, this.filePath);
461
+ await chmod(this.filePath, 384);
462
+ }
463
+ enqueue(fn) {
464
+ const run2 = this.queue.then(fn, fn);
465
+ this.queue = run2.catch(() => {
466
+ return;
467
+ });
468
+ return run2;
469
+ }
470
+ get(host) {
471
+ return this.enqueue(async () => {
472
+ try {
473
+ const data = await this.read();
474
+ return data.credentials[normalizeHost(host)] ?? null;
475
+ } catch {
476
+ return null;
477
+ }
478
+ });
479
+ }
480
+ set(host, credential) {
481
+ return this.enqueue(async () => {
482
+ const data = await this.read();
483
+ data.credentials[normalizeHost(host)] = credential;
484
+ await this.write(data);
485
+ });
486
+ }
487
+ delete(host) {
488
+ return this.enqueue(async () => {
489
+ const data = await this.read();
490
+ delete data.credentials[normalizeHost(host)];
491
+ await this.write(data);
492
+ });
493
+ }
494
+ list() {
495
+ return this.enqueue(async () => {
496
+ try {
497
+ const data = await this.read();
498
+ return Object.values(data.credentials);
499
+ } catch {
500
+ return [];
501
+ }
502
+ });
503
+ }
504
+ }
505
+ function normalizeHost(host) {
506
+ return host.trim().toLowerCase();
507
+ }
508
+ function extractUrlCredential(url) {
509
+ let parsed;
510
+ try {
511
+ parsed = new URL(url);
512
+ } catch {
513
+ return { cleanUrl: url };
514
+ }
515
+ if (!/^https?:$/.test(parsed.protocol))
516
+ return { cleanUrl: url };
517
+ if (!parsed.username && !parsed.password)
518
+ return { cleanUrl: url };
519
+ const token = parsed.password ? decodeURIComponent(parsed.password) : decodeURIComponent(parsed.username);
520
+ const username = parsed.password ? decodeURIComponent(parsed.username) : undefined;
521
+ parsed.username = "";
522
+ parsed.password = "";
523
+ const credential = {
524
+ host: credentialHostKey(parsed.toString()),
525
+ kind: "token",
526
+ token,
527
+ ...username ? { username } : {},
528
+ createdAt: Date.now()
529
+ };
530
+ return { cleanUrl: parsed.toString(), credential };
531
+ }
532
+
533
+ // src/lib/diagnostics.ts
534
+ import { platform as platform2, arch, release } from "node:os";
535
+
536
+ // src/lib/chromium.ts
537
+ import { existsSync as existsSync2 } from "node:fs";
538
+
539
+ // src/lib/install-hints.ts
540
+ var INSTALL_HINTS = {
541
+ chromium: {
542
+ label: "Google Chrome, Chromium, or Microsoft Edge",
543
+ body: ` macOS: brew install --cask google-chrome
544
+ ` + ` Ubuntu: sudo apt install -y chromium-browser
545
+ ` + " Windows: https://www.google.com/chrome/ (Edge is auto-detected if pre-installed)"
546
+ },
547
+ gs: {
548
+ label: "Ghostscript",
549
+ body: ` macOS: brew install ghostscript
550
+ ` + ` Ubuntu: sudo apt install -y ghostscript
551
+ ` + " Windows: https://www.ghostscript.com/releases/gsdnld.html (standard installs are auto-detected; or: choco install ghostscript)"
552
+ },
553
+ qpdf: {
554
+ label: "qpdf",
555
+ body: ` macOS: brew install qpdf
556
+ ` + ` Ubuntu: sudo apt install -y qpdf
557
+ ` + " Windows: choco install qpdf (or: https://github.com/qpdf/qpdf/releases)"
558
+ }
559
+ };
560
+ function fullInstallHint(tool) {
561
+ const hint = INSTALL_HINTS[tool];
562
+ return `Install ${hint.label}:
563
+ ${hint.body}`;
564
+ }
565
+
566
+ // src/lib/chromium.ts
567
+ var SYSTEM_PATHS = [
568
+ process.env.CHROMIUM_PATH,
569
+ process.env.PUPPETEER_EXECUTABLE_PATH,
570
+ "/usr/bin/google-chrome",
571
+ "/usr/bin/google-chrome-stable",
572
+ "/usr/bin/chromium",
573
+ "/usr/bin/chromium-browser",
574
+ "/snap/bin/chromium",
575
+ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
576
+ "/Applications/Chromium.app/Contents/MacOS/Chromium",
577
+ "/opt/homebrew/bin/chromium",
578
+ "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
579
+ "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
580
+ "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
581
+ "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
582
+ process.env.LOCALAPPDATA ? `${process.env.LOCALAPPDATA}\\Google\\Chrome\\Application\\chrome.exe` : undefined,
583
+ "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
584
+ "C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe",
585
+ process.env.LOCALAPPDATA ? `${process.env.LOCALAPPDATA}\\Microsoft\\Edge\\Application\\msedge.exe` : undefined,
586
+ process.env.LOCALAPPDATA ? `${process.env.LOCALAPPDATA}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe` : undefined
587
+ ].filter(Boolean);
588
+ var PATH_CANDIDATES = [
589
+ "google-chrome",
590
+ "google-chrome-stable",
591
+ "chromium",
592
+ "chromium-browser",
593
+ "chrome",
594
+ "chrome.exe",
595
+ "msedge",
596
+ "msedge.exe",
597
+ "brave",
598
+ "brave-browser",
599
+ "brave.exe",
600
+ "vivaldi",
601
+ "vivaldi-stable",
602
+ "vivaldi.exe",
603
+ "opera",
604
+ "opera-stable",
605
+ "opera.exe"
606
+ ];
607
+ async function resolveChromiumExecutable() {
608
+ for (const candidate of SYSTEM_PATHS) {
609
+ if (existsSync2(candidate))
610
+ return candidate;
611
+ }
612
+ for (const candidate of PATH_CANDIDATES) {
613
+ const found = await findTool(candidate);
614
+ if (found)
615
+ return found;
616
+ }
617
+ return;
618
+ }
619
+ async function requireChromiumExecutable() {
620
+ const found = await resolveChromiumExecutable();
621
+ if (found)
622
+ return found;
623
+ throw new Error([
624
+ "No Chrome / Chromium / Edge binary found. Gutterpress needs a Chromium-based browser to render PDFs.",
625
+ "",
626
+ "Install one of:",
627
+ INSTALL_HINTS.chromium.body,
628
+ "",
629
+ "Or point to an existing install:",
630
+ " CHROMIUM_PATH=/path/to/chrome gutterpress build ...",
631
+ "",
632
+ "The Gutterpress desktop app includes its own browser and needs no separate browser installation."
633
+ ].join(`
634
+ `));
635
+ }
636
+
637
637
  // src/lib/version.ts
638
638
  var PACKAGE_META = {
639
639
  version: package_default.version ?? "unknown",
@@ -739,7 +739,7 @@ async function getSystemDiagnostics() {
739
739
  },
740
740
  tools: [chromium, ...tools],
741
741
  configDir: defaultConfigDir(),
742
- docsUrl: "https://github.com/dimm-city/gutterpress/blob/main/examples/gutterpress-user-guide/08-system-setup.md"
742
+ docsUrl: "https://github.com/dimm-city/gutterpress/blob/main/examples/gutterpress-user-guide/07-system-setup.md"
743
743
  };
744
744
  }
745
745
 
@@ -86,6 +86,9 @@ async function detectProjectSource(folderPath) {
86
86
  }
87
87
  return { type: "local-folder", path: folderPath };
88
88
  }
89
+ function repoRootForSource(source, fallbackDir) {
90
+ return source.type === "local-git-folder" ? source.repoRoot || fallbackDir : fallbackDir;
91
+ }
89
92
  function capabilitiesFor(source) {
90
93
  switch (source.type) {
91
94
  case "local-folder":
@@ -121,4 +124,4 @@ function capabilitiesFor(source) {
121
124
  }
122
125
  }
123
126
 
124
- export { pickSyncRemote, syncRemoteFor, findEnclosingRepoDir, repoSubPath, detectProjectSource, capabilitiesFor };
127
+ export { syncRemoteFor, findEnclosingRepoDir, repoSubPath, detectProjectSource, repoRootForSource, capabilitiesFor };
@@ -2,7 +2,7 @@ import {
2
2
  capabilitiesFor,
3
3
  detectProjectSource,
4
4
  findEnclosingRepoDir
5
- } from "./cli-1tyj4bk3.js";
5
+ } from "./cli-wchtvxvw.js";
6
6
 
7
7
  // src/lib/source-provider.ts
8
8
  import * as fs from "node:fs";
@@ -461,4 +461,4 @@ async function restoreVersionWithBackup(options) {
461
461
  });
462
462
  }
463
463
 
464
- export { resolveLogger, shortOid, gitScopeFor, HISTORY_PAGE_LIMIT, SNAPSHOT_STAGING_MARKER, withRepoLock, __repoLockQueueSizeForTests, gitAuthor, readGitAuthor, resolveGitAuthor, listWorkdirChanges, stageChanges, hasPendingChanges, hasUncommittedChanges, snapshotWorkingTreeUnlocked, isNoChangesError, providerFor, gitDirFor, snapshotStagingMarkerPath, RESTORE_BACKUP_MESSAGE, AUTO_SNAPSHOT_MESSAGE, restoreVersionWithBackup };
464
+ export { resolveLogger, shortOid, gitScopeFor, HISTORY_PAGE_LIMIT, withRepoLock, __repoLockQueueSizeForTests, resolveGitAuthor, listWorkdirChanges, stageChanges, hasPendingChanges, hasUncommittedChanges, snapshotWorkingTreeUnlocked, isNoChangesError, providerFor, gitDirFor, snapshotStagingMarkerPath, RESTORE_BACKUP_MESSAGE, AUTO_SNAPSHOT_MESSAGE, restoreVersionWithBackup };
package/dist/cli.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  UsageError,
8
8
  package_default,
9
9
  rejectUnknownFlags
10
- } from "./cli-hvqjs342.js";
10
+ } from "./cli-e5zhb0xs.js";
11
11
  import {
12
12
  __require
13
13
  } from "./cli-37x76zdn.js";
@@ -16,17 +16,17 @@ import {
16
16
  import { defineCommand, parseArgs, runMain } from "citty";
17
17
  import { statSync } from "node:fs";
18
18
  var SUBCOMMANDS = {
19
- new: () => import("./new-7b08a42h.js").then((m) => m.default),
20
- preview: () => import("./preview-h2bwbb2x.js").then((m) => m.default),
21
- build: () => import("./build-5s92kgpc.js").then((m) => m.default),
22
- publish: () => import("./publish-ztaet53r.js").then((m) => m.default),
23
- lint: () => import("./lint-f63nxjfj.js").then((m) => m.default),
24
- validate: () => import("./validate-k2drs19j.js").then((m) => m.default),
25
- audit: () => import("./audit-1jrwwacz.js").then((m) => m.default),
26
- preflight: () => import("./preflight-tg4mpz1h.js").then((m) => m.default),
27
- repair: () => import("./repair-jkp4n3j8.js").then((m) => m.default),
28
- doctor: () => import("./doctor-25zjt8dz.js").then((m) => m.default),
29
- plugin: () => import("./plugin-wf2cbmwc.js").then((m) => m.default)
19
+ new: () => import("./new-8p38wavc.js").then((m) => m.default),
20
+ preview: () => import("./preview-y5a2zen1.js").then((m) => m.default),
21
+ build: () => import("./build-san7fv2z.js").then((m) => m.default),
22
+ publish: () => import("./publish-rm9yb3wh.js").then((m) => m.default),
23
+ lint: () => import("./lint-96j9hrj4.js").then((m) => m.default),
24
+ validate: () => import("./validate-nr0xa6sa.js").then((m) => m.default),
25
+ audit: () => import("./audit-nhn2pjz3.js").then((m) => m.default),
26
+ preflight: () => import("./preflight-1q6c2edh.js").then((m) => m.default),
27
+ repair: () => import("./repair-zgq7q2g6.js").then((m) => m.default),
28
+ doctor: () => import("./doctor-hrk0kxxz.js").then((m) => m.default),
29
+ plugin: () => import("./plugin-ees6nhkc.js").then((m) => m.default)
30
30
  };
31
31
  var VERSION = package_default.version;
32
32
  var main = defineCommand({
@@ -51,7 +51,7 @@ async function preflightRequiredInvocations(rawArgs) {
51
51
  const [command, ...commandArgs] = rawArgs;
52
52
  try {
53
53
  if (command === "new") {
54
- const { newArgs } = await import("./new-7b08a42h.js");
54
+ const { newArgs } = await import("./new-8p38wavc.js");
55
55
  rejectUnknownFlags(commandArgs, newArgs, "new");
56
56
  const parsed2 = parseArgs(commandArgs, {
57
57
  ...newArgs,
@@ -63,7 +63,7 @@ async function preflightRequiredInvocations(rawArgs) {
63
63
  return;
64
64
  }
65
65
  if (command === "preflight") {
66
- const { preflightArgs } = await import("./preflight-tg4mpz1h.js");
66
+ const { preflightArgs } = await import("./preflight-1q6c2edh.js");
67
67
  rejectUnknownFlags(commandArgs, preflightArgs, "preflight");
68
68
  const parsed2 = parseArgs(commandArgs, {
69
69
  ...preflightArgs,
@@ -87,7 +87,7 @@ async function preflightRequiredInvocations(rawArgs) {
87
87
  if (subcommand !== "add") {
88
88
  throw new UsageError(`gutterpress plugin: unknown command "${subcommand}"`);
89
89
  }
90
- const { pluginAddArgs } = await import("./plugin-wf2cbmwc.js");
90
+ const { pluginAddArgs } = await import("./plugin-ees6nhkc.js");
91
91
  rejectUnknownFlags(subcommandArgs, pluginAddArgs, "plugin add");
92
92
  const parsed = parseArgs(subcommandArgs, {
93
93
  ...pluginAddArgs,
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  getSystemDiagnostics,
3
3
  log
4
- } from "./cli-h7phg3ka.js";
4
+ } from "./cli-najycadg.js";
5
5
  import {
6
6
  UsageError,
7
7
  rejectExtraPositionals,
8
8
  rejectUnknownFlags
9
- } from "./cli-hvqjs342.js";
9
+ } from "./cli-e5zhb0xs.js";
10
10
  import"./cli-37x76zdn.js";
11
11
 
12
12
  // src/commands/doctor.ts