diffwiki-core 0.13.0 → 0.14.0-rc.202608012127.a1298c2
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/{chunk-7V2DIQNL.js → chunk-B67AZFRA.js} +6 -2
- package/dist/{chunk-EEETAETA.js → chunk-HDJUZIQP.js} +72 -0
- package/dist/{events-AVD3G5AX.js → events-QZYAWK7I.js} +1 -1
- package/dist/frontmatter-DQL69ovH.d.cts +375 -0
- package/dist/frontmatter-DQL69ovH.d.ts +375 -0
- package/dist/index.cjs +11 -1
- package/dist/index.d.cts +3 -359
- package/dist/index.d.ts +3 -359
- package/dist/index.js +13 -74
- package/dist/plugin.cjs +81 -2
- package/dist/plugin.d.cts +10 -0
- package/dist/plugin.d.ts +10 -0
- package/dist/plugin.js +7 -3
- package/package.json +1 -1
|
@@ -116,7 +116,7 @@ ${problems.map((p) => ` - ${p}`).join("\n")}`);
|
|
|
116
116
|
// src/collections.ts
|
|
117
117
|
async function fireHook(event, collection) {
|
|
118
118
|
try {
|
|
119
|
-
const { emitPluginEvent: emitPluginEvent2 } = await import("./events-
|
|
119
|
+
const { emitPluginEvent: emitPluginEvent2 } = await import("./events-QZYAWK7I.js");
|
|
120
120
|
await emitPluginEvent2(event, collection);
|
|
121
121
|
} catch {
|
|
122
122
|
}
|
|
@@ -351,7 +351,11 @@ function mapHits(result, collections) {
|
|
|
351
351
|
tags: Array.isArray(h.tags) ? h.tags.filter((t) => typeof t === "string") : [],
|
|
352
352
|
snippet: typeof h.snippet === "string" ? h.snippet : void 0,
|
|
353
353
|
score: typeof h.score === "number" ? h.score : void 0,
|
|
354
|
-
docid: typeof h.docid === "string" ? h.docid : void 0
|
|
354
|
+
docid: typeof h.docid === "string" ? h.docid : void 0,
|
|
355
|
+
rawChunk: typeof h.rawChunk === "string" ? h.rawChunk : void 0,
|
|
356
|
+
cleanedChunk: typeof h.cleanedChunk === "string" ? h.cleanedChunk : void 0,
|
|
357
|
+
line: typeof h.line === "number" ? h.line : void 0,
|
|
358
|
+
snippetFromBody: h.snippetFromBody === true ? true : void 0
|
|
355
359
|
});
|
|
356
360
|
}
|
|
357
361
|
return out;
|
|
@@ -1,3 +1,72 @@
|
|
|
1
|
+
// src/frontmatter.ts
|
|
2
|
+
import matter from "gray-matter";
|
|
3
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
4
|
+
var YAML_ENGINE = {
|
|
5
|
+
parse: (input) => {
|
|
6
|
+
const data = parseYaml(input);
|
|
7
|
+
return data && typeof data === "object" ? data : {};
|
|
8
|
+
},
|
|
9
|
+
stringify: (data) => stringifyYaml(data)
|
|
10
|
+
};
|
|
11
|
+
var MATTER_OPTS = { engines: { yaml: YAML_ENGINE } };
|
|
12
|
+
function coerceAudience(value) {
|
|
13
|
+
return value === "private" || value === "system" ? value : "public";
|
|
14
|
+
}
|
|
15
|
+
function coerceStatus(value) {
|
|
16
|
+
return value === "draft" || value === "deprecated" ? value : "published";
|
|
17
|
+
}
|
|
18
|
+
function parseFallback(raw) {
|
|
19
|
+
const fenceRe = /^---[ \t]*\n([\s\S]*?)\n---[ \t]*\n/;
|
|
20
|
+
const fenceMatch = fenceRe.exec(raw);
|
|
21
|
+
let title = "";
|
|
22
|
+
let audience = "public";
|
|
23
|
+
let status = "published";
|
|
24
|
+
let body;
|
|
25
|
+
const clean = (s) => s.trim().replace(/^["']|["']$/g, "");
|
|
26
|
+
if (fenceMatch) {
|
|
27
|
+
const inner = fenceMatch[1];
|
|
28
|
+
const titleMatch = /^title:\s*(.+)$/m.exec(inner);
|
|
29
|
+
if (titleMatch) {
|
|
30
|
+
title = clean(titleMatch[1]);
|
|
31
|
+
}
|
|
32
|
+
const audienceMatch = /^audience:\s*(.+)$/m.exec(inner);
|
|
33
|
+
if (audienceMatch) {
|
|
34
|
+
audience = coerceAudience(clean(audienceMatch[1]));
|
|
35
|
+
}
|
|
36
|
+
const statusMatch = /^status:\s*(.+)$/m.exec(inner);
|
|
37
|
+
if (statusMatch) {
|
|
38
|
+
status = coerceStatus(clean(statusMatch[1]));
|
|
39
|
+
}
|
|
40
|
+
body = raw.slice(fenceMatch[0].length);
|
|
41
|
+
} else {
|
|
42
|
+
body = raw;
|
|
43
|
+
}
|
|
44
|
+
return { title, tags: [], audience, status, body: body.replace(/^\n+/, "") };
|
|
45
|
+
}
|
|
46
|
+
var FRONTMATTER_BLOCK_RE = /^\uFEFF?[ \t]*---\r?\n[\s\S]*?\r?\n---[ \t]*(?:\r?\n|$)/;
|
|
47
|
+
function stripFrontmatter(raw) {
|
|
48
|
+
return raw.replace(FRONTMATTER_BLOCK_RE, "");
|
|
49
|
+
}
|
|
50
|
+
function parseArticle(raw) {
|
|
51
|
+
try {
|
|
52
|
+
const { data, content } = matter(raw, MATTER_OPTS);
|
|
53
|
+
const title = typeof data.title === "string" ? data.title : "";
|
|
54
|
+
const tags = Array.isArray(data.tags) ? data.tags.map((t) => String(t)) : [];
|
|
55
|
+
const created = typeof data.created === "string" ? data.created : void 0;
|
|
56
|
+
const audience = coerceAudience(data.audience);
|
|
57
|
+
const status = coerceStatus(data.status);
|
|
58
|
+
return { title, tags, created, audience, status, body: content.replace(/^\n+/, "") };
|
|
59
|
+
} catch {
|
|
60
|
+
return parseFallback(raw);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function serializeArticle(article) {
|
|
64
|
+
const front = { title: article.title, tags: article.tags };
|
|
65
|
+
if (article.audience === "private" || article.audience === "system") front.audience = article.audience;
|
|
66
|
+
if (article.status === "draft" || article.status === "deprecated") front.status = article.status;
|
|
67
|
+
return matter.stringify(article.body, front, MATTER_OPTS);
|
|
68
|
+
}
|
|
69
|
+
|
|
1
70
|
// src/plugins/sdk.ts
|
|
2
71
|
import { execFile } from "child_process";
|
|
3
72
|
import { promisify } from "util";
|
|
@@ -137,6 +206,9 @@ function definePlugin(def) {
|
|
|
137
206
|
}
|
|
138
207
|
|
|
139
208
|
export {
|
|
209
|
+
stripFrontmatter,
|
|
210
|
+
parseArticle,
|
|
211
|
+
serializeArticle,
|
|
140
212
|
runProcess,
|
|
141
213
|
runProcessJson,
|
|
142
214
|
commandExists,
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
/** Audience axis — who an article is for. Private is never published; system is diffwiki-internal (hidden unless `showSystem`). Missing/invalid → 'public'. */
|
|
2
|
+
type Audience = 'public' | 'private' | 'system';
|
|
3
|
+
/** Lifecycle axis — readiness. Draft is unpublished; deprecated is superseded. Missing/invalid → 'published'. */
|
|
4
|
+
type PublishStatus = 'draft' | 'published' | 'deprecated';
|
|
5
|
+
type CollectionType = 'global' | 'repo' | 'external';
|
|
6
|
+
interface CollectionEntry {
|
|
7
|
+
name: string;
|
|
8
|
+
type: CollectionType;
|
|
9
|
+
/** Absolute path to the collection's content directory. */
|
|
10
|
+
path: string;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
/** Marks a diffwiki-internal collection (e.g. `transcripts`). 'system' hides it unless `showSystem`. */
|
|
13
|
+
audience?: Audience;
|
|
14
|
+
/** External only: stable git repo id (see `repoId`). Identity + dedupe key. */
|
|
15
|
+
id?: string;
|
|
16
|
+
/** External only: absolute repo root (branch/behind + open-at-root). */
|
|
17
|
+
repoRoot?: string;
|
|
18
|
+
/** External only: content dir relative to `repoRoot` (default "docs"). */
|
|
19
|
+
docsDir?: string;
|
|
20
|
+
}
|
|
21
|
+
interface Registry {
|
|
22
|
+
version: number;
|
|
23
|
+
collections: CollectionEntry[];
|
|
24
|
+
}
|
|
25
|
+
interface Config {
|
|
26
|
+
defaultCollection?: string;
|
|
27
|
+
defaultSearch?: string;
|
|
28
|
+
/** Editor command used by `diffwiki edit` (e.g. "code -w", "hx"). Falls back to $VISUAL/$EDITOR. */
|
|
29
|
+
editor?: string;
|
|
30
|
+
/** Reveal system-audience content in search, nav, and the UI (default: false). Stored as boolean or "true". */
|
|
31
|
+
showSystem?: boolean;
|
|
32
|
+
}
|
|
33
|
+
interface Article {
|
|
34
|
+
title: string;
|
|
35
|
+
tags: string[];
|
|
36
|
+
/** Absolute path to the article file. */
|
|
37
|
+
path: string;
|
|
38
|
+
collection: string;
|
|
39
|
+
}
|
|
40
|
+
interface RepoConfig {
|
|
41
|
+
collection: string;
|
|
42
|
+
/** Path to the wiki directory, relative to the repo root. */
|
|
43
|
+
path: string;
|
|
44
|
+
}
|
|
45
|
+
/** A home-page card (VitePress-style): icon + title + subtitle linking into the site. */
|
|
46
|
+
interface HomeCard {
|
|
47
|
+
/** Icon name from the curated home-card icon set; unknown/missing → no icon. */
|
|
48
|
+
icon?: string;
|
|
49
|
+
title: string;
|
|
50
|
+
subtitle?: string;
|
|
51
|
+
/** In-site path, e.g. "/getting-started". */
|
|
52
|
+
link: string;
|
|
53
|
+
}
|
|
54
|
+
/** Home-page customization from `diffwiki.yaml` → `site.home`. */
|
|
55
|
+
interface SiteHome {
|
|
56
|
+
/** Line shown under the wordmark on the home page. */
|
|
57
|
+
tagline?: string;
|
|
58
|
+
/** Cards rendered below the search bar. */
|
|
59
|
+
cards?: HomeCard[];
|
|
60
|
+
}
|
|
61
|
+
/** Footer copyright notice from `diffwiki.yaml` → `site.copyright`. Applies to the
|
|
62
|
+
* site/software; article CONTENT copyright stays with its respective authors. */
|
|
63
|
+
interface SiteCopyright {
|
|
64
|
+
/** The full notice text, e.g. "© 2026 Acme, Inc." */
|
|
65
|
+
text: string;
|
|
66
|
+
/** Optional URL — renders the notice as a link. */
|
|
67
|
+
url?: string;
|
|
68
|
+
}
|
|
69
|
+
/** Site-level config from `diffwiki.yaml` → `site`. The diffwiki logo + wordmark
|
|
70
|
+
* are fixed branding and deliberately not configurable. */
|
|
71
|
+
interface SiteConfig {
|
|
72
|
+
/** Project repository URL for the top-nav GitHub link. */
|
|
73
|
+
repo?: string;
|
|
74
|
+
/** Footer copyright notice; no default — the footer is empty when unset. */
|
|
75
|
+
copyright?: SiteCopyright;
|
|
76
|
+
home?: SiteHome;
|
|
77
|
+
}
|
|
78
|
+
/** One collection declared in `diffwiki.yaml` → `collections[]`. */
|
|
79
|
+
interface ProjectCollection {
|
|
80
|
+
name: string;
|
|
81
|
+
/** Content directory, relative to the project root. */
|
|
82
|
+
path: string;
|
|
83
|
+
/** Optional display order (ascending). Unset sorts after ordered ones, keeping list order. */
|
|
84
|
+
order?: number;
|
|
85
|
+
}
|
|
86
|
+
/** Optional recall/search context from `diffwiki.yaml` → `context`. */
|
|
87
|
+
interface ProjectContext {
|
|
88
|
+
/** Collection names recall/search should filter to by default. */
|
|
89
|
+
collections: string[];
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Normalised repo-root `diffwiki.yaml`. The extended form carries `site` +
|
|
93
|
+
* `collections[]`; the legacy `{ collection, path }` form is folded into a
|
|
94
|
+
* one-element `collections` by the parser.
|
|
95
|
+
*/
|
|
96
|
+
interface ProjectConfig {
|
|
97
|
+
site?: SiteConfig;
|
|
98
|
+
collections: ProjectCollection[];
|
|
99
|
+
context?: ProjectContext;
|
|
100
|
+
}
|
|
101
|
+
/** A node in a collection's article tree. Branches have `children`; leaves have `slug`. */
|
|
102
|
+
interface ArticleNode {
|
|
103
|
+
/** Segment label — dir name for branches, filename-without-ext for leaves. */
|
|
104
|
+
name: string;
|
|
105
|
+
/** Display title — frontmatter `title` (leaf) or the folder's index title, else `name`. */
|
|
106
|
+
title?: string;
|
|
107
|
+
/**
|
|
108
|
+
* Path within the collection, without extension, e.g. "guide/setup". Set on
|
|
109
|
+
* leaves (the article) and on branches (the folder, navigable to its index).
|
|
110
|
+
*/
|
|
111
|
+
slug?: string;
|
|
112
|
+
/** Audience, set only when 'private' (omitted for 'public'). */
|
|
113
|
+
audience?: Audience;
|
|
114
|
+
/** Lifecycle status, set only when 'draft' (omitted for 'published'). */
|
|
115
|
+
status?: PublishStatus;
|
|
116
|
+
/** Frontmatter `order` — nav sort within a folder (ascending; unset sorts after). */
|
|
117
|
+
order?: number;
|
|
118
|
+
/** Branch only: nested nodes. */
|
|
119
|
+
children?: ArticleNode[];
|
|
120
|
+
}
|
|
121
|
+
/** A resolved article's content, returned by `readArticle`. */
|
|
122
|
+
interface ArticleContent {
|
|
123
|
+
coll: string;
|
|
124
|
+
slug: string;
|
|
125
|
+
title: string;
|
|
126
|
+
tags: string[];
|
|
127
|
+
/** Audience from frontmatter ('public' when absent). */
|
|
128
|
+
audience: Audience;
|
|
129
|
+
/** Lifecycle status from frontmatter ('published' when absent). */
|
|
130
|
+
status: PublishStatus;
|
|
131
|
+
/** Frontmatter-stripped body (md/mdx). */
|
|
132
|
+
body: string;
|
|
133
|
+
/** Absolute path to the file on disk. */
|
|
134
|
+
path: string;
|
|
135
|
+
/**
|
|
136
|
+
* True when the resolved file is a folder-index page (`<slug>/index.md` or
|
|
137
|
+
* `<slug>/README.md`) rather than a leaf `<slug>.md`. The route slug is the
|
|
138
|
+
* same for both, so this flag is needed to resolve folder-local relative
|
|
139
|
+
* links against the article's own folder.
|
|
140
|
+
*/
|
|
141
|
+
isIndex: boolean;
|
|
142
|
+
}
|
|
143
|
+
type PluginKind = 'search';
|
|
144
|
+
declare const NATIVE_ENGINE = "native";
|
|
145
|
+
interface QueryOptions {
|
|
146
|
+
engine?: string;
|
|
147
|
+
/** Limit to a single collection name, or a set of names. Empty/undefined = all. */
|
|
148
|
+
collection?: string | string[];
|
|
149
|
+
type?: string;
|
|
150
|
+
limit?: number;
|
|
151
|
+
/** Reveal system-audience content (default: config `showSystem`, else false). */
|
|
152
|
+
showSystem?: boolean;
|
|
153
|
+
}
|
|
154
|
+
interface QueryHit {
|
|
155
|
+
collection: string;
|
|
156
|
+
path: string;
|
|
157
|
+
title: string;
|
|
158
|
+
tags: string[];
|
|
159
|
+
snippet?: string;
|
|
160
|
+
score?: number;
|
|
161
|
+
docid?: string;
|
|
162
|
+
/** Verbatim engine chunk (unsanitized) for the search UI's inspection popover. */
|
|
163
|
+
rawChunk?: string;
|
|
164
|
+
/** The chunk cleaned to plain text, untruncated (full form for the popover). */
|
|
165
|
+
cleanedChunk?: string;
|
|
166
|
+
/** Absolute source line the chunk starts at, when the engine reports it. */
|
|
167
|
+
line?: number;
|
|
168
|
+
/** True when `snippet` is a body-preview fallback rather than the cleaned chunk. */
|
|
169
|
+
snippetFromBody?: boolean;
|
|
170
|
+
}
|
|
171
|
+
type DiagnosticLevel = 'ok' | 'warn' | 'error';
|
|
172
|
+
interface Diagnostic {
|
|
173
|
+
level: DiagnosticLevel;
|
|
174
|
+
message: string;
|
|
175
|
+
}
|
|
176
|
+
interface PluginRecord {
|
|
177
|
+
name: string;
|
|
178
|
+
kind: PluginKind;
|
|
179
|
+
command: string[];
|
|
180
|
+
version?: string;
|
|
181
|
+
/** Capabilities cached at install/register time via the `describe` op. */
|
|
182
|
+
capabilities?: PluginCapabilities;
|
|
183
|
+
enabled: boolean;
|
|
184
|
+
managed?: boolean;
|
|
185
|
+
}
|
|
186
|
+
interface PluginRegistryFile {
|
|
187
|
+
version: number;
|
|
188
|
+
plugins: PluginRecord[];
|
|
189
|
+
}
|
|
190
|
+
/** Capabilities a plugin advertises via the `describe` op, cached in the registry. */
|
|
191
|
+
interface PluginCapabilities {
|
|
192
|
+
/** Search types the plugin supports (e.g. `['keyword', 'semantic', 'hybrid']`). */
|
|
193
|
+
searchTypes: string[];
|
|
194
|
+
/** Whether the plugin supports filtering results by collection. */
|
|
195
|
+
collectionFilter: boolean;
|
|
196
|
+
/** Whether the plugin handles lifecycle events (article/collection mutations). */
|
|
197
|
+
events: boolean;
|
|
198
|
+
}
|
|
199
|
+
interface PluginReadiness {
|
|
200
|
+
toolInstalled: boolean;
|
|
201
|
+
modelsPresent: boolean;
|
|
202
|
+
indexBuilt: boolean;
|
|
203
|
+
docsIndexed: number;
|
|
204
|
+
embeddingsPending: number;
|
|
205
|
+
firstSearchCost: 'instant' | 'model-load' | 'model-download';
|
|
206
|
+
}
|
|
207
|
+
interface PluginHealth {
|
|
208
|
+
ready: boolean;
|
|
209
|
+
readiness?: PluginReadiness;
|
|
210
|
+
diagnostics: Diagnostic[];
|
|
211
|
+
}
|
|
212
|
+
interface SearchMode {
|
|
213
|
+
plugin: string;
|
|
214
|
+
type: string;
|
|
215
|
+
label: string;
|
|
216
|
+
}
|
|
217
|
+
type PluginEvent = 'collection-added' | 'collection-removed' | 'article-created' | 'article-updated' | 'article-removed';
|
|
218
|
+
/**
|
|
219
|
+
* Host-side facade for a search plugin. Each method is backed by a one-shot
|
|
220
|
+
* subprocess invocation -- there is no persistent process and no `close()`.
|
|
221
|
+
*/
|
|
222
|
+
interface SearchProvider {
|
|
223
|
+
/** Plugin name. */
|
|
224
|
+
name: string;
|
|
225
|
+
/** Plugin capabilities (cached from the `describe` op). */
|
|
226
|
+
capabilities: PluginCapabilities;
|
|
227
|
+
/** Run a search query and return hits with absolute paths. */
|
|
228
|
+
handleSearch(term: string, collections: CollectionEntry[], opts?: QueryOptions): Promise<QueryHit[]>;
|
|
229
|
+
/** Rebuild the search index. Returns the number of documents indexed. */
|
|
230
|
+
reindex(collections: CollectionEntry[], opts?: {
|
|
231
|
+
embed?: boolean;
|
|
232
|
+
}): Promise<number>;
|
|
233
|
+
/** Emit a lifecycle event to the plugin (best-effort). */
|
|
234
|
+
emitEvent(event: PluginEvent, collection: string, relPath: string | undefined, collections: CollectionEntry[]): Promise<void>;
|
|
235
|
+
/** Check plugin health and readiness. */
|
|
236
|
+
health(collections: CollectionEntry[]): Promise<PluginHealth>;
|
|
237
|
+
}
|
|
238
|
+
interface NodeMeta {
|
|
239
|
+
branch?: string;
|
|
240
|
+
behind?: number;
|
|
241
|
+
}
|
|
242
|
+
interface TreeNode {
|
|
243
|
+
name: string;
|
|
244
|
+
title?: string;
|
|
245
|
+
path?: string;
|
|
246
|
+
/** Audience; present only when 'private' (drives the sidebar lock). */
|
|
247
|
+
audience?: Audience;
|
|
248
|
+
/** Lifecycle status; present only when 'draft' (drives the sidebar DRAFT tag). */
|
|
249
|
+
status?: PublishStatus;
|
|
250
|
+
children?: TreeNode[];
|
|
251
|
+
/** Set only on top-level collection rows: git branch/behind badge data. */
|
|
252
|
+
meta?: NodeMeta;
|
|
253
|
+
}
|
|
254
|
+
interface CollectionInfo {
|
|
255
|
+
name: string;
|
|
256
|
+
type: CollectionType;
|
|
257
|
+
path: string;
|
|
258
|
+
/** Display title from the collection's root index page frontmatter; falls back to `name` in the UI. */
|
|
259
|
+
title?: string;
|
|
260
|
+
branch?: string;
|
|
261
|
+
behind?: number;
|
|
262
|
+
/** Audience from the collection's root index page; present only when 'private'. */
|
|
263
|
+
audience?: Audience;
|
|
264
|
+
/** Lifecycle status from the collection's root index page; present only when 'draft'. */
|
|
265
|
+
status?: PublishStatus;
|
|
266
|
+
}
|
|
267
|
+
interface CollectionTree {
|
|
268
|
+
collection: CollectionInfo;
|
|
269
|
+
nodes: TreeNode[];
|
|
270
|
+
}
|
|
271
|
+
interface TocItem {
|
|
272
|
+
slug: string;
|
|
273
|
+
text: string;
|
|
274
|
+
depth: number;
|
|
275
|
+
}
|
|
276
|
+
interface DocData {
|
|
277
|
+
coll: string;
|
|
278
|
+
slug: string;
|
|
279
|
+
title: string;
|
|
280
|
+
tags: string[];
|
|
281
|
+
/** Audience; present only when 'private'. */
|
|
282
|
+
audience?: Audience;
|
|
283
|
+
/** Lifecycle status; present only when 'draft'. */
|
|
284
|
+
status?: PublishStatus;
|
|
285
|
+
html: string;
|
|
286
|
+
toc: TocItem[];
|
|
287
|
+
path: string;
|
|
288
|
+
/** ISO-8601 creation date, sourced from git history / filesystem (not frontmatter). */
|
|
289
|
+
created?: string;
|
|
290
|
+
/** ISO-8601 last-update date, sourced from git history / filesystem (not frontmatter). */
|
|
291
|
+
updated?: string;
|
|
292
|
+
/** Local knowledge-graph neighbourhood for this page (this node + its direct links). */
|
|
293
|
+
graph: LocalGraph;
|
|
294
|
+
}
|
|
295
|
+
interface ListingEntry {
|
|
296
|
+
name: string;
|
|
297
|
+
title: string;
|
|
298
|
+
path: string;
|
|
299
|
+
isDir: boolean;
|
|
300
|
+
}
|
|
301
|
+
type PageData = ({
|
|
302
|
+
kind: 'doc';
|
|
303
|
+
} & DocData) | {
|
|
304
|
+
kind: 'listing';
|
|
305
|
+
coll: string;
|
|
306
|
+
slug: string;
|
|
307
|
+
title: string;
|
|
308
|
+
entries: ListingEntry[];
|
|
309
|
+
};
|
|
310
|
+
/**
|
|
311
|
+
* One node in the knowledge graph. Two kinds:
|
|
312
|
+
* - `article` — a wiki page. `id` is `"<coll>/<slug>"`, with `coll`/`slug` set.
|
|
313
|
+
* - `tag` — an Obsidian-style tag hub. `id` is `"tag:<name>"`; `coll`/`slug` are
|
|
314
|
+
* empty (a tag is not a page, so clicking it never navigates), `title` is `#name`.
|
|
315
|
+
*/
|
|
316
|
+
interface GraphNode {
|
|
317
|
+
id: string;
|
|
318
|
+
kind: 'article' | 'tag';
|
|
319
|
+
coll: string;
|
|
320
|
+
slug: string;
|
|
321
|
+
title: string;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* A graph edge. `kind` distinguishes an explicit hyperlink between two articles
|
|
325
|
+
* (`link`) from an article↔tag-hub membership edge (`tag`). For `link` edges the
|
|
326
|
+
* direction (source→target) is the link direction; `tag` edges go article→tag.
|
|
327
|
+
*/
|
|
328
|
+
interface GraphEdge {
|
|
329
|
+
source: string;
|
|
330
|
+
target: string;
|
|
331
|
+
kind: 'link' | 'tag';
|
|
332
|
+
}
|
|
333
|
+
/** The whole-wiki knowledge graph. */
|
|
334
|
+
interface LinkGraph {
|
|
335
|
+
nodes: GraphNode[];
|
|
336
|
+
edges: GraphEdge[];
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* The local neighbourhood of one node: the node itself plus its directly linked
|
|
340
|
+
* (outgoing) and linking (incoming) neighbours, and the edges among them. `focus`
|
|
341
|
+
* is the id of the page this neighbourhood is centred on.
|
|
342
|
+
*/
|
|
343
|
+
interface LocalGraph {
|
|
344
|
+
focus: string;
|
|
345
|
+
nodes: GraphNode[];
|
|
346
|
+
edges: GraphEdge[];
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
interface ParsedArticle {
|
|
350
|
+
title: string;
|
|
351
|
+
tags: string[];
|
|
352
|
+
created?: string;
|
|
353
|
+
audience: Audience;
|
|
354
|
+
status: PublishStatus;
|
|
355
|
+
body: string;
|
|
356
|
+
}
|
|
357
|
+
interface SerializableArticle {
|
|
358
|
+
title: string;
|
|
359
|
+
tags: string[];
|
|
360
|
+
audience?: Audience;
|
|
361
|
+
status?: PublishStatus;
|
|
362
|
+
body: string;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Remove a leading frontmatter block, returning the body **verbatim** — unlike
|
|
366
|
+
* {@link parseArticle}, no leading-whitespace trimming — so a caller that needs
|
|
367
|
+
* the body's original line offsets (e.g. a search index that blanks frontmatter
|
|
368
|
+
* to keep source line numbers aligned) can reconstruct them from the removed
|
|
369
|
+
* span. Returns the input unchanged when there is no frontmatter.
|
|
370
|
+
*/
|
|
371
|
+
declare function stripFrontmatter(raw: string): string;
|
|
372
|
+
declare function parseArticle(raw: string): ParsedArticle;
|
|
373
|
+
declare function serializeArticle(article: SerializableArticle): string;
|
|
374
|
+
|
|
375
|
+
export { type Audience as A, type PluginHealth as B, type Config as C, type Diagnostic as D, type PluginReadiness as E, type ProjectCollection as F, type GraphEdge as G, type HomeCard as H, type ProjectContext as I, type SerializableArticle as J, type SiteCopyright as K, type LinkGraph as L, type SiteHome as M, NATIVE_ENGINE as N, parseArticle as O, type PublishStatus as P, type QueryHit as Q, type Registry as R, type SiteConfig as S, type TreeNode as T, serializeArticle as U, stripFrontmatter as V, type CollectionEntry as a, type Article as b, type RepoConfig as c, type ProjectConfig as d, type CollectionInfo as e, type CollectionTree as f, type PageData as g, type ArticleNode as h, type QueryOptions as i, type ParsedArticle as j, type ArticleContent as k, type TocItem as l, type LocalGraph as m, type SearchMode as n, type SearchProvider as o, type PluginRecord as p, type PluginEvent as q, type PluginKind as r, type PluginRegistryFile as s, type CollectionType as t, type DiagnosticLevel as u, type DocData as v, type GraphNode as w, type ListingEntry as x, type NodeMeta as y, type PluginCapabilities as z };
|