mrplex 0.0.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/LICENSE +21 -0
- package/README.md +284 -0
- package/dist/cli/config.d.ts +28 -0
- package/dist/cli/config.js +48 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/exit-codes.d.ts +13 -0
- package/dist/cli/exit-codes.js +39 -0
- package/dist/cli/exit-codes.js.map +1 -0
- package/dist/cli/format.d.ts +22 -0
- package/dist/cli/format.js +148 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/main.d.ts +16 -0
- package/dist/cli/main.js +1518 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/client/kernel-client.d.ts +97 -0
- package/dist/client/kernel-client.js +14 -0
- package/dist/client/kernel-client.js.map +1 -0
- package/dist/client/local.d.ts +26 -0
- package/dist/client/local.js +103 -0
- package/dist/client/local.js.map +1 -0
- package/dist/client/remote-mcp.d.ts +35 -0
- package/dist/client/remote-mcp.js +174 -0
- package/dist/client/remote-mcp.js.map +1 -0
- package/dist/embed/backfill.d.ts +24 -0
- package/dist/embed/backfill.js +33 -0
- package/dist/embed/backfill.js.map +1 -0
- package/dist/embed/chunker.d.ts +31 -0
- package/dist/embed/chunker.js +121 -0
- package/dist/embed/chunker.js.map +1 -0
- package/dist/embed/cmd-hook.d.ts +21 -0
- package/dist/embed/cmd-hook.js +100 -0
- package/dist/embed/cmd-hook.js.map +1 -0
- package/dist/embed/config.d.ts +61 -0
- package/dist/embed/config.js +109 -0
- package/dist/embed/config.js.map +1 -0
- package/dist/embed/hook.d.ts +38 -0
- package/dist/embed/hook.js +56 -0
- package/dist/embed/hook.js.map +1 -0
- package/dist/embed/http-hook.d.ts +13 -0
- package/dist/embed/http-hook.js +39 -0
- package/dist/embed/http-hook.js.map +1 -0
- package/dist/embed/worker.d.ts +62 -0
- package/dist/embed/worker.js +228 -0
- package/dist/embed/worker.js.map +1 -0
- package/dist/fixtures/hwe/characters/albion-ever.md +12 -0
- package/dist/fixtures/hwe/characters/cent.md +11 -0
- package/dist/fixtures/hwe/concepts/cent-demiurge-resonance.md +10 -0
- package/dist/fixtures/hwe/concepts/phase-looper.md +10 -0
- package/dist/fixtures/hwe/entities/demiurge.md +11 -0
- package/dist/fixtures/hwe/entities/monad.md +11 -0
- package/dist/fixtures/hwe/moc/globocorp-network.md +19 -0
- package/dist/fixtures/hwe/organizations/globocorp.md +11 -0
- package/dist/fixtures/hwe/readme.md +24 -0
- package/dist/fixtures/starship/crew/aria-okonkwo.md +14 -0
- package/dist/fixtures/starship/crew/bexley-orr.md +14 -0
- package/dist/fixtures/starship/crew/dax-thorne.md +14 -0
- package/dist/fixtures/starship/crew/isolde-marsh.md +16 -0
- package/dist/fixtures/starship/crew/kestrel-vance.md +15 -0
- package/dist/fixtures/starship/crew/quill-vasquez.md +14 -0
- package/dist/fixtures/starship/crew/soren-halloway.md +16 -0
- package/dist/fixtures/starship/encounters/the-drift-choir.md +14 -0
- package/dist/fixtures/starship/encounters/the-hollow-signal.md +16 -0
- package/dist/fixtures/starship/encounters/the-wandering-buoy.md +14 -0
- package/dist/fixtures/starship/equipment/coolant-loop-b.md +13 -0
- package/dist/fixtures/starship/equipment/emergency-ration-bars.md +12 -0
- package/dist/fixtures/starship/equipment/long-range-sensors.md +13 -0
- package/dist/fixtures/starship/equipment/plasma-manifold-3.md +15 -0
- package/dist/fixtures/starship/equipment/shuttle-corvid.md +13 -0
- package/dist/fixtures/starship/logs/marsh-4419-1.md +13 -0
- package/dist/fixtures/starship/logs/okonkwo-4415-1.md +13 -0
- package/dist/fixtures/starship/logs/orr-4413-1.md +13 -0
- package/dist/fixtures/starship/logs/orr-4420-1.md +12 -0
- package/dist/fixtures/starship/logs/thorne-4413-2.md +13 -0
- package/dist/fixtures/starship/logs/vance-4419-2.md +13 -0
- package/dist/fixtures/starship/misc/the-galley-ficus.md +11 -0
- package/dist/fixtures/starship/missions/the-cinder-run.md +17 -0
- package/dist/fixtures/starship/missions/the-drift-choir.md +17 -0
- package/dist/fixtures/starship/missions/the-hollow-signal.md +17 -0
- package/dist/fixtures/starship/missions/the-silent-beacon.md +17 -0
- package/dist/fixtures/starship/moc/crew.md +19 -0
- package/dist/fixtures/starship/moc/encounters.md +14 -0
- package/dist/fixtures/starship/moc/missions.md +15 -0
- package/dist/fixtures/starship/readme.md +60 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/auth/glob.d.ts +46 -0
- package/dist/kernel/auth/glob.js +112 -0
- package/dist/kernel/auth/glob.js.map +1 -0
- package/dist/kernel/auth/scope.d.ts +53 -0
- package/dist/kernel/auth/scope.js +83 -0
- package/dist/kernel/auth/scope.js.map +1 -0
- package/dist/kernel/casefold.d.ts +37 -0
- package/dist/kernel/casefold.js +44 -0
- package/dist/kernel/casefold.js.map +1 -0
- package/dist/kernel/constants.d.ts +21 -0
- package/dist/kernel/constants.js +22 -0
- package/dist/kernel/constants.js.map +1 -0
- package/dist/kernel/context.d.ts +70 -0
- package/dist/kernel/context.js +114 -0
- package/dist/kernel/context.js.map +1 -0
- package/dist/kernel/deletion.d.ts +50 -0
- package/dist/kernel/deletion.js +83 -0
- package/dist/kernel/deletion.js.map +1 -0
- package/dist/kernel/diff.d.ts +36 -0
- package/dist/kernel/diff.js +61 -0
- package/dist/kernel/diff.js.map +1 -0
- package/dist/kernel/errors.d.ts +37 -0
- package/dist/kernel/errors.js +55 -0
- package/dist/kernel/errors.js.map +1 -0
- package/dist/kernel/frontmatter-input.d.ts +32 -0
- package/dist/kernel/frontmatter-input.js +85 -0
- package/dist/kernel/frontmatter-input.js.map +1 -0
- package/dist/kernel/graph.d.ts +34 -0
- package/dist/kernel/graph.js +559 -0
- package/dist/kernel/graph.js.map +1 -0
- package/dist/kernel/history.d.ts +74 -0
- package/dist/kernel/history.js +143 -0
- package/dist/kernel/history.js.map +1 -0
- package/dist/kernel/kernel.d.ts +162 -0
- package/dist/kernel/kernel.js +675 -0
- package/dist/kernel/kernel.js.map +1 -0
- package/dist/kernel/path-config.d.ts +101 -0
- package/dist/kernel/path-config.js +171 -0
- package/dist/kernel/path-config.js.map +1 -0
- package/dist/kernel/query/ast.d.ts +24 -0
- package/dist/kernel/query/ast.js +52 -0
- package/dist/kernel/query/ast.js.map +1 -0
- package/dist/kernel/query/cel-parse.d.ts +37 -0
- package/dist/kernel/query/cel-parse.js +88 -0
- package/dist/kernel/query/cel-parse.js.map +1 -0
- package/dist/kernel/query/degrees.d.ts +31 -0
- package/dist/kernel/query/degrees.js +135 -0
- package/dist/kernel/query/degrees.js.map +1 -0
- package/dist/kernel/query/graph-ast.d.ts +51 -0
- package/dist/kernel/query/graph-ast.js +139 -0
- package/dist/kernel/query/graph-ast.js.map +1 -0
- package/dist/kernel/query/query.d.ts +56 -0
- package/dist/kernel/query/query.js +276 -0
- package/dist/kernel/query/query.js.map +1 -0
- package/dist/kernel/validation.d.ts +64 -0
- package/dist/kernel/validation.js +183 -0
- package/dist/kernel/validation.js.map +1 -0
- package/dist/kernel/version-id.d.ts +10 -0
- package/dist/kernel/version-id.js +21 -0
- package/dist/kernel/version-id.js.map +1 -0
- package/dist/kernel/wire.d.ts +148 -0
- package/dist/kernel/wire.js +6 -0
- package/dist/kernel/wire.js.map +1 -0
- package/dist/links/backfill.d.ts +28 -0
- package/dist/links/backfill.js +33 -0
- package/dist/links/backfill.js.map +1 -0
- package/dist/links/extract.d.ts +29 -0
- package/dist/links/extract.js +233 -0
- package/dist/links/extract.js.map +1 -0
- package/dist/links/link-config.d.ts +70 -0
- package/dist/links/link-config.js +107 -0
- package/dist/links/link-config.js.map +1 -0
- package/dist/links/maintain.d.ts +37 -0
- package/dist/links/maintain.js +91 -0
- package/dist/links/maintain.js.map +1 -0
- package/dist/links/repair.d.ts +46 -0
- package/dist/links/repair.js +96 -0
- package/dist/links/repair.js.map +1 -0
- package/dist/links/resolve.d.ts +41 -0
- package/dist/links/resolve.js +121 -0
- package/dist/links/resolve.js.map +1 -0
- package/dist/links/stale.d.ts +32 -0
- package/dist/links/stale.js +73 -0
- package/dist/links/stale.js.map +1 -0
- package/dist/markdown/content-hash.d.ts +34 -0
- package/dist/markdown/content-hash.js +46 -0
- package/dist/markdown/content-hash.js.map +1 -0
- package/dist/markdown/frontmatter.d.ts +69 -0
- package/dist/markdown/frontmatter.js +147 -0
- package/dist/markdown/frontmatter.js.map +1 -0
- package/dist/markdown/hash-backfill.d.ts +22 -0
- package/dist/markdown/hash-backfill.js +43 -0
- package/dist/markdown/hash-backfill.js.map +1 -0
- package/dist/mcp/query-syntax.d.ts +20 -0
- package/dist/mcp/query-syntax.js +194 -0
- package/dist/mcp/query-syntax.js.map +1 -0
- package/dist/mcp/render.d.ts +31 -0
- package/dist/mcp/render.js +110 -0
- package/dist/mcp/render.js.map +1 -0
- package/dist/mcp/server.d.ts +60 -0
- package/dist/mcp/server.js +170 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +93 -0
- package/dist/mcp/tools.js +1218 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/rest/conditional.d.ts +37 -0
- package/dist/rest/conditional.js +58 -0
- package/dist/rest/conditional.js.map +1 -0
- package/dist/rest/negotiate.d.ts +33 -0
- package/dist/rest/negotiate.js +54 -0
- package/dist/rest/negotiate.js.map +1 -0
- package/dist/rest/routes.d.ts +37 -0
- package/dist/rest/routes.js +744 -0
- package/dist/rest/routes.js.map +1 -0
- package/dist/seed/fixture-seed.d.ts +35 -0
- package/dist/seed/fixture-seed.js +75 -0
- package/dist/seed/fixture-seed.js.map +1 -0
- package/dist/seed/starship-config.d.ts +3 -0
- package/dist/seed/starship-config.js +5 -0
- package/dist/seed/starship-config.js.map +1 -0
- package/dist/server/headers.d.ts +36 -0
- package/dist/server/headers.js +30 -0
- package/dist/server/headers.js.map +1 -0
- package/dist/server/http-error.d.ts +53 -0
- package/dist/server/http-error.js +104 -0
- package/dist/server/http-error.js.map +1 -0
- package/dist/server/serve.d.ts +56 -0
- package/dist/server/serve.js +135 -0
- package/dist/server/serve.js.map +1 -0
- package/dist/shell/audit.d.ts +32 -0
- package/dist/shell/audit.js +28 -0
- package/dist/shell/audit.js.map +1 -0
- package/dist/shell/guard.d.ts +50 -0
- package/dist/shell/guard.js +176 -0
- package/dist/shell/guard.js.map +1 -0
- package/dist/shell/keys.d.ts +36 -0
- package/dist/shell/keys.js +64 -0
- package/dist/shell/keys.js.map +1 -0
- package/dist/shell/login.d.ts +56 -0
- package/dist/shell/login.js +130 -0
- package/dist/shell/login.js.map +1 -0
- package/dist/shell/oidc.d.ts +62 -0
- package/dist/shell/oidc.js +102 -0
- package/dist/shell/oidc.js.map +1 -0
- package/dist/shell/policy.d.ts +100 -0
- package/dist/shell/policy.js +232 -0
- package/dist/shell/policy.js.map +1 -0
- package/dist/shell/proxy-policy.d.ts +34 -0
- package/dist/shell/proxy-policy.js +120 -0
- package/dist/shell/proxy-policy.js.map +1 -0
- package/dist/shell/proxy.d.ts +47 -0
- package/dist/shell/proxy.js +253 -0
- package/dist/shell/proxy.js.map +1 -0
- package/dist/shell/serve.d.ts +86 -0
- package/dist/shell/serve.js +0 -0
- package/dist/shell/serve.js.map +1 -0
- package/dist/shell/stdio.d.ts +55 -0
- package/dist/shell/stdio.js +63 -0
- package/dist/shell/stdio.js.map +1 -0
- package/dist/storage/registry.d.ts +20 -0
- package/dist/storage/registry.js +38 -0
- package/dist/storage/registry.js.map +1 -0
- package/dist/storage/search-plan.d.ts +93 -0
- package/dist/storage/search-plan.js +15 -0
- package/dist/storage/search-plan.js.map +1 -0
- package/dist/storage/types.d.ts +448 -0
- package/dist/storage/types.js +14 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/storage/versions-since.d.ts +72 -0
- package/dist/storage/versions-since.js +92 -0
- package/dist/storage/versions-since.js.map +1 -0
- package/dist/storage-postgres/adapter.d.ts +17 -0
- package/dist/storage-postgres/adapter.js +782 -0
- package/dist/storage-postgres/adapter.js.map +1 -0
- package/dist/storage-postgres/compile-postgres.d.ts +22 -0
- package/dist/storage-postgres/compile-postgres.js +830 -0
- package/dist/storage-postgres/compile-postgres.js.map +1 -0
- package/dist/storage-postgres/errors.d.ts +34 -0
- package/dist/storage-postgres/errors.js +50 -0
- package/dist/storage-postgres/errors.js.map +1 -0
- package/dist/storage-postgres/migrations/0001_init.sql +113 -0
- package/dist/storage-postgres/migrations/0002_content_hash.sql +7 -0
- package/dist/storage-postgres/migrations/index.d.ts +22 -0
- package/dist/storage-postgres/migrations/index.js +70 -0
- package/dist/storage-postgres/migrations/index.js.map +1 -0
- package/dist/storage-sqlite/adapter.d.ts +2 -0
- package/dist/storage-sqlite/adapter.js +688 -0
- package/dist/storage-sqlite/adapter.js.map +1 -0
- package/dist/storage-sqlite/compile-filter.d.ts +41 -0
- package/dist/storage-sqlite/compile-filter.js +881 -0
- package/dist/storage-sqlite/compile-filter.js.map +1 -0
- package/dist/storage-sqlite/compile-sqlite.d.ts +19 -0
- package/dist/storage-sqlite/compile-sqlite.js +176 -0
- package/dist/storage-sqlite/compile-sqlite.js.map +1 -0
- package/dist/storage-sqlite/migrations/0001_init.sql +123 -0
- package/dist/storage-sqlite/migrations/0002_content_hash.sql +7 -0
- package/dist/storage-sqlite/migrations/index.d.ts +6 -0
- package/dist/storage-sqlite/migrations/index.js +41 -0
- package/dist/storage-sqlite/migrations/index.js.map +1 -0
- package/dist/storage-sqlite/vec.d.ts +40 -0
- package/dist/storage-sqlite/vec.js +62 -0
- package/dist/storage-sqlite/vec.js.map +1 -0
- package/dist/sync/cursor.d.ts +36 -0
- package/dist/sync/cursor.js +66 -0
- package/dist/sync/cursor.js.map +1 -0
- package/dist/sync/daemon.d.ts +40 -0
- package/dist/sync/daemon.js +202 -0
- package/dist/sync/daemon.js.map +1 -0
- package/dist/sync/feed.d.ts +38 -0
- package/dist/sync/feed.js +125 -0
- package/dist/sync/feed.js.map +1 -0
- package/dist/sync/fs-store.d.ts +8 -0
- package/dist/sync/fs-store.js +76 -0
- package/dist/sync/fs-store.js.map +1 -0
- package/dist/sync/intrinsics.d.ts +52 -0
- package/dist/sync/intrinsics.js +76 -0
- package/dist/sync/intrinsics.js.map +1 -0
- package/dist/sync/paths.d.ts +38 -0
- package/dist/sync/paths.js +56 -0
- package/dist/sync/paths.js.map +1 -0
- package/dist/sync/push.d.ts +48 -0
- package/dist/sync/push.js +328 -0
- package/dist/sync/push.js.map +1 -0
- package/dist/sync/reconcile.d.ts +54 -0
- package/dist/sync/reconcile.js +252 -0
- package/dist/sync/reconcile.js.map +1 -0
- package/dist/sync/run.d.ts +27 -0
- package/dist/sync/run.js +46 -0
- package/dist/sync/run.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic link extraction — design §11.2 "Extraction" (WS2).
|
|
3
|
+
*
|
|
4
|
+
* Body and frontmatter string values each honor their own LinkSyntaxes profile.
|
|
5
|
+
* Frontmatter links are discovered by walking all scalar string values — no
|
|
6
|
+
* per-field opt-in list.
|
|
7
|
+
*/
|
|
8
|
+
import { parse, postprocess, preprocess } from "micromark";
|
|
9
|
+
/** The `field` value for body-derived edges (§11.2 reserved sentinel). */
|
|
10
|
+
export const BODY_FIELD = "$body";
|
|
11
|
+
/** Repo-root absolute path ending in `.md` — whole frontmatter value form. */
|
|
12
|
+
export const FRONTMATTER_FULLPATH_WHOLE = /^\/[^\s#]+\.md(?:#.*)?$/;
|
|
13
|
+
/** Inline repo-root `/…/*.md` paths in prose (body scan). Requires `/` at a token boundary. */
|
|
14
|
+
const BODY_FULLPATH = /(?:^|[\s(\["'`<>])(\/[^\s\])"'`<>]+\.md(?:#[^\s\])"'`<>]*)?)/g;
|
|
15
|
+
export function extractEdges(input) {
|
|
16
|
+
const { body, frontmatter, config } = input;
|
|
17
|
+
const bodyEdges = extractBodyEdges(body, config.body);
|
|
18
|
+
const fmEdges = extractFrontmatterEdges(frontmatter, config.frontmatter);
|
|
19
|
+
const out = [];
|
|
20
|
+
let ord = 0;
|
|
21
|
+
for (const e of bodyEdges)
|
|
22
|
+
out.push({ ...e, ord: ord++ });
|
|
23
|
+
for (const e of fmEdges)
|
|
24
|
+
out.push({ ...e, ord: ord++ });
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
function extractBodyEdges(body, syntaxes) {
|
|
28
|
+
const hits = [];
|
|
29
|
+
const codeRanges = collectCommonMark(body, syntaxes, hits);
|
|
30
|
+
if (syntaxes.wikilink)
|
|
31
|
+
collectWikilinks(body, codeRanges, hits);
|
|
32
|
+
if (syntaxes.fullpath)
|
|
33
|
+
collectBodyFullpaths(body, codeRanges, hits);
|
|
34
|
+
hits.sort((a, b) => a.offset - b.offset);
|
|
35
|
+
return hits.map((h) => ({
|
|
36
|
+
field: BODY_FIELD,
|
|
37
|
+
target: h.target,
|
|
38
|
+
wikilink: h.wikilink,
|
|
39
|
+
...(h.dest_span ? { dest_span: h.dest_span } : {}),
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
function collectBodyFullpaths(body, codeRanges, hits) {
|
|
43
|
+
for (const m of body.matchAll(BODY_FULLPATH)) {
|
|
44
|
+
const target = m[1];
|
|
45
|
+
const offset = (m.index ?? 0) + m[0].length - target.length;
|
|
46
|
+
if (inAnyRange(offset, codeRanges))
|
|
47
|
+
continue;
|
|
48
|
+
hits.push({
|
|
49
|
+
offset,
|
|
50
|
+
target,
|
|
51
|
+
wikilink: false,
|
|
52
|
+
dest_span: { start: offset, end: offset + target.length },
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// -----------------------------------------------------------------------------
|
|
57
|
+
// Frontmatter extraction — walk all string values.
|
|
58
|
+
// -----------------------------------------------------------------------------
|
|
59
|
+
function extractFrontmatterEdges(frontmatter, syntaxes) {
|
|
60
|
+
const out = [];
|
|
61
|
+
walkFrontmatterStrings(frontmatter, [], (field, value) => {
|
|
62
|
+
for (const hit of extractFromFrontmatterString(value, syntaxes)) {
|
|
63
|
+
out.push({ field, target: hit.target, wikilink: hit.wikilink });
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
function walkFrontmatterStrings(node, path, visit) {
|
|
69
|
+
if (typeof node === "string") {
|
|
70
|
+
visit(path.join("."), node);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (Array.isArray(node)) {
|
|
74
|
+
for (const el of node)
|
|
75
|
+
walkFrontmatterStrings(el, path, visit);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (node !== null && typeof node === "object") {
|
|
79
|
+
for (const [key, val] of Object.entries(node)) {
|
|
80
|
+
walkFrontmatterStrings(val, [...path, key], visit);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function extractFromFrontmatterString(value, syntaxes) {
|
|
85
|
+
const hits = [];
|
|
86
|
+
if (syntaxes.fullpath) {
|
|
87
|
+
const trimmed = value.trim();
|
|
88
|
+
if (FRONTMATTER_FULLPATH_WHOLE.test(trimmed)) {
|
|
89
|
+
hits.push({ offset: 0, target: trimmed, wikilink: false });
|
|
90
|
+
return hits;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const codeRanges = collectCommonMark(value, syntaxes, hits);
|
|
94
|
+
if (syntaxes.wikilink)
|
|
95
|
+
collectWikilinks(value, codeRanges, hits);
|
|
96
|
+
hits.sort((a, b) => a.offset - b.offset);
|
|
97
|
+
return hits;
|
|
98
|
+
}
|
|
99
|
+
// -----------------------------------------------------------------------------
|
|
100
|
+
// CommonMark + wikilinks (shared by body and frontmatter strings)
|
|
101
|
+
// -----------------------------------------------------------------------------
|
|
102
|
+
function collectCommonMark(text, syntaxes, hits) {
|
|
103
|
+
const events = tokenize(text);
|
|
104
|
+
const slice = (t) => text.slice(t.start.offset, t.end.offset);
|
|
105
|
+
const definitions = new Map();
|
|
106
|
+
for (const [kind, token] of events) {
|
|
107
|
+
if (kind !== "enter")
|
|
108
|
+
continue;
|
|
109
|
+
if (token.type === "definition") {
|
|
110
|
+
const label = childValue(events, text, token, "definitionLabelString");
|
|
111
|
+
const destTok = childToken(events, token, "definitionDestinationString");
|
|
112
|
+
if (label !== undefined && destTok !== undefined) {
|
|
113
|
+
const key = normalizeLabel(label);
|
|
114
|
+
if (!definitions.has(key)) {
|
|
115
|
+
definitions.set(key, {
|
|
116
|
+
dest: text.slice(destTok.start.offset, destTok.end.offset),
|
|
117
|
+
span: { start: destTok.start.offset, end: destTok.end.offset },
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const codeRanges = [];
|
|
124
|
+
const stack = [];
|
|
125
|
+
for (const [kind, token] of events) {
|
|
126
|
+
const T = token.type;
|
|
127
|
+
if (kind === "enter") {
|
|
128
|
+
if (T === "codeText" || T === "codeFenced" || T === "codeIndented") {
|
|
129
|
+
codeRanges.push([token.start.offset, token.end.offset]);
|
|
130
|
+
}
|
|
131
|
+
else if (T === "link" || T === "image") {
|
|
132
|
+
stack.push({ isImage: T === "image", start: token.start.offset, label: "" });
|
|
133
|
+
}
|
|
134
|
+
else if (T === "labelText") {
|
|
135
|
+
const top = stack[stack.length - 1];
|
|
136
|
+
if (top && top.dest === undefined && top.refKey === undefined)
|
|
137
|
+
top.label += slice(token);
|
|
138
|
+
}
|
|
139
|
+
else if (T === "resourceDestinationString") {
|
|
140
|
+
const top = stack[stack.length - 1];
|
|
141
|
+
if (top) {
|
|
142
|
+
top.dest = slice(token);
|
|
143
|
+
top.destSpan = { start: token.start.offset, end: token.end.offset };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else if (T === "referenceString") {
|
|
147
|
+
const top = stack[stack.length - 1];
|
|
148
|
+
if (top)
|
|
149
|
+
top.refKey = normalizeLabel(slice(token));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else if (kind === "exit" && (T === "link" || T === "image")) {
|
|
153
|
+
const frame = stack.pop();
|
|
154
|
+
if (!frame)
|
|
155
|
+
continue;
|
|
156
|
+
const resolved = resolveDestination(frame, definitions);
|
|
157
|
+
if (resolved !== undefined && resolved.dest.length > 0 && syntaxEnabled(frame, syntaxes)) {
|
|
158
|
+
const span = frame.destSpan ?? resolved.span;
|
|
159
|
+
hits.push({
|
|
160
|
+
offset: frame.start,
|
|
161
|
+
target: resolved.dest,
|
|
162
|
+
wikilink: false,
|
|
163
|
+
...(span ? { dest_span: span } : {}),
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return codeRanges;
|
|
169
|
+
}
|
|
170
|
+
function resolveDestination(frame, definitions) {
|
|
171
|
+
if (frame.dest !== undefined)
|
|
172
|
+
return { dest: frame.dest, span: frame.destSpan };
|
|
173
|
+
const key = frame.refKey && frame.refKey.length > 0 ? frame.refKey : normalizeLabel(frame.label);
|
|
174
|
+
const def = definitions.get(key);
|
|
175
|
+
return def ? { dest: def.dest, span: def.span } : undefined;
|
|
176
|
+
}
|
|
177
|
+
function syntaxEnabled(frame, syntaxes) {
|
|
178
|
+
return frame.dest !== undefined ? syntaxes.inline : syntaxes.reference;
|
|
179
|
+
}
|
|
180
|
+
function normalizeLabel(raw) {
|
|
181
|
+
return raw.trim().replace(/\s+/g, " ").toLowerCase();
|
|
182
|
+
}
|
|
183
|
+
const WIKILINK = () => /!?\[\[([^\]\n]+?)\]\]/g;
|
|
184
|
+
function collectWikilinks(text, codeRanges, hits) {
|
|
185
|
+
for (const m of text.matchAll(WIKILINK())) {
|
|
186
|
+
const offset = m.index ?? 0;
|
|
187
|
+
if (inAnyRange(offset, codeRanges))
|
|
188
|
+
continue;
|
|
189
|
+
const full = m[0];
|
|
190
|
+
const inner = m[1];
|
|
191
|
+
const pageRaw = inner.split("|")[0];
|
|
192
|
+
const target = pageRaw.trim();
|
|
193
|
+
if (target.length === 0)
|
|
194
|
+
continue;
|
|
195
|
+
const innerStart = offset + full.indexOf(inner);
|
|
196
|
+
const lead = pageRaw.length - pageRaw.trimStart().length;
|
|
197
|
+
const start = innerStart + lead;
|
|
198
|
+
hits.push({
|
|
199
|
+
offset,
|
|
200
|
+
target,
|
|
201
|
+
wikilink: true,
|
|
202
|
+
dest_span: { start, end: start + target.length },
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function inAnyRange(offset, ranges) {
|
|
207
|
+
for (const [start, end] of ranges) {
|
|
208
|
+
if (offset >= start && offset < end)
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
function tokenize(md) {
|
|
214
|
+
const p = parse();
|
|
215
|
+
return postprocess(p.document().write(preprocess()(md, "utf8", true)));
|
|
216
|
+
}
|
|
217
|
+
function childValue(events, body, parent, type) {
|
|
218
|
+
const tok = childToken(events, parent, type);
|
|
219
|
+
return tok ? body.slice(tok.start.offset, tok.end.offset) : undefined;
|
|
220
|
+
}
|
|
221
|
+
function childToken(events, parent, type) {
|
|
222
|
+
for (const [kind, token] of events) {
|
|
223
|
+
if (kind !== "enter")
|
|
224
|
+
continue;
|
|
225
|
+
if (token.type === type &&
|
|
226
|
+
token.start.offset >= parent.start.offset &&
|
|
227
|
+
token.end.offset <= parent.end.offset) {
|
|
228
|
+
return token;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return undefined;
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/links/extract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Link config layering — design §11.2 (Phase 1, links-plan.md §1.2).
|
|
3
|
+
*
|
|
4
|
+
* HARDCODED_DEFAULTS → server config → per-repo override
|
|
5
|
+
* (in code) (operator) (repos.link_config JSON)
|
|
6
|
+
*
|
|
7
|
+
* Body and frontmatter each declare which link *syntaxes* are recognized in
|
|
8
|
+
* that region. Frontmatter string values are scanned automatically — no
|
|
9
|
+
* per-field opt-in list.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Which link syntaxes extraction recognizes. Each is a boolean knob; the
|
|
13
|
+
* `!` embed/transclusion prefix is NOT a syntax — it's a rendering hint
|
|
14
|
+
* captured as an ordinary edge from its base syntax (§1.1).
|
|
15
|
+
*
|
|
16
|
+
* `fullpath` matches repo-root paths written as `/dir/doc.md` (optional
|
|
17
|
+
* `#anchor`). In the document body, matches may appear inline in prose; in
|
|
18
|
+
* frontmatter, only a string value that *is* such a path (after trim) counts.
|
|
19
|
+
*/
|
|
20
|
+
export type LinkSyntaxes = {
|
|
21
|
+
inline: boolean;
|
|
22
|
+
reference: boolean;
|
|
23
|
+
autolink: boolean;
|
|
24
|
+
wikilink: boolean;
|
|
25
|
+
fullpath: boolean;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Path-resolution knobs. Absolute-vs-relative and case policy follow the
|
|
29
|
+
* repo's §3.5.1 path policy — one path-normalization authority — so they
|
|
30
|
+
* are deliberately NOT knobs here.
|
|
31
|
+
*/
|
|
32
|
+
export type LinkResolution = {
|
|
33
|
+
wikilink_elision: boolean;
|
|
34
|
+
preserve_anchors: boolean;
|
|
35
|
+
index_basename: string;
|
|
36
|
+
};
|
|
37
|
+
/** The full config after merging tiers — every field populated. */
|
|
38
|
+
export type LinkConfig = {
|
|
39
|
+
/** Syntaxes recognized in the Markdown body. */
|
|
40
|
+
body: LinkSyntaxes;
|
|
41
|
+
/** Syntaxes recognized inside frontmatter string values. */
|
|
42
|
+
frontmatter: LinkSyntaxes;
|
|
43
|
+
resolution: LinkResolution;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Optional per-field override — the shape stored in `repos.link_config`
|
|
47
|
+
* JSON and accepted by `repos.set_link_config`. Omitting a field means
|
|
48
|
+
* "inherit"; setting it means "replace the inherited value wholesale."
|
|
49
|
+
*/
|
|
50
|
+
export type LinkConfigOverride = {
|
|
51
|
+
body?: LinkSyntaxes;
|
|
52
|
+
frontmatter?: LinkSyntaxes;
|
|
53
|
+
resolution?: LinkResolution;
|
|
54
|
+
};
|
|
55
|
+
/** All body syntaxes on — the default document-body profile. */
|
|
56
|
+
export declare const DEFAULT_BODY_SYNTAXES: LinkSyntaxes;
|
|
57
|
+
/**
|
|
58
|
+
* Frontmatter profile: whole-value `/…/*.md` paths plus embedded wikilinks
|
|
59
|
+
* and inline links. Reference/autolink off — uncommon inside YAML scalars.
|
|
60
|
+
*/
|
|
61
|
+
export declare const DEFAULT_FRONTMATTER_SYNTAXES: LinkSyntaxes;
|
|
62
|
+
export declare const HARDCODED_DEFAULTS: LinkConfig;
|
|
63
|
+
export declare function mergeConfig(base: LinkConfig, override: LinkConfigOverride | null): LinkConfig;
|
|
64
|
+
export declare function effectiveLinkConfig(serverConfig: LinkConfig, repoOverride: LinkConfigOverride | null): LinkConfig;
|
|
65
|
+
export declare function parseRepoOverride(json: string | null): LinkConfigOverride | null;
|
|
66
|
+
export declare class ConfigError extends Error {
|
|
67
|
+
constructor(message: string);
|
|
68
|
+
}
|
|
69
|
+
export declare function validateConfig(config: LinkConfig): void;
|
|
70
|
+
export declare function validateRepoOverride(override: LinkConfigOverride, serverConfig: LinkConfig): void;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Link config layering — design §11.2 (Phase 1, links-plan.md §1.2).
|
|
3
|
+
*
|
|
4
|
+
* HARDCODED_DEFAULTS → server config → per-repo override
|
|
5
|
+
* (in code) (operator) (repos.link_config JSON)
|
|
6
|
+
*
|
|
7
|
+
* Body and frontmatter each declare which link *syntaxes* are recognized in
|
|
8
|
+
* that region. Frontmatter string values are scanned automatically — no
|
|
9
|
+
* per-field opt-in list.
|
|
10
|
+
*/
|
|
11
|
+
import { KernelError } from "../kernel/errors.js";
|
|
12
|
+
const SYNTAX_KEYS = ["inline", "reference", "autolink", "wikilink", "fullpath"];
|
|
13
|
+
/** All body syntaxes on — the default document-body profile. */
|
|
14
|
+
export const DEFAULT_BODY_SYNTAXES = {
|
|
15
|
+
inline: true,
|
|
16
|
+
reference: true,
|
|
17
|
+
autolink: true,
|
|
18
|
+
wikilink: true,
|
|
19
|
+
fullpath: true,
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Frontmatter profile: whole-value `/…/*.md` paths plus embedded wikilinks
|
|
23
|
+
* and inline links. Reference/autolink off — uncommon inside YAML scalars.
|
|
24
|
+
*/
|
|
25
|
+
export const DEFAULT_FRONTMATTER_SYNTAXES = {
|
|
26
|
+
inline: true,
|
|
27
|
+
reference: false,
|
|
28
|
+
autolink: false,
|
|
29
|
+
wikilink: true,
|
|
30
|
+
fullpath: true,
|
|
31
|
+
};
|
|
32
|
+
export const HARDCODED_DEFAULTS = {
|
|
33
|
+
body: DEFAULT_BODY_SYNTAXES,
|
|
34
|
+
frontmatter: DEFAULT_FRONTMATTER_SYNTAXES,
|
|
35
|
+
resolution: {
|
|
36
|
+
wikilink_elision: true,
|
|
37
|
+
preserve_anchors: true,
|
|
38
|
+
index_basename: "index",
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
// -----------------------------------------------------------------------------
|
|
42
|
+
// Merging.
|
|
43
|
+
// -----------------------------------------------------------------------------
|
|
44
|
+
export function mergeConfig(base, override) {
|
|
45
|
+
if (!override)
|
|
46
|
+
return base;
|
|
47
|
+
return {
|
|
48
|
+
body: override.body ?? base.body,
|
|
49
|
+
frontmatter: override.frontmatter ?? base.frontmatter,
|
|
50
|
+
resolution: override.resolution ?? base.resolution,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export function effectiveLinkConfig(serverConfig, repoOverride) {
|
|
54
|
+
return mergeConfig(serverConfig, repoOverride);
|
|
55
|
+
}
|
|
56
|
+
export function parseRepoOverride(json) {
|
|
57
|
+
if (json === null)
|
|
58
|
+
return null;
|
|
59
|
+
const parsed = JSON.parse(json);
|
|
60
|
+
if (parsed === null || parsed === undefined)
|
|
61
|
+
return null;
|
|
62
|
+
if (typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
63
|
+
throw new Error(`corrupt repos.link_config JSON: expected object, got ${typeof parsed}`);
|
|
64
|
+
}
|
|
65
|
+
return parsed;
|
|
66
|
+
}
|
|
67
|
+
// -----------------------------------------------------------------------------
|
|
68
|
+
// Startup invariants.
|
|
69
|
+
// -----------------------------------------------------------------------------
|
|
70
|
+
export class ConfigError extends Error {
|
|
71
|
+
constructor(message) {
|
|
72
|
+
super(message);
|
|
73
|
+
this.name = "ConfigError";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function validateSyntaxes(label, syn) {
|
|
77
|
+
for (const key of SYNTAX_KEYS) {
|
|
78
|
+
if (typeof syn[key] !== "boolean") {
|
|
79
|
+
throw new ConfigError(`${label}.${key} must be a boolean, got ${JSON.stringify(syn[key])}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function validateConfig(config) {
|
|
84
|
+
validateSyntaxes("body", config.body);
|
|
85
|
+
validateSyntaxes("frontmatter", config.frontmatter);
|
|
86
|
+
if (typeof config.resolution.index_basename !== "string" ||
|
|
87
|
+
config.resolution.index_basename.length === 0) {
|
|
88
|
+
throw new ConfigError(`resolution.index_basename must be a non-empty string, got ${JSON.stringify(config.resolution.index_basename)}`);
|
|
89
|
+
}
|
|
90
|
+
for (const key of ["wikilink_elision", "preserve_anchors"]) {
|
|
91
|
+
if (typeof config.resolution[key] !== "boolean") {
|
|
92
|
+
throw new ConfigError(`resolution.${key} must be a boolean, got ${JSON.stringify(config.resolution[key])}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export function validateRepoOverride(override, serverConfig) {
|
|
97
|
+
try {
|
|
98
|
+
validateConfig(mergeConfig(serverConfig, override));
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
if (err instanceof ConfigError) {
|
|
102
|
+
throw new KernelError("link_config_invalid", { reason: err.message });
|
|
103
|
+
}
|
|
104
|
+
throw err;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=link-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-config.js","sourceRoot":"","sources":["../../src/links/link-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Link-index maintenance — the write-path glue (design §11.2, WS3).
|
|
3
|
+
*
|
|
4
|
+
* Extraction is pure CPU (no external I/O), so the design runs it in the
|
|
5
|
+
* write transaction alongside version_insert rather than on the async
|
|
6
|
+
* backlog worker (links-plan.md §5 decision 1). These helpers are called
|
|
7
|
+
* from inside the kernel's create/put/delete tx closures.
|
|
8
|
+
*
|
|
9
|
+
* The flow for a source document D whose current version just advanced:
|
|
10
|
+
* 1. extractEdges(body, frontmatter, config) → RawEdge[] (parse)
|
|
11
|
+
* 2. normalizeEdges(edges, srcPath, config) → NormalizedEdge[] (paths)
|
|
12
|
+
* 3. resolve each edge's candidates against live paths → target_id | null
|
|
13
|
+
* 4. links_replace(repo, D, resolved)
|
|
14
|
+
*
|
|
15
|
+
* Resolution is case-insensitive: candidates are matched via the storage
|
|
16
|
+
* layer's version_current (which folds to path_norm, §3.5.1), and the
|
|
17
|
+
* folded key of the primary candidate is stored as target_norm so a later
|
|
18
|
+
* dangling re-resolution can rebind by folded path.
|
|
19
|
+
*/
|
|
20
|
+
import type { FrontmatterJson } from "../markdown/frontmatter.js";
|
|
21
|
+
import type { Storage } from "../storage/types.js";
|
|
22
|
+
import type { LinkConfig } from "./link-config.js";
|
|
23
|
+
/**
|
|
24
|
+
* Extract + resolve + persist document `sourceId`'s outbound edges. Called
|
|
25
|
+
* after every create/put that advances the doc's current version, inside
|
|
26
|
+
* the same tx. `sourcePath` is the new current version's repo-root-relative
|
|
27
|
+
* path (edges resolve relative to it).
|
|
28
|
+
*/
|
|
29
|
+
export declare function reindexOutboundLinks(storage: Storage, config: LinkConfig, repoId: number, sourceId: number, sourcePath: string, body: string, frontmatter: FrontmatterJson): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Bind dangling edges that name `path` (in `repoId`) to `documentId`, so a
|
|
32
|
+
* document appearing at a path (create / move-in / restore) resolves the
|
|
33
|
+
* links that were waiting for it. Matches on the folded path (§3.5.1),
|
|
34
|
+
* consistent with how resolution stored target_norm. Returns the count
|
|
35
|
+
* bound. Bind-only — never unbinds (a move produces zero inbound churn).
|
|
36
|
+
*/
|
|
37
|
+
export declare function bindDanglingToPath(storage: Storage, repoId: number, path: string, documentId: number): Promise<number>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Link-index maintenance — the write-path glue (design §11.2, WS3).
|
|
3
|
+
*
|
|
4
|
+
* Extraction is pure CPU (no external I/O), so the design runs it in the
|
|
5
|
+
* write transaction alongside version_insert rather than on the async
|
|
6
|
+
* backlog worker (links-plan.md §5 decision 1). These helpers are called
|
|
7
|
+
* from inside the kernel's create/put/delete tx closures.
|
|
8
|
+
*
|
|
9
|
+
* The flow for a source document D whose current version just advanced:
|
|
10
|
+
* 1. extractEdges(body, frontmatter, config) → RawEdge[] (parse)
|
|
11
|
+
* 2. normalizeEdges(edges, srcPath, config) → NormalizedEdge[] (paths)
|
|
12
|
+
* 3. resolve each edge's candidates against live paths → target_id | null
|
|
13
|
+
* 4. links_replace(repo, D, resolved)
|
|
14
|
+
*
|
|
15
|
+
* Resolution is case-insensitive: candidates are matched via the storage
|
|
16
|
+
* layer's version_current (which folds to path_norm, §3.5.1), and the
|
|
17
|
+
* folded key of the primary candidate is stored as target_norm so a later
|
|
18
|
+
* dangling re-resolution can rebind by folded path.
|
|
19
|
+
*/
|
|
20
|
+
import { normalizeKey } from "../kernel/casefold.js";
|
|
21
|
+
import { extractEdges } from "./extract.js";
|
|
22
|
+
import { normalizeEdges } from "./resolve.js";
|
|
23
|
+
/**
|
|
24
|
+
* Resolve one normalized edge's ordered candidates against the repo's live
|
|
25
|
+
* paths, returning the storable edge. The first candidate that resolves to
|
|
26
|
+
* a live document wins; if none resolve, the edge is dangling (target_id
|
|
27
|
+
* null) and keyed by the folded primary candidate for later rebinding.
|
|
28
|
+
*
|
|
29
|
+
* An edge with no candidates (external URI / bare fragment) yields null —
|
|
30
|
+
* it never enters the index (links are repo-local, §11.2).
|
|
31
|
+
*/
|
|
32
|
+
async function resolveEdge(storage, repoId, edge) {
|
|
33
|
+
if (edge.candidates.length === 0)
|
|
34
|
+
return null;
|
|
35
|
+
let targetId = null;
|
|
36
|
+
for (const candidate of edge.candidates) {
|
|
37
|
+
const current = await storage.version_current(repoId, candidate);
|
|
38
|
+
if (current) {
|
|
39
|
+
targetId = current.document_id;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// The primary candidate is the canonical resolution key: its folded form
|
|
44
|
+
// is what a later-appearing document's path will match against to rebind.
|
|
45
|
+
const primary = edge.candidates[0];
|
|
46
|
+
return {
|
|
47
|
+
ord: edge.ord,
|
|
48
|
+
field: edge.field,
|
|
49
|
+
target_raw: edge.target_raw,
|
|
50
|
+
target_norm: normalizeKey(primary),
|
|
51
|
+
target_id: targetId,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Extract + resolve + persist document `sourceId`'s outbound edges. Called
|
|
56
|
+
* after every create/put that advances the doc's current version, inside
|
|
57
|
+
* the same tx. `sourcePath` is the new current version's repo-root-relative
|
|
58
|
+
* path (edges resolve relative to it).
|
|
59
|
+
*/
|
|
60
|
+
export async function reindexOutboundLinks(storage, config, repoId, sourceId, sourcePath, body, frontmatter) {
|
|
61
|
+
const rawEdges = extractEdges({ body, frontmatter, config });
|
|
62
|
+
const normalized = normalizeEdges(rawEdges, sourcePath, config);
|
|
63
|
+
const resolved = [];
|
|
64
|
+
let ord = 0;
|
|
65
|
+
for (const edge of normalized) {
|
|
66
|
+
const stored = await resolveEdge(storage, repoId, edge);
|
|
67
|
+
if (stored === null)
|
|
68
|
+
continue;
|
|
69
|
+
// Drop self-links: an edge resolving to the source document itself is
|
|
70
|
+
// noise — it would make the doc appear in its own $backlinks_static() /
|
|
71
|
+
// $links_static() and match $in_static against itself. A self-reference
|
|
72
|
+
// is never a meaningful graph edge, so it never enters the index.
|
|
73
|
+
if (stored.target_id === sourceId)
|
|
74
|
+
continue;
|
|
75
|
+
// Re-pack ord densely: dropped edges (external, self) must not leave
|
|
76
|
+
// gaps, and the PK is (source_id, ord). Extraction order is preserved.
|
|
77
|
+
resolved.push({ ...stored, ord: ord++ });
|
|
78
|
+
}
|
|
79
|
+
await storage.links_replace(repoId, sourceId, resolved);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Bind dangling edges that name `path` (in `repoId`) to `documentId`, so a
|
|
83
|
+
* document appearing at a path (create / move-in / restore) resolves the
|
|
84
|
+
* links that were waiting for it. Matches on the folded path (§3.5.1),
|
|
85
|
+
* consistent with how resolution stored target_norm. Returns the count
|
|
86
|
+
* bound. Bind-only — never unbinds (a move produces zero inbound churn).
|
|
87
|
+
*/
|
|
88
|
+
export async function bindDanglingToPath(storage, repoId, path, documentId) {
|
|
89
|
+
return storage.links_resolve_dangling(repoId, normalizeKey(path), documentId);
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=maintain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maintain.js","sourceRoot":"","sources":["../../src/links/maintain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGrD,OAAO,EAAgB,YAAY,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,EAAuB,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnE;;;;;;;;GAQG;AACH,KAAK,UAAU,WAAW,CACxB,OAAgB,EAChB,MAAc,EACd,IAAoB;IAEpB,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE9C,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACxC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACjE,IAAI,OAAO,EAAE,CAAC;YACZ,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC;YAC/B,MAAM;QACR,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,0EAA0E;IAC1E,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAW,CAAC;IAC7C,OAAO;QACL,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,WAAW,EAAE,YAAY,CAAC,OAAO,CAAC;QAClC,SAAS,EAAE,QAAQ;KACpB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAgB,EAChB,MAAkB,EAClB,MAAc,EACd,QAAgB,EAChB,UAAkB,EAClB,IAAY,EACZ,WAA4B;IAE5B,MAAM,QAAQ,GAAc,YAAY,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;IACxE,MAAM,UAAU,GAAG,cAAc,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAEhE,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACxD,IAAI,MAAM,KAAK,IAAI;YAAE,SAAS;QAC9B,sEAAsE;QACtE,wEAAwE;QACxE,wEAAwE;QACxE,kEAAkE;QAClE,IAAI,MAAM,CAAC,SAAS,KAAK,QAAQ;YAAE,SAAS;QAC5C,qEAAqE;QACrE,uEAAuE;QACvE,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAgB,EAChB,MAAc,EACd,IAAY,EACZ,UAAkB;IAElB,OAAO,OAAO,CAAC,sBAAsB,CAAC,MAAM,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mrplex links repair — rewrite stale link text so the written destination
|
|
3
|
+
* matches the target's current path (design §11.2 "Link rewriting is
|
|
4
|
+
* cosmetic, not structural — and opt-in").
|
|
5
|
+
*
|
|
6
|
+
* The graph is identity-bound, so a move breaks nothing structurally; this
|
|
7
|
+
* only repairs the visible text. Each source document is rewritten as an
|
|
8
|
+
* ordinary optimistic `docs.put` under the caller's token — `prev` checks
|
|
9
|
+
* apply, conflicts are reported and skipped, and every repair is a normal
|
|
10
|
+
* authored version in the chain (NOT a silent side effect of the move).
|
|
11
|
+
*
|
|
12
|
+
* Rewriting is surgical: only the destination spans of stale edges are
|
|
13
|
+
* spliced (right-to-left so earlier offsets stay valid); the rest of the
|
|
14
|
+
* body is byte-identical. Only inline/wikilink edges with a captured
|
|
15
|
+
* destination span are rewritten; reference-definition links are left for a
|
|
16
|
+
* later phase.
|
|
17
|
+
*/
|
|
18
|
+
import type { Storage, VersionRow } from "../storage/types.js";
|
|
19
|
+
import type { LinkConfig } from "./link-config.js";
|
|
20
|
+
export type RepairOutcome = {
|
|
21
|
+
repaired: {
|
|
22
|
+
path: string;
|
|
23
|
+
edges: number;
|
|
24
|
+
}[];
|
|
25
|
+
skipped: {
|
|
26
|
+
path: string;
|
|
27
|
+
reason: string;
|
|
28
|
+
}[];
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* A single planned rewrite of one source document: the new body plus the
|
|
32
|
+
* version to base the optimistic put on. Returned by planRepairs so a
|
|
33
|
+
* caller (the kernel op) can drive the actual docs.put and handle conflicts.
|
|
34
|
+
*/
|
|
35
|
+
export type RepairPlan = {
|
|
36
|
+
version: VersionRow;
|
|
37
|
+
newBody: string;
|
|
38
|
+
edges: number;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Compute the body rewrites needed to repair stale links across a repo's
|
|
42
|
+
* live documents. Pure w.r.t. storage reads — no writes. The caller issues
|
|
43
|
+
* the puts (so auth, conflict handling, and dry-run all live at the op
|
|
44
|
+
* layer, where the actor and kernel are in scope).
|
|
45
|
+
*/
|
|
46
|
+
export declare function planRepairs(storage: Storage, repoId: number, config: LinkConfig): Promise<RepairPlan[]>;
|