@commentray/core 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/angles-toml.d.ts +18 -0
  2. package/dist/angles-toml.d.ts.map +1 -0
  3. package/dist/angles-toml.js +62 -0
  4. package/dist/angles-toml.js.map +1 -0
  5. package/dist/angles.d.ts +6 -0
  6. package/dist/angles.d.ts.map +1 -0
  7. package/dist/angles.js +14 -0
  8. package/dist/angles.js.map +1 -0
  9. package/dist/blocks.d.ts +66 -0
  10. package/dist/blocks.d.ts.map +1 -0
  11. package/dist/blocks.js +101 -0
  12. package/dist/blocks.js.map +1 -0
  13. package/dist/commentray-path-resolution.d.ts +20 -0
  14. package/dist/commentray-path-resolution.d.ts.map +1 -0
  15. package/dist/commentray-path-resolution.js +38 -0
  16. package/dist/commentray-path-resolution.js.map +1 -0
  17. package/dist/config.d.ts +48 -0
  18. package/dist/config.d.ts.map +1 -1
  19. package/dist/config.js +66 -2
  20. package/dist/config.js.map +1 -1
  21. package/dist/github-url.d.ts +14 -0
  22. package/dist/github-url.d.ts.map +1 -0
  23. package/dist/github-url.js +25 -0
  24. package/dist/github-url.js.map +1 -0
  25. package/dist/index.d.ts +14 -4
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +8 -2
  28. package/dist/index.js.map +1 -1
  29. package/dist/metadata.js +48 -22
  30. package/dist/metadata.js.map +1 -1
  31. package/dist/migrate.d.ts.map +1 -1
  32. package/dist/migrate.js +32 -10
  33. package/dist/migrate.js.map +1 -1
  34. package/dist/model.d.ts +37 -2
  35. package/dist/model.d.ts.map +1 -1
  36. package/dist/model.js +1 -1
  37. package/dist/model.js.map +1 -1
  38. package/dist/paths.d.ts +17 -1
  39. package/dist/paths.d.ts.map +1 -1
  40. package/dist/paths.js +31 -1
  41. package/dist/paths.js.map +1 -1
  42. package/dist/scroll-sync.d.ts +27 -0
  43. package/dist/scroll-sync.d.ts.map +1 -0
  44. package/dist/scroll-sync.js +80 -0
  45. package/dist/scroll-sync.js.map +1 -0
  46. package/dist/validate-project.d.ts +6 -0
  47. package/dist/validate-project.d.ts.map +1 -1
  48. package/dist/validate-project.js +45 -14
  49. package/dist/validate-project.js.map +1 -1
  50. package/package.json +1 -1
@@ -0,0 +1,25 @@
1
+ import { normalizeRepoRelativePath } from "./paths.js";
2
+ /**
3
+ * Parses a GitHub repository web URL into owner + repo name (no API calls).
4
+ * Accepts optional trailing slash and `.git` suffix.
5
+ */
6
+ export function parseGithubRepoWebUrl(url) {
7
+ const t = url.trim().replace(/\/+$/, "");
8
+ const m = t.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/i);
9
+ if (!m)
10
+ return null;
11
+ return { owner: m[1], repo: m[2] };
12
+ }
13
+ /**
14
+ * Builds a `https://github.com/owner/repo/blob/<branch>/path` URL for a repo-relative file path.
15
+ * Used for static-site “open another file” links when only `_site/index.html` is deployed.
16
+ */
17
+ export function githubRepoBlobFileUrl(owner, repo, branch, repoRelativePath) {
18
+ const posix = normalizeRepoRelativePath(repoRelativePath.replace(/\\/g, "/"));
19
+ const tail = posix
20
+ .split("/")
21
+ .map((s) => encodeURIComponent(s))
22
+ .join("/");
23
+ return `https://github.com/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/blob/${encodeURIComponent(branch)}/${tail}`;
24
+ }
25
+ //# sourceMappingURL=github-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-url.js","sourceRoot":"","sources":["../src/github-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAa,EACb,IAAY,EACZ,MAAc,EACd,gBAAwB;IAExB,MAAM,KAAK,GAAG,yBAAyB,CAAC,gBAAgB,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IAC9E,MAAM,IAAI,GAAG,KAAK;SACf,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;SACjC,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,OAAO,sBAAsB,kBAAkB,CAAC,KAAK,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,SAAS,kBAAkB,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;AAClI,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,16 @@
1
- export type { CommentrayBlock, CommentrayIndex, SourceFileIndexEntry } from "./model.js";
1
+ export type { CommentrayBlock, CommentrayBlockFingerprint, CommentrayIndex, SourceFileIndexEntry, } from "./model.js";
2
2
  export { CURRENT_SCHEMA_VERSION } from "./model.js";
