@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.
- package/dist/angles-toml.d.ts +18 -0
- package/dist/angles-toml.d.ts.map +1 -0
- package/dist/angles-toml.js +62 -0
- package/dist/angles-toml.js.map +1 -0
- package/dist/angles.d.ts +6 -0
- package/dist/angles.d.ts.map +1 -0
- package/dist/angles.js +14 -0
- package/dist/angles.js.map +1 -0
- package/dist/blocks.d.ts +66 -0
- package/dist/blocks.d.ts.map +1 -0
- package/dist/blocks.js +101 -0
- package/dist/blocks.js.map +1 -0
- package/dist/commentray-path-resolution.d.ts +20 -0
- package/dist/commentray-path-resolution.d.ts.map +1 -0
- package/dist/commentray-path-resolution.js +38 -0
- package/dist/commentray-path-resolution.js.map +1 -0
- package/dist/config.d.ts +48 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +66 -2
- package/dist/config.js.map +1 -1
- package/dist/github-url.d.ts +14 -0
- package/dist/github-url.d.ts.map +1 -0
- package/dist/github-url.js +25 -0
- package/dist/github-url.js.map +1 -0
- package/dist/index.d.ts +14 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/metadata.js +48 -22
- package/dist/metadata.js.map +1 -1
- package/dist/migrate.d.ts.map +1 -1
- package/dist/migrate.js +32 -10
- package/dist/migrate.js.map +1 -1
- package/dist/model.d.ts +37 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +1 -1
- package/dist/model.js.map +1 -1
- package/dist/paths.d.ts +17 -1
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +31 -1
- package/dist/paths.js.map +1 -1
- package/dist/scroll-sync.d.ts +27 -0
- package/dist/scroll-sync.d.ts.map +1 -0
- package/dist/scroll-sync.js +80 -0
- package/dist/scroll-sync.js.map +1 -0
- package/dist/validate-project.d.ts +6 -0
- package/dist/validate-project.d.ts.map +1 -1
- package/dist/validate-project.js +45 -14
- package/dist/validate-project.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type UpsertAngleDefinitionInput = {
|
|
2
|
+
id: string;
|
|
3
|
+
title?: string;
|
|
4
|
+
/** When true, set `angles.default_angle` to this id after the merge. */
|
|
5
|
+
makeDefault?: boolean;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Ensures `{storage.dir}/source/.default` exists so the repository uses **Angles** on-disk layout
|
|
9
|
+
* (see `docs/spec/storage.md`).
|
|
10
|
+
*/
|
|
11
|
+
export declare function ensureAnglesSentinelFile(repoRoot: string, storageDir: string): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Reads `.commentray.toml`, appends a new `[[angles.definitions]]` row (or throws if the id
|
|
14
|
+
* already exists), validates via {@link mergeCommentrayConfig}, and writes the file back using
|
|
15
|
+
* TOML stringify (comments and key order are not preserved).
|
|
16
|
+
*/
|
|
17
|
+
export declare function upsertAngleDefinitionInCommentrayToml(repoRoot: string, input: UpsertAngleDefinitionInput): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=angles-toml.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"angles-toml.d.ts","sourceRoot":"","sources":["../src/angles-toml.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,0BAA0B,GAAG;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAMF;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAaf;AAED;;;;GAIG;AACH,wBAAsB,qCAAqC,CACzD,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,IAAI,CAAC,CAmCf"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { parse as parseToml, stringify } from "@iarna/toml";
|
|
4
|
+
import { assertValidAngleId } from "./angles.js";
|
|
5
|
+
import { mergeCommentrayConfig } from "./config.js";
|
|
6
|
+
import { commentrayAnglesSentinelPath } from "./paths.js";
|
|
7
|
+
const MINIMAL_NEW_TOML = `[storage]
|
|
8
|
+
dir = ".commentray"
|
|
9
|
+
`;
|
|
10
|
+
/**
|
|
11
|
+
* Ensures `{storage.dir}/source/.default` exists so the repository uses **Angles** on-disk layout
|
|
12
|
+
* (see `docs/spec/storage.md`).
|
|
13
|
+
*/
|
|
14
|
+
export async function ensureAnglesSentinelFile(repoRoot, storageDir) {
|
|
15
|
+
const rel = commentrayAnglesSentinelPath(storageDir);
|
|
16
|
+
const absolute = path.join(repoRoot, ...rel.split("/"));
|
|
17
|
+
await fs.mkdir(path.dirname(absolute), { recursive: true });
|
|
18
|
+
try {
|
|
19
|
+
await fs.access(absolute);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
await fs.writeFile(absolute, "# Commentray Angles layout sentinel (see docs/spec/storage.md).\n", "utf8");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Reads `.commentray.toml`, appends a new `[[angles.definitions]]` row (or throws if the id
|
|
27
|
+
* already exists), validates via {@link mergeCommentrayConfig}, and writes the file back using
|
|
28
|
+
* TOML stringify (comments and key order are not preserved).
|
|
29
|
+
*/
|
|
30
|
+
export async function upsertAngleDefinitionInCommentrayToml(repoRoot, input) {
|
|
31
|
+
const id = assertValidAngleId(input.id);
|
|
32
|
+
const configPath = path.join(repoRoot, ".commentray.toml");
|
|
33
|
+
let raw = "";
|
|
34
|
+
try {
|
|
35
|
+
raw = await fs.readFile(configPath, "utf8");
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
const code = err.code;
|
|
39
|
+
if (code !== "ENOENT")
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
const parsed = raw.trim() ? parseToml(raw) : {};
|
|
43
|
+
const angles = parsed.angles ?? {};
|
|
44
|
+
const definitions = [...(angles.definitions ?? [])];
|
|
45
|
+
if (definitions.some((d) => d && typeof d === "object" && "id" in d && String(d.id) === id)) {
|
|
46
|
+
throw new Error(`Angle "${id}" is already listed in [angles].definitions`);
|
|
47
|
+
}
|
|
48
|
+
definitions.push({
|
|
49
|
+
id,
|
|
50
|
+
title: input.title?.trim() || undefined,
|
|
51
|
+
});
|
|
52
|
+
angles.definitions = definitions;
|
|
53
|
+
if (input.makeDefault === true || definitions.length === 1) {
|
|
54
|
+
angles.default_angle = id;
|
|
55
|
+
}
|
|
56
|
+
parsed.angles = angles;
|
|
57
|
+
mergeCommentrayConfig(parsed);
|
|
58
|
+
const serialized = stringify(parsed);
|
|
59
|
+
const body = raw.trim() ? serialized : `${MINIMAL_NEW_TOML.trim()}\n\n${serialized}`;
|
|
60
|
+
await fs.writeFile(configPath, `${body}\n`, "utf8");
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=angles-toml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"angles-toml.js","sourceRoot":"","sources":["../src/angles-toml.ts"],"names":[],"mappings":"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"}
|
package/dist/angles.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates and returns a trimmed Angle id. Used for TOML `angles.*` keys and path segments.
|
|
3
|
+
* Rejects empty, `.`, `..`, and anything outside `[a-zA-Z0-9_-]` so paths stay predictable and safe.
|
|
4
|
+
*/
|
|
5
|
+
export declare function assertValidAngleId(angleId: string): string;
|
|
6
|
+
//# sourceMappingURL=angles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"angles.d.ts","sourceRoot":"","sources":["../src/angles.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQ1D"}
|
package/dist/angles.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Allowed characters for an Angle id (folder / file segment). */
|
|
2
|
+
const ANGLE_ID_RE = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
3
|
+
/**
|
|
4
|
+
* Validates and returns a trimmed Angle id. Used for TOML `angles.*` keys and path segments.
|
|
5
|
+
* Rejects empty, `.`, `..`, and anything outside `[a-zA-Z0-9_-]` so paths stay predictable and safe.
|
|
6
|
+
*/
|
|
7
|
+
export function assertValidAngleId(angleId) {
|
|
8
|
+
const t = angleId.trim();
|
|
9
|
+
if (t === "." || t === ".." || !ANGLE_ID_RE.test(t)) {
|
|
10
|
+
throw new Error(`Invalid angle id "${angleId}" (use 1–64 characters from [a-zA-Z0-9_-] only; not "." or "..")`);
|
|
11
|
+
}
|
|
12
|
+
return t;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=angles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"angles.js","sourceRoot":"","sources":["../src/angles.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,WAAW,GAAG,uBAAuB,CAAC;AAE5C;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CACb,qBAAqB,OAAO,kEAAkE,CAC/F,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
package/dist/blocks.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { CommentrayBlock, CommentrayIndex } from "./model.js";
|
|
2
|
+
/** 1-based inclusive range of source lines a block points to. */
|
|
3
|
+
export type BlockRange = {
|
|
4
|
+
startLine: number;
|
|
5
|
+
endLine: number;
|
|
6
|
+
};
|
|
7
|
+
export type CreateBlockForRangeInput = {
|
|
8
|
+
/**
|
|
9
|
+
* Repo-relative path to the primary source file. Shown in the block's
|
|
10
|
+
* heading so readers can see where the range lives without leaving the
|
|
11
|
+
* commentary pane.
|
|
12
|
+
*/
|
|
13
|
+
sourcePath: string;
|
|
14
|
+
/** Full source text (lines separated by `\n`). */
|
|
15
|
+
sourceText: string;
|
|
16
|
+
/** Selected range to anchor the block to. */
|
|
17
|
+
range: BlockRange;
|
|
18
|
+
/** Optional explicit id; one is generated when omitted. */
|
|
19
|
+
id?: string;
|
|
20
|
+
/** Seam for deterministic tests. Default: `Math.random`. */
|
|
21
|
+
rng?: () => number;
|
|
22
|
+
};
|
|
23
|
+
export type CreatedBlock = {
|
|
24
|
+
block: CommentrayBlock;
|
|
25
|
+
/**
|
|
26
|
+
* Markdown fragment to append to the commentray file. Starts with the
|
|
27
|
+
* invisible `<!-- commentray:block ... -->` marker and ends with a
|
|
28
|
+
* trailing newline so subsequent appends stay separated.
|
|
29
|
+
*/
|
|
30
|
+
markdown: string;
|
|
31
|
+
/**
|
|
32
|
+
* 0-based line offset within `markdown` where the author's caret should
|
|
33
|
+
* land after insertion — the placeholder line ready to be overwritten.
|
|
34
|
+
*/
|
|
35
|
+
caretLineOffset: number;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Create a block (domain entity) together with the Markdown fragment that
|
|
39
|
+
* carries it in the commentary file. Pure: no I/O, deterministic when a
|
|
40
|
+
* fixed `rng` and `id` are supplied.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createBlockForRange(input: CreateBlockForRangeInput): CreatedBlock;
|
|
43
|
+
/**
|
|
44
|
+
* Append `blockMarkdown` to existing commentary content, guaranteeing a
|
|
45
|
+
* single blank-line separator regardless of how the existing content ended.
|
|
46
|
+
*/
|
|
47
|
+
export declare function appendBlockToCommentray(existing: string, blockMarkdown: string): string;
|
|
48
|
+
export type AddBlockToIndexInput = {
|
|
49
|
+
sourcePath: string;
|
|
50
|
+
commentrayPath: string;
|
|
51
|
+
block: CommentrayBlock;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Return a new index with the block added under the given source file.
|
|
55
|
+
* The source entry is created lazily when it does not exist yet. Throws
|
|
56
|
+
* when the block id already exists under that source so callers cannot
|
|
57
|
+
* silently corrupt the index.
|
|
58
|
+
*/
|
|
59
|
+
export declare function addBlockToIndex(index: CommentrayIndex, input: AddBlockToIndexInput): CommentrayIndex;
|
|
60
|
+
/**
|
|
61
|
+
* Six-character base-36 id. Alphabet excludes uppercase so ids are case-
|
|
62
|
+
* insensitive-safe on filesystems and URLs. Collision space ≈ 2 billion,
|
|
63
|
+
* comfortably larger than any plausible per-file block count.
|
|
64
|
+
*/
|
|
65
|
+
export declare function generateBlockId(rng?: () => number): string;
|
|
66
|
+
//# sourceMappingURL=blocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EAEf,eAAe,EAEhB,MAAM,YAAY,CAAC;AAEpB,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,KAAK,EAAE,UAAU,CAAC;IAClB,2DAA2D;IAC3D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,4DAA4D;IAC5D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,eAAe,CAAC;IACvB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAMF;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,YAAY,CASjF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAKvF;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,eAAe,CAAC;CACxB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,eAAe,EACtB,KAAK,EAAE,oBAAoB,GAC1B,eAAe,CAuBjB;AAKD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,MAAoB,GAAG,MAAM,CAMvE"}
|
package/dist/blocks.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { formatLineRange } from "./anchors.js";
|
|
2
|
+
const BLOCK_MARKER_PREFIX = "<!-- commentray:block id=";
|
|
3
|
+
const BLOCK_MARKER_SUFFIX = " -->";
|
|
4
|
+
const CARET_PLACEHOLDER = "_(write commentary here)_";
|
|
5
|
+
/**
|
|
6
|
+
* Create a block (domain entity) together with the Markdown fragment that
|
|
7
|
+
* carries it in the commentary file. Pure: no I/O, deterministic when a
|
|
8
|
+
* fixed `rng` and `id` are supplied.
|
|
9
|
+
*/
|
|
10
|
+
export function createBlockForRange(input) {
|
|
11
|
+
const range = clampRange(input.range, input.sourceText);
|
|
12
|
+
const anchor = formatLineRange({ start: range.startLine, end: range.endLine });
|
|
13
|
+
const fingerprint = computeFingerprint(input.sourceText, range);
|
|
14
|
+
const id = input.id ?? generateBlockId(input.rng);
|
|
15
|
+
const block = { id, anchor, fingerprint };
|
|
16
|
+
const markdown = renderBlockMarkdown({ block, sourcePath: input.sourcePath, range });
|
|
17
|
+
const caretLineOffset = placeholderLineOffset(markdown);
|
|
18
|
+
return { block, markdown, caretLineOffset };
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Append `blockMarkdown` to existing commentary content, guaranteeing a
|
|
22
|
+
* single blank-line separator regardless of how the existing content ended.
|
|
23
|
+
*/
|
|
24
|
+
export function appendBlockToCommentray(existing, blockMarkdown) {
|
|
25
|
+
const trimmed = existing.replace(/\s+$/, "");
|
|
26
|
+
const body = trimmed.length === 0 ? "" : `${trimmed}\n\n`;
|
|
27
|
+
const fragment = blockMarkdown.endsWith("\n") ? blockMarkdown : `${blockMarkdown}\n`;
|
|
28
|
+
return `${body}${fragment}`;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Return a new index with the block added under the given source file.
|
|
32
|
+
* The source entry is created lazily when it does not exist yet. Throws
|
|
33
|
+
* when the block id already exists under that source so callers cannot
|
|
34
|
+
* silently corrupt the index.
|
|
35
|
+
*/
|
|
36
|
+
export function addBlockToIndex(index, input) {
|
|
37
|
+
const key = input.commentrayPath;
|
|
38
|
+
const existing = index.byCommentrayPath[key];
|
|
39
|
+
if (existing && existing.sourcePath !== input.sourcePath) {
|
|
40
|
+
throw new Error(`commentrayPath ${key} is already indexed for ${existing.sourcePath}, not ${input.sourcePath}`);
|
|
41
|
+
}
|
|
42
|
+
const previousBlocks = existing?.blocks ?? [];
|
|
43
|
+
if (previousBlocks.some((b) => b.id === input.block.id)) {
|
|
44
|
+
throw new Error(`block id ${input.block.id} already exists under ${key}; choose a different id`);
|
|
45
|
+
}
|
|
46
|
+
const nextEntry = {
|
|
47
|
+
sourcePath: input.sourcePath,
|
|
48
|
+
commentrayPath: input.commentrayPath,
|
|
49
|
+
blocks: [...previousBlocks, input.block],
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
schemaVersion: index.schemaVersion,
|
|
53
|
+
byCommentrayPath: { ...index.byCommentrayPath, [key]: nextEntry },
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const ID_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
57
|
+
const ID_LENGTH = 6;
|
|
58
|
+
/**
|
|
59
|
+
* Six-character base-36 id. Alphabet excludes uppercase so ids are case-
|
|
60
|
+
* insensitive-safe on filesystems and URLs. Collision space ≈ 2 billion,
|
|
61
|
+
* comfortably larger than any plausible per-file block count.
|
|
62
|
+
*/
|
|
63
|
+
export function generateBlockId(rng = Math.random) {
|
|
64
|
+
let id = "";
|
|
65
|
+
for (let i = 0; i < ID_LENGTH; i++) {
|
|
66
|
+
id += ID_ALPHABET[Math.floor(rng() * ID_ALPHABET.length)];
|
|
67
|
+
}
|
|
68
|
+
return id;
|
|
69
|
+
}
|
|
70
|
+
function clampRange(range, sourceText) {
|
|
71
|
+
const lineCount = Math.max(1, sourceText.split("\n").length);
|
|
72
|
+
const start = Math.max(1, Math.min(Math.floor(range.startLine), lineCount));
|
|
73
|
+
const endRaw = Math.max(start, Math.floor(range.endLine));
|
|
74
|
+
const end = Math.min(endRaw, lineCount);
|
|
75
|
+
return { startLine: start, endLine: end };
|
|
76
|
+
}
|
|
77
|
+
function computeFingerprint(sourceText, range) {
|
|
78
|
+
const lines = sourceText.split("\n");
|
|
79
|
+
const startText = (lines[range.startLine - 1] ?? "").trim();
|
|
80
|
+
const endText = (lines[range.endLine - 1] ?? "").trim();
|
|
81
|
+
return {
|
|
82
|
+
startLine: startText,
|
|
83
|
+
endLine: endText,
|
|
84
|
+
lineCount: range.endLine - range.startLine + 1,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function renderBlockMarkdown(args) {
|
|
88
|
+
const marker = `${BLOCK_MARKER_PREFIX}${args.block.id}${BLOCK_MARKER_SUFFIX}`;
|
|
89
|
+
const heading = `## \`${args.sourcePath}\` ${rangeLabel(args.range)}`;
|
|
90
|
+
return `${marker}\n${heading}\n\n${CARET_PLACEHOLDER}\n`;
|
|
91
|
+
}
|
|
92
|
+
function rangeLabel(range) {
|
|
93
|
+
if (range.startLine === range.endLine)
|
|
94
|
+
return `line ${range.startLine}`;
|
|
95
|
+
return `lines ${range.startLine}–${range.endLine}`;
|
|
96
|
+
}
|
|
97
|
+
function placeholderLineOffset(markdown) {
|
|
98
|
+
const lines = markdown.split("\n");
|
|
99
|
+
return Math.max(0, lines.indexOf(CARET_PLACEHOLDER));
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=blocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocks.js","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ResolvedCommentrayConfig } from "./config.js";
|
|
2
|
+
/**
|
|
3
|
+
* When Angles layout is on and the user has not configured a default, tools pick this id so a
|
|
4
|
+
* concrete file path exists (`…/main.md`). Authors may rename via `[angles]` in `.commentray.toml`.
|
|
5
|
+
*/
|
|
6
|
+
export declare const FALLBACK_DEFAULT_ANGLE_ID: "main";
|
|
7
|
+
export declare function defaultAngleIdForOpen(config: ResolvedCommentrayConfig): string;
|
|
8
|
+
export type ResolvedCommentrayMarkdownPath = {
|
|
9
|
+
/** Repo-relative path to the paired `.md` file. */
|
|
10
|
+
commentrayPath: string;
|
|
11
|
+
/** Present when `{storage}/source/.default` exists (Angles layout). */
|
|
12
|
+
angleId: string | null;
|
|
13
|
+
anglesLayout: boolean;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Resolves the commentray Markdown path for a primary source file, honoring Angles layout and
|
|
17
|
+
* optional explicit `angleId` (when Angles layout is active).
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveCommentrayMarkdownPath(repoRoot: string, sourceRepoRelativePath: string, config: ResolvedCommentrayConfig, angleId?: string | null): ResolvedCommentrayMarkdownPath;
|
|
20
|
+
//# sourceMappingURL=commentray-path-resolution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commentray-path-resolution.d.ts","sourceRoot":"","sources":["../src/commentray-path-resolution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAQ5D;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAG,MAAe,CAAC;AAEzD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CAK9E;AAED,MAAM,MAAM,8BAA8B,GAAG;IAC3C,mDAAmD;IACnD,cAAc,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,EAChB,sBAAsB,EAAE,MAAM,EAC9B,MAAM,EAAE,wBAAwB,EAChC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GACtB,8BAA8B,CAkBhC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { assertValidAngleId } from "./angles.js";
|
|
2
|
+
import { commentrayAnglesLayoutEnabled, commentrayMarkdownPath, commentrayMarkdownPathForAngle, } from "./paths.js";
|
|
3
|
+
/**
|
|
4
|
+
* When Angles layout is on and the user has not configured a default, tools pick this id so a
|
|
5
|
+
* concrete file path exists (`…/main.md`). Authors may rename via `[angles]` in `.commentray.toml`.
|
|
6
|
+
*/
|
|
7
|
+
export const FALLBACK_DEFAULT_ANGLE_ID = "main";
|
|
8
|
+
export function defaultAngleIdForOpen(config) {
|
|
9
|
+
if (config.angles.defaultAngleId)
|
|
10
|
+
return config.angles.defaultAngleId;
|
|
11
|
+
const first = config.angles.definitions[0];
|
|
12
|
+
if (first)
|
|
13
|
+
return first.id;
|
|
14
|
+
return FALLBACK_DEFAULT_ANGLE_ID;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolves the commentray Markdown path for a primary source file, honoring Angles layout and
|
|
18
|
+
* optional explicit `angleId` (when Angles layout is active).
|
|
19
|
+
*/
|
|
20
|
+
export function resolveCommentrayMarkdownPath(repoRoot, sourceRepoRelativePath, config, angleId) {
|
|
21
|
+
const anglesLayout = commentrayAnglesLayoutEnabled(repoRoot, config.storageDir);
|
|
22
|
+
if (!anglesLayout) {
|
|
23
|
+
return {
|
|
24
|
+
commentrayPath: commentrayMarkdownPath(sourceRepoRelativePath),
|
|
25
|
+
angleId: null,
|
|
26
|
+
anglesLayout: false,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const id = angleId !== undefined && angleId !== null && String(angleId).trim() !== ""
|
|
30
|
+
? assertValidAngleId(String(angleId))
|
|
31
|
+
: defaultAngleIdForOpen(config);
|
|
32
|
+
return {
|
|
33
|
+
commentrayPath: commentrayMarkdownPathForAngle(sourceRepoRelativePath, id, config.storageDir),
|
|
34
|
+
angleId: id,
|
|
35
|
+
anglesLayout: true,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=commentray-path-resolution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commentray-path-resolution.js","sourceRoot":"","sources":["../src/commentray-path-resolution.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,8BAA8B,GAC/B,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAe,CAAC;AAEzD,MAAM,UAAU,qBAAqB,CAAC,MAAgC;IACpE,IAAI,MAAM,CAAC,MAAM,CAAC,cAAc;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC;IACtE,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAC3C,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC,EAAE,CAAC;IAC3B,OAAO,yBAAyB,CAAC;AACnC,CAAC;AAUD;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAC3C,QAAgB,EAChB,sBAA8B,EAC9B,MAAgC,EAChC,OAAuB;IAEvB,MAAM,YAAY,GAAG,6BAA6B,CAAC,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAChF,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO;YACL,cAAc,EAAE,sBAAsB,CAAC,sBAAsB,CAAC;YAC9D,OAAO,EAAE,IAAI;YACb,YAAY,EAAE,KAAK;SACpB,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,GACN,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE;QACxE,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO;QACL,cAAc,EAAE,8BAA8B,CAAC,sBAAsB,EAAE,EAAE,EAAE,MAAM,CAAC,UAAU,CAAC;QAC7F,OAAO,EAAE,EAAE;QACX,YAAY,EAAE,IAAI;KACnB,CAAC;AACJ,CAAC"}
|
package/dist/config.d.ts
CHANGED
|
@@ -8,10 +8,29 @@ export type CommentrayToml = {
|
|
|
8
8
|
render?: {
|
|
9
9
|
mermaid?: boolean;
|
|
10
10
|
syntaxTheme?: string;
|
|
11
|
+
/**
|
|
12
|
+
* When true, `https://github.com/<owner>/<repo>/blob|tree/<branch>/…` links in commentray
|
|
13
|
+
* Markdown are rewritten to paths relative to the generated HTML file (see
|
|
14
|
+
* `static_site.github_url` for owner/repo). Requires a parseable repository URL.
|
|
15
|
+
*/
|
|
16
|
+
relative_github_blob_links?: boolean;
|
|
11
17
|
};
|
|
12
18
|
anchors?: {
|
|
13
19
|
defaultStrategy?: string[];
|
|
14
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* Named **Angles** — multiple commentrays per source file (see `docs/spec/storage.md`).
|
|
23
|
+
* Keys use snake_case in TOML (`[angles]`).
|
|
24
|
+
*/
|
|
25
|
+
angles?: {
|
|
26
|
+
/** Which Angle is selected by default in tooling and the static viewer (must match a `definitions` id when that list is non-empty). */
|
|
27
|
+
default_angle?: string;
|
|
28
|
+
/** Optional list of known Angles with display titles for UI (static browser, editor). */
|
|
29
|
+
definitions?: {
|
|
30
|
+
id: string;
|
|
31
|
+
title?: string;
|
|
32
|
+
}[];
|
|
33
|
+
};
|
|
15
34
|
/**
|
|
16
35
|
* Optional settings for publishing a single-file static “code browser” (GitHub Pages, etc.).
|
|
17
36
|
* Keys use snake_case in TOML (`[static_site]`).
|
|
@@ -27,14 +46,41 @@ export type CommentrayToml = {
|
|
|
27
46
|
commentray_markdown?: string;
|
|
28
47
|
/** @deprecated Renamed to `commentray_markdown`. */
|
|
29
48
|
commentary_markdown?: string;
|
|
49
|
+
/** Branch name embedded in GitHub blob URLs for `related_github_files` (default `main`). */
|
|
50
|
+
github_blob_branch?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Optional toolbar links on the static code browser: open other repo files on GitHub
|
|
53
|
+
* (single-page Pages deploys cannot serve arbitrary paths next to `index.html`).
|
|
54
|
+
*/
|
|
55
|
+
related_github_files?: {
|
|
56
|
+
label?: string;
|
|
57
|
+
path: string;
|
|
58
|
+
}[];
|
|
30
59
|
};
|
|
31
60
|
};
|
|
61
|
+
export type ResolvedGithubNavLink = {
|
|
62
|
+
label: string;
|
|
63
|
+
href: string;
|
|
64
|
+
};
|
|
32
65
|
export type ResolvedStaticSite = {
|
|
33
66
|
title: string;
|
|
34
67
|
introMarkdown: string;
|
|
35
68
|
githubUrl: string | null;
|
|
69
|
+
/** Branch used when building `relatedGithubNav` blob URLs. */
|
|
70
|
+
githubBlobBranch: string;
|
|
36
71
|
sourceFile: string;
|
|
37
72
|
commentrayMarkdownFile: string;
|
|
73
|
+
/** Toolbar “Also on GitHub …” links for the static code browser. */
|
|
74
|
+
relatedGithubNav: ResolvedGithubNavLink[];
|
|
75
|
+
};
|
|
76
|
+
export type ResolvedAngleDefinition = {
|
|
77
|
+
id: string;
|
|
78
|
+
title: string;
|
|
79
|
+
};
|
|
80
|
+
export type ResolvedAngles = {
|
|
81
|
+
/** When `definitions` is non-empty, this must match one of them (enforced at merge). */
|
|
82
|
+
defaultAngleId: string | null;
|
|
83
|
+
definitions: ResolvedAngleDefinition[];
|
|
38
84
|
};
|
|
39
85
|
export type ResolvedCommentrayConfig = {
|
|
40
86
|
storageDir: string;
|
|
@@ -42,10 +88,12 @@ export type ResolvedCommentrayConfig = {
|
|
|
42
88
|
render: {
|
|
43
89
|
mermaid: boolean;
|
|
44
90
|
syntaxTheme: string;
|
|
91
|
+
relativeGithubBlobLinks: boolean;
|
|
45
92
|
};
|
|
46
93
|
anchors: {
|
|
47
94
|
defaultStrategy: string[];
|
|
48
95
|
};
|
|
96
|
+
angles: ResolvedAngles;
|
|
49
97
|
staticSite: ResolvedStaticSite;
|
|
50
98
|
};
|
|
51
99
|
export declare function mergeCommentrayConfig(parsed: CommentrayToml | null): ResolvedCommentrayConfig;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3B,GAAG,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5B,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB;;;;WAIG;QACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;KACtC,CAAC;IACF,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACzC;;;OAGG;IACH,MAAM,CAAC,EAAE;QACP,uIAAuI;QACvI,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,yFAAyF;QACzF,WAAW,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KAChD,CAAC;IACF;;;OAGG;IACH,WAAW,CAAC,EAAE;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,yEAAyE;QACzE,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,wFAAwF;QACxF,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,uEAAuE;QACvE,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,oDAAoD;QACpD,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,4FAA4F;QAC5F,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B;;;WAGG;QACH,oBAAoB,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KAC3D,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,8DAA8D;IAC9D,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,oEAAoE;IACpE,gBAAgB,EAAE,qBAAqB,EAAE,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE,MAAM,MAAM,cAAc,GAAG;IAC3B,wFAAwF;IACxF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,uBAAuB,EAAE,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,KAAK,CAAC;IACnB,MAAM,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,uBAAuB,EAAE,OAAO,CAAA;KAAE,CAAC;IACpF,OAAO,EAAE;QAAE,eAAe,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACvC,MAAM,EAAE,cAAc,CAAC;IACvB,UAAU,EAAE,kBAAkB,CAAC;CAChC,CAAC;AA+JF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,GAAG,wBAAwB,CAsB7F;AAED,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAY9F"}
|
package/dist/config.js
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { parse as parseToml } from "@iarna/toml";
|
|
4
|
+
import { assertValidAngleId } from "./angles.js";
|
|
5
|
+
import { githubRepoBlobFileUrl, parseGithubRepoWebUrl } from "./github-url.js";
|
|
4
6
|
import { normalizeRepoRelativePath } from "./paths.js";
|
|
5
7
|
const defaultStaticSite = {
|
|
6
8
|
title: "Commentray",
|
|
7
9
|
introMarkdown: "",
|
|
8
10
|
githubUrl: null,
|
|
11
|
+
githubBlobBranch: "main",
|
|
9
12
|
sourceFile: "README.md",
|
|
10
13
|
commentrayMarkdownFile: "",
|
|
14
|
+
relatedGithubNav: [],
|
|
11
15
|
};
|
|
16
|
+
const defaultAngles = { defaultAngleId: null, definitions: [] };
|
|
12
17
|
const defaultConfig = {
|
|
13
18
|
storageDir: ".commentray",
|
|
14
19
|
scmProvider: "git",
|
|
15
|
-
render: { mermaid: true, syntaxTheme: "github-dark" },
|
|
20
|
+
render: { mermaid: true, syntaxTheme: "github-dark", relativeGithubBlobLinks: false },
|
|
16
21
|
anchors: { defaultStrategy: ["symbol", "lines"] },
|
|
22
|
+
angles: { ...defaultAngles },
|
|
17
23
|
staticSite: { ...defaultStaticSite },
|
|
18
24
|
};
|
|
19
25
|
function nonEmptyTrimmed(s) {
|
|
@@ -52,17 +58,70 @@ function assertStorageDirNotInsideGit(value) {
|
|
|
52
58
|
`Git treats .git/ as opaque metadata and routine operations can wipe it.`);
|
|
53
59
|
}
|
|
54
60
|
}
|
|
61
|
+
function mergeAngleDefinitions(raw) {
|
|
62
|
+
if (!raw?.length)
|
|
63
|
+
return [];
|
|
64
|
+
const out = [];
|
|
65
|
+
const seen = new Set();
|
|
66
|
+
for (const row of raw) {
|
|
67
|
+
const id = assertValidAngleId(row.id);
|
|
68
|
+
if (seen.has(id)) {
|
|
69
|
+
throw new Error(`Duplicate angles.definitions id: ${id}`);
|
|
70
|
+
}
|
|
71
|
+
seen.add(id);
|
|
72
|
+
const title = row.title?.trim() || id;
|
|
73
|
+
out.push({ id, title });
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
function resolveAngles(parsed) {
|
|
78
|
+
const a = parsed.angles;
|
|
79
|
+
if (!a) {
|
|
80
|
+
return { ...defaultAngles };
|
|
81
|
+
}
|
|
82
|
+
const definitions = mergeAngleDefinitions(a.definitions);
|
|
83
|
+
const defaultRaw = a.default_angle?.trim();
|
|
84
|
+
const defaultAngleId = defaultRaw ? assertValidAngleId(defaultRaw) : null;
|
|
85
|
+
if (definitions.length > 0 &&
|
|
86
|
+
defaultAngleId &&
|
|
87
|
+
!definitions.some((d) => d.id === defaultAngleId)) {
|
|
88
|
+
throw new Error(`angles.default_angle "${defaultAngleId}" must match one of angles.definitions (got: ${definitions.map((d) => d.id).join(", ")})`);
|
|
89
|
+
}
|
|
90
|
+
return { defaultAngleId, definitions };
|
|
91
|
+
}
|
|
92
|
+
function mergeRelatedGithubNav(githubUrl, branch, raw) {
|
|
93
|
+
const gh = githubUrl ? parseGithubRepoWebUrl(githubUrl) : null;
|
|
94
|
+
if (!gh || !raw?.length)
|
|
95
|
+
return [];
|
|
96
|
+
const b = branch.trim() || defaultStaticSite.githubBlobBranch;
|
|
97
|
+
const out = [];
|
|
98
|
+
for (const row of raw) {
|
|
99
|
+
if (!row?.path?.trim())
|
|
100
|
+
continue;
|
|
101
|
+
const p = normalizeRepoRelativePath(row.path.trim());
|
|
102
|
+
const label = row.label?.trim() || path.posix.basename(p);
|
|
103
|
+
out.push({
|
|
104
|
+
label,
|
|
105
|
+
href: githubRepoBlobFileUrl(gh.owner, gh.repo, b, p),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
55
110
|
function resolveStaticSite(parsed) {
|
|
56
111
|
const ss = parsed.static_site;
|
|
57
112
|
const mdFile = ss?.commentray_markdown?.trim() ??
|
|
58
113
|
ss?.commentary_markdown?.trim() ??
|
|
59
114
|
defaultStaticSite.commentrayMarkdownFile;
|
|
115
|
+
const githubUrl = nonEmptyTrimmed(ss?.github_url);
|
|
116
|
+
const githubBlobBranch = nonEmptyTrimmed(ss?.github_blob_branch) ?? defaultStaticSite.githubBlobBranch;
|
|
60
117
|
return {
|
|
61
118
|
title: nonEmptyTrimmed(ss?.title) ?? defaultStaticSite.title,
|
|
62
119
|
introMarkdown: ss?.intro ?? defaultStaticSite.introMarkdown,
|
|
63
|
-
githubUrl
|
|
120
|
+
githubUrl,
|
|
121
|
+
githubBlobBranch,
|
|
64
122
|
sourceFile: nonEmptyTrimmed(ss?.source_file) ?? defaultStaticSite.sourceFile,
|
|
65
123
|
commentrayMarkdownFile: mdFile,
|
|
124
|
+
relatedGithubNav: mergeRelatedGithubNav(githubUrl, githubBlobBranch, ss?.related_github_files),
|
|
66
125
|
};
|
|
67
126
|
}
|
|
68
127
|
function assertSafeConfigPaths(parsed) {
|
|
@@ -72,6 +131,9 @@ function assertSafeConfigPaths(parsed) {
|
|
|
72
131
|
assertSafeRepoRelativePath("static_site.source_file", ss?.source_file);
|
|
73
132
|
assertSafeRepoRelativePath("static_site.commentray_markdown", ss?.commentray_markdown);
|
|
74
133
|
assertSafeRepoRelativePath("static_site.commentary_markdown", ss?.commentary_markdown);
|
|
134
|
+
for (let i = 0; i < (ss?.related_github_files?.length ?? 0); i++) {
|
|
135
|
+
assertSafeRepoRelativePath(`static_site.related_github_files[${i}].path`, ss?.related_github_files?.[i]?.path);
|
|
136
|
+
}
|
|
75
137
|
}
|
|
76
138
|
export function mergeCommentrayConfig(parsed) {
|
|
77
139
|
if (!parsed)
|
|
@@ -87,10 +149,12 @@ export function mergeCommentrayConfig(parsed) {
|
|
|
87
149
|
render: {
|
|
88
150
|
mermaid: parsed.render?.mermaid ?? defaultConfig.render.mermaid,
|
|
89
151
|
syntaxTheme: parsed.render?.syntaxTheme ?? defaultConfig.render.syntaxTheme,
|
|
152
|
+
relativeGithubBlobLinks: parsed.render?.relative_github_blob_links ?? defaultConfig.render.relativeGithubBlobLinks,
|
|
90
153
|
},
|
|
91
154
|
anchors: {
|
|
92
155
|
defaultStrategy: parsed.anchors?.defaultStrategy ?? defaultConfig.anchors.defaultStrategy,
|
|
93
156
|
},
|
|
157
|
+
angles: resolveAngles(parsed),
|
|
94
158
|
staticSite: resolveStaticSite(parsed),
|
|
95
159
|
};
|
|
96
160
|
}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a GitHub repository web URL into owner + repo name (no API calls).
|
|
3
|
+
* Accepts optional trailing slash and `.git` suffix.
|
|
4
|
+
*/
|
|
5
|
+
export declare function parseGithubRepoWebUrl(url: string): {
|
|
6
|
+
owner: string;
|
|
7
|
+
repo: string;
|
|
8
|
+
} | null;
|
|
9
|
+
/**
|
|
10
|
+
* Builds a `https://github.com/owner/repo/blob/<branch>/path` URL for a repo-relative file path.
|
|
11
|
+
* Used for static-site “open another file” links when only `_site/index.html` is deployed.
|
|
12
|
+
*/
|
|
13
|
+
export declare function githubRepoBlobFileUrl(owner: string, repo: string, branch: string, repoRelativePath: string): string;
|
|
14
|
+
//# sourceMappingURL=github-url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-url.d.ts","sourceRoot":"","sources":["../src/github-url.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAKzF;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,GACvB,MAAM,CAOR"}
|