gutterpress 0.11.10-alpha.2 → 0.11.10-alpha.6

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 (59) hide show
  1. package/README.md +24 -46
  2. package/dist/api/index.d.ts +1 -1
  3. package/dist/api/index.js +10 -6
  4. package/dist/{build-dfpvvhys.js → build-npxq1tvm.js} +7 -6
  5. package/dist/cdp-jg95s674.js +15 -0
  6. package/dist/cdp-smdx6mr3.js +16 -0
  7. package/dist/{cli-d8rdk1y7.js → cli-30j93gzt.js} +11 -335
  8. package/dist/{cli-pfczdbyd.js → cli-5qr3z0qa.js} +10 -404
  9. package/dist/{cli-c41yr7he.js → cli-7fkhgtfn.js} +3 -1
  10. package/dist/{cli-k2hwrp7s.js → cli-97bdz5k0.js} +1 -4
  11. package/dist/cli-kkzka31p.js +261 -0
  12. package/dist/{cli-p679pvce.js → cli-vbzkkcbv.js} +2 -2
  13. package/dist/{cli-4xksazfr.js → cli-z8ye91f0.js} +283 -1142
  14. package/dist/cli.js +12 -14
  15. package/dist/{doctor-hheax5yc.js → doctor-ykr6gtpv.js} +3 -3
  16. package/dist/engine/shared/cdp.d.ts +23 -19
  17. package/dist/engine-3gwctsty.js +24 -0
  18. package/dist/engine-mwshptgf.js +25 -0
  19. package/dist/{ext-q5024j6v.js → ext-bna9nr3v.js} +7 -6
  20. package/dist/{index-1a4rx87v.js → index-322fxk25.js} +344 -1130
  21. package/dist/{index-kqftehgy.js → index-dzp0hc2c.js} +4 -2
  22. package/dist/{index-fnhak0nh.js → index-qf7y4d85.js} +10 -404
  23. package/dist/index-r4wvy5v3.js +267 -0
  24. package/dist/{index-t43k5rq1.js → index-rzm1phg0.js} +23 -356
  25. package/dist/index.d.ts +0 -1
  26. package/dist/index.js +12 -87
  27. package/dist/lib/build-error.d.ts +4 -5
  28. package/dist/lib/build-preflight.d.ts +1 -35
  29. package/dist/lib/build-runner.d.ts +27 -44
  30. package/dist/lib/chromium.d.ts +5 -1
  31. package/dist/lib/engine.d.ts +3 -18
  32. package/dist/lib/extension-manager.d.ts +2 -2
  33. package/dist/lib/extension-manifest.d.ts +1 -1
  34. package/dist/lib/markdown/assemble.d.ts +2 -9
  35. package/dist/lib/markdown/index.d.ts +2 -4
  36. package/dist/lib/markdown/plugins.d.ts +0 -3
  37. package/dist/lib/npm-plugin-installer.d.ts +6 -1
  38. package/dist/lib/plugin-vendor.d.ts +10 -78
  39. package/dist/lib/source-provider.d.ts +1 -1
  40. package/dist/lib/validation-exec.d.ts +5 -6
  41. package/dist/{new-6xm4tdxb.js → new-0hv3nwqj.js} +9 -8
  42. package/dist/{preflight-ezt8rvg3.js → preflight-pk0k25fm.js} +7 -6
  43. package/dist/preview/file-watcher.d.ts +4 -43
  44. package/dist/preview/http-server.d.ts +1 -3
  45. package/dist/{preview-hehs46dd.js → preview-8b1fn59h.js} +7 -6
  46. package/dist/{preview-shell-gqnc5xxe.js → preview-shell-tqndvhbx.js} +5 -7
  47. package/dist/{publish-ha505ejq.js → publish-ba5h76tz.js} +7 -6
  48. package/dist/render.d.ts +1 -1
  49. package/dist/render.js +1 -9
  50. package/dist/{source-provider-ta09wegv.js → source-provider-pzmz0br9.js} +1 -1
  51. package/dist/{source-provider-7c2ww3bz.js → source-provider-qbthnmqw.js} +1 -1
  52. package/dist/{validate-je56vdbj.js → validate-4rq2r5b3.js} +7 -6
  53. package/package.json +1 -4
  54. package/dist/audit-v9594a72.js +0 -69
  55. package/dist/engine-qtfrfbpk.js +0 -41
  56. package/dist/engine-trte2tg2.js +0 -40
  57. package/dist/lib/browser-pool.d.ts +0 -35
  58. package/dist/lib/lint-runner.d.ts +0 -29
  59. package/dist/lint-tbywt66a.js +0 -68