3
- export { commentrayMarkdownPath, defaultMetadataIndexPath, normalizeRepoRelativePath, } from "./paths.js";
4
- export type { CommentrayToml, ResolvedCommentrayConfig, ResolvedStaticSite } from "./config.js";
3
+ export type { AddBlockToIndexInput, BlockRange, CreateBlockForRangeInput, CreatedBlock, } from "./blocks.js";
4
+ export { addBlockToIndex, appendBlockToCommentray, createBlockForRange, generateBlockId, } from "./blocks.js";
5
+ export { assertValidAngleId } from "./angles.js";
6
+ export { ensureAnglesSentinelFile, upsertAngleDefinitionInCommentrayToml } from "./angles-toml.js";
7
+ export type { UpsertAngleDefinitionInput } from "./angles-toml.js";
8
+ export { defaultAngleIdForOpen, FALLBACK_DEFAULT_ANGLE_ID, resolveCommentrayMarkdownPath, } from "./commentray-path-resolution.js";
9
+ export type { ResolvedCommentrayMarkdownPath } from "./commentray-path-resolution.js";
10
+ export { commentrayAnglesLayoutEnabled, commentrayAnglesSentinelPath, commentrayMarkdownPath, commentrayMarkdownPathForAngle, defaultMetadataIndexPath, normalizeRepoRelativePath, } from "./paths.js";
11
+ export type { CommentrayToml, ResolvedAngleDefinition, ResolvedAngles, ResolvedCommentrayConfig, ResolvedGithubNavLink, ResolvedStaticSite, } from "./config.js";
5
12
  export { loadCommentrayConfig, mergeCommentrayConfig } from "./config.js";
13
+ export { githubRepoBlobFileUrl, parseGithubRepoWebUrl } from "./github-url.js";
6
14
  export { assertValidIndex, emptyIndex } from "./metadata.js";
7
15
  export { migrateIndex } from "./migrate.js";
8
16
  export type { ParsedAnchor } from "./anchors.js";
@@ -12,6 +20,8 @@ export { GitScmProvider } from "./scm/git-scm-provider.js";
12
20
  export type { BlockDiagnostic } from "./staleness.js";
13
21
  export { diagnoseBlock } from "./staleness.js";
14
22
  export type { ValidationIssue, ValidationResult } from "./validate-project.js";
15
- export { readIndex, validateProject } from "./validate-project.js";
23
+ export { readIndex, validateProject, writeIndex } from "./validate-project.js";
16
24
  export { runCommanderMain } from "./cli-bootstrap.js";
25
+ export type { BlockScrollLink } from "./scroll-sync.js";
26
+ export { buildBlockScrollLinks, pickCommentrayLineForSourceScroll, pickSourceLine0ForCommentrayScroll, } from "./scroll-sync.js";
17
27
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACzF,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,cAAc,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC5D,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,eAAe,EACf,0BAA0B,EAC1B,eAAe,EACf,oBAAoB,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,YAAY,EACV,oBAAoB,EACpB,UAAU,EACV,wBAAwB,EACxB,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,mBAAmB,EACnB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,wBAAwB,EAAE,qCAAqC,EAAE,MAAM,kBAAkB,CAAC;AACnG,YAAY,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,iCAAiC,CAAC;AACzC,YAAY,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EACL,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,EACtB,8BAA8B,EAC9B,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,cAAc,EACd,uBAAuB,EACvB,cAAc,EACd,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC5D,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EACL,qBAAqB,EACrB,iCAAiC,EACjC,kCAAkC,GACnC,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -1,11 +1,17 @@
1
1
  export { CURRENT_SCHEMA_VERSION } from "./model.js";
2
- export { commentrayMarkdownPath, defaultMetadataIndexPath, normalizeRepoRelativePath, } from "./paths.js";
2
+ export { addBlockToIndex, appendBlockToCommentray, createBlockForRange, generateBlockId, } from "./blocks.js";
3
+ export { assertValidAngleId } from "./angles.js";
4
+ export { ensureAnglesSentinelFile, upsertAngleDefinitionInCommentrayToml } from "./angles-toml.js";
5
+ export { defaultAngleIdForOpen, FALLBACK_DEFAULT_ANGLE_ID, resolveCommentrayMarkdownPath, } from "./commentray-path-resolution.js";
6
+ export { commentrayAnglesLayoutEnabled, commentrayAnglesSentinelPath, commentrayMarkdownPath, commentrayMarkdownPathForAngle, defaultMetadataIndexPath, normalizeRepoRelativePath, } from "./paths.js";
3
7
  export { loadCommentrayConfig, mergeCommentrayConfig } from "./config.js";
8
+ export { githubRepoBlobFileUrl, parseGithubRepoWebUrl } from "./github-url.js";
4
9
  export { assertValidIndex, emptyIndex } from "./metadata.js";
5
10
  export { migrateIndex } from "./migrate.js";
6
11
  export { formatLineRange, parseAnchor } from "./anchors.js";
7
12
  export { GitScmProvider } from "./scm/git-scm-provider.js";
8
13
  export { diagnoseBlock } from "./staleness.js";
9
- export { readIndex, validateProject } from "./validate-project.js";
14
+ export { readIndex, validateProject, writeIndex } from "./validate-project.js";
10
15
  export { runCommanderMain } from "./cli-bootstrap.js";
