@nowline/embed 0.0.0-dev.20261025020025.gc2cc722 → 0.0.0-dev.20261026035511.g8612a42

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/meta.json CHANGED
@@ -5135,17 +5135,17 @@
5135
5135
  "format": "esm"
5136
5136
  },
5137
5137
  "../core/dist/i18n/codes.js": {
5138
- "bytes": 2642,
5138
+ "bytes": 2770,
5139
5139
  "imports": [],
5140
5140
  "format": "esm"
5141
5141
  },
5142
5142
  "../core/dist/i18n/messages.en.js": {
5143
- "bytes": 20818,
5143
+ "bytes": 23135,
5144
5144
  "imports": [],
5145
5145
  "format": "esm"
5146
5146
  },
5147
5147
  "../core/dist/i18n/messages.fr.js": {
5148
- "bytes": 24547,
5148
+ "bytes": 27177,
5149
5149
  "imports": [],
5150
5150
  "format": "esm"
5151
5151
  },
@@ -5186,7 +5186,7 @@
5186
5186
  "format": "esm"
5187
5187
  },
5188
5188
  "../core/dist/util/posix-path.js": {
5189
- "bytes": 3360,
5189
+ "bytes": 4409,
5190
5190
  "imports": [],
5191
5191
  "format": "esm"
5192
5192
  },
@@ -5274,7 +5274,7 @@
5274
5274
  "format": "esm"
5275
5275
  },