@@ -148,42 +148,14 @@ function formatData(data, clean) {
148
148
  }
149
149
 
150
150
  // src/lib/plugin-vendor.ts
151
- import { createHash } from "node:crypto";
152
- import { createReadStream } from "node:fs";
153
- import { lstat, readFile, readdir, realpath } from "node:fs/promises";
151
+ import { lstat, readFile, realpath } from "node:fs/promises";
154
152
  import path2 from "node:path";
155
153
  import { exports as resolveExports } from "resolve.exports";
156
- import { satisfies, validRange } from "semver";
157
-
158
- // src/lib/npm-registry.ts
159
- var DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org";
160
- var ENV_OVERRIDE = "GUTTERPRESS_NPM_REGISTRY";
161
- function npmRegistryUrl() {
162
- const configured = process.env[ENV_OVERRIDE]?.trim();
163
- if (!configured)
164
- return DEFAULT_NPM_REGISTRY;
165
- let scheme;
166
- try {
167
- scheme = new URL(configured).protocol;
168
- } catch {
169
- throw new Error(`Invalid ${ENV_OVERRIDE} URL "${configured}".`);
170
- }
171
- if (scheme !== "http:" && scheme !== "https:") {
172
- throw new Error(`${ENV_OVERRIDE} must be an http(s) URL — got "${scheme}".`);
173
- }
174
- return configured.replace(/\/+$/, "");
175
- }
176
-
177
- // src/lib/plugin-vendor.ts
178
154
  var PLUGINS_DIR = "plugins";
179
155
  var VENDORED_NPM_DIR = "npm";
180
- var VENDOR_RECEIPT_FILE = ".gutterpress-install.json";
181
- var VENDOR_RECEIPT_VERSION = 2;
182
156
  var NPM_SEGMENT = /^[a-z0-9][a-z0-9._~-]*$/;
183
157
  var EXACT_VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
184
158
  var WINDOWS_RESERVED = /^(con|prn|aux|nul|clock\$|conin\$|conout\$|com[1-9¹²³]|lpt[1-9¹²³])(?:\..*)?$/i;
