@wiki0/core 0.0.1 → 0.0.3
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/README.md +48 -0
- package/dist/database.d.ts +3 -2
- package/dist/database.js +2 -2
- package/dist/database.js.map +1 -1
- package/dist/facts.d.ts +3 -0
- package/dist/facts.js +43 -0
- package/dist/facts.js.map +1 -0
- package/dist/graph.d.ts +2 -0
- package/dist/graph.js +34 -0
- package/dist/graph.js.map +1 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/indexer.d.ts +3 -1
- package/dist/indexer.js +118 -10
- package/dist/indexer.js.map +1 -1
- package/dist/lint.d.ts +2 -0
- package/dist/lint.js +58 -0
- package/dist/lint.js.map +1 -0
- package/dist/markdown.js +32 -54
- package/dist/markdown.js.map +1 -1
- package/dist/pages.d.ts +1 -0
- package/dist/pages.js +29 -15
- package/dist/pages.js.map +1 -1
- package/dist/review.js +3 -1
- package/dist/review.js.map +1 -1
- package/dist/schema.sql +6 -0
- package/dist/search.d.ts +2 -0
- package/dist/search.js +83 -13
- package/dist/search.js.map +1 -1
- package/dist/types.d.ts +95 -1
- package/dist/workflow.d.ts +4 -0
- package/dist/workflow.js +203 -0
- package/dist/workflow.js.map +1 -0
- package/package.json +2 -3
package/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# @wiki0/core
|
|
2
|
+
|
|
3
|
+
Core wiki0 primitives for local-first Markdown wiki memory.
|
|
4
|
+
|
|
5
|
+
## What it provides
|
|
6
|
+
|
|
7
|
+
- Markdown and frontmatter parsing.
|
|
8
|
+
- Obsidian-style `[[WikiLinks]]` parsing.
|
|
9
|
+
- Page create/read/append/frontmatter operations.
|
|
10
|
+
- SQLite indexing and FTS search.
|
|
11
|
+
- Context snippets with `wiki/...` citations.
|
|
12
|
+
- Backlinks, graph data, lint results, review queues, and structured
|
|
13
|
+
facts.
|
|
14
|
+
- Wiki-building workflow planning for agents that need a deterministic
|
|
15
|
+
source-to-wiki recipe.
|
|
16
|
+
|
|
17
|
+
## Basic usage
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import {
|
|
21
|
+
bootstrap_wiki,
|
|
22
|
+
create_page,
|
|
23
|
+
index_status,
|
|
24
|
+
index_wiki,
|
|
25
|
+
search_wiki,
|
|
26
|
+
get_wiki_context,
|
|
27
|
+
lint_wiki,
|
|
28
|
+
plan_wiki,
|
|
29
|
+
} from "@wiki0/core";
|
|
30
|
+
|
|
31
|
+
create_page("projects/wiki0", "Local-first [[topics/memory]].", {
|
|
32
|
+
root: ".",
|
|
33
|
+
});
|
|
34
|
+
index_wiki(".");
|
|
35
|
+
console.log(index_status("."));
|
|
36
|
+
console.log(search_wiki("memory", ".", 10));
|
|
37
|
+
console.log(get_wiki_context("what is wiki0?", ".", 5).markdown);
|
|
38
|
+
console.log(lint_wiki("."));
|
|
39
|
+
console.log(plan_wiki({ sourceType: "codebase", scope: "current repo" }));
|
|
40
|
+
console.log(bootstrap_wiki({ root: ".", sourceType: "docs" }));
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Storage model
|
|
44
|
+
|
|
45
|
+
Markdown files under `wiki/` are canonical. The `.wiki0/wiki0.sqlite`
|
|
46
|
+
database is a rebuildable cache for search, backlinks, graph data, and
|
|
47
|
+
facts. `index_status` reports indexed-at time, schema version, and
|
|
48
|
+
stale reasons when Markdown has changed since the last rebuild.
|
package/dist/database.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
export type WikiDatabase = DatabaseSync;
|
|
2
3
|
export declare function wiki_db_path(root?: string): string;
|
|
3
|
-
export declare function open_wiki_database(root?: string):
|
|
4
|
+
export declare function open_wiki_database(root?: string): WikiDatabase;
|
package/dist/database.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import Database from 'better-sqlite3';
|
|
2
1
|
import { mkdirSync } from 'node:fs';
|
|
3
2
|
import { dirname, join } from 'node:path';
|
|
3
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
4
4
|
import { resolve_wiki_root } from './paths.js';
|
|
5
5
|
import { schema_sql } from './schema.js';
|
|
6
6
|
export function wiki_db_path(root = '.') {
|
|
@@ -10,7 +10,7 @@ export function open_wiki_database(root = '.') {
|
|
|
10
10
|
const wiki_root = resolve_wiki_root(root);
|
|
11
11
|
const db_path = wiki_db_path(wiki_root);
|
|
12
12
|
mkdirSync(dirname(db_path), { recursive: true });
|
|
13
|
-
const db = new
|
|
13
|
+
const db = new DatabaseSync(db_path);
|
|
14
14
|
db.exec(schema_sql);
|
|
15
15
|
return db;
|
|
16
16
|
}
|
package/dist/database.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC,MAAM,UAAU,YAAY,CAAC,IAAI,GAAG,GAAG;IACtC,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAI,GAAG,GAAG;IAC5C,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACxC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACpB,OAAO,EAAE,CAAC;AACX,CAAC"}
|
package/dist/facts.d.ts
ADDED
package/dist/facts.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { open_wiki_database } from './database.js';
|
|
2
|
+
import { resolve_page_path } from './pages.js';
|
|
3
|
+
import { resolve_wiki_root } from './paths.js';
|
|
4
|
+
export function add_fact(fact) {
|
|
5
|
+
const wiki_root = resolve_wiki_root(fact.root);
|
|
6
|
+
const db = open_wiki_database(wiki_root);
|
|
7
|
+
const page_path = fact.page
|
|
8
|
+
? resolve_page_path(fact.page, wiki_root)
|
|
9
|
+
: null;
|
|
10
|
+
const page = page_path
|
|
11
|
+
? db
|
|
12
|
+
.prepare('SELECT id FROM pages WHERE path = ?')
|
|
13
|
+
.get(page_path)
|
|
14
|
+
: undefined;
|
|
15
|
+
const result = db
|
|
16
|
+
.prepare(`INSERT INTO facts (page_id, category, summary, body, confidence)
|
|
17
|
+
VALUES (?, ?, ?, ?, ?)`)
|
|
18
|
+
.run(page?.id ?? null, fact.category, fact.summary, fact.body ?? null, fact.confidence ?? 'unknown');
|
|
19
|
+
const inserted = db
|
|
20
|
+
.prepare(`SELECT facts.id, pages.path AS pagePath, facts.category,
|
|
21
|
+
facts.summary, facts.body, facts.confidence, facts.created_at AS createdAt
|
|
22
|
+
FROM facts
|
|
23
|
+
LEFT JOIN pages ON pages.id = facts.page_id
|
|
24
|
+
WHERE facts.id = ?`)
|
|
25
|
+
.get(result.lastInsertRowid);
|
|
26
|
+
db.close();
|
|
27
|
+
return inserted;
|
|
28
|
+
}
|
|
29
|
+
export function list_facts(root = '.', category) {
|
|
30
|
+
const db = open_wiki_database(root);
|
|
31
|
+
const sql = `SELECT facts.id, pages.path AS pagePath, facts.category,
|
|
32
|
+
facts.summary, facts.body, facts.confidence, facts.created_at AS createdAt
|
|
33
|
+
FROM facts
|
|
34
|
+
LEFT JOIN pages ON pages.id = facts.page_id
|
|
35
|
+
${category ? 'WHERE facts.category = ?' : ''}
|
|
36
|
+
ORDER BY facts.created_at DESC, facts.id DESC`;
|
|
37
|
+
const rows = category
|
|
38
|
+
? db.prepare(sql).all(category)
|
|
39
|
+
: db.prepare(sql).all();
|
|
40
|
+
db.close();
|
|
41
|
+
return rows;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=facts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facts.js","sourceRoot":"","sources":["../src/facts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAG/C,MAAM,UAAU,QAAQ,CAAC,IAAsB;IAC9C,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI;QAC1B,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;QACzC,CAAC,CAAC,IAAI,CAAC;IACR,MAAM,IAAI,GAAG,SAAS;QACrB,CAAC,CAAE,EAAE;aACF,OAAO,CAAC,qCAAqC,CAAC;aAC9C,GAAG,CAAC,SAAS,CAAgC;QAChD,CAAC,CAAC,SAAS,CAAC;IAEb,MAAM,MAAM,GAAG,EAAE;SACf,OAAO,CACP;0BACuB,CACvB;SACA,GAAG,CACH,IAAI,EAAE,EAAE,IAAI,IAAI,EAChB,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,IAAI,IAAI,IAAI,EACjB,IAAI,CAAC,UAAU,IAAI,SAAS,CAC5B,CAAC;IACH,MAAM,QAAQ,GAAG,EAAE;SACjB,OAAO,CACP;;;;sBAImB,CACnB;SACA,GAAG,CAAC,MAAM,CAAC,eAAe,CAAS,CAAC;IACtC,EAAE,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAI,GAAG,GAAG,EAAE,QAAiB;IACvD,MAAM,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG;;;;IAIT,QAAQ,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,EAAE;gDACE,CAAC;IAChD,MAAM,IAAI,GAAG,QAAQ;QACpB,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC/B,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACzB,EAAE,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,IAAc,CAAC;AACvB,CAAC"}
|
package/dist/graph.d.ts
ADDED
package/dist/graph.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { open_wiki_database } from './database.js';
|
|
2
|
+
import { resolve_wiki_root, wikilink_target_path } from './paths.js';
|
|
3
|
+
export function graph_wiki(root = '.') {
|
|
4
|
+
const wiki_root = resolve_wiki_root(root);
|
|
5
|
+
const db = open_wiki_database(wiki_root);
|
|
6
|
+
const nodes = db
|
|
7
|
+
.prepare('SELECT path, title FROM pages ORDER BY path')
|
|
8
|
+
.all();
|
|
9
|
+
const edges = db
|
|
10
|
+
.prepare(`SELECT pages.path AS "from",
|
|
11
|
+
COALESCE(page_links.to_path, page_links.target) AS "to",
|
|
12
|
+
page_links.target,
|
|
13
|
+
page_links.raw_text AS rawText,
|
|
14
|
+
page_links.alias,
|
|
15
|
+
page_links.embed,
|
|
16
|
+
page_links.status
|
|
17
|
+
FROM page_links
|
|
18
|
+
JOIN pages ON pages.id = page_links.from_page_id
|
|
19
|
+
ORDER BY pages.path, page_links.target`)
|
|
20
|
+
.all();
|
|
21
|
+
db.close();
|
|
22
|
+
return {
|
|
23
|
+
root: wiki_root,
|
|
24
|
+
nodes,
|
|
25
|
+
edges: edges.map((edge) => ({
|
|
26
|
+
...edge,
|
|
27
|
+
to: edge.status === 'resolved'
|
|
28
|
+
? edge.to
|
|
29
|
+
: wikilink_target_path(edge.target),
|
|
30
|
+
embed: Boolean(edge.embed),
|
|
31
|
+
})),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGrE,MAAM,UAAU,UAAU,CAAC,IAAI,GAAG,GAAG;IACpC,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,EAAE;SACd,OAAO,CAAC,6CAA6C,CAAC;SACtD,GAAG,EAAiB,CAAC;IACvB,MAAM,KAAK,GAAG,EAAE;SACd,OAAO,CACP;;;;;;;;;0CASuC,CACvC;SACA,GAAG,EAA4B,CAAC;IAClC,EAAE,CAAC,KAAK,EAAE,CAAC;IAEX,OAAO;QACN,IAAI,EAAE,SAAS;QACf,KAAK;QACL,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC3B,GAAG,IAAI;YACP,EAAE,EACD,IAAI,CAAC,MAAM,KAAK,UAAU;gBACzB,CAAC,CAAC,IAAI,CAAC,EAAE;gBACT,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC;YACrC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;SAC1B,CAAC,CAAC;KACH,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
export { open_wiki_database, wiki_db_path } from './database.js';
|
|
2
|
-
export {
|
|
2
|
+
export { add_fact, list_facts } from './facts.js';
|
|
3
|
+
export { graph_wiki } from './graph.js';
|
|
4
|
+
export { current_index_schema_version, index_status, index_wiki, } from './indexer.js';
|
|
5
|
+
export { lint_wiki } from './lint.js';
|
|
3
6
|
export { page_title_from_markdown, parse_frontmatter, parse_markdown, parse_wikilinks, serialize_frontmatter, strip_fenced_code_blocks, strip_inline_code, } from './markdown.js';
|
|
4
|
-
export { append_page, create_page, list_markdown_page_paths, read_page, set_page_frontmatter, } from './pages.js';
|
|
7
|
+
export { append_page, create_page, list_markdown_page_paths, read_page, resolve_page_path, set_page_frontmatter, } from './pages.js';
|
|
5
8
|
export { display_page_title, page_file_path, page_relative_path, resolve_wiki_root, slugify_title, wikilink_target_path, } from './paths.js';
|
|
6
9
|
export { review_wiki } from './review.js';
|
|
7
10
|
export { schema_sql } from './schema.js';
|
|
8
11
|
export { backlinks_for_page, format_context_markdown, get_wiki_context, search_wiki, } from './search.js';
|
|
9
12
|
export type * from './types.js';
|
|
13
|
+
export { bootstrap_wiki, plan_wiki, wiki_building_workflow_markdown, } from './workflow.js';
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
export { open_wiki_database, wiki_db_path } from './database.js';
|
|
2
|
-
export {
|
|
2
|
+
export { add_fact, list_facts } from './facts.js';
|
|
3
|
+
export { graph_wiki } from './graph.js';
|
|
4
|
+
export { current_index_schema_version, index_status, index_wiki, } from './indexer.js';
|
|
5
|
+
export { lint_wiki } from './lint.js';
|
|
3
6
|
export { page_title_from_markdown, parse_frontmatter, parse_markdown, parse_wikilinks, serialize_frontmatter, strip_fenced_code_blocks, strip_inline_code, } from './markdown.js';
|
|
4
|
-
export { append_page, create_page, list_markdown_page_paths, read_page, set_page_frontmatter, } from './pages.js';
|
|
7
|
+
export { append_page, create_page, list_markdown_page_paths, read_page, resolve_page_path, set_page_frontmatter, } from './pages.js';
|
|
5
8
|
export { display_page_title, page_file_path, page_relative_path, resolve_wiki_root, slugify_title, wikilink_target_path, } from './paths.js';
|
|
6
9
|
export { review_wiki } from './review.js';
|
|
7
10
|
export { schema_sql } from './schema.js';
|
|
8
11
|
export { backlinks_for_page, format_context_markdown, get_wiki_context, search_wiki, } from './search.js';
|
|
12
|
+
export { bootstrap_wiki, plan_wiki, wiki_building_workflow_markdown, } from './workflow.js';
|
|
9
13
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EACN,4BAA4B,EAC5B,YAAY,EACZ,UAAU,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACN,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,WAAW,EACX,WAAW,EACX,wBAAwB,EACxB,SAAS,EACT,iBAAiB,EACjB,oBAAoB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,oBAAoB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,gBAAgB,EAChB,WAAW,GACX,MAAM,aAAa,CAAC;AAErB,OAAO,EACN,cAAc,EACd,SAAS,EACT,+BAA+B,GAC/B,MAAM,eAAe,CAAC"}
|
package/dist/indexer.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
import type { IndexResult } from './types.js';
|
|
1
|
+
import type { IndexResult, IndexStatus } from './types.js';
|
|
2
|
+
export declare const current_index_schema_version = 1;
|
|
2
3
|
export declare function index_wiki(root?: string): IndexResult;
|
|
4
|
+
export declare function index_status(root?: string): IndexStatus;
|
package/dist/indexer.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { statSync } from 'node:fs';
|
|
2
|
+
import { existsSync, statSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { open_wiki_database, wiki_db_path } from './database.js';
|
|
5
5
|
import { list_markdown_page_paths, read_page_by_path, } from './pages.js';
|
|
6
6
|
import { resolve_wiki_root, wikilink_target_path } from './paths.js';
|
|
7
|
+
export const current_index_schema_version = 1;
|
|
7
8
|
export function index_wiki(root = '.') {
|
|
8
9
|
const wiki_root = resolve_wiki_root(root);
|
|
9
10
|
const db_path = wiki_db_path(wiki_root);
|
|
@@ -28,13 +29,37 @@ export function index_wiki(root = '.') {
|
|
|
28
29
|
`);
|
|
29
30
|
const clear_fts = db.prepare('DELETE FROM fts_pages');
|
|
30
31
|
const insert_fts = db.prepare('INSERT INTO fts_pages (path, title, body) VALUES (?, ?, ?)');
|
|
32
|
+
const set_meta = db.prepare(`
|
|
33
|
+
INSERT INTO wiki_meta (key, value, updated_at)
|
|
34
|
+
VALUES (?, ?, datetime('now'))
|
|
35
|
+
ON CONFLICT(key) DO UPDATE SET
|
|
36
|
+
value = excluded.value,
|
|
37
|
+
updated_at = datetime('now')
|
|
38
|
+
`);
|
|
31
39
|
const page_paths = list_markdown_page_paths(wiki_root);
|
|
32
40
|
const known_paths = new Set(page_paths);
|
|
33
|
-
const
|
|
41
|
+
const pages = page_paths.map((page_path) => read_page_by_path(page_path, wiki_root));
|
|
42
|
+
const name_paths = new Map();
|
|
43
|
+
for (const page of pages) {
|
|
44
|
+
const aliases = page.frontmatter.aliases;
|
|
45
|
+
const alias_list = Array.isArray(aliases)
|
|
46
|
+
? aliases.filter((alias) => typeof alias === 'string')
|
|
47
|
+
: typeof aliases === 'string'
|
|
48
|
+
? [aliases]
|
|
49
|
+
: [];
|
|
50
|
+
for (const name of [page.title, ...alias_list]) {
|
|
51
|
+
const normalized_name = name.trim().toLowerCase();
|
|
52
|
+
if (normalized_name)
|
|
53
|
+
name_paths.set(normalized_name, page.path);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
let indexed_at = new Date().toISOString();
|
|
57
|
+
db.exec('BEGIN');
|
|
58
|
+
try {
|
|
59
|
+
indexed_at = new Date().toISOString();
|
|
34
60
|
clear_fts.run();
|
|
35
|
-
for (const
|
|
36
|
-
const file_path = join(wiki_root, 'wiki',
|
|
37
|
-
const page = read_page_by_path(page_path, wiki_root);
|
|
61
|
+
for (const page of pages) {
|
|
62
|
+
const file_path = join(wiki_root, 'wiki', page.path);
|
|
38
63
|
const modified_at = statSync(file_path).mtime.toISOString();
|
|
39
64
|
const content_hash = createHash('sha256')
|
|
40
65
|
.update(page.body)
|
|
@@ -49,9 +74,13 @@ export function index_wiki(root = '.') {
|
|
|
49
74
|
const row = page_id_query.get(page.path);
|
|
50
75
|
delete_links.run(row.id);
|
|
51
76
|
for (const link of page.links) {
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
|
|
77
|
+
const direct_path = wikilink_target_path(link.target);
|
|
78
|
+
const target_name = link.target.split('#')[0]?.trim().toLowerCase() ?? '';
|
|
79
|
+
const resolved_path = known_paths.has(direct_path)
|
|
80
|
+
? direct_path
|
|
81
|
+
: name_paths.get(target_name);
|
|
82
|
+
const is_resolved = Boolean(resolved_path);
|
|
83
|
+
insert_link.run(row.id, resolved_path ?? null, link.raw, link.target, link.alias ?? null, link.embed ? 1 : 0, is_resolved ? 'resolved' : 'unresolved');
|
|
55
84
|
link_count += 1;
|
|
56
85
|
}
|
|
57
86
|
insert_fts.run(page.path, page.title, page.content);
|
|
@@ -64,14 +93,93 @@ export function index_wiki(root = '.') {
|
|
|
64
93
|
else {
|
|
65
94
|
db.prepare('DELETE FROM pages').run();
|
|
66
95
|
}
|
|
67
|
-
|
|
68
|
-
|
|
96
|
+
set_meta.run('indexed_at', indexed_at);
|
|
97
|
+
set_meta.run('schema_version', String(current_index_schema_version));
|
|
98
|
+
db.exec('COMMIT');
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
db.exec('ROLLBACK');
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
69
104
|
db.close();
|
|
70
105
|
return {
|
|
71
106
|
root: wiki_root,
|
|
72
107
|
dbPath: db_path,
|
|
73
108
|
pageCount: page_count,
|
|
74
109
|
linkCount: link_count,
|
|
110
|
+
indexedAt: indexed_at,
|
|
111
|
+
schemaVersion: current_index_schema_version,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
export function index_status(root = '.') {
|
|
115
|
+
const wiki_root = resolve_wiki_root(root);
|
|
116
|
+
const db_path = wiki_db_path(wiki_root);
|
|
117
|
+
const page_paths = list_markdown_page_paths(wiki_root);
|
|
118
|
+
const reasons = [];
|
|
119
|
+
if (!existsSync(db_path)) {
|
|
120
|
+
return {
|
|
121
|
+
root: wiki_root,
|
|
122
|
+
dbPath: db_path,
|
|
123
|
+
exists: false,
|
|
124
|
+
indexedAt: null,
|
|
125
|
+
schemaVersion: null,
|
|
126
|
+
currentSchemaVersion: current_index_schema_version,
|
|
127
|
+
pageCount: page_paths.length,
|
|
128
|
+
indexedPageCount: 0,
|
|
129
|
+
stale: true,
|
|
130
|
+
reasons: ['missing-index'],
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const db = open_wiki_database(wiki_root);
|
|
134
|
+
const meta_rows = db
|
|
135
|
+
.prepare('SELECT key, value FROM wiki_meta')
|
|
136
|
+
.all();
|
|
137
|
+
const meta = new Map(meta_rows.map((row) => [row.key, row.value]));
|
|
138
|
+
const indexed_at = meta.get('indexed_at') ?? null;
|
|
139
|
+
const schema_version = Number(meta.get('schema_version') ?? NaN);
|
|
140
|
+
const indexed_page_count = db.prepare('SELECT COUNT(*) AS count FROM pages').get().count;
|
|
141
|
+
const indexed_pages = db
|
|
142
|
+
.prepare('SELECT path, content_hash AS contentHash FROM pages')
|
|
143
|
+
.all();
|
|
144
|
+
db.close();
|
|
145
|
+
if (!indexed_at)
|
|
146
|
+
reasons.push('never-indexed');
|
|
147
|
+
if (schema_version !== current_index_schema_version) {
|
|
148
|
+
reasons.push('schema-version-mismatch');
|
|
149
|
+
}
|
|
150
|
+
if (indexed_page_count !== page_paths.length) {
|
|
151
|
+
reasons.push('page-count-changed');
|
|
152
|
+
}
|
|
153
|
+
const current_paths = new Set(page_paths);
|
|
154
|
+
const indexed_hashes = new Map(indexed_pages.map((page) => [page.path, page.contentHash]));
|
|
155
|
+
for (const page of indexed_pages) {
|
|
156
|
+
if (!current_paths.has(page.path))
|
|
157
|
+
reasons.push('deleted-pages');
|
|
158
|
+
}
|
|
159
|
+
for (const page_path of page_paths) {
|
|
160
|
+
const page = read_page_by_path(page_path, wiki_root);
|
|
161
|
+
const current_hash = createHash('sha256')
|
|
162
|
+
.update(page.body)
|
|
163
|
+
.digest('hex');
|
|
164
|
+
const indexed_hash = indexed_hashes.get(page_path);
|
|
165
|
+
if (!indexed_hash)
|
|
166
|
+
reasons.push('new-pages');
|
|
167
|
+
else if (indexed_hash !== current_hash)
|
|
168
|
+
reasons.push('modified-pages');
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
root: wiki_root,
|
|
172
|
+
dbPath: db_path,
|
|
173
|
+
exists: true,
|
|
174
|
+
indexedAt: indexed_at,
|
|
175
|
+
schemaVersion: Number.isNaN(schema_version)
|
|
176
|
+
? null
|
|
177
|
+
: schema_version,
|
|
178
|
+
currentSchemaVersion: current_index_schema_version,
|
|
179
|
+
pageCount: page_paths.length,
|
|
180
|
+
indexedPageCount: indexed_page_count,
|
|
181
|
+
stale: reasons.length > 0,
|
|
182
|
+
reasons: [...new Set(reasons)],
|
|
75
183
|
};
|
|
76
184
|
}
|
|
77
185
|
//# sourceMappingURL=indexer.js.map
|
package/dist/indexer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indexer.js","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"indexer.js","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"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"}
|
package/dist/lint.d.ts
ADDED
package/dist/lint.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { list_markdown_page_paths, read_page_by_path, } from './pages.js';
|
|
2
|
+
import { resolve_wiki_root, wikilink_target_path } from './paths.js';
|
|
3
|
+
export function lint_wiki(root = '.') {
|
|
4
|
+
const wiki_root = resolve_wiki_root(root);
|
|
5
|
+
const page_paths = list_markdown_page_paths(wiki_root);
|
|
6
|
+
const known_paths = new Set(page_paths);
|
|
7
|
+
const issues = [];
|
|
8
|
+
const names = new Map();
|
|
9
|
+
const pages = page_paths.map((page_path) => read_page_by_path(page_path, wiki_root));
|
|
10
|
+
for (const page of pages) {
|
|
11
|
+
const aliases = page.frontmatter.aliases;
|
|
12
|
+
const alias_list = Array.isArray(aliases)
|
|
13
|
+
? aliases.filter((alias) => typeof alias === 'string')
|
|
14
|
+
: typeof aliases === 'string'
|
|
15
|
+
? [aliases]
|
|
16
|
+
: [];
|
|
17
|
+
for (const name of [page.title, ...alias_list]) {
|
|
18
|
+
const normalized_name = name.trim().toLowerCase();
|
|
19
|
+
if (!normalized_name)
|
|
20
|
+
continue;
|
|
21
|
+
const existing_path = names.get(normalized_name);
|
|
22
|
+
if (existing_path && existing_path !== page.path) {
|
|
23
|
+
issues.push({
|
|
24
|
+
code: 'duplicate-name',
|
|
25
|
+
severity: 'warning',
|
|
26
|
+
path: page.path,
|
|
27
|
+
target: name,
|
|
28
|
+
message: `Duplicate title or alias "${name}" also used by wiki/${existing_path}`,
|
|
29
|
+
});
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
names.set(normalized_name, page.path);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
for (const page of pages) {
|
|
36
|
+
for (const link of page.links) {
|
|
37
|
+
const target_path = wikilink_target_path(link.target);
|
|
38
|
+
const target_name = link.target.split('#')[0]?.trim().toLowerCase() ?? '';
|
|
39
|
+
if (known_paths.has(target_path) || names.has(target_name)) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
issues.push({
|
|
43
|
+
code: 'unresolved-wikilink',
|
|
44
|
+
severity: 'error',
|
|
45
|
+
path: page.path,
|
|
46
|
+
target: link.target,
|
|
47
|
+
message: `Unresolved wikilink ${link.raw}`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
root: wiki_root,
|
|
53
|
+
ok: issues.every((issue) => issue.severity !== 'error'),
|
|
54
|
+
issueCount: issues.length,
|
|
55
|
+
issues: issues.sort((left, right) => `${left.path}:${left.code}:${left.target ?? ''}`.localeCompare(`${right.path}:${right.code}:${right.target ?? ''}`)),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=lint.js.map
|
package/dist/lint.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"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"}
|
package/dist/markdown.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isMap, parseDocument, stringify } from 'yaml';
|
|
1
2
|
export function parse_wikilinks(markdown) {
|
|
2
3
|
const links = [];
|
|
3
4
|
const pattern = /(!?)\[\[([^\]|]+)(?:\|([^\]]+))?\]\]/gu;
|
|
@@ -33,65 +34,42 @@ export function parse_markdown(markdown) {
|
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
36
|
export function parse_frontmatter(source) {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const line = raw_line.trimEnd();
|
|
40
|
-
if (line.trim().length === 0)
|
|
41
|
-
continue;
|
|
42
|
-
const list_match = line.match(/^\s*-\s+(.+)$/u);
|
|
43
|
-
if (list_match && current_key) {
|
|
44
|
-
const value = frontmatter[current_key];
|
|
45
|
-
const values = Array.isArray(value)
|
|
46
|
-
? value
|
|
47
|
-
: value === undefined
|
|
48
|
-
? []
|
|
49
|
-
: [String(value)];
|
|
50
|
-
values.push(String(parse_frontmatter_scalar(list_match[1] ?? '')));
|
|
51
|
-
frontmatter[current_key] = values;
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
const pair_match = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/u);
|
|
55
|
-
if (!pair_match)
|
|
56
|
-
continue;
|
|
57
|
-
const [, key, value] = pair_match;
|
|
58
|
-
current_key = key;
|
|
59
|
-
frontmatter[key] =
|
|
60
|
-
value.length > 0 ? parse_frontmatter_scalar(value) : [];
|
|
37
|
+
const document = parseDocument(source, { prettyErrors: false });
|
|
38
|
+
if (document.errors.length > 0) {
|
|
39
|
+
throw new Error(`Invalid YAML frontmatter: ${document.errors[0]?.message}`);
|
|
61
40
|
}
|
|
62
|
-
|
|
41
|
+
if (document.contents === null)
|
|
42
|
+
return {};
|
|
43
|
+
if (!isMap(document.contents)) {
|
|
44
|
+
throw new Error('YAML frontmatter must be a mapping/object');
|
|
45
|
+
}
|
|
46
|
+
return normalize_frontmatter_value(document.toJSON());
|
|
63
47
|
}
|
|
64
48
|
export function serialize_frontmatter(frontmatter) {
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
for (const item of value)
|
|
70
|
-
lines.push(` - ${item}`);
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
lines.push(`${key}: ${String(value)}`);
|
|
74
|
-
}
|
|
75
|
-
lines.push('---', '');
|
|
76
|
-
return `${lines.join('\n')}\n`;
|
|
49
|
+
const yaml = stringify(frontmatter, {
|
|
50
|
+
lineWidth: 0,
|
|
51
|
+
}).trimEnd();
|
|
52
|
+
return `---\n${yaml}\n---\n\n`;
|
|
77
53
|
}
|
|
78
|
-
function
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
return
|
|
87
|
-
if (
|
|
88
|
-
return
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
54
|
+
function normalize_frontmatter_value(value) {
|
|
55
|
+
if (value === null ||
|
|
56
|
+
typeof value === 'string' ||
|
|
57
|
+
typeof value === 'number' ||
|
|
58
|
+
typeof value === 'boolean') {
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
if (value instanceof Date)
|
|
62
|
+
return value.toISOString();
|
|
63
|
+
if (Array.isArray(value)) {
|
|
64
|
+
return value.map((item) => normalize_frontmatter_value(item));
|
|
65
|
+
}
|
|
66
|
+
if (typeof value === 'object') {
|
|
67
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [
|
|
68
|
+
key,
|
|
69
|
+
normalize_frontmatter_value(item),
|
|
70
|
+
]));
|
|
93
71
|
}
|
|
94
|
-
return
|
|
72
|
+
return JSON.stringify(value) ?? null;
|
|
95
73
|
}
|
|
96
74
|
export function page_title_from_markdown(markdown, fallback) {
|
|
97
75
|
const parsed_markdown = parse_markdown(markdown);
|
package/dist/markdown.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"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"}
|
package/dist/pages.d.ts
CHANGED
|
@@ -4,5 +4,6 @@ export declare function create_page(title: string, body: string, options?: PageW
|
|
|
4
4
|
export declare function read_page(title: string, root?: string): WikiPage;
|
|
5
5
|
export declare function set_page_frontmatter(title: string, frontmatter: Parameters<typeof serialize_frontmatter>[0], options?: PageFrontmatterOptions): WikiPage;
|
|
6
6
|
export declare function append_page(title: string, body: string, root?: string): WikiPage;
|
|
7
|
+
export declare function resolve_page_path(title: string, root?: string): string;
|
|
7
8
|
export declare function list_markdown_page_paths(root?: string): string[];
|
|
8
9
|
export declare function read_page_by_path(page_path: string, root?: string): WikiPage;
|