5276
5276
  "../core/dist/language/include-waves.js": {
5277
- "bytes": 12694,
5277
+ "bytes": 12647,
5278
5278
  "imports": [
5279
5279
  {
5280
5280
  "path": "../../node_modules/.pnpm/langium@4.4.0/node_modules/langium/lib/index.js",
@@ -5372,7 +5372,7 @@
5372
5372
  "format": "esm"
5373
5373
  },
5374
5374
  "../core/dist/language/include-resolver.js": {
5375
- "bytes": 23037,
5375
+ "bytes": 25389,
5376
5376
  "imports": [
5377
5377
  {
5378
5378
  "path": "../../node_modules/.pnpm/langium@4.4.0/node_modules/langium/lib/index.js",
@@ -5389,6 +5389,11 @@
5389
5389
  "kind": "import-statement",
5390
5390
  "original": "../generated/ast.js"
5391
5391
  },
5392
+ {
5393
+ "path": "../core/dist/i18n/index.js",
5394
+ "kind": "import-statement",
5395
+ "original": "../i18n/index.js"
5396
+ },
5392
5397
  {
5393
5398
  "path": "../core/dist/util/posix-path.js",
5394
5399
  "kind": "import-statement",
@@ -5414,6 +5419,11 @@
5414
5419
  "kind": "import-statement",
5415
5420
  "original": "./waves.js"
5416
5421
  },
5422
+ {
5423
+ "path": "stub-node-read-file:../util/node-read-file.js",
5424
+ "kind": "dynamic-import",
5425
+ "original": "../util/node-read-file.js"
5426
+ },
5417
5427
  {
5418
5428
  "path": "stub-node-read-file:../util/node-read-file.js",
5419
5429
  "kind": "dynamic-import",
@@ -5835,7 +5845,7 @@
5835
5845
  "format": "esm"
5836
5846
  },
5837
5847
  "../core/dist/index.js": {
5838
- "bytes": 1352,
5848
+ "bytes": 1371,
5839
5849
  "imports": [
5840
5850
  {
5841
5851
  "path": "../core/dist/convert/parse-json.js",
@@ -10077,7 +10087,7 @@
10077
10087
  "format": "esm"
10078
10088
  },
10079
10089
  "../renderer/dist/stage.js": {
10080
- "bytes": 3853,
10090
+ "bytes": 4072,
10081
10091
  "imports": [
10082
10092
  {
10083
10093
  "path": "../core/dist/index.js",
@@ -10661,7 +10671,7 @@
10661
10671
  "imports": [],
10662
10672
  "exports": [],
10663
10673
  "inputs": {},
10664
- "bytes": 3710244
10674
+ "bytes": 3725877
10665
10675
  },
10666
10676
  "dist/nowline.min.js": {
10667
10677
  "imports": [],
@@ -11530,10 +11540,10 @@
11530
11540
  "bytesInOutput": 182
11531
11541
  },
11532
11542
  "../core/dist/i18n/messages.en.js": {
11533
- "bytesInOutput": 15721
11543
+ "bytesInOutput": 17491
11534
11544
  },
11535
11545
  "../core/dist/i18n/messages.fr.js": {
11536
- "bytesInOutput": 19755
11546
+ "bytesInOutput": 21876
11537
11547
  },
11538
11548
  "../core/dist/i18n/messages.fr-CA.js": {
11539
11549
  "bytesInOutput": 10
@@ -11545,7 +11555,7 @@
11545
11555
  "bytesInOutput": 460
11546
11556
  },
11547
11557
  "../core/dist/util/posix-path.js": {
11548
- "bytesInOutput": 924
11558
+ "bytesInOutput": 1356
11549
11559
  },
11550
11560
  "../core/dist/util/single-line.js": {
11551
11561
  "bytesInOutput": 79
@@ -11560,7 +11570,7 @@
11560
11570
  "bytesInOutput": 9621
11561
11571
  },
11562
11572
  "../core/dist/language/include-waves.js": {
11563
- "bytesInOutput": 3941
11573
+ "bytesInOutput": 3936
11564
11574
  },
11565
11575
  "../core/dist/language/references.js": {
11566
11576
  "bytesInOutput": 281
@@ -11569,7 +11579,7 @@
11569
11579
  "bytesInOutput": 375
11570
11580
  },
11571
11581
  "../core/dist/language/include-resolver.js": {
11572
- "bytesInOutput": 7670
11582
+ "bytesInOutput": 8116
11573
11583
  },
11574
11584
  "../core/dist/language/validator/support.js": {
11575
11585
  "bytesInOutput": 580
@@ -11803,7 +11813,7 @@
11803
11813
  "bytesInOutput": 777
11804
11814
  },
11805
11815
  "../renderer/dist/stage.js": {
11806
- "bytesInOutput": 1220
11816
+ "bytesInOutput": 1294
11807
11817
  },
11808
11818
  "../renderer/dist/index.js": {
11809
11819
  "bytesInOutput": 0
@@ -11881,7 +11891,7 @@
11881
11891
  "bytesInOutput": 257
11882
11892
  }
11883
11893
  },
11884
- "bytes": 674209
11894
+ "bytes": 679047
11885
11895
  }
11886
11896
  }
11887
11897
  }
@@ -1,4 +1,4 @@
1
- /*! @nowline/embed 0.0.0-dev.20261025020025.gc2cc722 sha=c2cc722 built=2026-10-25T01:54:49Z */
1
+ /*! @nowline/embed 0.0.0-dev.20261026035511.g8612a42 sha=8612a42 built=2026-10-26T03:49:20Z */
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -15082,7 +15082,7 @@ var UriUtils;
15082
15082
  return a?.toString() === b?.toString();
15083
15083
  }
15084
15084
  UriUtils2.equals = equals;
15085
- function relative(from, to) {
15085
+ function relative2(from, to) {
15086
15086
  const fromPath = typeof from === "string" ? URI.parse(from).path : from.path;
15087
15087
  const toPath = typeof to === "string" ? URI.parse(to).path : to.path;
15088
15088
  const fromParts = fromPath.split("/").filter((e) => e.length > 0);
@@ -15109,7 +15109,7 @@ var UriUtils;
15109
15109
  const toPart = toParts.slice(i2).join("/");
15110
15110
  return backPart + toPart;
15111
15111
  }
15112
- UriUtils2.relative = relative;
15112
+ UriUtils2.relative = relative2;
15113
15113
  function normalize3(uri) {
15114
15114
  return URI.parse(uri.toString()).toString();
15115
15115
  }
@@ -26425,6 +26425,44 @@ var messages = {
26425
26425
  return `Wave "${a.id}" in "${a.path}" ${floorClause(a.childFloor)}, but this file's wave "${a.id}" ${floorClause(a.parentFloor)}. A wave must have the same start floor in every included roadmap.`;
26426
26426
  }
26427
26427
  },
26428
+ "NL.E0203": (a) => {
26429
+ switch (a.reason) {
26430
+ case "not-found":
26431
+ return `Cannot read include "${a.path}": file not found.`;
26432
+ case "is-directory":
26433
+ return `Cannot read include "${a.path}": it is a directory.`;
26434
+ case "permission-denied":
26435
+ return `Cannot read include "${a.path}": permission denied.`;
26436
+ case "not-nowline":
26437
+ return `Cannot read include "${a.path}": only .nowline files can be included.`;
26438
+ case "unreadable":
26439
+ return a.detail ? `Cannot read include "${a.path}": ${a.detail}` : `Cannot read include "${a.path}".`;
26440
+ }
26441
+ },
26442
+ "NL.E0204": (a) => `Circular include: "${a.path}" is already being included (${a.chain}).`,
26443
+ "NL.E0205": (a) => `Duplicate include "${a.path}". Include each file once.`,
26444
+ "NL.E0206": (a) => `Cannot isolate "${a.path}": it has no roadmap declaration.`,
26445
+ "NL.E0207": (a) => {
26446
+ if (a.parentStart && a.childStart) {
26447
+ return `Included "${a.path}" declares start:${a.childStart}, which doesn't match this file's start:${a.parentStart}. Both files must declare the same start date, or neither should.`;
26448
+ }
26449
+ if (a.parentStart) {
26450
+ return `Included "${a.path}" has no start:, but this file declares start:${a.parentStart}. Both files must declare the same start date, or neither should.`;
26451
+ }
26452
+ return `Included "${a.path}" declares start:${a.childStart}, but this file has no start:. Both files must declare the same start date, or neither should.`;
26453
+ },
26454
+ "NL.E0208": (a) => {
26455
+ switch (a.reason) {
26456
+ case "absolute":
26457
+ return `Include "${a.path}" is an absolute path. With an include root, an include must be a relative path inside it.`;
26458
+ case "parent":
26459
+ return `Include "${a.path}" resolves outside the include root.`;
26460
+ case "symlink":
26461
+ return `Include "${a.path}" resolves outside the include root through a symbolic link.`;
26462
+ }
26463
+ },
26464
+ "NL.E0209": (a) => `Includes are not supported in this context: "${a.path}" was not read.`,
26465
+ "NL.E0210": (a) => `Include "${a.path}" is more than ${a.max} includes deep. Flatten the include chain.`,
26428
26466
  // Identifier
26429
26467
  "NL.E0300": (a) => `Duplicate identifier "${a.name}". First declared at ${a.location}.`,
26430
26468
  "NL.E0301": (a) => `${a.type} must have an identifier, a title, or both.`,
@@ -26687,6 +26725,44 @@ var messages2 = {
26687
26725
  return `La vague ${q(a.id)} dans ${q(a.path)} ${floorText(a.childFloor)}, mais la vague ${q(a.id)} de ce fichier ${floorText(a.parentFloor)}. Une vague doit avoir la m\xEAme borne de d\xE9part dans chaque roadmap incluse.`;
26688
26726
  }
26689
26727
  },
26728
+ "NL.E0203": (a) => {
26729
+ switch (a.reason) {
26730
+ case "not-found":
26731
+ return `Impossible de lire l'include ${q(a.path)}\xA0: fichier introuvable.`;
26732
+ case "is-directory":
26733
+ return `Impossible de lire l'include ${q(a.path)}\xA0: c'est un r\xE9pertoire.`;
26734
+ case "permission-denied":
26735
+ return `Impossible de lire l'include ${q(a.path)}\xA0: permission refus\xE9e.`;
26736
+ case "not-nowline":
26737
+ return `Impossible de lire l'include ${q(a.path)}\xA0: seuls les fichiers .nowline peuvent \xEAtre inclus.`;
26738
+ case "unreadable":
26739
+ return a.detail ? `Impossible de lire l'include ${q(a.path)}\xA0: ${a.detail}` : `Impossible de lire l'include ${q(a.path)}.`;
26740
+ }
26741
+ },
26742
+ "NL.E0204": (a) => `Include circulaire\xA0: ${q(a.path)} est d\xE9j\xE0 en cours d'inclusion (${a.chain}).`,
26743
+ "NL.E0205": (a) => `Include ${q(a.path)} en double. Incluez chaque fichier une seule fois.`,
26744
+ "NL.E0206": (a) => `Impossible d'isoler ${q(a.path)}\xA0: il ne d\xE9clare aucune roadmap.`,
26745
+ "NL.E0207": (a) => {
26746
+ if (a.parentStart && a.childStart) {
26747
+ return `L'include ${q(a.path)} d\xE9clare start:${a.childStart}, qui ne correspond pas au start:${a.parentStart} de ce fichier. Les deux fichiers doivent d\xE9clarer la m\xEAme date de d\xE9but, ou aucun des deux.`;
26748
+ }
26749
+ if (a.parentStart) {
26750
+ return `L'include ${q(a.path)} n'a pas de start:, mais ce fichier d\xE9clare start:${a.parentStart}. Les deux fichiers doivent d\xE9clarer la m\xEAme date de d\xE9but, ou aucun des deux.`;
26751
+ }
26752
+ return `L'include ${q(a.path)} d\xE9clare start:${a.childStart}, mais ce fichier n'a pas de start:. Les deux fichiers doivent d\xE9clarer la m\xEAme date de d\xE9but, ou aucun des deux.`;
26753
+ },
26754
+ "NL.E0208": (a) => {
26755
+ switch (a.reason) {
26756
+ case "absolute":
26757
+ return `L'include ${q(a.path)} est un chemin absolu. Avec une racine d'include, un include doit \xEAtre un chemin relatif \xE0 l'int\xE9rieur de celle-ci.`;
26758
+ case "parent":
26759
+ return `L'include ${q(a.path)} se r\xE9sout hors de la racine d'include.`;
26760
+ case "symlink":
26761
+ return `L'include ${q(a.path)} se r\xE9sout hors de la racine d'include par un lien symbolique.`;
26762
+ }
26763
+ },
26764
+ "NL.E0209": (a) => `Les includes ne sont pas pris en charge dans ce contexte\xA0: ${q(a.path)} n'a pas \xE9t\xE9 lu.`,
26765
+ "NL.E0210": (a) => `L'include ${q(a.path)} d\xE9passe ${a.max} niveaux d'inclusion. Aplatissez la cha\xEEne d'includes.`,
26690
26766
  // Identifiant
26691
26767
  "NL.E0300": (a) => `Identifiant en double \xAB\xA0${a.name}\xA0\xBB. Premi\xE8re d\xE9claration \xE0 ${a.location}.`,
26692
26768
  "NL.E0301": (a) => `${a.type} doit comporter un identifiant, un titre, ou les deux.`,
@@ -26942,6 +27018,27 @@ function normalize2(p, sep) {
26942
27018
  }
26943
27019
  return prefix + segments.join(sep);
26944
27020
  }
27021
+ function segmentsOf(p) {
27022
+ const normalized = resolve("", p).replace(/\\/g, "/");
27023
+ const drive = /^[A-Za-z]:/.test(normalized) ? normalized.slice(0, 2).toLowerCase() : "";
27024
+ const body = drive ? normalized.slice(2) : normalized;
27025
+ return [drive, ...body.split("/").filter((s) => s !== "")];
27026
+ }
27027
+ function isWithin(dir, p) {
27028
+ const d = segmentsOf(dir);
27029
+ const t = segmentsOf(p);
27030
+ return d.length <= t.length && d.every((seg, i2) => seg === t[i2]);
27031
+ }
27032
+ function relative(from, to) {
27033
+ const f = segmentsOf(from);
27034
+ const t = segmentsOf(to);
27035
+ if (f[0] !== t[0])
27036
+ return to;
27037
+ let i2 = 0;
27038
+ while (i2 < f.length && i2 < t.length && f[i2] === t[i2])
27039
+ i2++;
27040
+ return [...f.slice(i2).map(() => ".."), ...t.slice(i2)].join("/") || ".";
27041
+ }
26945
27042
 
26946
27043
  // ../core/dist/util/single-line.js
26947
27044
  function singleLine(text) {
@@ -28158,8 +28255,8 @@ function hasParseErrors(file) {
28158
28255
  const result = file.$document?.parseResult;
28159
28256
  return !!result && (result.lexerErrors.length > 0 || result.parserErrors.length > 0);
28160
28257
  }
28161
- function participates(childFile, childContent, isStub) {
28162
- if (isStub || hasParseErrors(childFile))
28258
+ function participates(childFile, childContent) {
28259
+ if (hasParseErrors(childFile))
28163
28260
  return false;
28164
28261
  return !!childFile.roadmapDecl || childContent.swimlanes.size > 0 || ownWaves(childFile).length > 0;
28165
28262
  }
@@ -28464,15 +28561,6 @@ function readStartProp(decl) {
28464
28561
  return void 0;
28465
28562
  return prop.value;
28466
28563
  }
28467
- function formatStartMismatch(childRelPath, parentStart, childStart) {
28468
- if (parentStart && childStart) {
28469
- return `Included "${childRelPath}" declares start:${childStart}, which doesn't match this file's start:${parentStart}. Both files must declare the same start date, or neither should.`;
28470
- }
28471
- if (parentStart) {
28472
- return `Included "${childRelPath}" has no start:, but this file declares start:${parentStart}. Both files must declare the same start date, or neither should.`;
28473
- }
28474
- return `Included "${childRelPath}" declares start:${childStart}, but this file has no start:. Both files must declare the same start date, or neither should.`;
28475
- }
28476
28564
  function isRoutedResolveDiagnostic(d) {
28477
28565
  return d.code !== void 0 || d.rule === "wave" || d.syntax !== void 0;
28478
28566
  }
@@ -28498,22 +28586,30 @@ function emptyContent() {
28498
28586
  isolatedRegions: []
28499
28587
  };
28500
28588
  }
28589
+ var MAX_INCLUDE_DEPTH = 16;
28501
28590
  async function resolveIncludes(file, filePath, options) {
28502
28591
  const readFile = options.readFile ?? (async (p) => {
28503
28592
  const { nodeReadFile: nodeReadFile2 } = await Promise.resolve().then(() => (init_node_read_file(), node_read_file_exports));
28504
28593
  return nodeReadFile2(p);
28505
28594
  });
28595
+ const policy = options.includePolicy;
28596
+ const realPath = (policy?.kind === "rooted" ? policy.realPath : void 0) ?? (async (p) => {
28597
+ const { nodeRealPath } = await Promise.resolve().then(() => (init_node_read_file(), node_read_file_exports));
28598
+ return nodeRealPath(p);
28599
+ });
28506
28600
  const absPath = resolve("", filePath);
28507
28601
  const ctx = {
28508
28602
  services: options.services,
28509
28603
  rootAbs: absPath,
28604
+ policy,
28605
+ realPath,
28606
+ displayBase: policy?.kind === "rooted" ? policy.root : dirname(absPath),
28510
28607
  diagnostics: [],
28511
28608
  resolving: [],
28512
28609
  processed: /* @__PURE__ */ new Map(),
28513
28610
  readFile,
28514
28611
  files: /* @__PURE__ */ new Map(),
28515
28612
  edges: /* @__PURE__ */ new Map(),
28516
- stubs: /* @__PURE__ */ new Set(),
28517
28613
  failedWaves: /* @__PURE__ */ new Set()
28518
28614
  };
28519
28615
  const { config: config2, content } = await resolveFile(file, absPath, ctx);
@@ -28537,17 +28633,6 @@ async function resolveFile(file, absPath, ctx) {
28537
28633
  if (ctx.processed.has(absPath)) {
28538
28634
  return ctx.processed.get(absPath);
28539
28635
  }
28540
- if (ctx.resolving.includes(absPath)) {
28541
- ctx.diagnostics.push({
28542
- severity: "error",
28543
- message: `Circular include detected: ${[...ctx.resolving, absPath].join(" \u2192 ")}`,
28544
- sourcePath: absPath
28545
- });
28546
- const empty = { config: emptyConfig(), content: emptyContent() };
28547
- ctx.stubs.add(empty.content);
28548
- ctx.processed.set(absPath, empty);
28549
- return empty;
28550
- }
28551
28636
  if (absPath !== ctx.rootAbs)
28552
28637
  ctx.diagnostics.push(...syntaxDiagnostics(file, absPath));
28553
28638
  ctx.resolving.push(absPath);
@@ -28565,17 +28650,42 @@ async function resolveFile(file, absPath, ctx) {
28565
28650
  const seenIncludes = /* @__PURE__ */ new Set();
28566
28651
  for (const inc of file.includes) {
28567
28652
  const childRelPath = inc.path;
28568
- const childAbsPath = resolve(dirname(absPath), childRelPath);
28653
+ const fail = (code, ...args) => {
28654
+ ctx.diagnostics.push(includeError(absPath, inc, code, ...args));
28655
+ };
28656
+ if (ctx.policy?.kind === "disabled") {
28657
+ fail("NL.E0209", { path: childRelPath });
28658
+ continue;
28659
+ }
28660
+ const located = await locateInclude(absPath, childRelPath, ctx);
28661
+ if ("refused" in located) {
28662
+ fail("NL.E0208", located.refused);
28663
+ continue;
28664
+ }
28665
+ if ("unreadable" in located) {
28666
+ fail("NL.E0203", located.unreadable);
28667
+ continue;
28668
+ }
28669
+ const childAbsPath = located.absPath;
28569
28670
  if (seenIncludes.has(childAbsPath)) {
28570
- ctx.diagnostics.push({
28571
- severity: "error",
28572
- message: `Duplicate include "${childRelPath}" in ${basename(absPath)}.`,
28573
- sourcePath: absPath,
28574
- line: inc.$cstNode?.range.start.line
28575
- });
28671
+ fail("NL.E0205", { path: childRelPath });
28576
28672
  continue;
28577
28673
  }
28578
28674
  seenIncludes.add(childAbsPath);
28675
+ const cycleStart = ctx.resolving.indexOf(childAbsPath);
28676
+ if (cycleStart >= 0) {
28677
+ const chain = [...ctx.resolving.slice(cycleStart), childAbsPath].map((p) => relative(ctx.displayBase, p)).join(" \u2192 ");
28678
+ fail("NL.E0204", { path: childRelPath, chain });
28679
+ continue;
28680
+ }
28681
+ if (ctx.resolving.length > MAX_INCLUDE_DEPTH) {
28682
+ fail("NL.E0210", { path: childRelPath, max: MAX_INCLUDE_DEPTH });
28683
+ continue;
28684
+ }
28685
+ if (!childAbsPath.endsWith(".nowline")) {
28686
+ fail("NL.E0203", { reason: "not-nowline", path: childRelPath });
28687
+ continue;
28688
+ }
28579
28689
  const configMode = getIncludeMode(inc, "config") ?? "merge";
28580
28690
  const roadmapMode = getIncludeMode(inc, "roadmap") ?? "merge";
28581
28691
  let childFile;
@@ -28583,12 +28693,7 @@ async function resolveFile(file, absPath, ctx) {
28583
28693
  const text = await ctx.readFile(childAbsPath);
28584
28694
  childFile = await parseString(ctx.services, text, childAbsPath);
28585
28695
  } catch (err) {
28586
- ctx.diagnostics.push({
28587
- severity: "error",
28588
- message: `Could not read include "${childRelPath}": ${err.message}`,
28589
- sourcePath: absPath,
28590
- line: inc.$cstNode?.range.start.line
28591
- });
28696
+ fail("NL.E0203", unreadableArgs(childRelPath, err));
28592
28697
  continue;
28593
28698
  }
28594
28699
  const { config: childConfig, content: childContent } = await resolveFile(childFile, childAbsPath, ctx);
@@ -28600,28 +28705,22 @@ async function resolveFile(file, absPath, ctx) {
28600
28705
  mode: roadmapMode,
28601
28706
  childFile,
28602
28707
  childContent,
28603
- participates: participates(childFile, childContent, ctx.stubs.has(childContent))
28708
+ participates: participates(childFile, childContent)
28604
28709
  });
28605
28710
  applyConfigMode(config2, childConfig, configMode, childAbsPath, ctx.diagnostics);
28606
28711
  applyRoadmapMode(content, childContent, childConfig, roadmapMode, childAbsPath, childRelPath, ctx.diagnostics);
28607
28712
  const isParsed = !hasParseErrors(childFile);
28608
28713
  if (isParsed && roadmapMode === "isolate" && !childContent.roadmap) {
28609
- ctx.diagnostics.push({
28610
- severity: "error",
28611
- message: `Cannot isolate "${childRelPath}": it has no roadmap declaration.`,
28612
- sourcePath: absPath,
28613
- line: inc.$cstNode?.range.start.line
28614
- });
28714
+ fail("NL.E0206", { path: childRelPath });
28615
28715
  }
28616
28716
  if (isParsed && roadmapMode !== "ignore" && childFile.roadmapDecl) {
28617
28717
  const parentStart = readStartProp(file.roadmapDecl);
28618
28718
  const childStart = readStartProp(childFile.roadmapDecl);
28619
28719
  if (parentStart !== childStart) {
28620
- ctx.diagnostics.push({
28621
- severity: "error",
28622
- message: formatStartMismatch(childRelPath, parentStart, childStart),
28623
- sourcePath: absPath,
28624
- line: inc.$cstNode?.range.start.line
28720
+ fail("NL.E0207", {
28721
+ path: childRelPath,
28722
+ ...parentStart ? { parentStart } : {},
28723
+ ...childStart ? { childStart } : {}
28625
28724
  });
28626
28725
  }
28627
28726
  }
@@ -28639,6 +28738,49 @@ async function resolveFile(file, absPath, ctx) {
28639
28738
  ctx.processed.set(absPath, result);
28640
28739
  return result;
28641
28740
  }
28741
+ function includeError(sourcePath, inc, code, ...args) {
28742
+ return {
28743
+ severity: "error",
28744
+ message: tr("en-US", code, ...args),
28745
+ sourcePath,
28746
+ ...nodeLocation(inc, "path"),
28747
+ code,
28748
+ args
28749
+ };
28750
+ }
28751
+ async function locateInclude(parentAbs, path, ctx) {
28752
+ const policy = ctx.policy;
28753
+ if (policy?.kind !== "rooted")
28754
+ return { absPath: resolve(dirname(parentAbs), path) };
28755
+ if (isAbsolute(path))
28756
+ return { refused: { reason: "absolute", path } };
28757
+ const lexical = resolve(dirname(parentAbs), path);
28758
+ if (!isWithin(policy.root, lexical))
28759
+ return { refused: { reason: "parent", path } };
28760
+ let real;
28761
+ try {
28762
+ real = await ctx.realPath(lexical);
28763
+ } catch (err) {
28764
+ return { unreadable: unreadableArgs(path, err) };
28765
+ }
28766
+ if (!isWithin(policy.root, real))
28767
+ return { refused: { reason: "symlink", path } };
28768
+ return { absPath: real };
28769
+ }
28770
+ function unreadableArgs(path, err) {
28771
+ switch (err?.code) {
28772
+ case "ENOENT":
28773
+ case "ENOTDIR":
28774
+ return { reason: "not-found", path };
28775
+ case "EISDIR":
28776
+ return { reason: "is-directory", path };
28777
+ case "EACCES":
28778
+ case "EPERM":
28779
+ return { reason: "permission-denied", path };
28780
+ }
28781
+ const detail = err instanceof Error ? err.message : void 0;
28782
+ return { reason: "unreadable", path, ...detail ? { detail } : {} };
28783
+ }
28642
28784
  function syntaxDiagnostics(file, absPath) {
28643
28785
  const doc = file.$document;
28644
28786
  if (!doc)
@@ -38071,11 +38213,13 @@ async function stageRoadmap(inputs) {
38071
38213
  const ast = document2.parseResult.value;
38072
38214
  const resolved = await resolveIncludes(ast, inputs.sourcePath, {
38073
38215
  services: inputs.services.Nowline,
38074
- readFile: inputs.readSource
38216
+ readFile: inputs.readSource,
38217
+ includePolicy: inputs.includePolicy
38075
38218
  });
38076
38219
  const isTolerated = inputs.isToleratedIncludeError ?? (() => false);
38077
- const errors = resolved.diagnostics.filter((d) => d.severity === "error" && !isTolerated(d));
38078
- const routed = resolved.diagnostics.filter(isRoutedResolveDiagnostic);
38220
+ const isCounted = (d) => d.severity !== "error" || !isTolerated(d);
38221
+ const errors = resolved.diagnostics.filter((d) => d.severity === "error" && isCounted(d));
38222
+ const routed = resolved.diagnostics.filter((d) => isRoutedResolveDiagnostic(d) && isCounted(d));
38079
38223
  const legacy = errors.find((d) => !isRoutedResolveDiagnostic(d));
38080
38224
  if (legacy) {
38081
38225
  return { kind: "include-error", document: document2, legacy, routed: [], resolved };
@@ -40879,8 +41023,8 @@ function effectiveTheme(theme, systemTheme) {
40879
41023
  }
40880
41024
 
40881
41025
  // src/index.ts
40882
- var version = true ? "0.0.0-dev.20261025020025.gc2cc722" : "0.0.0";
40883
- var sha = true ? "c2cc722" : "unknown";
41026
+ var version = true ? "0.0.0-dev.20261026035511.g8612a42" : "0.0.0";
41027
+ var sha = true ? "8612a42" : "unknown";
40884
41028
  var DEFAULT_SELECTOR = "pre code.language-nowline, code.language-nowline";
40885
41029
  var initialConfig = {
40886
41030
  theme: "auto",