docbridge 0.5.2 → 0.6.1

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/index.js CHANGED
@@ -1,5 +1,5 @@
1
- #!/usr/bin/env bun
2
- // @bun
1
+ #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
3
3
  var __create = Object.create;
4
4
  var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
@@ -31,7 +31,7 @@ var __toESM = (mod, isNodeMode, target) => {
31
31
  return to;
32
32
  };
33
33
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
- var __require = import.meta.require;
34
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
35
35
 
36
36
  // node_modules/typescript/lib/typescript.js
37
37
  var require_typescript = __commonJS((exports, module) => {
@@ -337,7 +337,7 @@ var require_typescript = __commonJS((exports, module) => {
337
337
  compareDiagnostics: () => compareDiagnostics,
338
338
  compareEmitHelpers: () => compareEmitHelpers,
339
339
  compareNumberOfDirectorySeparators: () => compareNumberOfDirectorySeparators,
340
- comparePaths: () => comparePaths,
340
+ comparePaths: () => comparePaths2,
341
341
  comparePathsCaseInsensitive: () => comparePathsCaseInsensitive,
342
342
  comparePathsCaseSensitive: () => comparePathsCaseSensitive,
343
343
  comparePatternKeys: () => comparePatternKeys,
@@ -4391,17 +4391,17 @@ m2: ${this.mapper2.__debugToString().split(`
4391
4391
  }
4392
4392
  let BoxCharacter;
4393
4393
  ((BoxCharacter2) => {
4394
- BoxCharacter2["lr"] = "\u2500";
4395
- BoxCharacter2["ud"] = "\u2502";
4396
- BoxCharacter2["dr"] = "\u256D";
4397
- BoxCharacter2["dl"] = "\u256E";
4398
- BoxCharacter2["ul"] = "\u256F";
4399
- BoxCharacter2["ur"] = "\u2570";
4400
- BoxCharacter2["udr"] = "\u251C";
4401
- BoxCharacter2["udl"] = "\u2524";
4402
- BoxCharacter2["dlr"] = "\u252C";
4403
- BoxCharacter2["ulr"] = "\u2534";
4404
- BoxCharacter2["udlr"] = "\u256B";
4394
+ BoxCharacter2["lr"] = "─";
4395
+ BoxCharacter2["ud"] = "│";
4396
+ BoxCharacter2["dr"] = "╭";
4397
+ BoxCharacter2["dl"] = "╮";
4398
+ BoxCharacter2["ul"] = "╯";
4399
+ BoxCharacter2["ur"] = "╰";
4400
+ BoxCharacter2["udr"] = "├";
4401
+ BoxCharacter2["udl"] = "┤";
4402
+ BoxCharacter2["dlr"] = "┬";
4403
+ BoxCharacter2["ulr"] = "┴";
4404
+ BoxCharacter2["udlr"] = "╫";
4405
4405
  })(BoxCharacter || (BoxCharacter = {}));
4406
4406
  let Connection;
4407
4407
  ((Connection2) => {
@@ -4652,7 +4652,7 @@ m2: ${this.mapper2.__debugToString().split(`
4652
4652
  for (let column = 0;column < columnCount; column++) {
4653
4653
  for (let lane = 0;lane < lanes.length; lane++) {
4654
4654
  const connector = connectors[column][lane];
4655
- const fill2 = connector & 4 ? "\u2500" : " ";
4655
+ const fill2 = connector & 4 ? "─" : " ";
4656
4656
  const node = grid[column][lane];
4657
4657
  if (!node) {
4658
4658
  if (column < columnCount - 1) {
@@ -4666,7 +4666,7 @@ m2: ${this.mapper2.__debugToString().split(`
4666
4666
  }
4667
4667
  }
4668
4668
  writeLane(lane, getBoxCharacter(connector));
4669
- writeLane(lane, connector & 8 && column < columnCount - 1 && !grid[column + 1][lane] ? "\u2500" : " ");
4669
+ writeLane(lane, connector & 8 && column < columnCount - 1 && !grid[column + 1][lane] ? "─" : " ");
4670
4670
  }
4671
4671
  }
4672
4672
  return `
@@ -4680,27 +4680,27 @@ ${lanes.join(`
4680
4680
  function getBoxCharacter(connector) {
4681
4681
  switch (connector) {
4682
4682
  case 3:
4683
- return "\u2502";
4683
+ return "│";
4684
4684
  case 12:
4685
- return "\u2500";
4685
+ return "─";
4686
4686
  case 5:
4687
- return "\u256F";
4687
+ return "╯";
4688
4688
  case 9:
4689
- return "\u2570";
4689
+ return "╰";
4690
4690
  case 6:
4691
- return "\u256E";
4691
+ return "╮";
4692
4692
  case 10:
4693
- return "\u256D";
4693
+ return "╭";
4694
4694
  case 7:
4695
- return "\u2524";
4695
+ return "┤";
4696
4696
  case 11:
4697
- return "\u251C";
4697
+ return "├";
4698
4698
  case 13:
4699
- return "\u2534";
4699
+ return "┴";
4700
4700
  case 14:
4701
- return "\u252C";
4701
+ return "┬";
4702
4702
  case 15:
4703
- return "\u256B";
4703
+ return "╫";
4704
4704
  }
4705
4705
  return " ";
4706
4706
  }
@@ -8840,7 +8840,7 @@ ${lanes.join(`
8840
8840
  function comparePathsCaseInsensitive(a, b) {
8841
8841
  return comparePathsWorker(a, b, compareStringsCaseInsensitive);
8842
8842
  }
8843
- function comparePaths(a, b, currentDirectory, ignoreCase) {
8843
+ function comparePaths2(a, b, currentDirectory, ignoreCase) {
8844
8844
  if (typeof currentDirectory === "string") {
8845
8845
  a = combinePaths(currentDirectory, a);
8846
8846
  b = combinePaths(currentDirectory, b);
@@ -11766,7 +11766,7 @@ ${lanes.join(`
11766
11766
  Object.defineProperty(scanner2, "__debugShowCurrentPositionInText", {
11767
11767
  get: () => {
11768
11768
  const text2 = scanner2.getText();
11769
- return text2.slice(0, scanner2.getTokenFullStart()) + "\u2551" + text2.slice(scanner2.getTokenFullStart());
11769
+ return text2.slice(0, scanner2.getTokenFullStart()) + "║" + text2.slice(scanner2.getTokenFullStart());
11770
11770
  }
11771
11771
  });
11772
11772
  }
@@ -19270,7 +19270,7 @@ ${lanes.join(`
19270
19270
  "`": "\\`",
19271
19271
  "\u2028": "\\u2028",
19272
19272
  "\u2029": "\\u2029",
19273
- "\x85": "\\u0085",
19273
+ "…": "\\u0085",
19274
19274
  "\r\n": "\\r\\n"
19275
19275
  }));
19276
19276
  function encodeUtf16EscapeSequence(charCode) {
@@ -19607,7 +19607,7 @@ ${lanes.join(`
19607
19607
  if (options.rootDir || options.composite && options.configFilePath) {
19608
19608
  const commonDir = getNormalizedAbsolutePath(getCommonSourceDirectory(options, () => [], host.getCurrentDirectory(), host.getCanonicalFileName), host.getCurrentDirectory());
19609
19609
  const outputPath = getSourceFilePathInNewDirWorker(sourceFile.fileName, options.outDir, host.getCurrentDirectory(), commonDir, host.getCanonicalFileName);
19610
- if (comparePaths(sourceFile.fileName, outputPath, host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === 0)
19610
+ if (comparePaths2(sourceFile.fileName, outputPath, host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === 0)
19611
19611
  return false;
19612
19612
  }
19613
19613
  return true;
@@ -41023,7 +41023,7 @@ ${lanes.join(`
41023
41023
  var nodeModulesAtTypes = combinePaths("node_modules", "@types");
41024
41024
  function arePathsEqual(path1, path2, host) {
41025
41025
  const useCaseSensitiveFileNames2 = typeof host.useCaseSensitiveFileNames === "function" ? host.useCaseSensitiveFileNames() : host.useCaseSensitiveFileNames;
41026
- return comparePaths(path1, path2, !useCaseSensitiveFileNames2) === 0;
41026
+ return comparePaths2(path1, path2, !useCaseSensitiveFileNames2) === 0;
41027
41027
  }
41028
41028
  function getOriginalAndResolvedFileName(fileName, host, traceEnabled) {
41029
41029
  const resolvedFileName = realPath(fileName, host, traceEnabled);
@@ -46147,7 +46147,7 @@ ${lanes.join(`
46147
46147
  return true;
46148
46148
  if (a === undefined || b === undefined)
46149
46149
  return false;
46150
- return comparePaths(a, b, ignoreCase) === 0;
46150
+ return comparePaths2(a, b, ignoreCase) === 0;
46151
46151
  }
46152
46152
  function countPathComponents(path) {
46153
46153
  let count = 0;
@@ -46363,7 +46363,7 @@ ${lanes.join(`
46363
46363
  const canTryTsExtension = preferTsExtension && hasImplementationTSFileExtension(targetFilePath);
46364
46364
  switch (mode) {
46365
46365
  case 0:
46366
- if (extensionSwappedTarget && comparePaths(extensionSwappedTarget, pathOrPattern, ignoreCase) === 0 || comparePaths(targetFilePath, pathOrPattern, ignoreCase) === 0 || outputFile && comparePaths(outputFile, pathOrPattern, ignoreCase) === 0 || declarationFile && comparePaths(declarationFile, pathOrPattern, ignoreCase) === 0) {
46366
+ if (extensionSwappedTarget && comparePaths2(extensionSwappedTarget, pathOrPattern, ignoreCase) === 0 || comparePaths2(targetFilePath, pathOrPattern, ignoreCase) === 0 || outputFile && comparePaths2(outputFile, pathOrPattern, ignoreCase) === 0 || declarationFile && comparePaths2(declarationFile, pathOrPattern, ignoreCase) === 0) {
46367
46367
  return { moduleFileToTry: packageName };
46368
46368
  }
46369
46369
  break;
@@ -47927,7 +47927,7 @@ ${lanes.join(`
47927
47927
  const isTargetPlainJs = isPlainJsFile(targetSymbolFile, compilerOptions.checkJs);
47928
47928
  const symbolName2 = symbolToString(source2);
47929
47929
  if (sourceSymbolFile && targetSymbolFile && amalgamatedDuplicates && !isEitherEnum && sourceSymbolFile !== targetSymbolFile) {
47930
- const firstFile = comparePaths(sourceSymbolFile.path, targetSymbolFile.path) === -1 ? sourceSymbolFile : targetSymbolFile;
47930
+ const firstFile = comparePaths2(sourceSymbolFile.path, targetSymbolFile.path) === -1 ? sourceSymbolFile : targetSymbolFile;
47931
47931
  const secondFile = firstFile === sourceSymbolFile ? targetSymbolFile : sourceSymbolFile;
47932
47932
  const filesDuplicates = getOrUpdate(amalgamatedDuplicates, `${firstFile.path}|${secondFile.path}`, () => ({ firstFile, secondFile, conflictingSymbols: /* @__PURE__ */ new Map }));
47933
47933
  const conflictingSymbolInfo = getOrUpdate(filesDuplicates.conflictingSymbols, symbolName2, () => ({ isBlockScoped: isEitherBlockScoped, firstFileLocations: [], secondFileLocations: [] }));
@@ -102037,7 +102037,7 @@ ${lanes.join(`
102037
102037
  } else {
102038
102038
  const ownOutputFilePath = getOwnEmitOutputFilePath(sourceFile.fileName, host, getOutputExtension(sourceFile.fileName, options));
102039
102039
  const isJsonFile = isJsonSourceFile(sourceFile);
102040
- const isJsonEmittedToSameLocation = isJsonFile && comparePaths(sourceFile.fileName, ownOutputFilePath, host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === 0;
102040
+ const isJsonEmittedToSameLocation = isJsonFile && comparePaths2(sourceFile.fileName, ownOutputFilePath, host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === 0;
102041
102041
  const jsFilePath = options.emitDeclarationOnly || isJsonEmittedToSameLocation ? undefined : ownOutputFilePath;
102042
102042
  const sourceMapFilePath = !jsFilePath || isJsonSourceFile(sourceFile) ? undefined : getSourceMapFilePath(jsFilePath, options);
102043
102043
  const declarationFilePath = forceDtsPaths || getEmitDeclarations(options) && !isJsonFile ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined;
@@ -102065,7 +102065,7 @@ ${lanes.join(`
102065
102065
  return;
102066
102066
  const isJsonFile = fileExtensionIs(inputFileName, ".json");
102067
102067
  const outputFileName = getOutputJSFileNameWorker(inputFileName, configFile.options, ignoreCase, getCommonSourceDirectory2);
102068
- return !isJsonFile || comparePaths(inputFileName, outputFileName, Debug.checkDefined(configFile.options.configFilePath), ignoreCase) !== 0 ? outputFileName : undefined;
102068
+ return !isJsonFile || comparePaths2(inputFileName, outputFileName, Debug.checkDefined(configFile.options.configFilePath), ignoreCase) !== 0 ? outputFileName : undefined;
102069
102069
  }
102070
102070
  function getOutputJSFileNameWorker(inputFileName, options, ignoreCase, getCommonSourceDirectory2) {
102071
102071
  return changeExtension(getOutputPathWithoutChangingExt(inputFileName, ignoreCase, options.outDir, getCommonSourceDirectory2), getOutputExtension(inputFileName, options));
@@ -109855,7 +109855,7 @@ ${lanes.join(`
109855
109855
  return false;
109856
109856
  }
109857
109857
  function isSameFile(file1, file2) {
109858
- return comparePaths(file1, file2, currentDirectory, !host.useCaseSensitiveFileNames()) === 0;
109858
+ return comparePaths2(file1, file2, currentDirectory, !host.useCaseSensitiveFileNames()) === 0;
109859
109859
  }
109860
109860
  function getSymlinkCache() {
109861
109861
  if (host.getSymlinkCache) {
@@ -113100,7 +113100,7 @@ ${lanes.join(`
113100
113100
  return contains(screenStartingMessageCodes, diagnostic.code) ? newLine + newLine : newLine;
113101
113101
  }
113102
113102
  function getLocaleTimeString(system) {
113103
- return !system.now ? (/* @__PURE__ */ new Date()).toLocaleTimeString() : system.now().toLocaleTimeString("en-US", { timeZone: "UTC" }).replace("\u202F", " ");
113103
+ return !system.now ? (/* @__PURE__ */ new Date()).toLocaleTimeString() : system.now().toLocaleTimeString("en-US", { timeZone: "UTC" }).replace(" ", " ");
113104
113104
  }
113105
113105
  function createWatchStatusReporter(system, pretty) {
113106
113106
  return pretty ? (diagnostic, newLine, options) => {
@@ -145523,7 +145523,7 @@ ${newComment.split(`
145523
145523
  if (files) {
145524
145524
  for (let filePath of files) {
145525
145525
  filePath = normalizePath(filePath);
145526
- if (exclude && comparePaths(filePath, exclude, scriptDirectory, ignoreCase) === 0) {
145526
+ if (exclude && comparePaths2(filePath, exclude, scriptDirectory, ignoreCase) === 0) {
145527
145527
  continue;
145528
145528
  }
145529
145529
  const { name, extension } = getFilenameWithExtensionOption(getBaseFileName(filePath), program, extensionOptions, false);
@@ -145568,16 +145568,16 @@ ${newComment.split(`
145568
145568
  }
145569
145569
  function addCompletionEntriesFromPaths(result, fragment, baseDirectory, extensionOptions, program, host, moduleSpecifierResolutionHost, paths) {
145570
145570
  const getPatternsForKey = (key) => paths[key];
145571
- const comparePaths2 = (a, b) => {
145571
+ const comparePaths22 = (a, b) => {
145572
145572
  const patternA = tryParsePattern(a);
145573
145573
  const patternB = tryParsePattern(b);
145574
145574
  const lengthA = typeof patternA === "object" ? patternA.prefix.length : a.length;
145575
145575
  const lengthB = typeof patternB === "object" ? patternB.prefix.length : b.length;
145576
145576
  return compareValues(lengthB, lengthA);
145577
145577
  };
145578
- return addCompletionEntriesFromPathsOrExportsOrImports(result, false, false, fragment, baseDirectory, extensionOptions, program, host, moduleSpecifierResolutionHost, getOwnKeys(paths), getPatternsForKey, comparePaths2);
145578
+ return addCompletionEntriesFromPathsOrExportsOrImports(result, false, false, fragment, baseDirectory, extensionOptions, program, host, moduleSpecifierResolutionHost, getOwnKeys(paths), getPatternsForKey, comparePaths22);
145579
145579
  }
145580
- function addCompletionEntriesFromPathsOrExportsOrImports(result, isExports, isImports, fragment, baseDirectory, extensionOptions, program, host, moduleSpecifierResolutionHost, keys, getPatternsForKey, comparePaths2) {
145580
+ function addCompletionEntriesFromPathsOrExportsOrImports(result, isExports, isImports, fragment, baseDirectory, extensionOptions, program, host, moduleSpecifierResolutionHost, keys, getPatternsForKey, comparePaths22) {
145581
145581
  let pathResults = [];
145582
145582
  let matchedPath;
145583
145583
  for (const key of keys) {
@@ -145590,12 +145590,12 @@ ${newComment.split(`
145590
145590
  if (!pathPattern)
145591
145591
  continue;
145592
145592
  const isMatch = typeof pathPattern === "object" && isPatternMatch(pathPattern, fragment);
145593
- const isLongestMatch = isMatch && (matchedPath === undefined || comparePaths2(keyWithoutLeadingDotSlash, matchedPath) === -1);
145593
+ const isLongestMatch = isMatch && (matchedPath === undefined || comparePaths22(keyWithoutLeadingDotSlash, matchedPath) === -1);
145594
145594
  if (isLongestMatch) {
145595
145595
  matchedPath = keyWithoutLeadingDotSlash;
145596
145596
  pathResults = pathResults.filter((r) => !r.matchedPattern);
145597
145597
  }
145598
- if (typeof pathPattern === "string" || matchedPath === undefined || comparePaths2(keyWithoutLeadingDotSlash, matchedPath) !== 1) {
145598
+ if (typeof pathPattern === "string" || matchedPath === undefined || comparePaths22(keyWithoutLeadingDotSlash, matchedPath) !== 1) {
145599
145599
  pathResults.push({
145600
145600
  matchedPattern: isMatch,
145601
145601
  results: getCompletionsForPathMapping(keyWithoutLeadingDotSlash, patterns, fragment, baseDirectory, extensionOptions, isExports, isImports, program, host, moduleSpecifierResolutionHost).map(({ name, kind, extension }) => nameAndKind(name, kind, extension))
@@ -156337,7 +156337,7 @@ ${options.prefix}` : `
156337
156337
  compareDiagnostics: () => compareDiagnostics,
156338
156338
  compareEmitHelpers: () => compareEmitHelpers,
156339
156339
  compareNumberOfDirectorySeparators: () => compareNumberOfDirectorySeparators,
156340
- comparePaths: () => comparePaths,
156340
+ comparePaths: () => comparePaths2,
156341
156341
  comparePathsCaseInsensitive: () => comparePathsCaseInsensitive,
156342
156342
  comparePathsCaseSensitive: () => comparePathsCaseSensitive,
156343
156343
  comparePatternKeys: () => comparePatternKeys,
@@ -160561,7 +160561,7 @@ ${options.prefix}` : `
160561
160561
  return this.writeLog(`TypingWatchers already invoked`);
160562
160562
  if (!fileExtensionIs(f, ".json"))
160563
160563
  return this.writeLog(`Ignoring files that are not *.json`);
160564
- if (comparePaths(f, combinePaths(this.projectService.typingsInstaller.globalTypingsCacheLocation, "package.json"), !this.useCaseSensitiveFileNames()))
160564
+ if (comparePaths2(f, combinePaths(this.projectService.typingsInstaller.globalTypingsCacheLocation, "package.json"), !this.useCaseSensitiveFileNames()))
160565
160565
  return this.writeLog(`Ignoring package.json change at global typings location`);
160566
160566
  this.onTypingInstallerWatchInvoke();
160567
160567
  }, 1, this.projectService.getWatchOptions(this), watchType, this) : (this.writeLog(`Skipping watcher creation at ${path}:: ${getDetailWatchInfo(watchType, this)}`), noopFileWatcher));
@@ -168755,36 +168755,33 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
168755
168755
  });
168756
168756
 
168757
168757
  // src/cli/index.ts
168758
- import { readFileSync as readFileSync5, statSync as statSync4 } from "fs";
168759
- import { resolve as resolve4 } from "path";
168758
+ import { readFileSync as readFileSync5, statSync as statSync5 } from "node:fs";
168759
+ import { resolve as resolve4 } from "node:path";
168760
168760
  // package.json
168761
168761
  var package_default = {
168762
168762
  name: "docbridge",
168763
- version: "0.5.2",
168764
- description: "A Bun CLI that links Markdown specifications and code declarations.",
168765
- license: "MIT",
168766
- type: "module",
168767
- bin: {
168768
- docbridge: "./dist/index.js"
168763
+ version: "0.6.1",
168764
+ description: "A CLI that links Markdown specifications and code declarations. Runs on Node.js and Bun.",
168765
+ keywords: [
168766
+ "bun",
168767
+ "cli",
168768
+ "documentation",
168769
+ "lsp",
168770
+ "markdown",
168771
+ "node",
168772
+ "specification"
168773
+ ],
168774
+ homepage: "https://github.com/salan70/docbridge#readme",
168775
+ bugs: {
168776
+ url: "https://github.com/salan70/docbridge/issues"
168769
168777
  },
168778
+ license: "MIT",
168770
168779
  repository: {
168771
168780
  type: "git",
168772
168781
  url: "git+https://github.com/salan70/docbridge.git"
168773
168782
  },
168774
- bugs: {
168775
- url: "https://github.com/salan70/docbridge/issues"
168776
- },
168777
- homepage: "https://github.com/salan70/docbridge#readme",
168778
- keywords: [
168779
- "documentation",
168780
- "markdown",
168781
- "specification",
168782
- "cli",
168783
- "bun",
168784
- "lsp"
168785
- ],
168786
- engines: {
168787
- bun: ">=1.1.31"
168783
+ bin: {
168784
+ docbridge: "./dist/index.js"
168788
168785
  },
168789
168786
  files: [
168790
168787
  "dist",
@@ -168794,6 +168791,7 @@ var package_default = {
168794
168791
  "CHANGELOG.md",
168795
168792
  "LICENSE"
168796
168793
  ],
168794
+ type: "module",
168797
168795
  scripts: {
168798
168796
  docbridge: "bun run src/cli/index.ts",
168799
168797
  check: "bun run src/cli/index.ts check",
@@ -168803,18 +168801,24 @@ var package_default = {
168803
168801
  },
168804
168802
  devDependencies: {
168805
168803
  "@types/bun": "^1.3.14",
168804
+ oxfmt: "0.57.0",
168805
+ oxlint: "1.73.0",
168806
168806
  typescript: "^5.9.0"
168807
+ },
168808
+ engines: {
168809
+ bun: ">=1.1.31",
168810
+ node: ">=22"
168807
168811
  }
168808
168812
  };
168809
168813
 
168810
168814
  // src/core/code-language.ts
168811
- import { existsSync, realpathSync } from "fs";
168812
- import { dirname, join as join3, resolve } from "path";
168813
- import { fileURLToPath } from "url";
168815
+ import { accessSync, chmodSync, constants, existsSync, realpathSync, statSync } from "node:fs";
168816
+ import { dirname as dirname2, join as join3, resolve } from "node:path";
168817
+ import { fileURLToPath } from "node:url";
168814
168818
 
168815
168819
  // src/core/glob.ts
168816
- import { lstatSync, readFileSync, readdirSync } from "fs";
168817
- import { join } from "path";
168820
+ import { lstatSync, readFileSync, readdirSync } from "node:fs";
168821
+ import { join } from "node:path";
168818
168822
  var IGNORED_SEGMENTS = new Set(["node_modules", ".git"]);
168819
168823
  function validateGlobPattern(pattern) {
168820
168824
  if (pattern.length === 0) {
@@ -168897,7 +168901,16 @@ function collectFiles(projectRoot, patterns) {
168897
168901
  }
168898
168902
  };
168899
168903
  walk("");
168900
- return [...matched].sort((left, right) => left < right ? -1 : left > right ? 1 : 0);
168904
+ return [...matched].toSorted(comparePaths);
168905
+ }
168906
+ function comparePaths(left, right) {
168907
+ if (left < right) {
168908
+ return -1;
168909
+ }
168910
+ if (left > right) {
168911
+ return 1;
168912
+ }
168913
+ return 0;
168901
168914
  }
168902
168915
  function readManagedFile(projectRoot, relativePath) {
168903
168916
  try {
@@ -168951,9 +168964,10 @@ function escapeRegExpChar(char) {
168951
168964
  }
168952
168965
 
168953
168966
  // src/core/scanner-worker.ts
168954
- import { mkdirSync } from "fs";
168955
- import { tmpdir } from "os";
168956
- import { join as join2 } from "path";
168967
+ import { spawnSync } from "node:child_process";
168968
+ import { mkdirSync } from "node:fs";
168969
+ import { tmpdir } from "node:os";
168970
+ import { dirname, join as join2 } from "node:path";
168957
168971
  function invokeScannerWorker(request, command, run = runScannerWorkerProcess) {
168958
168972
  const processResult = run({
168959
168973
  command,
@@ -168962,7 +168976,7 @@ function invokeScannerWorker(request, command, run = runScannerWorkerProcess) {
168962
168976
  if (!processResult.ok) {
168963
168977
  return {
168964
168978
  ok: false,
168965
- diagnostic: scannerUnavailableDiagnostic(request.language, processResult.error),
168979
+ diagnostic: scannerUnavailableDiagnostic(request.language, processResult.error, command[0]),
168966
168980
  stderr: processResult.stderr
168967
168981
  };
168968
168982
  }
@@ -169009,21 +169023,32 @@ function runScannerWorkerProcess(input) {
169009
169023
  try {
169010
169024
  const moduleCachePath = clangModuleCachePath();
169011
169025
  mkdirSync(moduleCachePath, { recursive: true });
169012
- const result = Bun.spawnSync({
169013
- cmd: input.command,
169026
+ const [executable = "", ...args] = input.command;
169027
+ const result = spawnSync(executable, args, {
169014
169028
  env: {
169015
- ...Bun.env,
169029
+ ...process.env,
169016
169030
  CLANG_MODULE_CACHE_PATH: moduleCachePath
169017
169031
  },
169018
- stdin: new TextEncoder().encode(input.stdin),
169019
- stdout: "pipe",
169020
- stderr: "pipe"
169032
+ input: input.stdin,
169033
+ encoding: "utf8",
169034
+ maxBuffer: 1024 * 1024 * 1024
169021
169035
  });
169036
+ const stderr = result.stderr ?? "";
169037
+ if (result.error !== undefined) {
169038
+ return { ok: false, error: result.error, stderr };
169039
+ }
169040
+ if (result.status === null) {
169041
+ return {
169042
+ ok: false,
169043
+ error: new Error(`worker terminated by signal ${result.signal ?? "unknown"}`),
169044
+ stderr
169045
+ };
169046
+ }
169022
169047
  return {
169023
169048
  ok: true,
169024
- exitCode: result.exitCode,
169025
- stdout: new TextDecoder().decode(result.stdout),
169026
- stderr: new TextDecoder().decode(result.stderr)
169049
+ exitCode: result.status,
169050
+ stdout: result.stdout ?? "",
169051
+ stderr
169027
169052
  };
169028
169053
  } catch (error) {
169029
169054
  return { ok: false, error, stderr: "" };
@@ -169075,16 +169100,30 @@ function isResponseFile(value) {
169075
169100
  function isRecord(value) {
169076
169101
  return typeof value === "object" && value !== null && !Array.isArray(value);
169077
169102
  }
169078
- function scannerUnavailableDiagnostic(language, error) {
169103
+ function scannerUnavailableDiagnostic(language, error, executable) {
169079
169104
  const label = languageLabel(language);
169080
169105
  return {
169081
169106
  severity: "error",
169082
169107
  code: "code_scanner_unavailable",
169083
169108
  language,
169084
169109
  target: language,
169085
- message: `${label} scanner worker is unavailable: ${reasonOf(error)}`
169110
+ message: `${label} scanner worker is unavailable: ${spawnFailureReason(error, executable)}`
169086
169111
  };
169087
169112
  }
169113
+ function spawnFailureReason(error, executable) {
169114
+ const reason = reasonOf(error);
169115
+ if (!isExecDenied(error) || executable === undefined) {
169116
+ return reason;
169117
+ }
169118
+ return `${reason}; the scanner is executable but ${dirname(executable)} refuses to ` + `execute it, which a \`noexec\` mount does. Install DocBridge as a project ` + `dependency, or point the installer cache at an exec-capable directory, ` + `instead of running through \`bunx\``;
169119
+ }
169120
+ function isExecDenied(error) {
169121
+ if (!(error instanceof Error)) {
169122
+ return false;
169123
+ }
169124
+ const code = error.code;
169125
+ return code === "EACCES" || code === "EPERM";
169126
+ }
169088
169127
  function scannerFailedDiagnostic(language, reason) {
169089
169128
  const label = languageLabel(language);
169090
169129
  return {
@@ -169517,11 +169556,7 @@ function duplicateLinkDiagnostic(source, target, location, range) {
169517
169556
  }
169518
169557
 
169519
169558
  // src/core/code-language.ts
169520
- var KNOWN_CODE_LANGUAGES = [
169521
- "typescript",
169522
- "swift",
169523
- "dart"
169524
- ];
169559
+ var KNOWN_CODE_LANGUAGES = ["typescript", "swift", "dart"];
169525
169560
  function isCodeLanguage(value) {
169526
169561
  return KNOWN_CODE_LANGUAGES.includes(value);
169527
169562
  }
@@ -169540,6 +169575,10 @@ function resolveScannerWorkerCommand(language, options = {}) {
169540
169575
  const candidates = scannerExecutableCandidates(language, platformKey, platformSupported, options);
169541
169576
  const found = candidates.find((candidate) => existsSync(candidate));
169542
169577
  if (found !== undefined) {
169578
+ const repair = ensureExecutable(found, options.chmod ?? chmodSync);
169579
+ if (!repair.ok) {
169580
+ return { ok: false, diagnostic: scannerUnavailableDiagnostic2(language, repair.reason) };
169581
+ }
169543
169582
  return { ok: true, command: [found] };
169544
169583
  }
169545
169584
  if (!platformSupported) {
@@ -169564,9 +169603,7 @@ function createScannerWorkerAdapter(language, command, adapterOptions = {}) {
169564
169603
  if (!commandResolution.ok) {
169565
169604
  return {
169566
169605
  ...emptyScan(language, filePath),
169567
- diagnostics: [
169568
- fileScopedScannerDiagnostic(commandResolution.diagnostic, filePath)
169569
- ]
169606
+ diagnostics: [fileScopedScannerDiagnostic(commandResolution.diagnostic, filePath)]
169570
169607
  };
169571
169608
  }
169572
169609
  const result = invokeScannerWorker({
@@ -169604,9 +169641,18 @@ function collectCodeFiles(projectRoot, codeInclude) {
169604
169641
  collected.push({ language, relPath });
169605
169642
  }
169606
169643
  }
169607
- collected.sort((left, right) => left.relPath < right.relPath ? -1 : left.relPath > right.relPath ? 1 : 0);
169644
+ collected.sort((left, right) => comparePaths2(left.relPath, right.relPath));
169608
169645
  return collected;
169609
169646
  }
169647
+ function comparePaths2(left, right) {
169648
+ if (left < right) {
169649
+ return -1;
169650
+ }
169651
+ if (left > right) {
169652
+ return 1;
169653
+ }
169654
+ return 0;
169655
+ }
169610
169656
  function scanCodeFiles(projectRoot, files, codeInclude, read, onContent) {
169611
169657
  const codeFiles = [];
169612
169658
  const diagnostics = [];
@@ -169681,6 +169727,40 @@ function scannerExecutableCandidates(language, platformKey, platformSupported, o
169681
169727
  ...platformSupported ? [join3(distRoot, "bin", platformKey, executable)] : []
169682
169728
  ];
169683
169729
  }
169730
+ function ensureExecutable(path, chmod) {
169731
+ let mode;
169732
+ try {
169733
+ mode = statSync(path).mode;
169734
+ } catch (error) {
169735
+ return { ok: false, reason: `cannot stat ${path}: ${reasonOf2(error)}` };
169736
+ }
169737
+ if (isExecutableByThisProcess(path)) {
169738
+ return { ok: true };
169739
+ }
169740
+ try {
169741
+ chmod(path, mode | 73);
169742
+ } catch (error) {
169743
+ return {
169744
+ ok: false,
169745
+ reason: `${path} is not executable (mode ${formatMode(mode)}) and the executable ` + `bit could not be restored: ${reasonOf2(error)}; run \`chmod +x ${path}\` ` + `or reinstall DocBridge into a writable location`
169746
+ };
169747
+ }
169748
+ return { ok: true };
169749
+ }
169750
+ function isExecutableByThisProcess(path) {
169751
+ try {
169752
+ accessSync(path, constants.X_OK);
169753
+ return true;
169754
+ } catch {
169755
+ return false;
169756
+ }
169757
+ }
169758
+ function formatMode(mode) {
169759
+ return `0${(mode & 4095).toString(8).padStart(3, "0")}`;
169760
+ }
169761
+ function reasonOf2(error) {
169762
+ return error instanceof Error ? error.message : String(error);
169763
+ }
169684
169764
  function isSupportedScannerPlatformKey(platformKey) {
169685
169765
  return SUPPORTED_SCANNER_PLATFORM_KEYS.includes(platformKey);
169686
169766
  }
@@ -169692,7 +169772,7 @@ function scannerRootsFromModuleUrl(moduleUrl) {
169692
169772
  } catch {
169693
169773
  resolved = modulePath;
169694
169774
  }
169695
- const moduleDir = dirname(resolved);
169775
+ const moduleDir = dirname2(resolved);
169696
169776
  return { distRoot: moduleDir, sourceRoot: resolve(moduleDir, "..", "..") };
169697
169777
  }
169698
169778
  function sourceRootPath() {
@@ -169702,7 +169782,7 @@ function distRootPath() {
169702
169782
  return scannerRootsFromModuleUrl(import.meta.url).distRoot;
169703
169783
  }
169704
169784
  function scannerExecutableName(language) {
169705
- return language === "swift" ? "speclink-swift-scanner" : "speclink_dart_scanner";
169785
+ return language === "swift" ? "docbridge-swift-scanner" : "docbridge_dart_scanner";
169706
169786
  }
169707
169787
  function scannerUnavailableDiagnostic2(language, reason) {
169708
169788
  const label = language.charAt(0).toUpperCase() + language.slice(1);
@@ -169716,8 +169796,8 @@ function scannerUnavailableDiagnostic2(language, reason) {
169716
169796
  }
169717
169797
 
169718
169798
  // src/core/config.ts
169719
- import { readFileSync as readFileSync2 } from "fs";
169720
- import { join as join4 } from "path";
169799
+ import { readFileSync as readFileSync2 } from "node:fs";
169800
+ import { join as join4 } from "node:path";
169721
169801
  var CONFIG_FILE_NAME = "docbridge.config.json";
169722
169802
  var EMPTY_CONFIG = {
169723
169803
  include: { code: {}, docs: [] }
@@ -169932,24 +170012,18 @@ function isStringArray(value) {
169932
170012
 
169933
170013
  // src/core/diagnostics.ts
169934
170014
  function sortDiagnostics(diagnostics) {
169935
- return [...diagnostics].sort(compareDiagnostics);
170015
+ return [...diagnostics].toSorted(compareDiagnostics);
169936
170016
  }
169937
170017
  function summarizeDiagnostics(diagnostics) {
169938
- return diagnostics.reduce((summary, diagnostic) => {
170018
+ const summary = { errors: 0, warnings: 0 };
170019
+ for (const diagnostic of diagnostics) {
169939
170020
  if (diagnostic.severity === "error") {
169940
- return {
169941
- ...summary,
169942
- errors: summary.errors + 1
169943
- };
170021
+ summary.errors += 1;
170022
+ } else {
170023
+ summary.warnings += 1;
169944
170024
  }
169945
- return {
169946
- ...summary,
169947
- warnings: summary.warnings + 1
169948
- };
169949
- }, {
169950
- errors: 0,
169951
- warnings: 0
169952
- });
170025
+ }
170026
+ return summary;
169953
170027
  }
169954
170028
  function formatDiagnostic(diagnostic) {
169955
170029
  const location = diagnostic.location;
@@ -170042,7 +170116,7 @@ function counterpartsOf(graph, endpoint) {
170042
170116
  resolved.push(doc);
170043
170117
  }
170044
170118
  }
170045
- return resolved.sort(compareEndpoints);
170119
+ return resolved.toSorted(compareEndpoints);
170046
170120
  }
170047
170121
  function addTo(map, key, value) {
170048
170122
  const existing = map.get(key);
@@ -170299,7 +170373,7 @@ function flushDanglingWith(pending, diagnostics, message) {
170299
170373
  }
170300
170374
 
170301
170375
  // src/core/related.ts
170302
- import { isAbsolute, relative } from "path";
170376
+ import { isAbsolute, relative } from "node:path";
170303
170377
  function normalizeChangedPaths(projectRoot, paths) {
170304
170378
  const normalized = new Set;
170305
170379
  for (const raw of paths) {
@@ -170314,7 +170388,7 @@ function normalizeChangedPaths(projectRoot, paths) {
170314
170388
  }
170315
170389
  function computeRelated(graph, changedFiles) {
170316
170390
  const changedSet = new Set(changedFiles);
170317
- const sortedPaths = [...changedSet].sort((left, right) => left.localeCompare(right));
170391
+ const sortedPaths = [...changedSet].toSorted((left, right) => left.localeCompare(right));
170318
170392
  const endpointsByFile = indexEndpointsByFile(graph);
170319
170393
  const files = [];
170320
170394
  for (const filePath of sortedPaths) {
@@ -170607,7 +170681,7 @@ function relationshipDiagnostic(code, source, target, message, link) {
170607
170681
  var MAX_SECTION_LENGTH = 2000;
170608
170682
  var TRUNCATION_MARKER = `
170609
170683
 
170610
- \u2026`;
170684
+ …`;
170611
170685
  var atxHeadingPattern2 = /^ {0,3}(#{1,6})(?:[ \t]+.*)?$/;
170612
170686
  var fenceOpenPattern2 = /^ {0,3}(?:`{3,}|~{3,})/;
170613
170687
  function extractDocSection(content, headingLine) {
@@ -170703,9 +170777,9 @@ function computeContext(graph, contentByFile, inputFiles) {
170703
170777
  linkedFromByEndpoint.get(counterpart.endpoint)?.add(endpoint.endpoint);
170704
170778
  }
170705
170779
  }
170706
- const contexts = [...blockByEndpoint.values()].sort(compareBlocks);
170780
+ const contexts = [...blockByEndpoint.values()].toSorted(compareBlocks);
170707
170781
  for (const block of contexts) {
170708
- block.linkedFrom = [...linkedFromByEndpoint.get(block.endpoint) ?? []].sort((left, right) => left.localeCompare(right));
170782
+ block.linkedFrom = [...linkedFromByEndpoint.get(block.endpoint) ?? []].toSorted((left, right) => left.localeCompare(right));
170709
170783
  }
170710
170784
  return {
170711
170785
  contexts,
@@ -170933,8 +171007,8 @@ function computeGraphResult(options) {
170933
171007
  return docNode(doc, options.contentByFile, options.includeContent);
170934
171008
  }
170935
171009
  return;
170936
- }).filter((node) => node !== undefined).sort(compareNodes);
170937
- const pairs = computePairs(includedEdges).sort(comparePairs);
171010
+ }).filter((node) => node !== undefined).toSorted(compareNodes);
171011
+ const pairs = computePairs(includedEdges).toSorted(comparePairs);
170938
171012
  const diagnostics = filterDiagnostics(options.diagnostics, nodes, options.inputFiles);
170939
171013
  const bidirectionalPairs = pairs.filter((pair) => pair.hasDocEdge && pair.hasCodeEdge).length;
170940
171014
  const oneWayEdges = pairs.filter((pair) => pair.hasDocEdge !== pair.hasCodeEdge).length;
@@ -171141,7 +171215,7 @@ function computePairs(edges) {
171141
171215
  return [...byKey.values()];
171142
171216
  }
171143
171217
  function appendDocsOrientedLines(lines, result) {
171144
- const docs = result.nodes.filter((node) => node.kind === "doc").sort(compareNodes);
171218
+ const docs = result.nodes.filter((node) => node.kind === "doc").toSorted(compareNodes);
171145
171219
  for (const doc of docs) {
171146
171220
  const pairs = result.pairs.filter((pair) => pair.docEndpoint === doc.endpoint);
171147
171221
  if (pairs.length === 0) {
@@ -171154,21 +171228,21 @@ function appendDocsOrientedLines(lines, result) {
171154
171228
  lines.push("");
171155
171229
  }
171156
171230
  lines.push(doc.filePath);
171157
- for (const pair of pairs.sort(comparePairs)) {
171231
+ for (const pair of pairs.toSorted(comparePairs)) {
171158
171232
  lines.push(` ${fragmentOf2(pair.docEndpoint)} -> ${pair.codeEndpoint} (${pairStatus(pair)})`);
171159
171233
  }
171160
171234
  }
171161
171235
  }
171162
171236
  function appendScopedLines(lines, result, inputFiles) {
171163
171237
  const inputSet = new Set(inputFiles);
171164
- const nodes = result.nodes.filter((node) => inputSet.has(node.filePath)).sort(compareNodes);
171238
+ const nodes = result.nodes.filter((node) => inputSet.has(node.filePath)).toSorted(compareNodes);
171165
171239
  for (const node of nodes) {
171166
171240
  if (lines.length > 0) {
171167
171241
  lines.push("");
171168
171242
  }
171169
171243
  lines.push(node.filePath);
171170
171244
  const pairs = result.pairs.filter((pair) => pair.codeEndpoint === node.endpoint || pair.docEndpoint === node.endpoint);
171171
- for (const pair of pairs.sort(comparePairs)) {
171245
+ for (const pair of pairs.toSorted(comparePairs)) {
171172
171246
  if (node.kind === "doc") {
171173
171247
  lines.push(` ${fragmentOf2(pair.docEndpoint)} -> ${pair.codeEndpoint} (${pairStatus(pair)})`);
171174
171248
  } else {
@@ -171214,73 +171288,7 @@ function comparePairs(left, right) {
171214
171288
  }
171215
171289
 
171216
171290
  // src/lsp/server.ts
171217
- import { fileURLToPath as fileURLToPath3 } from "url";
171218
-
171219
- // src/lsp/transport.ts
171220
- var HEADER_SEPARATOR = `\r
171221
- \r
171222
- `;
171223
- var CONTENT_LENGTH_HEADER = "content-length";
171224
- function encodeMessage(message) {
171225
- const body = Buffer.from(JSON.stringify(message), "utf8");
171226
- const header = Buffer.from(`Content-Length: ${body.byteLength}${HEADER_SEPARATOR}`, "utf8");
171227
- return Buffer.concat([header, body]);
171228
- }
171229
-
171230
- class MessageReader {
171231
- buffer = Buffer.alloc(0);
171232
- append(chunk) {
171233
- this.buffer = Buffer.concat([this.buffer, Buffer.from(chunk)]);
171234
- }
171235
- read() {
171236
- const messages = [];
171237
- for (;; ) {
171238
- const message = this.readOne();
171239
- if (message === null) {
171240
- break;
171241
- }
171242
- messages.push(message.value);
171243
- }
171244
- return messages;
171245
- }
171246
- readOne() {
171247
- const separatorText = HEADER_SEPARATOR;
171248
- const headerEnd = this.buffer.indexOf(separatorText, 0, "utf8");
171249
- if (headerEnd === -1) {
171250
- return null;
171251
- }
171252
- const headerText = this.buffer.toString("utf8", 0, headerEnd);
171253
- const contentLength = parseContentLength(headerText);
171254
- const bodyStart = headerEnd + separatorText.length;
171255
- if (this.buffer.byteLength - bodyStart < contentLength) {
171256
- return null;
171257
- }
171258
- const bodyEnd = bodyStart + contentLength;
171259
- const bodyText = this.buffer.toString("utf8", bodyStart, bodyEnd);
171260
- this.buffer = this.buffer.subarray(bodyEnd);
171261
- return { value: JSON.parse(bodyText) };
171262
- }
171263
- }
171264
- function parseContentLength(headerText) {
171265
- const lines = headerText.split(`\r
171266
- `);
171267
- for (const line of lines) {
171268
- const colonIndex = line.indexOf(":");
171269
- if (colonIndex === -1) {
171270
- continue;
171271
- }
171272
- const name = line.slice(0, colonIndex).trim().toLowerCase();
171273
- if (name !== CONTENT_LENGTH_HEADER) {
171274
- continue;
171275
- }
171276
- const value = Number.parseInt(line.slice(colonIndex + 1).trim(), 10);
171277
- if (Number.isNaN(value) || value < 0) {
171278
- throw new Error(`Invalid Content-Length header: ${line}`);
171279
- }
171280
- return value;
171281
- }
171282
- throw new Error("Malformed LSP message: missing Content-Length header.");
171283
- }
171291
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
171284
171292
 
171285
171293
  // src/lsp/position.ts
171286
171294
  function toLspPosition(position) {
@@ -171305,70 +171313,6 @@ function rangeContains(range, position) {
171305
171313
  return true;
171306
171314
  }
171307
171315
 
171308
- // src/lsp/index-lookup.ts
171309
- function buildPositionIndex(graph2) {
171310
- const byFile = new Map;
171311
- const add = (range, endpoint) => {
171312
- if (range === undefined) {
171313
- return;
171314
- }
171315
- addTo2(byFile, endpoint.filePath, { range, endpoint });
171316
- };
171317
- for (const symbol of graph2.codeByEndpoint.values()) {
171318
- add(symbol.nameRange, symbol);
171319
- }
171320
- for (const anchor of graph2.docByEndpoint.values()) {
171321
- add(anchor.headingTextRange, anchor);
171322
- }
171323
- return { byFile };
171324
- }
171325
- function endpointAt(index, filePath, position) {
171326
- const entries = index.byFile.get(filePath);
171327
- if (entries === undefined) {
171328
- return;
171329
- }
171330
- for (const entry of entries) {
171331
- if (rangeContains(entry.range, position)) {
171332
- return entry.endpoint;
171333
- }
171334
- }
171335
- return;
171336
- }
171337
- function addTo2(map, key, value) {
171338
- const existing = map.get(key);
171339
- if (existing === undefined) {
171340
- map.set(key, [value]);
171341
- return;
171342
- }
171343
- existing.push(value);
171344
- }
171345
-
171346
- // src/lsp/navigation.ts
171347
- function definition(state, filePath, position) {
171348
- return counterpartLocators(state, filePath, position);
171349
- }
171350
- function references(state, filePath, position) {
171351
- return counterpartLocators(state, filePath, position);
171352
- }
171353
- function counterpartLocators(state, filePath, position) {
171354
- const element = endpointAt(state.index, filePath, position);
171355
- if (element === undefined) {
171356
- return [];
171357
- }
171358
- return counterpartsOf(state.graph, element.endpoint).map((counterpart) => ({
171359
- filePath: counterpart.filePath,
171360
- range: elementRange(counterpart)
171361
- }));
171362
- }
171363
- function elementRange(element) {
171364
- const range = element.kind === "code" ? element.nameRange : element.headingTextRange;
171365
- if (range !== undefined) {
171366
- return range;
171367
- }
171368
- const { line, column } = element.location;
171369
- return { start: { line, column }, end: { line, column } };
171370
- }
171371
-
171372
171316
  // src/lsp/diagnostics.ts
171373
171317
  var SOURCE = "docbridge";
171374
171318
  function toLspDiagnostic(diagnostic, lineLengths) {
@@ -171407,6 +171351,44 @@ function rangeFor(diagnostic, lineLengths) {
171407
171351
  return { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } };
171408
171352
  }
171409
171353
 
171354
+ // src/lsp/index-lookup.ts
171355
+ function buildPositionIndex(graph2) {
171356
+ const byFile = new Map;
171357
+ const add = (range, endpoint) => {
171358
+ if (range === undefined) {
171359
+ return;
171360
+ }
171361
+ addTo2(byFile, endpoint.filePath, { range, endpoint });
171362
+ };
171363
+ for (const symbol of graph2.codeByEndpoint.values()) {
171364
+ add(symbol.nameRange, symbol);
171365
+ }
171366
+ for (const anchor of graph2.docByEndpoint.values()) {
171367
+ add(anchor.headingTextRange, anchor);
171368
+ }
171369
+ return { byFile };
171370
+ }
171371
+ function endpointAt(index, filePath, position) {
171372
+ const entries = index.byFile.get(filePath);
171373
+ if (entries === undefined) {
171374
+ return;
171375
+ }
171376
+ for (const entry of entries) {
171377
+ if (rangeContains(entry.range, position)) {
171378
+ return entry.endpoint;
171379
+ }
171380
+ }
171381
+ return;
171382
+ }
171383
+ function addTo2(map, key, value) {
171384
+ const existing = map.get(key);
171385
+ if (existing === undefined) {
171386
+ map.set(key, [value]);
171387
+ return;
171388
+ }
171389
+ existing.push(value);
171390
+ }
171391
+
171410
171392
  // src/lsp/hover.ts
171411
171393
  var DIVIDER = `
171412
171394
 
@@ -171472,6 +171454,52 @@ function lineAt(content, line) {
171472
171454
  `)[line - 1] ?? "";
171473
171455
  }
171474
171456
 
171457
+ // src/lsp/navigation.ts
171458
+ function definition(state, filePath, position) {
171459
+ return counterpartLocators(state, filePath, position);
171460
+ }
171461
+ function references(state, filePath, position) {
171462
+ return counterpartLocators(state, filePath, position);
171463
+ }
171464
+ function counterpartLocators(state, filePath, position) {
171465
+ const element = endpointAt(state.index, filePath, position);
171466
+ if (element === undefined) {
171467
+ return [];
171468
+ }
171469
+ return counterpartsOf(state.graph, element.endpoint).map((counterpart) => ({
171470
+ filePath: counterpart.filePath,
171471
+ range: elementRange(counterpart)
171472
+ }));
171473
+ }
171474
+ function elementRange(element) {
171475
+ const range = element.kind === "code" ? element.nameRange : element.headingTextRange;
171476
+ if (range !== undefined) {
171477
+ return range;
171478
+ }
171479
+ const { line, column } = element.location;
171480
+ return { start: { line, column }, end: { line, column } };
171481
+ }
171482
+
171483
+ // src/lsp/paths.ts
171484
+ import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2, sep } from "node:path";
171485
+ import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
171486
+ function uriToRelativePath(projectRoot, uri) {
171487
+ let absolute;
171488
+ try {
171489
+ absolute = fileURLToPath2(uri);
171490
+ } catch {
171491
+ return;
171492
+ }
171493
+ const rel = relative2(projectRoot, absolute);
171494
+ if (rel === "" || rel.startsWith("..") || isAbsolute2(rel)) {
171495
+ return;
171496
+ }
171497
+ return rel.split(sep).join("/");
171498
+ }
171499
+ function relativePathToUri(projectRoot, relPath) {
171500
+ return pathToFileURL(resolve2(projectRoot, relPath)).href;
171501
+ }
171502
+
171475
171503
  // src/lsp/project.ts
171476
171504
  class Project {
171477
171505
  projectRoot;
@@ -171556,7 +171584,7 @@ class Project {
171556
171584
  }
171557
171585
  }
171558
171586
  }
171559
- return all.sort((left, right) => left.relPath < right.relPath ? -1 : left.relPath > right.relPath ? 1 : 0);
171587
+ return all.toSorted((left, right) => comparePaths3(left.relPath, right.relPath));
171560
171588
  }
171561
171589
  readContent(relPath) {
171562
171590
  const overlaid = this.overlay.get(relPath);
@@ -171578,7 +171606,7 @@ class Project {
171578
171606
  paths.add(relPath);
171579
171607
  }
171580
171608
  }
171581
- return [...paths].sort((left, right) => left < right ? -1 : left > right ? 1 : 0);
171609
+ return [...paths].toSorted(comparePaths3);
171582
171610
  }
171583
171611
  contentFor(relPath, scanDiagnostics) {
171584
171612
  const overlaid = this.overlay.get(relPath);
@@ -171593,6 +171621,15 @@ class Project {
171593
171621
  return read.content;
171594
171622
  }
171595
171623
  }
171624
+ function comparePaths3(left, right) {
171625
+ if (left < right) {
171626
+ return -1;
171627
+ }
171628
+ if (left > right) {
171629
+ return 1;
171630
+ }
171631
+ return 0;
171632
+ }
171596
171633
  function emptyState() {
171597
171634
  const graph2 = buildLinkGraph([], []);
171598
171635
  return {
@@ -171603,24 +171640,70 @@ function emptyState() {
171603
171640
  };
171604
171641
  }
171605
171642
 
171606
- // src/lsp/paths.ts
171607
- import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2, sep } from "path";
171608
- import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
171609
- function uriToRelativePath(projectRoot, uri) {
171610
- let absolute;
171611
- try {
171612
- absolute = fileURLToPath2(uri);
171613
- } catch {
171614
- return;
171643
+ // src/lsp/transport.ts
171644
+ var HEADER_SEPARATOR = `\r
171645
+ \r
171646
+ `;
171647
+ var CONTENT_LENGTH_HEADER = "content-length";
171648
+ function encodeMessage(message) {
171649
+ const body = Buffer.from(JSON.stringify(message), "utf8");
171650
+ const header = Buffer.from(`Content-Length: ${body.byteLength}${HEADER_SEPARATOR}`, "utf8");
171651
+ return Buffer.concat([header, body]);
171652
+ }
171653
+
171654
+ class MessageReader {
171655
+ buffer = Buffer.alloc(0);
171656
+ append(chunk) {
171657
+ this.buffer = Buffer.concat([this.buffer, Buffer.from(chunk)]);
171615
171658
  }
171616
- const rel = relative2(projectRoot, absolute);
171617
- if (rel === "" || rel.startsWith("..") || isAbsolute2(rel)) {
171618
- return;
171659
+ read() {
171660
+ const messages = [];
171661
+ for (;; ) {
171662
+ const message = this.readOne();
171663
+ if (message === null) {
171664
+ break;
171665
+ }
171666
+ messages.push(message.value);
171667
+ }
171668
+ return messages;
171669
+ }
171670
+ readOne() {
171671
+ const separatorText = HEADER_SEPARATOR;
171672
+ const headerEnd = this.buffer.indexOf(separatorText, 0, "utf8");
171673
+ if (headerEnd === -1) {
171674
+ return null;
171675
+ }
171676
+ const headerText = this.buffer.toString("utf8", 0, headerEnd);
171677
+ const contentLength = parseContentLength(headerText);
171678
+ const bodyStart = headerEnd + separatorText.length;
171679
+ if (this.buffer.byteLength - bodyStart < contentLength) {
171680
+ return null;
171681
+ }
171682
+ const bodyEnd = bodyStart + contentLength;
171683
+ const bodyText = this.buffer.toString("utf8", bodyStart, bodyEnd);
171684
+ this.buffer = this.buffer.subarray(bodyEnd);
171685
+ return { value: JSON.parse(bodyText) };
171619
171686
  }
171620
- return rel.split(sep).join("/");
171621
171687
  }
171622
- function relativePathToUri(projectRoot, relPath) {
171623
- return pathToFileURL(resolve2(projectRoot, relPath)).href;
171688
+ function parseContentLength(headerText) {
171689
+ const lines = headerText.split(`\r
171690
+ `);
171691
+ for (const line of lines) {
171692
+ const colonIndex = line.indexOf(":");
171693
+ if (colonIndex === -1) {
171694
+ continue;
171695
+ }
171696
+ const name = line.slice(0, colonIndex).trim().toLowerCase();
171697
+ if (name !== CONTENT_LENGTH_HEADER) {
171698
+ continue;
171699
+ }
171700
+ const value = Number.parseInt(line.slice(colonIndex + 1).trim(), 10);
171701
+ if (Number.isNaN(value) || value < 0) {
171702
+ throw new Error(`Invalid Content-Length header: ${line}`);
171703
+ }
171704
+ return value;
171705
+ }
171706
+ throw new Error("Malformed LSP message: missing Content-Length header.");
171624
171707
  }
171625
171708
 
171626
171709
  // src/lsp/server.ts
@@ -171887,18 +171970,12 @@ function fullChangeText(changes) {
171887
171970
  }
171888
171971
 
171889
171972
  // src/cli/init.ts
171890
- import {
171891
- cpSync,
171892
- mkdirSync as mkdirSync2,
171893
- readFileSync as readFileSync4,
171894
- statSync as statSync3,
171895
- writeFileSync
171896
- } from "fs";
171897
- import { join as join7, resolve as resolve3 } from "path";
171973
+ import { cpSync, mkdirSync as mkdirSync2, readFileSync as readFileSync4, statSync as statSync4, writeFileSync } from "node:fs";
171974
+ import { join as join7, resolve as resolve3 } from "node:path";
171898
171975
 
171899
171976
  // src/core/init-discovery.ts
171900
- import { existsSync as existsSync2, readdirSync as readdirSync2, statSync } from "fs";
171901
- import { basename, dirname as dirname2, join as join5 } from "path";
171977
+ import { existsSync as existsSync2, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
171978
+ import { basename, dirname as dirname3, join as join5 } from "node:path";
171902
171979
  var HIGH_CONFIDENCE_DIR_NAMES = new Set([
171903
171980
  "docs/specs",
171904
171981
  "specs",
@@ -171961,7 +172038,7 @@ function discoverDocsScope(projectRoot) {
171961
172038
  }
171962
172039
  const grouped = new Map;
171963
172040
  for (const filePath of eligible) {
171964
- const directory = dirname2(filePath);
172041
+ const directory = dirname3(filePath);
171965
172042
  const existing = grouped.get(directory) ?? [];
171966
172043
  existing.push(filePath);
171967
172044
  grouped.set(directory, existing);
@@ -171971,7 +172048,7 @@ function discoverDocsScope(projectRoot) {
171971
172048
  pattern: `${directory}/**/*.md`,
171972
172049
  score: scoreDocsDirectory(directory),
171973
172050
  fileCount: files.length
171974
- })).sort((left, right) => right.score !== left.score ? right.score - left.score : left.directory.localeCompare(right.directory));
172051
+ })).toSorted((left, right) => right.score !== left.score ? right.score - left.score : left.directory.localeCompare(right.directory));
171975
172052
  const topScore = candidates[0]?.score ?? 0;
171976
172053
  if (topScore === 0) {
171977
172054
  return {
@@ -172068,7 +172145,7 @@ function collectMarkdownFiles(projectRoot, currentDir = ".") {
172068
172145
  const absolutePath = join5(projectRoot, relPath);
172069
172146
  let stats;
172070
172147
  try {
172071
- stats = statSync(absolutePath);
172148
+ stats = statSync2(absolutePath);
172072
172149
  } catch {
172073
172150
  continue;
172074
172151
  }
@@ -172080,7 +172157,7 @@ function collectMarkdownFiles(projectRoot, currentDir = ".") {
172080
172157
  files.push(relPath);
172081
172158
  }
172082
172159
  }
172083
- return files.sort();
172160
+ return files.toSorted();
172084
172161
  }
172085
172162
  function isEligibleDocsFile(filePath) {
172086
172163
  if (EXCLUDED_PROSE_BASENAMES.has(basename(filePath).toLowerCase())) {
@@ -172148,15 +172225,9 @@ function isExcludedCodeFile(filePath, language) {
172148
172225
  }
172149
172226
 
172150
172227
  // src/core/init-plan.ts
172151
- import {
172152
- existsSync as existsSync3,
172153
- readdirSync as readdirSync3,
172154
- readFileSync as readFileSync3,
172155
- realpathSync as realpathSync2,
172156
- statSync as statSync2
172157
- } from "fs";
172158
- import { dirname as dirname3, join as join6, relative as relative4 } from "path";
172159
- import { fileURLToPath as fileURLToPath4 } from "url";
172228
+ import { existsSync as existsSync3, readdirSync as readdirSync3, readFileSync as readFileSync3, realpathSync as realpathSync2, statSync as statSync3 } from "node:fs";
172229
+ import { dirname as dirname4, join as join6, relative as relative3 } from "node:path";
172230
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
172160
172231
  var CONFIG_FILE_NAME2 = "docbridge.config.json";
172161
172232
  var INIT_SKILL_NAMES = [
172162
172233
  "docbridge-adopt",
@@ -172253,12 +172324,12 @@ function resolvePackageRoot(moduleUrl = import.meta.url) {
172253
172324
  } catch {
172254
172325
  resolved = modulePath;
172255
172326
  }
172256
- let dir = dirname3(resolved);
172327
+ let dir = dirname4(resolved);
172257
172328
  for (;; ) {
172258
172329
  if (existsSync3(join6(dir, "templates", "skills"))) {
172259
172330
  return dir;
172260
172331
  }
172261
- const parent = dirname3(dir);
172332
+ const parent = dirname4(dir);
172262
172333
  if (parent === dir) {
172263
172334
  return dir;
172264
172335
  }
@@ -172273,7 +172344,7 @@ function listDistributableSkills(packageRoot) {
172273
172344
  } catch {
172274
172345
  return [];
172275
172346
  }
172276
- return entries.filter((entry) => entry.startsWith("docbridge-")).filter((entry) => existsSync3(join6(skillsRoot, entry, "SKILL.md"))).sort();
172347
+ return entries.filter((entry) => entry.startsWith("docbridge-")).filter((entry) => existsSync3(join6(skillsRoot, entry, "SKILL.md"))).toSorted();
172277
172348
  }
172278
172349
  function formatInitPlan(plan) {
172279
172350
  const lines = [];
@@ -172395,7 +172466,7 @@ function planSkillOperations(input) {
172395
172466
  }
172396
172467
  operations.push({
172397
172468
  action,
172398
- path: relative4(input.projectRoot, destinationDir),
172469
+ path: relative3(input.projectRoot, destinationDir),
172399
172470
  reason
172400
172471
  });
172401
172472
  }
@@ -172493,7 +172564,12 @@ function agentDestinations(agentTarget) {
172493
172564
  }
172494
172565
  }
172495
172566
  function formatFileOp(operation) {
172496
- const label = operation.action === "would-create" ? "would create" : operation.action === "would-overwrite" ? "would overwrite" : operation.action;
172567
+ let label = operation.action;
172568
+ if (operation.action === "would-create") {
172569
+ label = "would create";
172570
+ } else if (operation.action === "would-overwrite") {
172571
+ label = "would overwrite";
172572
+ }
172497
172573
  const reason = operation.reason ? ` (${operation.reason})` : "";
172498
172574
  return `- ${label} ${operation.path}${reason}`;
172499
172575
  }
@@ -172731,7 +172807,7 @@ function resolveProjectRoot(root) {
172731
172807
  const projectRoot = resolve3(root);
172732
172808
  let stats;
172733
172809
  try {
172734
- stats = statSync3(projectRoot);
172810
+ stats = statSync4(projectRoot);
172735
172811
  } catch {
172736
172812
  throw new InitCliError(`Root path does not exist: ${root}`);
172737
172813
  }
@@ -172954,7 +173030,7 @@ function resolveProjectRoot2(root) {
172954
173030
  const projectRoot = resolve4(root);
172955
173031
  let stats;
172956
173032
  try {
172957
- stats = statSync4(projectRoot);
173033
+ stats = statSync5(projectRoot);
172958
173034
  } catch {
172959
173035
  throw new CliError(`Root path does not exist: ${root}`);
172960
173036
  }
@@ -173137,8 +173213,8 @@ function run(argv, io = {
173137
173213
  return 1;
173138
173214
  }
173139
173215
  }
173140
- if (import.meta.main) {
173141
- process.exitCode = run(Bun.argv.slice(2));
173216
+ if (__require.main == __require.module) {
173217
+ process.exitCode = run(process.argv.slice(2));
173142
173218
  }
173143
173219
  export {
173144
173220
  run,