185
- var MAX_VERIFIED_FILES = 50000;
186
- var MAX_VERIFIED_BYTES = 512 * 1024 * 1024;
187
159
  function isValidNpmPackageName(name) {
188
160
  if (!name || name.length > 214 || name !== name.toLowerCase())
189
161
  return false;
@@ -236,10 +208,6 @@ function vendoredNpmPluginPackageDir(installRoot, name) {
236
208
  function toPosixPath(value) {
237
209
  return value.split(path2.sep).join("/");
238
210
  }
239
- function packageEntryFormat(manifest, relativeEntry) {
240
- const extension = path2.posix.extname(relativeEntry);
241
- return extension === ".cjs" || extension === ".json" || extension !== ".mjs" && manifest.type !== "module" ? "commonjs" : "module";
242
- }
243
211
  function assertWindowsSafeRelativePath(relative) {
244
212
  if (!relative || relative.includes("\\") || relative.startsWith("/") || /^[a-zA-Z]:/.test(relative)) {
245
213
  throw new Error(`Unsafe package path: ${relative || "(empty)"}`);
@@ -258,12 +226,6 @@ function assertWindowsSafeRelativePath(relative) {
258
226
  function windowsPathKey(relative) {
259
227
  return relative.normalize("NFKC").toLowerCase();
260
228
  }
261
- function safeReceiptPath(relative, label) {
262
- if (typeof relative !== "string")
263
- throw new Error(`${label} must be a string.`);
264
- assertWindowsSafeRelativePath(relative);
265
- return relative;
266
- }
267
229
  function isContained(root, candidate) {
268
230
  const relative = path2.relative(root, candidate);
269
231
  return relative === "" || !relative.startsWith("..") && !path2.isAbsolute(relative);
@@ -271,38 +233,6 @@ function isContained(root, candidate) {
271
233
  function object(value) {
272
234
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
273
235
  }
274
- function stringMap(value) {
275
- const map = object(value);
276
- if (!map)
277
- return {};
278
- const result = {};
279
- for (const [name, selector] of Object.entries(map)) {
280
- if (typeof selector === "string" && selector.trim())
281
- result[name] = selector.trim();
282
- }
283
- return result;
284
- }
285
- function dependencyDeclarations(manifest) {
286
- const required = stringMap(manifest.dependencies);
287
- const optional = stringMap(manifest.optionalDependencies);
288
- for (const name of Object.keys(optional))
289
- delete required[name];
290
- const peers = stringMap(manifest.peerDependencies);
291
- const peerMeta = object(manifest.peerDependenciesMeta) ?? {};
292
- const optionalPeers = {};
293
- for (const [name, selector] of Object.entries(peers)) {
294
- if (name in required || name in optional)
295
- continue;
296
- if (object(peerMeta[name])?.optional === true)
297
- optionalPeers[name] = selector;
298
- else
299
- required[name] = selector;
300
- }
301
- return { required, optional, optionalPeers };
302
- }
303
- function unsupportedRegistrySelector(selector) {
304
- return /^(?:file:|git\+|https?:|ssh:|github:|workspace:|link:|npm:)/i.test(selector);
305
- }
306
236
  async function readPackageJson(packageDir) {
307
237
  const packageJsonPath = path2.join(packageDir, "package.json");
308
238
  const info = await lstat(packageJsonPath);
@@ -314,26 +244,6 @@ async function readPackageJson(packageDir) {
314
244
  throw new Error(`Package metadata is not an object: ${packageJsonPath}`);
315
245
  return parsed;
316
246
  }
317
- async function verifyReceiptEntry(installRoot, packagePath, entry, label) {
318
- if (entry === undefined)
319
- return;
320
- const relative = safeReceiptPath(entry, label);
321
- if (!relative.startsWith(`${packagePath}/`)) {
322
- throw new Error(`${label} is outside its package.`);
323
- }
324
- const packageDir = path2.resolve(installRoot, ...packagePath.split("/"));
325
- const entryPath = path2.resolve(installRoot, ...relative.split("/"));
326
- const [realPackageDir, realEntry] = await Promise.all([
327
- realpath(packageDir),
328
- realpath(entryPath)
329
- ]);
330
- if (!isContained(realPackageDir, realEntry))
331
- throw new Error(`${label} escapes its package.`);
332
- const info = await lstat(realEntry);
333
- if (!info.isFile() || info.isSymbolicLink())
334
- throw new Error(`${label} is not a regular file.`);
335
- return realEntry;
336
- }
337
247
  function packageResolutionTargets(manifest, subpath, condition) {
338
248
  if (manifest.exports !== undefined) {
339
249
  try {
@@ -401,112 +311,16 @@ async function resolveEntryCandidate(packageDir, resolution) {
401
311
  }
402
312
  return null;
403
313
  }
404
- async function resolvePackageEntry(packageDir, packageJson, condition = "import") {
314
+ async function resolvePackageEntry(packageDir, packageJson) {
405
315
  const manifest = packageJson ?? await readPackageJson(packageDir);
406
- for (const target of packageResolutionTargets(manifest, "", condition)) {
407
- const resolved = await resolveEntryCandidate(packageDir, target);
408
- if (resolved)
409
- return resolved;
410
- }
411
- throw new Error("Package has no contained JavaScript entry point for ESM import.");
412
- }
413
- async function listTreeEntries(root) {
414
- const out = [];
415
- async function visit(dir) {
416
- const entries = await readdir(dir, { withFileTypes: true });
417
- entries.sort((a, b) => a.name.localeCompare(b.name));
418
- for (const entry of entries) {
419
- const absolute = path2.join(dir, entry.name);
420
- const relative = toPosixPath(path2.relative(root, absolute));
421
- if (relative === VENDOR_RECEIPT_FILE)
422
- continue;
423
- if (entry.isSymbolicLink())
424
- throw new Error(`Vendor tree contains a symbolic link: ${relative}`);
425
- if (entry.isDirectory()) {
426
- out.push({ relative, directory: true });
427
- await visit(absolute);
428
- } else if (entry.isFile())
429
- out.push({ relative, directory: false });
430
- else
431
- throw new Error(`Vendor tree contains an unsupported filesystem entry: ${relative}`);
316
+ for (const condition of ["import", "require"]) {
317
+ for (const target of packageResolutionTargets(manifest, "", condition)) {
318
+ const resolved = await resolveEntryCandidate(packageDir, target);
319
+ if (resolved)
320
+ return resolved;
432
321
  }
433
322
  }
434
- await visit(root);
435
- return out;
436
- }
437
- async function computeVendorTreeDigest(root) {
438
- const entries = await listTreeEntries(root);
439
- const files = entries.filter((entry) => !entry.directory);
440
- if (files.length > MAX_VERIFIED_FILES) {
441
- throw new Error(`Vendor tree contains more than ${MAX_VERIFIED_FILES} files.`);
442
- }
443
- const seen = new Set;
444
- const hash = createHash("sha256");
445
- let bytes = 0;
446
- for (const entry of entries) {
447
- const { relative } = entry;
448
- assertWindowsSafeRelativePath(relative);
449
- const key = windowsPathKey(relative);
450
- if (seen.has(key))
451
- throw new Error(`Vendor tree has a Windows-colliding path: ${relative}`);
452
- seen.add(key);
453
- if (entry.directory)
454
- continue;
455
- const absolute = path2.join(root, ...relative.split("/"));
456
- const info = await lstat(absolute);
457
- if (!info.isFile() || info.isSymbolicLink() || info.nlink !== 1) {
458
- throw new Error(`Vendor tree file is not an independent regular file: ${relative}`);
459
- }
460
- bytes += info.size;
461
- if (bytes > MAX_VERIFIED_BYTES) {
462
- throw new Error(`Vendor tree exceeds ${Math.round(MAX_VERIFIED_BYTES / 1024 / 1024)}MB.`);
463
- }
464
- hash.update(`${Buffer.byteLength(relative)}:${relative}:${info.size}\x00`);
465
- for await (const chunk of createReadStream(absolute))
466
- hash.update(chunk);
467
- }
468
- return { digest: hash.digest("hex"), files: files.length, bytes };
469
- }
470
- async function assertVendorPackageOwnership(root, packagePaths) {
471
- const packages = packagePaths.map((relative) => ({
472
- relative,
473
- key: windowsPathKey(relative),
474
- parts: relative.split("/").length
475
- })).sort((a, b) => b.key.length - a.key.length);
476
- for (const entry of await listTreeEntries(root)) {
477
- const actualParts = entry.relative.split("/");
478
- for (const part of actualParts) {
479
- if (part.normalize("NFKC").toLowerCase() === "node_modules" && part !== "node_modules") {
480
- throw new Error(`Vendor tree contains a non-canonical node_modules path: ${entry.relative}`);
481
- }
482
- }
483
- const key = windowsPathKey(entry.relative);
484
- const structural = packages.some((pkg) => pkg.key === key || pkg.key.startsWith(`${key}/`));
485
- if (entry.directory && structural)
486
- continue;
487
- const owner = packages.find((pkg) => key.startsWith(`${pkg.key}/`));
488
- if (!owner)
489
- throw new Error(`Vendor tree path is not owned by a receipt package: ${entry.relative}`);
490
- const packageRelative = actualParts.slice(owner.parts);
491
- const nodeModulesAt = packageRelative.findIndex((part) => part.normalize("NFKC").toLowerCase() === "node_modules");
492
- if (nodeModulesAt < 0)
493
- continue;
494
- const generatedEmptyDirectory = entry.directory && nodeModulesAt === 0 && (packageRelative.length === 1 || packageRelative.length === 2 && packageRelative[1].startsWith("@"));
495
- if (!generatedEmptyDirectory) {
496
- throw new Error(`Package contains bundled node_modules content: ${entry.relative}`);
497
- }
498
- }
499
- }
500
- async function recomputeReceiptEntry(packageDir, packagePath, manifest, condition) {
501
- try {
502
- const entry = await resolvePackageEntry(packageDir, manifest, condition);
503
- return `${packagePath}/${entry}`;
504
- } catch (error) {
505
- if (error instanceof Error && error.message.includes("no contained JavaScript entry point")) {
506
- return;
507
- }
508
- throw error;
509
- }
323
+ throw new Error("Package has no contained JavaScript entry point.");
510
324
  }
511
325
  async function resolveVendoredPluginInstallRoot(projectDir, expectedName, expectedVersion) {
512
326
  const requestedProjectRoot = path2.resolve(projectDir);
@@ -531,214 +345,6 @@ async function resolveVendoredPluginInstallRoot(projectDir, expectedName, expect
531
345
  }
532
346
  return installRoot;
533
347
  }
534
- function reconcileReceiptGraph(receipt, packages, manifests) {
535
- if (!Array.isArray(receipt.skipped))
536
- throw new Error("Vendor receipt skipped list is invalid.");
537
- const declarations = new Map;
538
- for (const [packagePath, manifest] of manifests) {
539
- declarations.set(packagePath, dependencyDeclarations(manifest));
540
- }
541
- const skippedByEdge = new Map;
542
- for (const skipped of receipt.skipped) {
543
- if (!packages.has(skipped.from) || !isValidNpmPackageName(skipped.name) || typeof skipped.selector !== "string" || !["optional", "optional-peer"].includes(skipped.kind) || typeof skipped.reason !== "string") {
544
- throw new Error("Vendor receipt contains an invalid skipped dependency.");
545
- }
546
- const declared = declarations.get(skipped.from);
547
- const expectedSelector = skipped.kind === "optional" ? declared.optional[skipped.name] : declared.optionalPeers[skipped.name];
548
- if (expectedSelector !== skipped.selector) {
549
- throw new Error(`Skipped dependency is not declared as ${skipped.kind}: ${skipped.name}`);
550
- }
551
- const key = `${skipped.from}\x00${skipped.name}`;
552
- if (skippedByEdge.has(key))
553
- throw new Error(`Duplicate skipped dependency: ${skipped.name}`);
554
- skippedByEdge.set(key, skipped);
555
- }
556
- for (const pkg of receipt.packages) {
557
- if (!object(pkg.dependencies))
558
- throw new Error(`Invalid dependency map for ${pkg.name}.`);
559
- const declared = declarations.get(pkg.path);
560
- for (const [dependency, target] of Object.entries(pkg.dependencies)) {
561
- const targetPackage = packages.get(target);
562
- if (!isValidNpmPackageName(dependency) || !targetPackage || targetPackage.name !== dependency) {
563
- throw new Error(`Broken dependency edge ${pkg.name} -> ${dependency}.`);
564
- }
565
- const selector = declared.required[dependency] ?? declared.optional[dependency];
566
- if (!selector)
567
- throw new Error(`Undeclared dependency edge ${pkg.name} -> ${dependency}.`);
568
- if (unsupportedRegistrySelector(selector)) {
569
- throw new Error(`Unsupported selector on dependency edge ${pkg.name} -> ${dependency}.`);
570
- }
571
- const range = validRange(selector);
572
- if (range && !satisfies(targetPackage.version, range)) {
573
- throw new Error(`Dependency edge ${pkg.name} -> ${dependency}@${targetPackage.version} does not satisfy ${selector}.`);
574
- }
575
- if (skippedByEdge.has(`${pkg.path}\x00${dependency}`)) {
576
- throw new Error(`Dependency is both installed and skipped: ${pkg.name} -> ${dependency}.`);
577
- }
578
- }
579
- for (const dependency of Object.keys(declared.required)) {
580
- if (!(dependency in pkg.dependencies)) {
581
- throw new Error(`Missing required dependency edge ${pkg.name} -> ${dependency}.`);
582
- }
583
- }
584
- for (const dependency of Object.keys(declared.optional)) {
585
- if (!(dependency in pkg.dependencies) && !skippedByEdge.has(`${pkg.path}\x00${dependency}`)) {
586
- throw new Error(`Optional dependency is neither installed nor skipped: ${pkg.name} -> ${dependency}.`);
587
- }
588
- }
589
- for (const dependency of Object.keys(declared.optionalPeers)) {
590
- if (!skippedByEdge.has(`${pkg.path}\x00${dependency}`)) {
591
- throw new Error(`Optional peer dependency is not recorded as skipped: ${pkg.name} -> ${dependency}.`);
592
- }
593
- }
594
- }
595
- }
596
- async function verifyVendoredPlugin(projectDir, expectedName, expectedVersion) {
597
- try {
598
- const installRoot = await resolveVendoredPluginInstallRoot(projectDir, expectedName, expectedVersion);
599
- if (!installRoot)
600
- return null;
601
- const receiptPath = path2.join(installRoot, VENDOR_RECEIPT_FILE);
602
- let raw;
603
- try {
604
- const info = await lstat(receiptPath);
605
- if (!info.isFile() || info.isSymbolicLink() || info.nlink !== 1 || info.size > 1024 * 1024) {
606
- throw new Error("Vendor receipt is not a small regular file.");
607
- }
608
- raw = await readFile(receiptPath, "utf8");
609
- } catch (error) {
610
- if (error.code === "ENOENT")
611
- return null;
612
- throw error;
613
- }
614
- const receipt = JSON.parse(raw);
615
- if (receipt.schemaVersion !== VENDOR_RECEIPT_VERSION) {
616
- throw new Error(`Unsupported vendor receipt schema ${String(receipt.schemaVersion)}.`);
617
- }
618
- if (receipt.root?.name !== expectedName || receipt.root?.version !== expectedVersion) {
619
- throw new Error("Vendor receipt identity does not match the manifest entry.");
620
- }
621
- if (!Array.isArray(receipt.packages) || receipt.packages.length === 0) {
622
- throw new Error("Vendor receipt has no package graph.");
623
- }
624
- const tree = await computeVendorTreeDigest(installRoot);
625
- if (receipt.tree?.algorithm !== "sha256" || receipt.tree.digest !== tree.digest || receipt.tree.files !== tree.files || receipt.tree.bytes !== tree.bytes) {
626
- throw new Error("Vendor tree hash does not match its receipt.");
627
- }
628
- const packages = new Map;
629
- const manifests = new Map;
630
- const verifiedPackages = [];
631
- const pathKeys = new Set;
632
- for (const pkg of receipt.packages) {
633
- const relative = safeReceiptPath(pkg.path, "Package receipt path");
634
- const key = windowsPathKey(relative);
635
- if (pathKeys.has(key))
636
- throw new Error(`Duplicate package receipt path: ${relative}`);
637
- pathKeys.add(key);
638
- if (!isValidNpmPackageName(pkg.name) || !isExactNpmVersion(pkg.version)) {
639
- throw new Error(`Invalid package identity in receipt: ${pkg.name}@${pkg.version}`);
640
- }
641
- const expectedSuffix = `node_modules/${pkg.name}`;
642
- if (relative !== expectedSuffix && !relative.endsWith(`/${expectedSuffix}`)) {
643
- throw new Error(`Package receipt path does not match ${pkg.name}: ${relative}`);
644
- }
645
- if (typeof pkg.integrity !== "string" || !/^(?:sha512|sha384|sha256|sha1)-(?:hex-)?[A-Za-z0-9+/=]+$/.test(pkg.integrity) || typeof pkg.legacySha1 !== "boolean" || pkg.legacySha1 !== pkg.integrity.startsWith("sha1-")) {
646
- throw new Error(`Package receipt is missing provenance: ${pkg.name}@${pkg.version}`);
647
- }
648
- const tarball = new URL(pkg.tarball);
649
- if (tarball.origin !== new URL(npmRegistryUrl()).origin || tarball.username || tarball.password) {
650
- throw new Error(`Package receipt has an invalid tarball URL: ${pkg.name}@${pkg.version}`);
651
- }
652
- const packageDir = path2.resolve(installRoot, ...relative.split("/"));
653
- if (!isContained(installRoot, packageDir))
654
- throw new Error(`Package escapes vendor root: ${relative}`);
655
- const realPackageDir2 = await realpath(packageDir);
656
- if (!isContained(installRoot, realPackageDir2)) {
657
- throw new Error(`Package resolves outside the vendor root: ${relative}`);
658
- }
659
- const manifest = await readPackageJson(packageDir);
660
- if (manifest.name !== pkg.name || manifest.version !== pkg.version) {
661
- throw new Error(`Installed package identity changed: ${pkg.name}@${pkg.version}`);
662
- }
663
- const [expectedEntry, expectedRequireEntry] = await Promise.all([
664
- recomputeReceiptEntry(packageDir, relative, manifest, "import"),
665
- recomputeReceiptEntry(packageDir, relative, manifest, "require")
666
- ]);
667
- if (pkg.entry !== expectedEntry || pkg.requireEntry !== expectedRequireEntry) {
668
- throw new Error(`Recorded package entries do not match package.json: ${pkg.name}@${pkg.version}`);
669
- }
670
- packages.set(relative, pkg);
671
- manifests.set(relative, manifest);
672
- verifiedPackages.push({
673
- path: relative,
674
- name: pkg.name,
675
- packageDir: realPackageDir2,
676
- manifest,
677
- entryPath: await verifyReceiptEntry(installRoot, relative, pkg.entry, "Package import entry"),
678
- requireEntryPath: await verifyReceiptEntry(installRoot, relative, pkg.requireEntry, "Package require entry"),
679
- dependencies: pkg.dependencies
680
- });
681
- }
682
- await assertVendorPackageOwnership(installRoot, receipt.packages.map((pkg) => pkg.path));
683
- reconcileReceiptGraph(receipt, packages, manifests);
684
- const rootPackagePath = safeReceiptPath(receipt.root.packagePath, "Root package path");
685
- const rootPackage = packages.get(rootPackagePath);
686
- if (!rootPackage || rootPackage.name !== expectedName || rootPackage.version !== expectedVersion) {
687
- throw new Error("Vendor receipt root package is missing.");
688
- }
689
- const reachablePackages = new Set([rootPackagePath]);
690
- const pendingPackages = [rootPackagePath];
691
- while (pendingPackages.length > 0) {
692
- const current = packages.get(pendingPackages.pop());
693
- for (const target of Object.values(current.dependencies)) {
694
- if (reachablePackages.has(target))
695
- continue;
696
- reachablePackages.add(target);
697
- pendingPackages.push(target);
698
- }
699
- }
700
- if (reachablePackages.size !== receipt.packages.length) {
701
- throw new Error("Vendor receipt contains a package that is not reachable from its root.");
702
- }
703
- const rootManifest = manifests.get(rootPackagePath);
704
- if (receipt.root.format !== "module" && receipt.root.format !== "commonjs") {
705
- throw new Error("Vendor receipt root format is invalid.");
706
- }
707
- const entryRelative = safeReceiptPath(receipt.root.entry, "Plugin entry path");
708
- if (!entryRelative.startsWith(`${rootPackagePath}/`)) {
709
- throw new Error("Plugin entry is outside its package.");
710
- }
711
- const expectedRootEntry = receipt.root.format === "commonjs" ? rootPackage.requireEntry ?? rootPackage.entry : rootPackage.entry;
712
- if (entryRelative !== expectedRootEntry) {
713
- throw new Error("Plugin entry does not match the package graph entry.");
714
- }
715
- if (packageEntryFormat(rootManifest, entryRelative) !== receipt.root.format) {
716
- throw new Error("Plugin entry format does not match its package metadata.");
717
- }
718
- const entryPath = path2.resolve(installRoot, ...entryRelative.split("/"));
719
- const rootPackageDir = path2.resolve(installRoot, ...rootPackagePath.split("/"));
720
- const [realPackageDir, realEntry] = await Promise.all([
721
- realpath(rootPackageDir),
722
- realpath(entryPath)
723
- ]);
724
- if (!isContained(installRoot, realEntry) || !isContained(realPackageDir, realEntry)) {
725
- throw new Error("Plugin entry resolves outside the verified vendor tree.");
726
- }
727
- const entryInfo = await lstat(realEntry);
728
- if (!entryInfo.isFile() || entryInfo.isSymbolicLink()) {
729
- throw new Error("Plugin entry is not a regular file.");
730
- }
731
- return {
732
- installRoot,
733
- entryPath: realEntry,
734
- format: receipt.root.format,
735
- packages: verifiedPackages,
736
- receipt
737
- };
738
- } catch (error) {
739
- throw new Error(`Vendored plugin "${expectedName}@${expectedVersion}" failed verification: ` + `${error instanceof Error ? error.message : String(error)} Reinstall it before building.`, { cause: error });
740
- }
741
- }
742
348
 
743
349
  // src/lib/source-provider.ts
744
350
  var noopLogger = {
@@ -1103,7 +709,7 @@ async function countUnversionedChanges(projectDir) {
1103
709
  const appWritten = `${bookPrefix}${PLUGINS_DIR}/${VENDORED_NPM_DIR}/`;
1104
710
  return withRepoLock(dir, async () => {
1105
711
  const { adds, removes } = await listWorkdirChanges(dir);
1106
- const mine = new Set([...adds, ...removes].filter((f) => f.startsWith(bookPrefix) && !f.startsWith(appWritten) && path3.posix.basename(f) !== VENDOR_RECEIPT_FILE));
712
+ const mine = new Set([...adds, ...removes].filter((f) => f.startsWith(bookPrefix) && !f.startsWith(appWritten)));
1107
713
  return { changedFiles: mine.size, stale: gitFs.existsSync(snapshotStagingMarkerPath(dir)) };
1108
714
  });
1109
715
  }
@@ -1279,4 +885,4 @@ async function switchBranch(options) {
1279
885
  });
1280
886
  }
1281
887
 
1282
- export { npmRegistryUrl, PLUGINS_DIR, VENDORED_NPM_DIR, VENDOR_RECEIPT_FILE, VENDOR_RECEIPT_VERSION, isValidNpmPackageName, parseNpmPluginSpec, isExactNpmVersion, vendoredNpmPluginRoot, vendoredNpmPluginPackageDir, packageEntryFormat, assertWindowsSafeRelativePath, windowsPathKey, packageResolutionTargets, resolvePackageEntry, computeVendorTreeDigest, resolveVendoredPluginInstallRoot, verifyVendoredPlugin, gitScopeFor, HISTORY_PAGE_LIMIT, withRepoLock, whenGitIdle, __repoLockQueueSizeForTests, resolveGitAuthor, listWorkdirChanges, stageChanges, hasPendingChanges, hasUncommittedChanges, snapshotWorkingTreeUnlocked, isNoChangesError, countUnversionedChanges, providerFor, gitDirFor, snapshotStagingMarkerPath, RESTORE_BACKUP_MESSAGE, AUTO_SNAPSHOT_MESSAGE, restoreVersionWithBackup, SWITCH_BRANCH_SNAPSHOT_MESSAGE, listLocalBranches, switchBranch };
888
+ export { PLUGINS_DIR, VENDORED_NPM_DIR, isValidNpmPackageName, parseNpmPluginSpec, isExactNpmVersion, vendoredNpmPluginRoot, vendoredNpmPluginPackageDir, assertWindowsSafeRelativePath, windowsPathKey, packageResolutionTargets, safePackageTarget, resolvePackageEntry, resolveVendoredPluginInstallRoot, gitScopeFor, HISTORY_PAGE_LIMIT, withRepoLock, whenGitIdle, __repoLockQueueSizeForTests, resolveGitAuthor, listWorkdirChanges, stageChanges, hasPendingChanges, hasUncommittedChanges, snapshotWorkingTreeUnlocked, isNoChangesError, countUnversionedChanges, providerFor, gitDirFor, snapshotStagingMarkerPath, RESTORE_BACKUP_MESSAGE, AUTO_SNAPSHOT_MESSAGE, restoreVersionWithBackup, SWITCH_BRANCH_SNAPSHOT_MESSAGE, listLocalBranches, switchBranch };
@@ -137,6 +137,9 @@ async function findTool(tool) {
137
137
  }
138
138
  }
139
139
 
140
+ // src/lib/chromium.ts
141
+ import { existsSync } from "node:fs";
142
+
140
143
  // src/lib/install-hints.ts
141
144
  var INSTALL_HINTS = {
142
145
  chromium: {
@@ -165,7 +168,6 @@ ${hint.body}`;
165
168
  }
166
169
 
167
170
  // src/lib/chromium.ts
168
- import { existsSync } from "node:fs";
169
171
  var SYSTEM_PATHS = [
170
172
  process.env.CHROMIUM_PATH,
171
173
  process.env.PUPPETEER_EXECUTABLE_PATH,
@@ -4,7 +4,7 @@ import {
4
4
  // package.json
5
5
  var package_default = {
6
6
  name: "gutterpress",
7
- version: "0.11.10-alpha.2",
7
+ version: "0.11.10-alpha.6",
8
8
  description: "Markdown-to-PDF converter for professional print layout using a native Chromium print engine and Ghostscript.",
9
9
  author: "itlackey",
10
10
  license: "MPL-2.0",
@@ -64,11 +64,9 @@ var package_default = {
64
64
  node: ">=22.0.0"
65
65
  },
66
66
  dependencies: {
67
- acorn: "8.16.0",
68
67
  chokidar: "^5.0.0",
69
68
  citty: "^0.2.0",
70
69
  diff3: "0.0.3",
71
- "es-module-lexer": "2.0.0",
72
70
  fflate: "0.8.3",
73
71
  glob: "^13.0.0",
74
72
  htmlhint: "^1.9.2",
@@ -85,7 +83,6 @@ var package_default = {
85
83
  markdownlint: "^0.40.0",
86
84
  "pdf-lib": "^1.17.1",
87
85
  postcss: "^8.5.18",
88
- "puppeteer-core": "^25.0.4",
89
86
  "resolve.exports": "2.0.3",
90
87
  semver: "7.8.0",
91
88
  tar: "7.5.20",