16
+ export { buildBlockScrollLinks, pickCommentrayLineForSourceScroll, pickSourceLine0ForCommentrayScroll, } from "./scroll-sync.js";
11
17
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAOpD,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,mBAAmB,EACnB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,wBAAwB,EAAE,qCAAqC,EAAE,MAAM,kBAAkB,CAAC;AAEnG,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,EACtB,8BAA8B,EAC9B,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,YAAY,CAAC;AASpB,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EACL,qBAAqB,EACrB,iCAAiC,EACjC,kCAAkC,GACnC,MAAM,kBAAkB,CAAC"}
package/dist/metadata.js CHANGED
@@ -1,55 +1,81 @@
1
1
  import { CURRENT_SCHEMA_VERSION } from "./model.js";
2
2
  export function emptyIndex() {
3
- return { schemaVersion: CURRENT_SCHEMA_VERSION, bySourceFile: {} };
3
+ return { schemaVersion: CURRENT_SCHEMA_VERSION, byCommentrayPath: {} };
4
4
  }
5
5
  export function assertValidIndex(value) {
6
6
  if (typeof value !== "object" || value === null) {
7
- throw new Error("index.json must be a JSON object");
7
+ throw new TypeError("index.json must be a JSON object");
8
8
  }
9
9
  const obj = value;
10
10
  const schemaVersion = obj.schemaVersion;
11
11
  if (schemaVersion !== CURRENT_SCHEMA_VERSION) {
12
12
  throw new Error(`Unsupported schemaVersion: ${String(schemaVersion)}`);
13
13
  }
14
- const bySourceFile = obj.bySourceFile;
15
- if (typeof bySourceFile !== "object" || bySourceFile === null) {
16
- throw new Error("index.json.bySourceFile must be an object");
14
+ const byCommentrayPath = obj.byCommentrayPath;
15
+ if (typeof byCommentrayPath !== "object" || byCommentrayPath === null) {
16
+ throw new TypeError("index.json.byCommentrayPath must be an object");
17
17
  }
18
- for (const [key, entry] of Object.entries(bySourceFile)) {
19
- validateSourceEntry(key, entry);
18
+ for (const [key, entry] of Object.entries(byCommentrayPath)) {
19
+ validateCommentrayEntry(key, entry);
20
20
  }
21
21
  return obj;
22
22
  }
23
- function validateSourceEntry(sourcePath, entry) {
23
+ function validateCommentrayEntry(commentrayPathKey, entry) {
24
24
  if (typeof entry !== "object" || entry === null) {
25
- throw new Error(`Invalid index entry for ${sourcePath}`);
25
+ throw new TypeError(`Invalid index entry for ${commentrayPathKey}`);
26
26
  }
27
27
  const e = entry;
28
- if (typeof e.sourcePath !== "string")
29
- throw new Error(`Missing sourcePath for ${sourcePath}`);
28
+ if (typeof e.sourcePath !== "string") {
29
+ throw new TypeError(`Missing sourcePath for ${commentrayPathKey}`);
30
+ }
30
31
  if (typeof e.commentrayPath !== "string") {
31
- throw new Error(`Missing commentrayPath for ${sourcePath}`);
32
+ throw new TypeError(`Missing commentrayPath for ${commentrayPathKey}`);
33
+ }
34
+ if (e.commentrayPath !== commentrayPathKey) {
35
+ throw new TypeError(`index key must equal entry.commentrayPath (key=${commentrayPathKey}, entry=${e.commentrayPath})`);
36
+ }
37
+ if (!Array.isArray(e.blocks)) {
38
+ throw new TypeError(`blocks must be an array for ${commentrayPathKey}`);
32
39
  }
33
- if (!Array.isArray(e.blocks))
34
- throw new Error(`blocks must be an array for ${sourcePath}`);
35
40
  for (const block of e.blocks)
36
- validateBlock(sourcePath, block);
41
+ validateBlock(commentrayPathKey, block);
37
42
  }
38
- function validateBlock(sourcePath, block) {
43
+ function validateBlock(commentrayPathKey, block) {
39
44
  if (typeof block !== "object" || block === null) {
40
- throw new Error(`Invalid block under ${sourcePath}`);
45
+ throw new TypeError(`Invalid block under ${commentrayPathKey}`);
41
46
  }
42
47
  const b = block;
43
- if (typeof b.id !== "string")
44
- throw new Error(`block.id must be a string under ${sourcePath}`);
48
+ if (typeof b.id !== "string") {
49
+ throw new TypeError(`block.id must be a string under ${commentrayPathKey}`);
50
+ }
45
51
  if (typeof b.anchor !== "string") {
46
- throw new Error(`block.anchor must be a string under ${sourcePath}`);
52
+ throw new TypeError(`block.anchor must be a string under ${commentrayPathKey}`);
47
53
  }
48
54
  if (b.lastVerifiedCommit !== undefined && typeof b.lastVerifiedCommit !== "string") {
49
- throw new Error(`block.lastVerifiedCommit must be a string when present under ${sourcePath}`);
55
+ throw new TypeError(`block.lastVerifiedCommit must be a string when present under ${commentrayPathKey}`);
50
56
  }
51
57
  if (b.lastVerifiedBlob !== undefined && typeof b.lastVerifiedBlob !== "string") {
52
- throw new Error(`block.lastVerifiedBlob must be a string when present under ${sourcePath}`);
58
+ throw new TypeError(`block.lastVerifiedBlob must be a string when present under ${commentrayPathKey}`);
59
+ }
60
+ if (b.markerId !== undefined && typeof b.markerId !== "string") {
61
+ throw new TypeError(`block.markerId must be a string when present under ${commentrayPathKey}`);
62
+ }
63
+ if (b.fingerprint !== undefined)
64
+ validateFingerprint(commentrayPathKey, b.fingerprint);
65
+ }
66
+ function validateFingerprint(commentrayPathKey, fp) {
67
+ if (typeof fp !== "object" || fp === null) {
68
+ throw new TypeError(`block.fingerprint must be an object under ${commentrayPathKey}`);
69
+ }
70
+ const f = fp;
71
+ if (typeof f.startLine !== "string") {
72
+ throw new TypeError(`block.fingerprint.startLine must be a string under ${commentrayPathKey}`);
73
+ }
74
+ if (typeof f.endLine !== "string") {
75
+ throw new TypeError(`block.fingerprint.endLine must be a string under ${commentrayPathKey}`);
76
+ }
77
+ if (typeof f.lineCount !== "number" || !Number.isInteger(f.lineCount) || f.lineCount < 1) {
78
+ throw new TypeError(`block.fingerprint.lineCount must be a positive integer under ${commentrayPathKey}`);
53
79
  }
54
80
  }
55
81
  //# sourceMappingURL=metadata.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,eAAe,EAGrB,MAAM,YAAY,CAAC;AAEpB,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CA2BvF"}
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,eAAe,EAGrB,MAAM,YAAY,CAAC;AAIpB,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAqCvF"}
package/dist/migrate.js CHANGED
@@ -1,26 +1,32 @@
1
1
  import { CURRENT_SCHEMA_VERSION, } from "./model.js";
2
+ const LEGACY_SCHEMA_VERSION = 2;
2
3
  /** Returns migrated index and whether the file should be rewritten. */
3
4
  export function migrateIndex(raw) {
4
5
  if (typeof raw !== "object" || raw === null) {
5
6
  return {
6
- index: { schemaVersion: CURRENT_SCHEMA_VERSION, bySourceFile: {} },
7
+ index: { schemaVersion: CURRENT_SCHEMA_VERSION, byCommentrayPath: {} },
7
8
  changed: true,
8
9
  };
9
10
  }
10
11
  const obj = raw;
11
12
  const version = obj.schemaVersion;
12
13
  if (version === CURRENT_SCHEMA_VERSION) {
13
- return { index: obj, changed: false };
14
+ const index = obj;
15
+ return { index, changed: false };
14
16
  }
15
- if (version === undefined || version === 0 || version === 1) {
16
- const bySourceFile = normalizeBySourceFile(obj.bySourceFile);
17
+ if (version === LEGACY_SCHEMA_VERSION ||
18
+ version === undefined ||
19
+ version === 0 ||
20
+ version === 1) {
21
+ const byCommentrayPath = toByCommentrayPath(obj);
17
22
  const next = {
18
23
  schemaVersion: CURRENT_SCHEMA_VERSION,
19
- bySourceFile,
24
+ byCommentrayPath,
20
25
  };
21
26
  const before = JSON.stringify({
22
27
  schemaVersion: version ?? 0,
23
28
  bySourceFile: obj.bySourceFile ?? {},
29
+ byCommentrayPath: obj.byCommentrayPath ?? {},
24
30
  });
25
31
  const after = JSON.stringify(next);
26
32
  const changed = before !== after;
@@ -28,12 +34,28 @@ export function migrateIndex(raw) {
28
34
  }
29
35
  throw new Error(`Cannot migrate from schemaVersion ${String(version)}`);
30
36
  }
31
- function normalizeBySourceFile(by) {
32
- if (typeof by !== "object" || by === null)
33
- return {};
37
+ function toByCommentrayPath(obj) {
38
+ if (obj.byCommentrayPath &&
39
+ typeof obj.byCommentrayPath === "object" &&
40
+ obj.byCommentrayPath !== null) {
41
+ const out = {};
42
+ for (const [k, entry] of Object.entries(obj.byCommentrayPath)) {
43
+ out[k] = normalizeEntry(entry);
44
+ }
45
+ return out;
46
+ }
47
+ const bySourceFile = obj.bySourceFile;
34
48
  const out = {};
35
- for (const [k, entry] of Object.entries(by)) {
36
- out[k] = normalizeEntry(entry);
49
+ if (typeof bySourceFile !== "object" || bySourceFile === null) {
50
+ return out;
51
+ }
52
+ for (const [, entry] of Object.entries(bySourceFile)) {
53
+ const norm = normalizeEntry(entry);
54
+ const cp = norm.commentrayPath;
55
+ if (out[cp]) {
56
+ throw new Error(`Duplicate commentrayPath in legacy index: ${cp}`);
57
+ }
58
+ out[cp] = norm;
37
59
  }
38
60
  return out;
39
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO;YACL,KAAK,EAAE,EAAE,aAAa,EAAE,sBAAsB,EAAE,YAAY,EAAE,EAAE,EAAE;YAClE,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,GAA8B,CAAC;IAC3C,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC;IAClC,IAAI,OAAO,KAAK,sBAAsB,EAAE,CAAC;QACvC,OAAO,EAAE,KAAK,EAAE,GAAsB,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;QAC5D,MAAM,YAAY,GAAG,qBAAqB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAoB;YAC5B,aAAa,EAAE,sBAAsB;YACrC,YAAY;SACb,CAAC;QACF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;YAC5B,aAAa,EAAE,OAAO,IAAI,CAAC;YAC3B,YAAY,EAAE,GAAG,CAAC,YAAY,IAAI,EAAE;SACrC,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,OAAO,GAAG,MAAM,KAAK,KAAK,CAAC;QACjC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAClC,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,qCAAqC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,qBAAqB,CAAC,EAAW;IACxC,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IACrD,MAAM,GAAG,GAAyC,EAAE,CAAC;IACrD,KAAK,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,EAA6B,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,IAAI,OAAO,CAAC,CAAC,cAAc,KAAK,QAAQ,EAAE,CAAC;QACzC,OAAO,CAAyB,CAAC;IACnC,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,cAAc,KAAK,QAAQ,EAAE,CAAC;QACzC,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;QACtC,OAAO,EAAE,GAAG,IAAI,EAAE,cAAc,EAAE,cAAc,EAA0B,CAAC;IAC7E,CAAC;IACD,OAAO,CAAyB,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"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"}
package/dist/model.d.ts CHANGED
@@ -1,9 +1,40 @@
1
+ /**
2
+ * Content fingerprint of a source range, used to re-resolve the block's
3
+ * anchor after lines drift (insertions or deletions in the source).
4
+ *
5
+ * A fingerprint is intentionally narrow: trimmed text of the first and last
6
+ * lines plus the original line count. Re-resolution is a search, not a
7
+ * guarantee: when the fingerprint still appears uniquely near the old
8
+ * location we silently update the line numbers; otherwise we surface a
9
+ * diagnostic so a human can decide.
10
+ */
11
+ export type CommentrayBlockFingerprint = {
12
+ /** Trimmed content of the first line of the original range. */
13
+ startLine: string;
14
+ /** Trimmed content of the last line of the original range. */
15
+ endLine: string;
16
+ /** Number of lines the range originally spanned (end - start + 1). */
17
+ lineCount: number;
18
+ };
1
19
  /** Commentray block aligned to a region of a primary source file. */
2
20
  export type CommentrayBlock = {
3
21
  /** Stable id within the commentray markdown file. */
4
22
  id: string;
5
23
  /** Human or machine anchor string (see anchor grammar in docs). */
6
24
  anchor: string;
25
+ /**
26
+ * Optional drift-resolution fingerprint. Present when the block's range
27
+ * was captured from source content; absent when the anchor is purely a
28
+ * symbol or marker reference that does not need content-based re-sync.
29
+ */
30
+ fingerprint?: CommentrayBlockFingerprint;
31
+ /**
32
+ * Optional marker-based anchor. When set, drift resolution looks for a
33
+ * pair of host-language comments of the form `commentray:start id=<markerId>`
34
+ * and `commentray:end` in the source; the lines between them become the
35
+ * block's effective range. Markers are drift-proof but invasive.
36
+ */
37
+ markerId?: string;
7
38
  /** Last human-verified commit (full SHA) when this block was considered accurate. */
8
39
  lastVerifiedCommit?: string;
9
40
  /** Git blob id at verification time for the primary file (when known). */
@@ -21,7 +52,11 @@ export type SourceFileIndexEntry = {
21
52
  /** Root metadata document stored as JSON under `.commentray/metadata/`. */
22
53
  export type CommentrayIndex = {
23
54
  schemaVersion: number;
24
- bySourceFile: Record<string, SourceFileIndexEntry>;
55
+ /**
56
+ * Blocks grouped by repo-relative commentray Markdown path so multiple **Angles**
57
+ * for the same `sourcePath` each keep their own block lists (schema v3+).
58
+ */
59
+ byCommentrayPath: Record<string, SourceFileIndexEntry>;
25
60
  };
26
- export declare const CURRENT_SCHEMA_VERSION: 2;
61
+ export declare const CURRENT_SCHEMA_VERSION: 3;
27
62
  //# sourceMappingURL=model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,MAAM,MAAM,eAAe,GAAG;IAC5B,qDAAqD;IACrD,EAAE,EAAE,MAAM,CAAC;IACX,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF,2EAA2E;AAC3E,MAAM,MAAM,eAAe,GAAG;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;CACpD,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAG,CAAU,CAAC"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,MAAM,0BAA0B,GAAG;IACvC,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,qEAAqE;AACrE,MAAM,MAAM,eAAe,GAAG;IAC5B,qDAAqD;IACrD,EAAE,EAAE,MAAM,CAAC;IACX,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,WAAW,CAAC,EAAE,0BAA0B,CAAC;IACzC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF,2EAA2E;AAC3E,MAAM,MAAM,eAAe,GAAG;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;CACxD,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAG,CAAU,CAAC"}
package/dist/model.js CHANGED
@@ -1,2 +1,2 @@
1
- export const CURRENT_SCHEMA_VERSION = 2;
1
+ export const CURRENT_SCHEMA_VERSION = 3;
2
2
  //# sourceMappingURL=model.js.map
package/dist/model.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AA4BA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAU,CAAC"}
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAgEA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAU,CAAC"}
package/dist/paths.d.ts CHANGED
@@ -11,8 +11,24 @@
11
11
  * `..` segments are traversal.
12
12
  */
13
13
  export declare function normalizeRepoRelativePath(relativePath: string): string;
14
- /** Commentray Markdown path for a repo-relative source file. */
14
+ /** Commentray Markdown path for a repo-relative source file (implicit default angle, flat layout). */
15
15
  export declare function commentrayMarkdownPath(sourceRepoRelativePath: string): string;
16
+ /**
17
+ * Repo-relative path to the **Angles sentinel**: if this path exists as a file or directory under
18
+ * the storage root, the repository opts into per-source **Angles** layout (see `docs/spec/storage.md`).
19
+ * When absent, the flat `{storage}/source/{P}.md` layout is the only supported shape.
20
+ */
21
+ export declare function commentrayAnglesSentinelPath(storageDir?: string): string;
22
+ /**
23
+ * Returns true when the repository opts into **Angles** layout: `{storage}/source/.default` exists
24
+ * (file or directory). When false, only the flat `{storage}/source/{P}.md` mapping applies.
25
+ */
26
+ export declare function commentrayAnglesLayoutEnabled(repoRoot: string, storageDir?: string): boolean;
27
+ /**
28
+ * Repo-relative path to commentray for `sourceRepoRelativePath` at a named **Angle** (multi-angle layout).
29
+ * Example: `README.md` + `architecture` → `.commentray/source/README.md/architecture.md` (with default storage dir).
30
+ */
31
+ export declare function commentrayMarkdownPathForAngle(sourceRepoRelativePath: string, angleId: string, storageDir?: string): string;
16
32
  /** Default metadata index location (repo-relative). */
17
33
  export declare function defaultMetadataIndexPath(): string;
18
34
  //# sourceMappingURL=paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAWtE;AAED,gEAAgE;AAChE,wBAAgB,sBAAsB,CAAC,sBAAsB,EAAE,MAAM,GAAG,MAAM,CAG7E;AAED,uDAAuD;AACvD,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAWtE;AAED,sGAAsG;AACtG,wBAAgB,sBAAsB,CAAC,sBAAsB,EAAE,MAAM,GAAG,MAAM,CAG7E;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,UAAU,SAAgB,GAAG,MAAM,CAG/E;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,EAChB,UAAU,SAAgB,GACzB,OAAO,CAIT;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,sBAAsB,EAAE,MAAM,EAC9B,OAAO,EAAE,MAAM,EACf,UAAU,SAAgB,GACzB,MAAM,CAKR;AAED,uDAAuD;AACvD,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD"}
package/dist/paths.js CHANGED
@@ -1,4 +1,6 @@
1
+ import fs from "node:fs";
1
2
  import path from "node:path";
3
+ import { assertValidAngleId } from "./angles.js";
2
4
  /**
3
5
  * Normalize a repo-relative path to POSIX separators and reject anything that
4
6
  * would escape the repository root when joined with it.
@@ -23,11 +25,39 @@ export function normalizeRepoRelativePath(relativePath) {
23
25
  }
24
26
  return segments.join("/");
25
27
  }
26
- /** Commentray Markdown path for a repo-relative source file. */
28
+ /** Commentray Markdown path for a repo-relative source file (implicit default angle, flat layout). */
27
29
  export function commentrayMarkdownPath(sourceRepoRelativePath) {
28
30
  const normalized = normalizeRepoRelativePath(sourceRepoRelativePath);
29
31
  return path.posix.join(".commentray", "source", `${normalized}.md`);
30
32
  }
33
+ /**
34
+ * Repo-relative path to the **Angles sentinel**: if this path exists as a file or directory under
35
+ * the storage root, the repository opts into per-source **Angles** layout (see `docs/spec/storage.md`).
36
+ * When absent, the flat `{storage}/source/{P}.md` layout is the only supported shape.
37
+ */
38
+ export function commentrayAnglesSentinelPath(storageDir = ".commentray") {
39
+ const root = normalizeRepoRelativePath(storageDir.replaceAll("\\", "/"));
40
+ return path.posix.join(root, "source", ".default");
41
+ }
42
+ /**
43
+ * Returns true when the repository opts into **Angles** layout: `{storage}/source/.default` exists
44
+ * (file or directory). When false, only the flat `{storage}/source/{P}.md` mapping applies.
45
+ */
46
+ export function commentrayAnglesLayoutEnabled(repoRoot, storageDir = ".commentray") {
47
+ const sentinel = commentrayAnglesSentinelPath(storageDir);
48
+ const absolute = path.join(repoRoot, ...sentinel.split("/"));
49
+ return fs.existsSync(absolute);
50
+ }
51
+ /**
52
+ * Repo-relative path to commentray for `sourceRepoRelativePath` at a named **Angle** (multi-angle layout).
53
+ * Example: `README.md` + `architecture` → `.commentray/source/README.md/architecture.md` (with default storage dir).
54
+ */
55
+ export function commentrayMarkdownPathForAngle(sourceRepoRelativePath, angleId, storageDir = ".commentray") {
56
+ const normalized = normalizeRepoRelativePath(sourceRepoRelativePath);
57
+ const sid = assertValidAngleId(angleId);
58
+ const root = normalizeRepoRelativePath(storageDir.replaceAll("\\", "/"));
59
+ return path.posix.join(root, "source", normalized, `${sid}.md`);
60
+ }
31
61
  /** Default metadata index location (repo-relative). */
32
62
  export function defaultMetadataIndexPath() {
33
63
  return path.posix.join(".commentray", "metadata", "index.json");
package/dist/paths.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,yBAAyB,CAAC,YAAoB;IAC5D,MAAM,KAAK,GAAG,YAAY,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACjD,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,mDAAmD,YAAY,GAAG,CAAC,CAAC;IACtF,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IAC1E,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,iCAAiC,YAAY,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,sBAAsB,CAAC,sBAA8B;IACnE,MAAM,UAAU,GAAG,yBAAyB,CAAC,sBAAsB,CAAC,CAAC;IACrE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,EAAE,GAAG,UAAU,KAAK,CAAC,CAAC;AACtE,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,wBAAwB;IACtC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AAClE,CAAC"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,yBAAyB,CAAC,YAAoB;IAC5D,MAAM,KAAK,GAAG,YAAY,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACjD,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,mDAAmD,YAAY,GAAG,CAAC,CAAC;IACtF,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IAC1E,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,iCAAiC,YAAY,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,sBAAsB,CAAC,sBAA8B;IACnE,MAAM,UAAU,GAAG,yBAAyB,CAAC,sBAAsB,CAAC,CAAC;IACrE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,EAAE,GAAG,UAAU,KAAK,CAAC,CAAC;AACtE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAAC,UAAU,GAAG,aAAa;IACrE,MAAM,IAAI,GAAG,yBAAyB,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IACzE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAC3C,QAAgB,EAChB,UAAU,GAAG,aAAa;IAE1B,MAAM,QAAQ,GAAG,4BAA4B,CAAC,UAAU,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7D,OAAO,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,8BAA8B,CAC5C,sBAA8B,EAC9B,OAAe,EACf,UAAU,GAAG,aAAa;IAE1B,MAAM,UAAU,GAAG,yBAAyB,CAAC,sBAAsB,CAAC,CAAC;IACrE,MAAM,GAAG,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,yBAAyB,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IACzE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,GAAG,KAAK,CAAC,CAAC;AAClE,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,wBAAwB;IACtC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AAClE,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { CommentrayIndex } from "./model.js";
2
+ /** One block as needed for scroll correlation (0-based commentray line, 1-based source range). */
3
+ export type BlockScrollLink = {
4
+ commentrayLine: number;
5
+ sourceStart: number;
6
+ sourceEnd: number;
7
+ };
8
+ /**
9
+ * Correlate index blocks (line anchors + ids) with `<!-- commentray:block id=… -->`
10
+ * markers in commentray. Only `lines:` anchors with a visible
11
+ * marker participate. Sorted by `sourceStart`.
12
+ */
13
+ export declare function buildBlockScrollLinks(index: CommentrayIndex | null | undefined, sourceRelative: string, commentrayPath: string, commentrayMarkdown: string): BlockScrollLink[];
14
+ /**
15
+ * Choose which commentray line (0-based) to reveal so the commentary matches
16
+ * the top of the source viewport. Prefers the block whose source range
17
+ * **contains** the top line; otherwise the nearest preceding block; if above
18
+ * all blocks, the first block.
19
+ */
20
+ export declare function pickCommentrayLineForSourceScroll(blocks: BlockScrollLink[], topSourceLine1Based: number): number | null;
21
+ /**
22
+ * Choose a 0-based source line to reveal from the top of the commentray
23
+ * viewport: the block whose marker is at or above that line wins; reveal the
24
+ * start of its source range.
25
+ */
26
+ export declare function pickSourceLine0ForCommentrayScroll(blocks: BlockScrollLink[], topCommentrayLine0Based: number): number | null;
27
+ //# sourceMappingURL=scroll-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-sync.d.ts","sourceRoot":"","sources":["../src/scroll-sync.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,kGAAkG;AAClG,MAAM,MAAM,eAAe,GAAG;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAcF;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,EACzC,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,MAAM,EACtB,kBAAkB,EAAE,MAAM,GACzB,eAAe,EAAE,CAkBnB;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,eAAe,EAAE,EACzB,mBAAmB,EAAE,MAAM,GAC1B,MAAM,GAAG,IAAI,CAaf;AAED;;;;GAIG;AACH,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,eAAe,EAAE,EACzB,uBAAuB,EAAE,MAAM,GAC9B,MAAM,GAAG,IAAI,CAQf"}
@@ -0,0 +1,80 @@
1
+ import { parseAnchor } from "./anchors.js";
2
+ const BLOCK_MARKER_RE = /<!-- commentray:block id=([a-z0-9]+) -->/;
3
+ function markerLineByIdFromMarkdown(markdown) {
4
+ const map = new Map();
5
+ const lines = markdown.split("\n");
6
+ for (let i = 0; i < lines.length; i++) {
7
+ const match = BLOCK_MARKER_RE.exec(lines[i]);
8
+ if (match)
9
+ map.set(match[1], i);
10
+ }
11
+ return map;
12
+ }
13
+ /**
14
+ * Correlate index blocks (line anchors + ids) with `<!-- commentray:block id=… -->`
15
+ * markers in commentray. Only `lines:` anchors with a visible
16
+ * marker participate. Sorted by `sourceStart`.
17
+ */
18
+ export function buildBlockScrollLinks(index, sourceRelative, commentrayPath, commentrayMarkdown) {
19
+ const entry = index?.byCommentrayPath[commentrayPath];
20
+ if (!entry || entry.sourcePath !== sourceRelative || entry.blocks.length === 0)
21
+ return [];
22
+ const markerLineById = markerLineByIdFromMarkdown(commentrayMarkdown);
23
+ const links = [];
24
+ for (const block of entry.blocks) {
25
+ const anchor = parseAnchor(block.anchor);
26
+ if (anchor.kind !== "lines")
27
+ continue;
28
+ const commentrayLine = markerLineById.get(block.id);
29
+ if (commentrayLine === undefined)
30
+ continue;
31
+ links.push({
32
+ commentrayLine,
33
+ sourceStart: anchor.range.start,
34
+ sourceEnd: anchor.range.end,
35
+ });
36
+ }
37
+ links.sort((a, b) => a.sourceStart - b.sourceStart);
38
+ return links;
39
+ }
40
+ /**
41
+ * Choose which commentray line (0-based) to reveal so the commentary matches
42
+ * the top of the source viewport. Prefers the block whose source range
43
+ * **contains** the top line; otherwise the nearest preceding block; if above
44
+ * all blocks, the first block.
45
+ */
46
+ export function pickCommentrayLineForSourceScroll(blocks, topSourceLine1Based) {
47
+ if (blocks.length === 0)
48
+ return null;
49
+ const inside = blocks.find((b) => b.sourceStart <= topSourceLine1Based && topSourceLine1Based <= b.sourceEnd);
50
+ if (inside)
51
+ return inside.commentrayLine;
52
+ if (topSourceLine1Based < blocks[0].sourceStart)
53
+ return blocks[0].commentrayLine;
54
+ let best = blocks[0];
55
+ for (const b of blocks) {
56
+ if (b.sourceStart <= topSourceLine1Based)
57
+ best = b;
58
+ else
59
+ break;
60
+ }
61
+ return best.commentrayLine;
62
+ }
63
+ /**
64
+ * Choose a 0-based source line to reveal from the top of the commentray
65
+ * viewport: the block whose marker is at or above that line wins; reveal the
66
+ * start of its source range.
67
+ */
68
+ export function pickSourceLine0ForCommentrayScroll(blocks, topCommentrayLine0Based) {
69
+ if (blocks.length === 0)
70
+ return null;
71
+ let best = blocks[0];
72
+ for (const b of blocks) {
73
+ if (b.commentrayLine <= topCommentrayLine0Based)
74
+ best = b;
75
+ else
76
+ break;
77
+ }
78
+ return best.sourceStart - 1;
79
+ }
80
+ //# sourceMappingURL=scroll-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-sync.js","sourceRoot":"","sources":["../src/scroll-sync.ts"],"names":[],"mappings":"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"}
@@ -8,4 +8,10 @@ export type ValidationResult = {
8
8
  };
9
9
  export declare function validateProject(repoRoot: string): Promise<ValidationResult>;
10
10
  export declare function readIndex(repoRoot: string): Promise<CommentrayIndex | null>;
11
+ /**
12
+ * Write the metadata index to the default location under `repoRoot`, creating
13
+ * the `.commentray/metadata/` directory if missing. The file is written with
14
+ * two-space indentation and a trailing newline so diffs are easy to read.
15
+ */
16
+ export declare function writeIndex(repoRoot: string, index: CommentrayIndex): Promise<void>;
11
17
  //# sourceMappingURL=validate-project.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate-project.d.ts","sourceRoot":"","sources":["../src/validate-project.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,eAAe,GAAG;IAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA2CjF;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAUjF"}
1
+ {"version":3,"file":"validate-project.d.ts","sourceRoot":"","sources":["../src/validate-project.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,MAAM,eAAe,GAAG;IAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAyCjF;AAiBD,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAmBjF;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAKxF"}