diffwiki-core 0.6.0-rc.202607240049.586dcb6 → 0.6.0
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/index.cjs +37 -174
- package/dist/index.d.cts +8 -101
- package/dist/index.d.ts +8 -101
- package/dist/index.js +36 -169
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -577,7 +577,6 @@ __export(index_exports, {
|
|
|
577
577
|
addTags: () => addTags,
|
|
578
578
|
buildArticleTree: () => buildArticleTree,
|
|
579
579
|
buildCollections: () => buildCollections,
|
|
580
|
-
buildLinkGraph: () => buildLinkGraph,
|
|
581
580
|
buildNavTree: () => buildNavTree,
|
|
582
581
|
buildSearchIndex: () => buildSearchIndex,
|
|
583
582
|
collectionDir: () => collectionDir,
|
|
@@ -601,7 +600,6 @@ __export(index_exports, {
|
|
|
601
600
|
gitToplevel: () => gitToplevel,
|
|
602
601
|
initRepoWiki: () => initRepoWiki,
|
|
603
602
|
installPlugin: () => installPlugin,
|
|
604
|
-
invalidateLinkGraph: () => invalidateLinkGraph,
|
|
605
603
|
isLinkedWorktree: () => isLinkedWorktree,
|
|
606
604
|
listArticleTree: () => listArticleTree,
|
|
607
605
|
listAvailablePlugins: () => listAvailablePlugins,
|
|
@@ -610,7 +608,6 @@ __export(index_exports, {
|
|
|
610
608
|
listPlugins: () => listPlugins,
|
|
611
609
|
listSearchModes: () => listSearchModes,
|
|
612
610
|
loadSearchProvider: () => loadSearchProvider,
|
|
613
|
-
localGraph: () => localGraph,
|
|
614
611
|
nativeSearch: () => nativeSearch,
|
|
615
612
|
parseAddTarget: () => parseAddTarget,
|
|
616
613
|
parseArticle: () => parseArticle,
|
|
@@ -1264,58 +1261,6 @@ function rehypeCollectToc(toc) {
|
|
|
1264
1261
|
});
|
|
1265
1262
|
};
|
|
1266
1263
|
}
|
|
1267
|
-
function isExternalHref(href) {
|
|
1268
|
-
if (!href) return true;
|
|
1269
|
-
if (href.startsWith("#")) return true;
|
|
1270
|
-
if (href.startsWith("//")) return true;
|
|
1271
|
-
return /^[a-z][a-z0-9+.-]*:/i.test(href);
|
|
1272
|
-
}
|
|
1273
|
-
function resolveHref(href, ctx) {
|
|
1274
|
-
if (isExternalHref(href)) return null;
|
|
1275
|
-
const clean = (p) => p.replace(/[?#].*$/, "").replace(/\.(mdx?|html)$/i, "").replace(/\/+$/, "");
|
|
1276
|
-
const target = clean(href);
|
|
1277
|
-
if (!target) return null;
|
|
1278
|
-
if (target.startsWith("/")) {
|
|
1279
|
-
const base = ctx.base ?? process.env.DIFFWIKI_BASE ?? "";
|
|
1280
|
-
const baseSegs2 = base.split("/").filter(Boolean);
|
|
1281
|
-
let segs = target.split("/").filter(Boolean);
|
|
1282
|
-
if (baseSegs2.length > 0 && baseSegs2.every((b, i) => segs[i] === b)) {
|
|
1283
|
-
segs = segs.slice(baseSegs2.length);
|
|
1284
|
-
}
|
|
1285
|
-
if (segs.length < 2) return null;
|
|
1286
|
-
const collIdx = segs.indexOf(ctx.coll);
|
|
1287
|
-
if (base === "" && collIdx > 0) return segs.slice(collIdx).join("/");
|
|
1288
|
-
return segs.join("/");
|
|
1289
|
-
}
|
|
1290
|
-
const dir = ctx.slug.includes("/") ? ctx.slug.slice(0, ctx.slug.lastIndexOf("/")) : "";
|
|
1291
|
-
const baseSegs = dir ? dir.split("/") : [];
|
|
1292
|
-
const out = [...baseSegs];
|
|
1293
|
-
for (const seg of target.split("/")) {
|
|
1294
|
-
if (seg === "" || seg === ".") continue;
|
|
1295
|
-
if (seg === "..") {
|
|
1296
|
-
if (out.length === 0) return null;
|
|
1297
|
-
out.pop();
|
|
1298
|
-
continue;
|
|
1299
|
-
}
|
|
1300
|
-
out.push(seg);
|
|
1301
|
-
}
|
|
1302
|
-
if (out.length === 0) return null;
|
|
1303
|
-
return `${ctx.coll}/${out.join("/")}`;
|
|
1304
|
-
}
|
|
1305
|
-
function rehypeCollectLinks(links, ctx) {
|
|
1306
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1307
|
-
return (tree) => {
|
|
1308
|
-
(0, import_unist_util_visit.visit)(tree, "element", (node) => {
|
|
1309
|
-
if (node.tagName !== "a") return;
|
|
1310
|
-
const href = node.properties?.href;
|
|
1311
|
-
if (typeof href !== "string") return;
|
|
1312
|
-
const id = resolveHref(href, ctx);
|
|
1313
|
-
if (!id || seen.has(id)) return;
|
|
1314
|
-
seen.add(id);
|
|
1315
|
-
links.push(id);
|
|
1316
|
-
});
|
|
1317
|
-
};
|
|
1318
|
-
}
|
|
1319
1264
|
function rehypeStripLeadingH1() {
|
|
1320
1265
|
return (tree) => {
|
|
1321
1266
|
let removed = false;
|
|
@@ -1341,92 +1286,15 @@ function rehypeMarkMermaid() {
|
|
|
1341
1286
|
});
|
|
1342
1287
|
};
|
|
1343
1288
|
}
|
|
1344
|
-
async function renderArticle(body
|
|
1289
|
+
async function renderArticle(body) {
|
|
1345
1290
|
const toc = [];
|
|
1346
|
-
const
|
|
1347
|
-
const pipeline = (0, import_unified.unified)().use(import_remark_parse.default).use(import_remark_gfm.default).use(import_remark_rehype.default).use(import_rehype_slug.default).use(rehypeCollectToc, toc);
|
|
1348
|
-
if (ctx) pipeline.use(rehypeCollectLinks, links, ctx);
|
|
1349
|
-
const file = await pipeline.use(rehypeStripLeadingH1).use(rehypeMarkMermaid).use(import_rehype.default, {
|
|
1291
|
+
const file = await (0, import_unified.unified)().use(import_remark_parse.default).use(import_remark_gfm.default).use(import_remark_rehype.default).use(import_rehype_slug.default).use(rehypeCollectToc, toc).use(rehypeStripLeadingH1).use(rehypeMarkMermaid).use(import_rehype.default, {
|
|
1350
1292
|
themes: { light: "github-light", dark: "github-dark" },
|
|
1351
1293
|
defaultColor: false,
|
|
1352
1294
|
langAlias: LANG_ALIASES,
|
|
1353
1295
|
fallbackLanguage: "plaintext"
|
|
1354
1296
|
}).use(import_rehype_stringify.default).process(body);
|
|
1355
|
-
return { html: String(file), toc
|
|
1356
|
-
}
|
|
1357
|
-
|
|
1358
|
-
// src/graph.ts
|
|
1359
|
-
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
1360
|
-
var import_node_path7 = __toESM(require("path"), 1);
|
|
1361
|
-
init_collections();
|
|
1362
|
-
async function readArticleParts(collDir, slug) {
|
|
1363
|
-
for (const ext of [".mdx", ".md"]) {
|
|
1364
|
-
try {
|
|
1365
|
-
const parsed = parseArticle(await import_promises8.default.readFile(import_node_path7.default.join(collDir, `${slug}${ext}`), "utf8"));
|
|
1366
|
-
return { title: parsed.title, body: parsed.body };
|
|
1367
|
-
} catch {
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1370
|
-
return { body: "" };
|
|
1371
|
-
}
|
|
1372
|
-
async function collectCollection(coll, collDir, nodes, outNodes, outEdges) {
|
|
1373
|
-
for (const n of nodes) {
|
|
1374
|
-
if (n.slug && !n.children) {
|
|
1375
|
-
const id = `${coll}/${n.slug}`;
|
|
1376
|
-
const { title, body } = await readArticleParts(collDir, n.slug);
|
|
1377
|
-
outNodes.push({ id, coll, slug: n.slug, title: title ?? n.title ?? n.name });
|
|
1378
|
-
const { links } = await renderArticle(body, { coll, slug: n.slug });
|
|
1379
|
-
for (const target of links) outEdges.push({ source: id, target });
|
|
1380
|
-
}
|
|
1381
|
-
if (n.children) await collectCollection(coll, collDir, n.children, outNodes, outEdges);
|
|
1382
|
-
}
|
|
1383
|
-
}
|
|
1384
|
-
var cached;
|
|
1385
|
-
function invalidateLinkGraph() {
|
|
1386
|
-
cached = void 0;
|
|
1387
|
-
}
|
|
1388
|
-
async function buildLinkGraph() {
|
|
1389
|
-
if (cached) return cached;
|
|
1390
|
-
const nodes = [];
|
|
1391
|
-
const rawEdges = [];
|
|
1392
|
-
for (const e of await listCollections()) {
|
|
1393
|
-
try {
|
|
1394
|
-
const collEntry = await findCollection(e.name);
|
|
1395
|
-
const collDir = import_node_path7.default.resolve(collEntry?.path ?? e.path);
|
|
1396
|
-
await collectCollection(e.name, collDir, await listArticleTree(e.name), nodes, rawEdges);
|
|
1397
|
-
} catch {
|
|
1398
|
-
}
|
|
1399
|
-
}
|
|
1400
|
-
const nodeIds = new Set(nodes.map((n) => n.id));
|
|
1401
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1402
|
-
const edges = [];
|
|
1403
|
-
for (const edge of rawEdges) {
|
|
1404
|
-
if (edge.source === edge.target) continue;
|
|
1405
|
-
if (!nodeIds.has(edge.target)) continue;
|
|
1406
|
-
const key = `${edge.source} ${edge.target}`;
|
|
1407
|
-
if (seen.has(key)) continue;
|
|
1408
|
-
seen.add(key);
|
|
1409
|
-
edges.push(edge);
|
|
1410
|
-
}
|
|
1411
|
-
cached = { nodes, edges };
|
|
1412
|
-
return cached;
|
|
1413
|
-
}
|
|
1414
|
-
function localGraph(graph, focusId, include) {
|
|
1415
|
-
const scoped = include ? {
|
|
1416
|
-
nodes: graph.nodes.filter((n) => include.has(n.coll)),
|
|
1417
|
-
edges: graph.edges
|
|
1418
|
-
} : graph;
|
|
1419
|
-
const byId = new Map(scoped.nodes.map((n) => [n.id, n]));
|
|
1420
|
-
const focus = byId.get(focusId);
|
|
1421
|
-
if (!focus) return { focus: focusId, nodes: [], edges: [] };
|
|
1422
|
-
const keep = /* @__PURE__ */ new Set([focusId]);
|
|
1423
|
-
for (const e of scoped.edges) {
|
|
1424
|
-
if (e.source === focusId && byId.has(e.target)) keep.add(e.target);
|
|
1425
|
-
if (e.target === focusId && byId.has(e.source)) keep.add(e.source);
|
|
1426
|
-
}
|
|
1427
|
-
const nodes = scoped.nodes.filter((n) => keep.has(n.id));
|
|
1428
|
-
const edges = scoped.edges.filter((e) => keep.has(e.source) && keep.has(e.target));
|
|
1429
|
-
return { focus: focusId, nodes, edges };
|
|
1297
|
+
return { html: String(file), toc };
|
|
1430
1298
|
}
|
|
1431
1299
|
|
|
1432
1300
|
// src/site.ts
|
|
@@ -1480,11 +1348,10 @@ function findNode(nodes, slug) {
|
|
|
1480
1348
|
}
|
|
1481
1349
|
return void 0;
|
|
1482
1350
|
}
|
|
1483
|
-
async function resolvePage(coll, slug
|
|
1351
|
+
async function resolvePage(coll, slug) {
|
|
1484
1352
|
try {
|
|
1485
1353
|
const art = await readArticle(coll, slug);
|
|
1486
|
-
const { html, toc } = await renderArticle(art.body
|
|
1487
|
-
const graph = localGraph(await buildLinkGraph(), `${art.coll}/${art.slug}`, opts?.include);
|
|
1354
|
+
const { html, toc } = await renderArticle(art.body);
|
|
1488
1355
|
return {
|
|
1489
1356
|
kind: "doc",
|
|
1490
1357
|
coll: art.coll,
|
|
@@ -1493,8 +1360,7 @@ async function resolvePage(coll, slug, opts) {
|
|
|
1493
1360
|
tags: art.tags,
|
|
1494
1361
|
html,
|
|
1495
1362
|
toc,
|
|
1496
|
-
path: `/${art.coll}/${art.slug}
|
|
1497
|
-
graph
|
|
1363
|
+
path: `/${art.coll}/${art.slug}`
|
|
1498
1364
|
};
|
|
1499
1365
|
} catch (err) {
|
|
1500
1366
|
if (err instanceof CollectionNotFoundError) return null;
|
|
@@ -1552,8 +1418,8 @@ function resolveCollectionSelection(all, sel = {}) {
|
|
|
1552
1418
|
}
|
|
1553
1419
|
|
|
1554
1420
|
// src/query.ts
|
|
1555
|
-
var
|
|
1556
|
-
var
|
|
1421
|
+
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
1422
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
1557
1423
|
init_collections();
|
|
1558
1424
|
init_errors();
|
|
1559
1425
|
init_logger();
|
|
@@ -1622,13 +1488,13 @@ var log2 = getLogger("query");
|
|
|
1622
1488
|
async function collectMarkdownFiles(dir) {
|
|
1623
1489
|
let entries;
|
|
1624
1490
|
try {
|
|
1625
|
-
entries = await
|
|
1491
|
+
entries = await import_promises8.default.readdir(dir, { withFileTypes: true });
|
|
1626
1492
|
} catch {
|
|
1627
1493
|
return [];
|
|
1628
1494
|
}
|
|
1629
1495
|
const files = [];
|
|
1630
1496
|
for (const entry of entries) {
|
|
1631
|
-
const full =
|
|
1497
|
+
const full = import_node_path7.default.join(dir, entry.name);
|
|
1632
1498
|
if (entry.isDirectory()) {
|
|
1633
1499
|
files.push(...await collectMarkdownFiles(full));
|
|
1634
1500
|
} else if (entry.isFile() && /\.mdx?$/.test(entry.name)) {
|
|
@@ -1647,12 +1513,12 @@ async function nativeSearch(term, collections, collection) {
|
|
|
1647
1513
|
const docs = [];
|
|
1648
1514
|
for (const entry of targets) {
|
|
1649
1515
|
for (const full of await collectMarkdownFiles(entry.path)) {
|
|
1650
|
-
const fallbackTitle =
|
|
1516
|
+
const fallbackTitle = import_node_path7.default.basename(full).replace(/\.mdx?$/, "");
|
|
1651
1517
|
let title = fallbackTitle;
|
|
1652
1518
|
let tags = [];
|
|
1653
1519
|
let body = "";
|
|
1654
1520
|
try {
|
|
1655
|
-
const parsed = parseArticle(await
|
|
1521
|
+
const parsed = parseArticle(await import_promises8.default.readFile(full, "utf8"));
|
|
1656
1522
|
if (parsed.title) title = parsed.title;
|
|
1657
1523
|
tags = parsed.tags;
|
|
1658
1524
|
body = parsed.body;
|
|
@@ -1735,13 +1601,13 @@ async function query(term, opts) {
|
|
|
1735
1601
|
}
|
|
1736
1602
|
|
|
1737
1603
|
// src/search.ts
|
|
1738
|
-
var
|
|
1739
|
-
var
|
|
1604
|
+
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
1605
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
1740
1606
|
init_collections();
|
|
1741
|
-
async function
|
|
1607
|
+
async function readArticleParts(collDir, slug) {
|
|
1742
1608
|
for (const ext of [".mdx", ".md"]) {
|
|
1743
1609
|
try {
|
|
1744
|
-
const parsed = parseArticle(await
|
|
1610
|
+
const parsed = parseArticle(await import_promises9.default.readFile(import_node_path8.default.join(collDir, `${slug}${ext}`), "utf8"));
|
|
1745
1611
|
return { tags: parsed.tags, body: parsed.body };
|
|
1746
1612
|
} catch {
|
|
1747
1613
|
}
|
|
@@ -1752,7 +1618,7 @@ async function flatten(coll, collDir, nodes, out) {
|
|
|
1752
1618
|
for (const n of nodes) {
|
|
1753
1619
|
if (n.slug && !n.children) {
|
|
1754
1620
|
const title = n.title ?? n.name;
|
|
1755
|
-
const { tags, body } = await
|
|
1621
|
+
const { tags, body } = await readArticleParts(collDir, n.slug);
|
|
1756
1622
|
out.push({
|
|
1757
1623
|
collection: coll,
|
|
1758
1624
|
slug: n.slug,
|
|
@@ -1775,7 +1641,7 @@ async function buildSearchIndex(collection) {
|
|
|
1775
1641
|
for (const e of entries) {
|
|
1776
1642
|
try {
|
|
1777
1643
|
const collEntry = await findCollection(e.name);
|
|
1778
|
-
const collDir =
|
|
1644
|
+
const collDir = import_node_path8.default.resolve(collEntry?.path ?? e.path);
|
|
1779
1645
|
await flatten(e.name, collDir, await listArticleTree(e.name), out);
|
|
1780
1646
|
} catch {
|
|
1781
1647
|
}
|
|
@@ -1784,15 +1650,15 @@ async function buildSearchIndex(collection) {
|
|
|
1784
1650
|
}
|
|
1785
1651
|
|
|
1786
1652
|
// src/doctor.ts
|
|
1787
|
-
var
|
|
1653
|
+
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
1788
1654
|
init_paths();
|
|
1789
1655
|
init_registry();
|
|
1790
1656
|
init_collections();
|
|
1791
1657
|
|
|
1792
1658
|
// src/plugins/manager.ts
|
|
1793
|
-
var
|
|
1659
|
+
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
1794
1660
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
1795
|
-
var
|
|
1661
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
1796
1662
|
init_paths();
|
|
1797
1663
|
init_errors();
|
|
1798
1664
|
init_collections();
|
|
@@ -1803,7 +1669,7 @@ init_host();
|
|
|
1803
1669
|
var import_node_child_process4 = require("child_process");
|
|
1804
1670
|
var import_node_util3 = require("util");
|
|
1805
1671
|
var import_node_fs = require("fs");
|
|
1806
|
-
var
|
|
1672
|
+
var import_node_path9 = require("path");
|
|
1807
1673
|
var import_node_url = require("url");
|
|
1808
1674
|
var execFileAsync3 = (0, import_node_util3.promisify)(import_node_child_process4.execFile);
|
|
1809
1675
|
async function runProcess(file, args, opts) {
|
|
@@ -1819,7 +1685,7 @@ async function runProcess(file, args, opts) {
|
|
|
1819
1685
|
// src/plugins/manager.ts
|
|
1820
1686
|
async function readPackageJson(file) {
|
|
1821
1687
|
try {
|
|
1822
|
-
return JSON.parse(await
|
|
1688
|
+
return JSON.parse(await import_promises10.default.readFile(file, "utf8"));
|
|
1823
1689
|
} catch {
|
|
1824
1690
|
return null;
|
|
1825
1691
|
}
|
|
@@ -1835,7 +1701,7 @@ function binOf(manifest) {
|
|
|
1835
1701
|
async function pluginManifestDirs(nodeModules) {
|
|
1836
1702
|
let entries;
|
|
1837
1703
|
try {
|
|
1838
|
-
entries = await
|
|
1704
|
+
entries = await import_promises10.default.readdir(nodeModules);
|
|
1839
1705
|
} catch {
|
|
1840
1706
|
return [];
|
|
1841
1707
|
}
|
|
@@ -1845,44 +1711,44 @@ async function pluginManifestDirs(nodeModules) {
|
|
|
1845
1711
|
if (entry.startsWith("@")) {
|
|
1846
1712
|
let scoped;
|
|
1847
1713
|
try {
|
|
1848
|
-
scoped = await
|
|
1714
|
+
scoped = await import_promises10.default.readdir(import_node_path10.default.join(nodeModules, entry));
|
|
1849
1715
|
} catch {
|
|
1850
1716
|
continue;
|
|
1851
1717
|
}
|
|
1852
1718
|
for (const pkg of scoped) {
|
|
1853
1719
|
if (pkg.startsWith(".")) continue;
|
|
1854
|
-
dirs.push(
|
|
1720
|
+
dirs.push(import_node_path10.default.join(nodeModules, entry, pkg));
|
|
1855
1721
|
}
|
|
1856
1722
|
} else {
|
|
1857
|
-
dirs.push(
|
|
1723
|
+
dirs.push(import_node_path10.default.join(nodeModules, entry));
|
|
1858
1724
|
}
|
|
1859
1725
|
}
|
|
1860
1726
|
return dirs;
|
|
1861
1727
|
}
|
|
1862
1728
|
async function ensurePluginRoot() {
|
|
1863
1729
|
const dir = pluginsDir();
|
|
1864
|
-
await
|
|
1865
|
-
const pkgPath =
|
|
1730
|
+
await import_promises10.default.mkdir(dir, { recursive: true });
|
|
1731
|
+
const pkgPath = import_node_path10.default.join(dir, "package.json");
|
|
1866
1732
|
if (await readPackageJson(pkgPath) === null) {
|
|
1867
1733
|
const pkg = { name: "diffwiki-plugins", private: true, version: "0.0.0" };
|
|
1868
|
-
await
|
|
1734
|
+
await import_promises10.default.writeFile(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
1869
1735
|
`, "utf8");
|
|
1870
1736
|
}
|
|
1871
1737
|
return dir;
|
|
1872
1738
|
}
|
|
1873
1739
|
async function asSearchPackage(pkgDir) {
|
|
1874
|
-
const manifest = await readPackageJson(
|
|
1740
|
+
const manifest = await readPackageJson(import_node_path10.default.join(pkgDir, "package.json"));
|
|
1875
1741
|
if (!manifest?.name || manifest.diffwiki?.kind !== "search") return null;
|
|
1876
1742
|
const bin = binOf(manifest);
|
|
1877
1743
|
if (!bin) return null;
|
|
1878
|
-
return { name: manifest.name, version: manifest.version, binAbs:
|
|
1744
|
+
return { name: manifest.name, version: manifest.version, binAbs: import_node_path10.default.resolve(pkgDir, bin) };
|
|
1879
1745
|
}
|
|
1880
1746
|
async function packageNameFromSpec(spec) {
|
|
1881
1747
|
const looksLikePath = spec.startsWith(".") || spec.startsWith("/") || spec.startsWith("~") || spec.startsWith("file:");
|
|
1882
1748
|
if (looksLikePath) {
|
|
1883
1749
|
const raw = spec.startsWith("file:") ? spec.slice("file:".length) : spec;
|
|
1884
|
-
const abs =
|
|
1885
|
-
return (await readPackageJson(
|
|
1750
|
+
const abs = import_node_path10.default.resolve(raw.replace(/^~(?=$|\/)/, import_node_os2.default.homedir()));
|
|
1751
|
+
return (await readPackageJson(import_node_path10.default.join(abs, "package.json")))?.name ?? null;
|
|
1886
1752
|
}
|
|
1887
1753
|
if (/^(git\+|git:|https?:|ssh:)/.test(spec)) return null;
|
|
1888
1754
|
if (spec.startsWith("@")) {
|
|
@@ -1893,10 +1759,10 @@ async function packageNameFromSpec(spec) {
|
|
|
1893
1759
|
return at <= 0 ? spec : spec.slice(0, at);
|
|
1894
1760
|
}
|
|
1895
1761
|
async function resolveSearchPackage(dir, name) {
|
|
1896
|
-
return asSearchPackage(
|
|
1762
|
+
return asSearchPackage(import_node_path10.default.join(dir, "node_modules", ...name.split("/")));
|
|
1897
1763
|
}
|
|
1898
1764
|
async function discoverSearchPackage(dir) {
|
|
1899
|
-
const nodeModules =
|
|
1765
|
+
const nodeModules = import_node_path10.default.join(dir, "node_modules");
|
|
1900
1766
|
for (const pkgDir of await pluginManifestDirs(nodeModules)) {
|
|
1901
1767
|
const found = await asSearchPackage(pkgDir);
|
|
1902
1768
|
if (found) return found;
|
|
@@ -2028,7 +1894,7 @@ init_host();
|
|
|
2028
1894
|
init_types();
|
|
2029
1895
|
async function exists(target) {
|
|
2030
1896
|
try {
|
|
2031
|
-
await
|
|
1897
|
+
await import_promises11.default.access(target);
|
|
2032
1898
|
return true;
|
|
2033
1899
|
} catch {
|
|
2034
1900
|
return false;
|
|
@@ -2181,7 +2047,6 @@ init_registry2();
|
|
|
2181
2047
|
addTags,
|
|
2182
2048
|
buildArticleTree,
|
|
2183
2049
|
buildCollections,
|
|
2184
|
-
buildLinkGraph,
|
|
2185
2050
|
buildNavTree,
|
|
2186
2051
|
buildSearchIndex,
|
|
2187
2052
|
collectionDir,
|
|
@@ -2205,7 +2070,6 @@ init_registry2();
|
|
|
2205
2070
|
gitToplevel,
|
|
2206
2071
|
initRepoWiki,
|
|
2207
2072
|
installPlugin,
|
|
2208
|
-
invalidateLinkGraph,
|
|
2209
2073
|
isLinkedWorktree,
|
|
2210
2074
|
listArticleTree,
|
|
2211
2075
|
listAvailablePlugins,
|
|
@@ -2214,7 +2078,6 @@ init_registry2();
|
|
|
2214
2078
|
listPlugins,
|
|
2215
2079
|
listSearchModes,
|
|
2216
2080
|
loadSearchProvider,
|
|
2217
|
-
localGraph,
|
|
2218
2081
|
nativeSearch,
|
|
2219
2082
|
parseAddTarget,
|
|
2220
2083
|
parseArticle,
|
package/dist/index.d.cts
CHANGED
|
@@ -181,8 +181,6 @@ interface DocData {
|
|
|
181
181
|
html: string;
|
|
182
182
|
toc: TocItem[];
|
|
183
183
|
path: string;
|
|
184
|
-
/** Local knowledge-graph neighbourhood for this page (this node + its direct links). */
|
|
185
|
-
graph: LocalGraph;
|
|
186
184
|
}
|
|
187
185
|
interface ListingEntry {
|
|
188
186
|
name: string;
|
|
@@ -199,33 +197,6 @@ type PageData = ({
|
|
|
199
197
|
title: string;
|
|
200
198
|
entries: ListingEntry[];
|
|
201
199
|
};
|
|
202
|
-
/** One article node in the knowledge graph. `id` is `"<coll>/<slug>"`. */
|
|
203
|
-
interface GraphNode {
|
|
204
|
-
id: string;
|
|
205
|
-
coll: string;
|
|
206
|
-
slug: string;
|
|
207
|
-
title: string;
|
|
208
|
-
}
|
|
209
|
-
/** A directed edge: article `source` links to article `target` (both node ids). */
|
|
210
|
-
interface GraphEdge {
|
|
211
|
-
source: string;
|
|
212
|
-
target: string;
|
|
213
|
-
}
|
|
214
|
-
/** The whole-wiki knowledge graph. */
|
|
215
|
-
interface LinkGraph {
|
|
216
|
-
nodes: GraphNode[];
|
|
217
|
-
edges: GraphEdge[];
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* The local neighbourhood of one node: the node itself plus its directly linked
|
|
221
|
-
* (outgoing) and linking (incoming) neighbours, and the edges among them. `focus`
|
|
222
|
-
* is the id of the page this neighbourhood is centred on.
|
|
223
|
-
*/
|
|
224
|
-
interface LocalGraph {
|
|
225
|
-
focus: string;
|
|
226
|
-
nodes: GraphNode[];
|
|
227
|
-
edges: GraphEdge[];
|
|
228
|
-
}
|
|
229
200
|
|
|
230
201
|
/** Base class for all expected, user-facing diffwiki failures. */
|
|
231
202
|
declare class DiffwikiError extends Error {
|
|
@@ -403,18 +374,8 @@ declare function ensureGitRepo(cwd: string): Promise<string>;
|
|
|
403
374
|
declare function toTreeNodes(coll: string, nodes: ArticleNode[]): TreeNode[];
|
|
404
375
|
declare function buildCollections(): Promise<CollectionInfo[]>;
|
|
405
376
|
declare function buildNavTree(): Promise<CollectionTree[]>;
|
|
406
|
-
/**
|
|
407
|
-
|
|
408
|
-
*
|
|
409
|
-
* `opts.include` restricts the doc's sidebar `graph` preview to the given set of
|
|
410
|
-
* collection names — supplied by the static exporter for subset exports so the
|
|
411
|
-
* per-page local graph matches the filtered overlay `graph.json` and never links
|
|
412
|
-
* to a page that was excluded from the build. Omitting it (the dynamic server
|
|
413
|
-
* path, which serves every collection) keeps the whole-wiki neighbourhood.
|
|
414
|
-
*/
|
|
415
|
-
declare function resolvePage(coll: string, slug: string, opts?: {
|
|
416
|
-
include?: ReadonlySet<string>;
|
|
417
|
-
}): Promise<PageData | null>;
|
|
377
|
+
/** Resolve a route to a rendered doc or a generated directory listing (or null). */
|
|
378
|
+
declare function resolvePage(coll: string, slug: string): Promise<PageData | null>;
|
|
418
379
|
|
|
419
380
|
/**
|
|
420
381
|
* Collection selection for `diffwiki export` — resolve which collection names to
|
|
@@ -616,75 +577,21 @@ declare function listArticleTree(coll: string): Promise<ArticleNode[]>;
|
|
|
616
577
|
*/
|
|
617
578
|
declare function readArticle(coll: string, slug: string): Promise<ArticleContent>;
|
|
618
579
|
|
|
619
|
-
/** Context used to resolve relative markdown links to absolute `coll/slug` node ids. */
|
|
620
|
-
interface RenderContext {
|
|
621
|
-
/** Collection name of the article being rendered. */
|
|
622
|
-
coll: string;
|
|
623
|
-
/** Slug (relative path without extension) of the article being rendered. */
|
|
624
|
-
slug: string;
|
|
625
|
-
/**
|
|
626
|
-
* Deployment base path (e.g. `/my-repo/`) for absolute route links. When set,
|
|
627
|
-
* a matching leading prefix is stripped from `/base/coll/slug` route links so
|
|
628
|
-
* the collection segment is resolved unambiguously — without it a non-trivial
|
|
629
|
-
* base makes `/my-repo/other-coll/page` mis-parse as node id `my-repo/other-coll/page`.
|
|
630
|
-
* Defaults to `DIFFWIKI_BASE` (the same env the exporter sets) when omitted.
|
|
631
|
-
*/
|
|
632
|
-
base?: string;
|
|
633
|
-
}
|
|
634
580
|
/** The result of rendering an article body to HTML. */
|
|
635
581
|
interface RenderedArticle {
|
|
636
582
|
/** Fully-rendered, Shiki-highlighted HTML — mounted directly on the client (no eval). */
|
|
637
583
|
html: string;
|
|
638
584
|
/** h2/h3 headings collected during render, in document order. */
|
|
639
585
|
toc: TocItem[];
|
|
640
|
-
/**
|
|
641
|
-
* Internal outgoing links as `coll/slug` node ids, de-duplicated, in document
|
|
642
|
-
* order. Only populated when a {@link RenderContext} is supplied; external
|
|
643
|
-
* links, in-page anchors, and unresolvable targets are dropped.
|
|
644
|
-
*/
|
|
645
|
-
links: string[];
|
|
646
586
|
}
|
|
647
587
|
/**
|
|
648
588
|
* Render an article body (markdown) to Shiki-highlighted HTML plus its table of
|
|
649
|
-
* contents
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
*
|
|
653
|
-
* {@link RenderContext} is supplied, internal links are collected for the
|
|
654
|
-
* knowledge graph; without it, `links` is empty.
|
|
655
|
-
*/
|
|
656
|
-
declare function renderArticle(body: string, ctx?: RenderContext): Promise<RenderedArticle>;
|
|
657
|
-
|
|
658
|
-
/** Clear the memoised whole-wiki graph (tests; future live-reload invalidation). */
|
|
659
|
-
declare function invalidateLinkGraph(): void;
|
|
660
|
-
/**
|
|
661
|
-
* Build the whole-wiki knowledge graph: one {@link GraphNode} per article and one
|
|
662
|
-
* directed {@link GraphEdge} per resolved internal link. Edges whose target is not
|
|
663
|
-
* a real node (dead links, external, unresolvable) are dropped, and duplicate
|
|
664
|
-
* edges are collapsed. Memoised per process — call {@link invalidateLinkGraph} to
|
|
665
|
-
* rebuild after content changes.
|
|
666
|
-
*
|
|
667
|
-
* TODO(live-reload): the memo is keyed only on the process, not on content or
|
|
668
|
-
* `DIFFWIKI_HOME`. The dynamic server fn (apps/wiki/src/server/graph.ts) never
|
|
669
|
-
* calls invalidateLinkGraph(), so a long-lived dev server freezes the graph at
|
|
670
|
-
* first build until restart. Wire this to a content watcher for live reload.
|
|
671
|
-
*/
|
|
672
|
-
declare function buildLinkGraph(): Promise<LinkGraph>;
|
|
673
|
-
/**
|
|
674
|
-
* Slice the local neighbourhood of `focusId` out of a whole-wiki graph: the focus
|
|
675
|
-
* node, every node it links to (outgoing) or that links to it (incoming), and all
|
|
676
|
-
* edges among the selected node set. If the focus id is not a node in `graph`
|
|
677
|
-
* (e.g. a folder listing, or a page with no entry), returns an empty-but-focused
|
|
678
|
-
* graph so the UI can render a single-node placeholder.
|
|
679
|
-
*
|
|
680
|
-
* When `include` is supplied, the graph is first pruned to only nodes whose
|
|
681
|
-
* collection is in the set (and edges with both endpoints surviving) BEFORE
|
|
682
|
-
* slicing — this keeps a subset static export's per-page sidebar preview in step
|
|
683
|
-
* with the filtered overlay `graph.json`, so a neighbour link never points at a
|
|
684
|
-
* page that was excluded from the export (which would 404 on click). Passing no
|
|
685
|
-
* set (the default, and the dynamic server path) keeps the whole-wiki graph.
|
|
589
|
+
* contents. Runs entirely server-side; the client mounts the HTML directly with
|
|
590
|
+
* no `eval`/`new Function`, so it works under a strict CSP. Code is highlighted
|
|
591
|
+
* here (dual github-light/github-dark via CSS variables); mermaid fences are
|
|
592
|
+
* marked for client rendering.
|
|
686
593
|
*/
|
|
687
|
-
declare function
|
|
594
|
+
declare function renderArticle(body: string): Promise<RenderedArticle>;
|
|
688
595
|
|
|
689
596
|
/**
|
|
690
597
|
* Host-side plugin invocation and search-provider loading.
|
|
@@ -855,4 +762,4 @@ declare function findEnabledPlugin(kind: PluginKind, name?: string): Promise<Plu
|
|
|
855
762
|
/** Find a plugin record by name (regardless of enabled state). */
|
|
856
763
|
declare function findPluginRecord(name: string): Promise<PluginRecord | undefined>;
|
|
857
764
|
|
|
858
|
-
export { type AddExternalOptions, type Article, type ArticleContent, type ArticleNode, ArticleNotFoundError, CollectionAlreadyAddedError, type CollectionEntry, CollectionExistsError, type CollectionGitStatus, type CollectionInfo, CollectionNotFoundError, type CollectionSelection, type CollectionSelectionResult, type CollectionTree, type CollectionType, type Config, type Diagnostic, type DiagnosticLevel, DiffwikiError, type DiffwikiLogLevel, type DocData, type
|
|
765
|
+
export { type AddExternalOptions, type Article, type ArticleContent, type ArticleNode, ArticleNotFoundError, CollectionAlreadyAddedError, type CollectionEntry, CollectionExistsError, type CollectionGitStatus, type CollectionInfo, CollectionNotFoundError, type CollectionSelection, type CollectionSelectionResult, type CollectionTree, type CollectionType, type Config, type Diagnostic, type DiagnosticLevel, DiffwikiError, type DiffwikiLogLevel, type DocData, type InitOptions, type InstallOutcome, InvalidExportSelectionError, InvalidTargetError, type KnownPlugin, type ListingEntry, NATIVE_ENGINE, NoDefaultCollectionError, type NodeMeta, type PageData, type ParsedArticle, type PluginCapabilities, PluginError, type PluginEvent, type PluginHealth, type PluginKind, type PluginReadiness, type PluginRecord, type PluginRegistryFile, type QueryHit, type QueryOptions, REPO_CONFIG_FILE, type Registry, type RenderedArticle, type RepoConfig, SearchDoc, type SearchMode, type SearchOutcome, type SearchProvider, type SerializableArticle, type SetupOutcome, type SetupStep, type TocItem, type TreeNode, type UpstreamStatus, WorktreeNotAllowedError, addExternalCollection, addTags, buildArticleTree, buildCollections, buildNavTree, buildSearchIndex, collectionDir, collectionGitStatus, collectionsDir, configPath, createArticle, createCollection, currentBranch, deregisterPlugin, doctor, emitPluginEvent, ensureGitRepo, ensurePluginRoot, findCollection, findCollectionById, findEnabledPlugin, findPluginRecord, getConfigValue, getLogger, gitToplevel, initRepoWiki, installPlugin, isLinkedWorktree, listArticleTree, listAvailablePlugins, listCollections, listEnabledPlugins, listPlugins, listSearchModes, loadSearchProvider, nativeSearch, parseAddTarget, parseArticle, parsePathTarget, pluginsDir, pluginsRegistryPath, query, readArticle, readConfig, readPluginRegistry, readRegistry, readRepoConfig, registerCollection, registerPlugin, registryPath, removeArticle, removeCollection, removePlugin, removeTags, renderArticle, repoId, repoRemoteName, resolveCollectionSelection, resolveCwdCollection, resolveDefaultSearchMode, resolveHome, resolveLogLevel, resolvePage, search, serializeArticle, setConfigValue, setTags, slugify, toTreeNodes, unregisterCollection, updateArticleBody, upsertPlugin, upstreamStatus, writeConfig, writePluginRegistry, writeRegistry };
|
package/dist/index.d.ts
CHANGED
|
@@ -181,8 +181,6 @@ interface DocData {
|
|
|
181
181
|
html: string;
|
|
182
182
|
toc: TocItem[];
|
|
183
183
|
path: string;
|
|
184
|
-
/** Local knowledge-graph neighbourhood for this page (this node + its direct links). */
|
|
185
|
-
graph: LocalGraph;
|
|
186
184
|
}
|
|
187
185
|
interface ListingEntry {
|
|
188
186
|
name: string;
|
|
@@ -199,33 +197,6 @@ type PageData = ({
|
|
|
199
197
|
title: string;
|
|
200
198
|
entries: ListingEntry[];
|
|
201
199
|
};
|
|
202
|
-
/** One article node in the knowledge graph. `id` is `"<coll>/<slug>"`. */
|
|
203
|
-
interface GraphNode {
|
|
204
|
-
id: string;
|
|
205
|
-
coll: string;
|
|
206
|
-
slug: string;
|
|
207
|
-
title: string;
|
|
208
|
-
}
|
|
209
|
-
/** A directed edge: article `source` links to article `target` (both node ids). */
|
|
210
|
-
interface GraphEdge {
|
|
211
|
-
source: string;
|
|
212
|
-
target: string;
|
|
213
|
-
}
|
|
214
|
-
/** The whole-wiki knowledge graph. */
|
|
215
|
-
interface LinkGraph {
|
|
216
|
-
nodes: GraphNode[];
|
|
217
|
-
edges: GraphEdge[];
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* The local neighbourhood of one node: the node itself plus its directly linked
|
|
221
|
-
* (outgoing) and linking (incoming) neighbours, and the edges among them. `focus`
|
|
222
|
-
* is the id of the page this neighbourhood is centred on.
|
|
223
|
-
*/
|
|
224
|
-
interface LocalGraph {
|
|
225
|
-
focus: string;
|
|
226
|
-
nodes: GraphNode[];
|
|
227
|
-
edges: GraphEdge[];
|
|
228
|
-
}
|
|
229
200
|
|
|
230
201
|
/** Base class for all expected, user-facing diffwiki failures. */
|
|
231
202
|
declare class DiffwikiError extends Error {
|
|
@@ -403,18 +374,8 @@ declare function ensureGitRepo(cwd: string): Promise<string>;
|
|
|
403
374
|
declare function toTreeNodes(coll: string, nodes: ArticleNode[]): TreeNode[];
|
|
404
375
|
declare function buildCollections(): Promise<CollectionInfo[]>;
|
|
405
376
|
declare function buildNavTree(): Promise<CollectionTree[]>;
|
|
406
|
-
/**
|
|
407
|
-
|
|
408
|
-
*
|
|
409
|
-
* `opts.include` restricts the doc's sidebar `graph` preview to the given set of
|
|
410
|
-
* collection names — supplied by the static exporter for subset exports so the
|
|
411
|
-
* per-page local graph matches the filtered overlay `graph.json` and never links
|
|
412
|
-
* to a page that was excluded from the build. Omitting it (the dynamic server
|
|
413
|
-
* path, which serves every collection) keeps the whole-wiki neighbourhood.
|
|
414
|
-
*/
|
|
415
|
-
declare function resolvePage(coll: string, slug: string, opts?: {
|
|
416
|
-
include?: ReadonlySet<string>;
|
|
417
|
-
}): Promise<PageData | null>;
|
|
377
|
+
/** Resolve a route to a rendered doc or a generated directory listing (or null). */
|
|
378
|
+
declare function resolvePage(coll: string, slug: string): Promise<PageData | null>;
|
|
418
379
|
|
|
419
380
|
/**
|
|
420
381
|
* Collection selection for `diffwiki export` — resolve which collection names to
|
|
@@ -616,75 +577,21 @@ declare function listArticleTree(coll: string): Promise<ArticleNode[]>;
|
|
|
616
577
|
*/
|
|
617
578
|
declare function readArticle(coll: string, slug: string): Promise<ArticleContent>;
|
|
618
579
|
|
|
619
|
-
/** Context used to resolve relative markdown links to absolute `coll/slug` node ids. */
|
|
620
|
-
interface RenderContext {
|
|
621
|
-
/** Collection name of the article being rendered. */
|
|
622
|
-
coll: string;
|
|
623
|
-
/** Slug (relative path without extension) of the article being rendered. */
|
|
624
|
-
slug: string;
|
|
625
|
-
/**
|
|
626
|
-
* Deployment base path (e.g. `/my-repo/`) for absolute route links. When set,
|
|
627
|
-
* a matching leading prefix is stripped from `/base/coll/slug` route links so
|
|
628
|
-
* the collection segment is resolved unambiguously — without it a non-trivial
|
|
629
|
-
* base makes `/my-repo/other-coll/page` mis-parse as node id `my-repo/other-coll/page`.
|
|
630
|
-
* Defaults to `DIFFWIKI_BASE` (the same env the exporter sets) when omitted.
|
|
631
|
-
*/
|
|
632
|
-
base?: string;
|
|
633
|
-
}
|
|
634
580
|
/** The result of rendering an article body to HTML. */
|
|
635
581
|
interface RenderedArticle {
|
|
636
582
|
/** Fully-rendered, Shiki-highlighted HTML — mounted directly on the client (no eval). */
|
|
637
583
|
html: string;
|
|
638
584
|
/** h2/h3 headings collected during render, in document order. */
|
|
639
585
|
toc: TocItem[];
|
|
640
|
-
/**
|
|
641
|
-
* Internal outgoing links as `coll/slug` node ids, de-duplicated, in document
|
|
642
|
-
* order. Only populated when a {@link RenderContext} is supplied; external
|
|
643
|
-
* links, in-page anchors, and unresolvable targets are dropped.
|
|
644
|
-
*/
|
|
645
|
-
links: string[];
|
|
646
586
|
}
|
|
647
587
|
/**
|
|
648
588
|
* Render an article body (markdown) to Shiki-highlighted HTML plus its table of
|
|
649
|
-
* contents
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
*
|
|
653
|
-
* {@link RenderContext} is supplied, internal links are collected for the
|
|
654
|
-
* knowledge graph; without it, `links` is empty.
|
|
655
|
-
*/
|
|
656
|
-
declare function renderArticle(body: string, ctx?: RenderContext): Promise<RenderedArticle>;
|
|
657
|
-
|
|
658
|
-
/** Clear the memoised whole-wiki graph (tests; future live-reload invalidation). */
|
|
659
|
-
declare function invalidateLinkGraph(): void;
|
|
660
|
-
/**
|
|
661
|
-
* Build the whole-wiki knowledge graph: one {@link GraphNode} per article and one
|
|
662
|
-
* directed {@link GraphEdge} per resolved internal link. Edges whose target is not
|
|
663
|
-
* a real node (dead links, external, unresolvable) are dropped, and duplicate
|
|
664
|
-
* edges are collapsed. Memoised per process — call {@link invalidateLinkGraph} to
|
|
665
|
-
* rebuild after content changes.
|
|
666
|
-
*
|
|
667
|
-
* TODO(live-reload): the memo is keyed only on the process, not on content or
|
|
668
|
-
* `DIFFWIKI_HOME`. The dynamic server fn (apps/wiki/src/server/graph.ts) never
|
|
669
|
-
* calls invalidateLinkGraph(), so a long-lived dev server freezes the graph at
|
|
670
|
-
* first build until restart. Wire this to a content watcher for live reload.
|
|
671
|
-
*/
|
|
672
|
-
declare function buildLinkGraph(): Promise<LinkGraph>;
|
|
673
|
-
/**
|
|
674
|
-
* Slice the local neighbourhood of `focusId` out of a whole-wiki graph: the focus
|
|
675
|
-
* node, every node it links to (outgoing) or that links to it (incoming), and all
|
|
676
|
-
* edges among the selected node set. If the focus id is not a node in `graph`
|
|
677
|
-
* (e.g. a folder listing, or a page with no entry), returns an empty-but-focused
|
|
678
|
-
* graph so the UI can render a single-node placeholder.
|
|
679
|
-
*
|
|
680
|
-
* When `include` is supplied, the graph is first pruned to only nodes whose
|
|
681
|
-
* collection is in the set (and edges with both endpoints surviving) BEFORE
|
|
682
|
-
* slicing — this keeps a subset static export's per-page sidebar preview in step
|
|
683
|
-
* with the filtered overlay `graph.json`, so a neighbour link never points at a
|
|
684
|
-
* page that was excluded from the export (which would 404 on click). Passing no
|
|
685
|
-
* set (the default, and the dynamic server path) keeps the whole-wiki graph.
|
|
589
|
+
* contents. Runs entirely server-side; the client mounts the HTML directly with
|
|
590
|
+
* no `eval`/`new Function`, so it works under a strict CSP. Code is highlighted
|
|
591
|
+
* here (dual github-light/github-dark via CSS variables); mermaid fences are
|
|
592
|
+
* marked for client rendering.
|
|
686
593
|
*/
|
|
687
|
-
declare function
|
|
594
|
+
declare function renderArticle(body: string): Promise<RenderedArticle>;
|
|
688
595
|
|
|
689
596
|
/**
|
|
690
597
|
* Host-side plugin invocation and search-provider loading.
|
|
@@ -855,4 +762,4 @@ declare function findEnabledPlugin(kind: PluginKind, name?: string): Promise<Plu
|
|
|
855
762
|
/** Find a plugin record by name (regardless of enabled state). */
|
|
856
763
|
declare function findPluginRecord(name: string): Promise<PluginRecord | undefined>;
|
|
857
764
|
|
|
858
|
-
export { type AddExternalOptions, type Article, type ArticleContent, type ArticleNode, ArticleNotFoundError, CollectionAlreadyAddedError, type CollectionEntry, CollectionExistsError, type CollectionGitStatus, type CollectionInfo, CollectionNotFoundError, type CollectionSelection, type CollectionSelectionResult, type CollectionTree, type CollectionType, type Config, type Diagnostic, type DiagnosticLevel, DiffwikiError, type DiffwikiLogLevel, type DocData, type
|
|
765
|
+
export { type AddExternalOptions, type Article, type ArticleContent, type ArticleNode, ArticleNotFoundError, CollectionAlreadyAddedError, type CollectionEntry, CollectionExistsError, type CollectionGitStatus, type CollectionInfo, CollectionNotFoundError, type CollectionSelection, type CollectionSelectionResult, type CollectionTree, type CollectionType, type Config, type Diagnostic, type DiagnosticLevel, DiffwikiError, type DiffwikiLogLevel, type DocData, type InitOptions, type InstallOutcome, InvalidExportSelectionError, InvalidTargetError, type KnownPlugin, type ListingEntry, NATIVE_ENGINE, NoDefaultCollectionError, type NodeMeta, type PageData, type ParsedArticle, type PluginCapabilities, PluginError, type PluginEvent, type PluginHealth, type PluginKind, type PluginReadiness, type PluginRecord, type PluginRegistryFile, type QueryHit, type QueryOptions, REPO_CONFIG_FILE, type Registry, type RenderedArticle, type RepoConfig, SearchDoc, type SearchMode, type SearchOutcome, type SearchProvider, type SerializableArticle, type SetupOutcome, type SetupStep, type TocItem, type TreeNode, type UpstreamStatus, WorktreeNotAllowedError, addExternalCollection, addTags, buildArticleTree, buildCollections, buildNavTree, buildSearchIndex, collectionDir, collectionGitStatus, collectionsDir, configPath, createArticle, createCollection, currentBranch, deregisterPlugin, doctor, emitPluginEvent, ensureGitRepo, ensurePluginRoot, findCollection, findCollectionById, findEnabledPlugin, findPluginRecord, getConfigValue, getLogger, gitToplevel, initRepoWiki, installPlugin, isLinkedWorktree, listArticleTree, listAvailablePlugins, listCollections, listEnabledPlugins, listPlugins, listSearchModes, loadSearchProvider, nativeSearch, parseAddTarget, parseArticle, parsePathTarget, pluginsDir, pluginsRegistryPath, query, readArticle, readConfig, readPluginRegistry, readRegistry, readRepoConfig, registerCollection, registerPlugin, registryPath, removeArticle, removeCollection, removePlugin, removeTags, renderArticle, repoId, repoRemoteName, resolveCollectionSelection, resolveCwdCollection, resolveDefaultSearchMode, resolveHome, resolveLogLevel, resolvePage, search, serializeArticle, setConfigValue, setTags, slugify, toTreeNodes, unregisterCollection, updateArticleBody, upsertPlugin, upstreamStatus, writeConfig, writePluginRegistry, writeRegistry };
|
package/dist/index.js
CHANGED
|
@@ -631,58 +631,6 @@ function rehypeCollectToc(toc) {
|
|
|
631
631
|
});
|
|
632
632
|
};
|
|
633
633
|
}
|
|
634
|
-
function isExternalHref(href) {
|
|
635
|
-
if (!href) return true;
|
|
636
|
-
if (href.startsWith("#")) return true;
|
|
637
|
-
if (href.startsWith("//")) return true;
|
|
638
|
-
return /^[a-z][a-z0-9+.-]*:/i.test(href);
|
|
639
|
-
}
|
|
640
|
-
function resolveHref(href, ctx) {
|
|
641
|
-
if (isExternalHref(href)) return null;
|
|
642
|
-
const clean = (p) => p.replace(/[?#].*$/, "").replace(/\.(mdx?|html)$/i, "").replace(/\/+$/, "");
|
|
643
|
-
const target = clean(href);
|
|
644
|
-
if (!target) return null;
|
|
645
|
-
if (target.startsWith("/")) {
|
|
646
|
-
const base = ctx.base ?? process.env.DIFFWIKI_BASE ?? "";
|
|
647
|
-
const baseSegs2 = base.split("/").filter(Boolean);
|
|
648
|
-
let segs = target.split("/").filter(Boolean);
|
|
649
|
-
if (baseSegs2.length > 0 && baseSegs2.every((b, i) => segs[i] === b)) {
|
|
650
|
-
segs = segs.slice(baseSegs2.length);
|
|
651
|
-
}
|
|
652
|
-
if (segs.length < 2) return null;
|
|
653
|
-
const collIdx = segs.indexOf(ctx.coll);
|
|
654
|
-
if (base === "" && collIdx > 0) return segs.slice(collIdx).join("/");
|
|
655
|
-
return segs.join("/");
|
|
656
|
-
}
|
|
657
|
-
const dir = ctx.slug.includes("/") ? ctx.slug.slice(0, ctx.slug.lastIndexOf("/")) : "";
|
|
658
|
-
const baseSegs = dir ? dir.split("/") : [];
|
|
659
|
-
const out = [...baseSegs];
|
|
660
|
-
for (const seg of target.split("/")) {
|
|
661
|
-
if (seg === "" || seg === ".") continue;
|
|
662
|
-
if (seg === "..") {
|
|
663
|
-
if (out.length === 0) return null;
|
|
664
|
-
out.pop();
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
out.push(seg);
|
|
668
|
-
}
|
|
669
|
-
if (out.length === 0) return null;
|
|
670
|
-
return `${ctx.coll}/${out.join("/")}`;
|
|
671
|
-
}
|
|
672
|
-
function rehypeCollectLinks(links, ctx) {
|
|
673
|
-
const seen = /* @__PURE__ */ new Set();
|
|
674
|
-
return (tree) => {
|
|
675
|
-
visit(tree, "element", (node) => {
|
|
676
|
-
if (node.tagName !== "a") return;
|
|
677
|
-
const href = node.properties?.href;
|
|
678
|
-
if (typeof href !== "string") return;
|
|
679
|
-
const id = resolveHref(href, ctx);
|
|
680
|
-
if (!id || seen.has(id)) return;
|
|
681
|
-
seen.add(id);
|
|
682
|
-
links.push(id);
|
|
683
|
-
});
|
|
684
|
-
};
|
|
685
|
-
}
|
|
686
634
|
function rehypeStripLeadingH1() {
|
|
687
635
|
return (tree) => {
|
|
688
636
|
let removed = false;
|
|
@@ -708,91 +656,15 @@ function rehypeMarkMermaid() {
|
|
|
708
656
|
});
|
|
709
657
|
};
|
|
710
658
|
}
|
|
711
|
-
async function renderArticle(body
|
|
659
|
+
async function renderArticle(body) {
|
|
712
660
|
const toc = [];
|
|
713
|
-
const
|
|
714
|
-
const pipeline = unified().use(remarkParse).use(remarkGfm).use(remarkRehype).use(rehypeSlug).use(rehypeCollectToc, toc);
|
|
715
|
-
if (ctx) pipeline.use(rehypeCollectLinks, links, ctx);
|
|
716
|
-
const file = await pipeline.use(rehypeStripLeadingH1).use(rehypeMarkMermaid).use(rehypeShiki, {
|
|
661
|
+
const file = await unified().use(remarkParse).use(remarkGfm).use(remarkRehype).use(rehypeSlug).use(rehypeCollectToc, toc).use(rehypeStripLeadingH1).use(rehypeMarkMermaid).use(rehypeShiki, {
|
|
717
662
|
themes: { light: "github-light", dark: "github-dark" },
|
|
718
663
|
defaultColor: false,
|
|
719
664
|
langAlias: LANG_ALIASES,
|
|
720
665
|
fallbackLanguage: "plaintext"
|
|
721
666
|
}).use(rehypeStringify).process(body);
|
|
722
|
-
return { html: String(file), toc
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
// src/graph.ts
|
|
726
|
-
import fs5 from "fs/promises";
|
|
727
|
-
import path5 from "path";
|
|
728
|
-
async function readArticleParts(collDir, slug) {
|
|
729
|
-
for (const ext of [".mdx", ".md"]) {
|
|
730
|
-
try {
|
|
731
|
-
const parsed = parseArticle(await fs5.readFile(path5.join(collDir, `${slug}${ext}`), "utf8"));
|
|
732
|
-
return { title: parsed.title, body: parsed.body };
|
|
733
|
-
} catch {
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
return { body: "" };
|
|
737
|
-
}
|
|
738
|
-
async function collectCollection(coll, collDir, nodes, outNodes, outEdges) {
|
|
739
|
-
for (const n of nodes) {
|
|
740
|
-
if (n.slug && !n.children) {
|
|
741
|
-
const id = `${coll}/${n.slug}`;
|
|
742
|
-
const { title, body } = await readArticleParts(collDir, n.slug);
|
|
743
|
-
outNodes.push({ id, coll, slug: n.slug, title: title ?? n.title ?? n.name });
|
|
744
|
-
const { links } = await renderArticle(body, { coll, slug: n.slug });
|
|
745
|
-
for (const target of links) outEdges.push({ source: id, target });
|
|
746
|
-
}
|
|
747
|
-
if (n.children) await collectCollection(coll, collDir, n.children, outNodes, outEdges);
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
var cached;
|
|
751
|
-
function invalidateLinkGraph() {
|
|
752
|
-
cached = void 0;
|
|
753
|
-
}
|
|
754
|
-
async function buildLinkGraph() {
|
|
755
|
-
if (cached) return cached;
|
|
756
|
-
const nodes = [];
|
|
757
|
-
const rawEdges = [];
|
|
758
|
-
for (const e of await listCollections()) {
|
|
759
|
-
try {
|
|
760
|
-
const collEntry = await findCollection(e.name);
|
|
761
|
-
const collDir = path5.resolve(collEntry?.path ?? e.path);
|
|
762
|
-
await collectCollection(e.name, collDir, await listArticleTree(e.name), nodes, rawEdges);
|
|
763
|
-
} catch {
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
const nodeIds = new Set(nodes.map((n) => n.id));
|
|
767
|
-
const seen = /* @__PURE__ */ new Set();
|
|
768
|
-
const edges = [];
|
|
769
|
-
for (const edge of rawEdges) {
|
|
770
|
-
if (edge.source === edge.target) continue;
|
|
771
|
-
if (!nodeIds.has(edge.target)) continue;
|
|
772
|
-
const key = `${edge.source} ${edge.target}`;
|
|
773
|
-
if (seen.has(key)) continue;
|
|
774
|
-
seen.add(key);
|
|
775
|
-
edges.push(edge);
|
|
776
|
-
}
|
|
777
|
-
cached = { nodes, edges };
|
|
778
|
-
return cached;
|
|
779
|
-
}
|
|
780
|
-
function localGraph(graph, focusId, include) {
|
|
781
|
-
const scoped = include ? {
|
|
782
|
-
nodes: graph.nodes.filter((n) => include.has(n.coll)),
|
|
783
|
-
edges: graph.edges
|
|
784
|
-
} : graph;
|
|
785
|
-
const byId = new Map(scoped.nodes.map((n) => [n.id, n]));
|
|
786
|
-
const focus = byId.get(focusId);
|
|
787
|
-
if (!focus) return { focus: focusId, nodes: [], edges: [] };
|
|
788
|
-
const keep = /* @__PURE__ */ new Set([focusId]);
|
|
789
|
-
for (const e of scoped.edges) {
|
|
790
|
-
if (e.source === focusId && byId.has(e.target)) keep.add(e.target);
|
|
791
|
-
if (e.target === focusId && byId.has(e.source)) keep.add(e.source);
|
|
792
|
-
}
|
|
793
|
-
const nodes = scoped.nodes.filter((n) => keep.has(n.id));
|
|
794
|
-
const edges = scoped.edges.filter((e) => keep.has(e.source) && keep.has(e.target));
|
|
795
|
-
return { focus: focusId, nodes, edges };
|
|
667
|
+
return { html: String(file), toc };
|
|
796
668
|
}
|
|
797
669
|
|
|
798
670
|
// src/site.ts
|
|
@@ -845,11 +717,10 @@ function findNode(nodes, slug) {
|
|
|
845
717
|
}
|
|
846
718
|
return void 0;
|
|
847
719
|
}
|
|
848
|
-
async function resolvePage(coll, slug
|
|
720
|
+
async function resolvePage(coll, slug) {
|
|
849
721
|
try {
|
|
850
722
|
const art = await readArticle(coll, slug);
|
|
851
|
-
const { html, toc } = await renderArticle(art.body
|
|
852
|
-
const graph = localGraph(await buildLinkGraph(), `${art.coll}/${art.slug}`, opts?.include);
|
|
723
|
+
const { html, toc } = await renderArticle(art.body);
|
|
853
724
|
return {
|
|
854
725
|
kind: "doc",
|
|
855
726
|
coll: art.coll,
|
|
@@ -858,8 +729,7 @@ async function resolvePage(coll, slug, opts) {
|
|
|
858
729
|
tags: art.tags,
|
|
859
730
|
html,
|
|
860
731
|
toc,
|
|
861
|
-
path: `/${art.coll}/${art.slug}
|
|
862
|
-
graph
|
|
732
|
+
path: `/${art.coll}/${art.slug}`
|
|
863
733
|
};
|
|
864
734
|
} catch (err) {
|
|
865
735
|
if (err instanceof CollectionNotFoundError) return null;
|
|
@@ -917,19 +787,19 @@ function resolveCollectionSelection(all, sel = {}) {
|
|
|
917
787
|
}
|
|
918
788
|
|
|
919
789
|
// src/query.ts
|
|
920
|
-
import
|
|
921
|
-
import
|
|
790
|
+
import fs5 from "fs/promises";
|
|
791
|
+
import path5 from "path";
|
|
922
792
|
var log2 = getLogger("query");
|
|
923
793
|
async function collectMarkdownFiles(dir) {
|
|
924
794
|
let entries;
|
|
925
795
|
try {
|
|
926
|
-
entries = await
|
|
796
|
+
entries = await fs5.readdir(dir, { withFileTypes: true });
|
|
927
797
|
} catch {
|
|
928
798
|
return [];
|
|
929
799
|
}
|
|
930
800
|
const files = [];
|
|
931
801
|
for (const entry of entries) {
|
|
932
|
-
const full =
|
|
802
|
+
const full = path5.join(dir, entry.name);
|
|
933
803
|
if (entry.isDirectory()) {
|
|
934
804
|
files.push(...await collectMarkdownFiles(full));
|
|
935
805
|
} else if (entry.isFile() && /\.mdx?$/.test(entry.name)) {
|
|
@@ -948,12 +818,12 @@ async function nativeSearch(term, collections, collection) {
|
|
|
948
818
|
const docs = [];
|
|
949
819
|
for (const entry of targets) {
|
|
950
820
|
for (const full of await collectMarkdownFiles(entry.path)) {
|
|
951
|
-
const fallbackTitle =
|
|
821
|
+
const fallbackTitle = path5.basename(full).replace(/\.mdx?$/, "");
|
|
952
822
|
let title = fallbackTitle;
|
|
953
823
|
let tags = [];
|
|
954
824
|
let body = "";
|
|
955
825
|
try {
|
|
956
|
-
const parsed = parseArticle(await
|
|
826
|
+
const parsed = parseArticle(await fs5.readFile(full, "utf8"));
|
|
957
827
|
if (parsed.title) title = parsed.title;
|
|
958
828
|
tags = parsed.tags;
|
|
959
829
|
body = parsed.body;
|
|
@@ -1036,12 +906,12 @@ async function query(term, opts) {
|
|
|
1036
906
|
}
|
|
1037
907
|
|
|
1038
908
|
// src/search.ts
|
|
1039
|
-
import
|
|
1040
|
-
import
|
|
1041
|
-
async function
|
|
909
|
+
import fs6 from "fs/promises";
|
|
910
|
+
import path6 from "path";
|
|
911
|
+
async function readArticleParts(collDir, slug) {
|
|
1042
912
|
for (const ext of [".mdx", ".md"]) {
|
|
1043
913
|
try {
|
|
1044
|
-
const parsed = parseArticle(await
|
|
914
|
+
const parsed = parseArticle(await fs6.readFile(path6.join(collDir, `${slug}${ext}`), "utf8"));
|
|
1045
915
|
return { tags: parsed.tags, body: parsed.body };
|
|
1046
916
|
} catch {
|
|
1047
917
|
}
|
|
@@ -1052,7 +922,7 @@ async function flatten(coll, collDir, nodes, out) {
|
|
|
1052
922
|
for (const n of nodes) {
|
|
1053
923
|
if (n.slug && !n.children) {
|
|
1054
924
|
const title = n.title ?? n.name;
|
|
1055
|
-
const { tags, body } = await
|
|
925
|
+
const { tags, body } = await readArticleParts(collDir, n.slug);
|
|
1056
926
|
out.push({
|
|
1057
927
|
collection: coll,
|
|
1058
928
|
slug: n.slug,
|
|
@@ -1075,7 +945,7 @@ async function buildSearchIndex(collection) {
|
|
|
1075
945
|
for (const e of entries) {
|
|
1076
946
|
try {
|
|
1077
947
|
const collEntry = await findCollection(e.name);
|
|
1078
|
-
const collDir =
|
|
948
|
+
const collDir = path6.resolve(collEntry?.path ?? e.path);
|
|
1079
949
|
await flatten(e.name, collDir, await listArticleTree(e.name), out);
|
|
1080
950
|
} catch {
|
|
1081
951
|
}
|
|
@@ -1084,15 +954,15 @@ async function buildSearchIndex(collection) {
|
|
|
1084
954
|
}
|
|
1085
955
|
|
|
1086
956
|
// src/doctor.ts
|
|
1087
|
-
import
|
|
957
|
+
import fs8 from "fs/promises";
|
|
1088
958
|
|
|
1089
959
|
// src/plugins/manager.ts
|
|
1090
|
-
import
|
|
960
|
+
import fs7 from "fs/promises";
|
|
1091
961
|
import os from "os";
|
|
1092
|
-
import
|
|
962
|
+
import path7 from "path";
|
|
1093
963
|
async function readPackageJson(file) {
|
|
1094
964
|
try {
|
|
1095
|
-
return JSON.parse(await
|
|
965
|
+
return JSON.parse(await fs7.readFile(file, "utf8"));
|
|
1096
966
|
} catch {
|
|
1097
967
|
return null;
|
|
1098
968
|
}
|
|
@@ -1108,7 +978,7 @@ function binOf(manifest) {
|
|
|
1108
978
|
async function pluginManifestDirs(nodeModules) {
|
|
1109
979
|
let entries;
|
|
1110
980
|
try {
|
|
1111
|
-
entries = await
|
|
981
|
+
entries = await fs7.readdir(nodeModules);
|
|
1112
982
|
} catch {
|
|
1113
983
|
return [];
|
|
1114
984
|
}
|
|
@@ -1118,44 +988,44 @@ async function pluginManifestDirs(nodeModules) {
|
|
|
1118
988
|
if (entry.startsWith("@")) {
|
|
1119
989
|
let scoped;
|
|
1120
990
|
try {
|
|
1121
|
-
scoped = await
|
|
991
|
+
scoped = await fs7.readdir(path7.join(nodeModules, entry));
|
|
1122
992
|
} catch {
|
|
1123
993
|
continue;
|
|
1124
994
|
}
|
|
1125
995
|
for (const pkg of scoped) {
|
|
1126
996
|
if (pkg.startsWith(".")) continue;
|
|
1127
|
-
dirs.push(
|
|
997
|
+
dirs.push(path7.join(nodeModules, entry, pkg));
|
|
1128
998
|
}
|
|
1129
999
|
} else {
|
|
1130
|
-
dirs.push(
|
|
1000
|
+
dirs.push(path7.join(nodeModules, entry));
|
|
1131
1001
|
}
|
|
1132
1002
|
}
|
|
1133
1003
|
return dirs;
|
|
1134
1004
|
}
|
|
1135
1005
|
async function ensurePluginRoot() {
|
|
1136
1006
|
const dir = pluginsDir();
|
|
1137
|
-
await
|
|
1138
|
-
const pkgPath =
|
|
1007
|
+
await fs7.mkdir(dir, { recursive: true });
|
|
1008
|
+
const pkgPath = path7.join(dir, "package.json");
|
|
1139
1009
|
if (await readPackageJson(pkgPath) === null) {
|
|
1140
1010
|
const pkg = { name: "diffwiki-plugins", private: true, version: "0.0.0" };
|
|
1141
|
-
await
|
|
1011
|
+
await fs7.writeFile(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
1142
1012
|
`, "utf8");
|
|
1143
1013
|
}
|
|
1144
1014
|
return dir;
|
|
1145
1015
|
}
|
|
1146
1016
|
async function asSearchPackage(pkgDir) {
|
|
1147
|
-
const manifest = await readPackageJson(
|
|
1017
|
+
const manifest = await readPackageJson(path7.join(pkgDir, "package.json"));
|
|
1148
1018
|
if (!manifest?.name || manifest.diffwiki?.kind !== "search") return null;
|
|
1149
1019
|
const bin = binOf(manifest);
|
|
1150
1020
|
if (!bin) return null;
|
|
1151
|
-
return { name: manifest.name, version: manifest.version, binAbs:
|
|
1021
|
+
return { name: manifest.name, version: manifest.version, binAbs: path7.resolve(pkgDir, bin) };
|
|
1152
1022
|
}
|
|
1153
1023
|
async function packageNameFromSpec(spec) {
|
|
1154
1024
|
const looksLikePath = spec.startsWith(".") || spec.startsWith("/") || spec.startsWith("~") || spec.startsWith("file:");
|
|
1155
1025
|
if (looksLikePath) {
|
|
1156
1026
|
const raw = spec.startsWith("file:") ? spec.slice("file:".length) : spec;
|
|
1157
|
-
const abs =
|
|
1158
|
-
return (await readPackageJson(
|
|
1027
|
+
const abs = path7.resolve(raw.replace(/^~(?=$|\/)/, os.homedir()));
|
|
1028
|
+
return (await readPackageJson(path7.join(abs, "package.json")))?.name ?? null;
|
|
1159
1029
|
}
|
|
1160
1030
|
if (/^(git\+|git:|https?:|ssh:)/.test(spec)) return null;
|
|
1161
1031
|
if (spec.startsWith("@")) {
|
|
@@ -1166,10 +1036,10 @@ async function packageNameFromSpec(spec) {
|
|
|
1166
1036
|
return at <= 0 ? spec : spec.slice(0, at);
|
|
1167
1037
|
}
|
|
1168
1038
|
async function resolveSearchPackage(dir, name) {
|
|
1169
|
-
return asSearchPackage(
|
|
1039
|
+
return asSearchPackage(path7.join(dir, "node_modules", ...name.split("/")));
|
|
1170
1040
|
}
|
|
1171
1041
|
async function discoverSearchPackage(dir) {
|
|
1172
|
-
const nodeModules =
|
|
1042
|
+
const nodeModules = path7.join(dir, "node_modules");
|
|
1173
1043
|
for (const pkgDir of await pluginManifestDirs(nodeModules)) {
|
|
1174
1044
|
const found = await asSearchPackage(pkgDir);
|
|
1175
1045
|
if (found) return found;
|
|
@@ -1299,7 +1169,7 @@ async function listPlugins() {
|
|
|
1299
1169
|
// src/doctor.ts
|
|
1300
1170
|
async function exists(target) {
|
|
1301
1171
|
try {
|
|
1302
|
-
await
|
|
1172
|
+
await fs8.access(target);
|
|
1303
1173
|
return true;
|
|
1304
1174
|
} catch {
|
|
1305
1175
|
return false;
|
|
@@ -1441,7 +1311,6 @@ export {
|
|
|
1441
1311
|
addTags,
|
|
1442
1312
|
buildArticleTree,
|
|
1443
1313
|
buildCollections,
|
|
1444
|
-
buildLinkGraph,
|
|
1445
1314
|
buildNavTree,
|
|
1446
1315
|
buildSearchIndex,
|
|
1447
1316
|
collectionDir,
|
|
@@ -1465,7 +1334,6 @@ export {
|
|
|
1465
1334
|
gitToplevel,
|
|
1466
1335
|
initRepoWiki,
|
|
1467
1336
|
installPlugin,
|
|
1468
|
-
invalidateLinkGraph,
|
|
1469
1337
|
isLinkedWorktree,
|
|
1470
1338
|
listArticleTree,
|
|
1471
1339
|
listAvailablePlugins,
|
|
@@ -1474,7 +1342,6 @@ export {
|
|
|
1474
1342
|
listPlugins,
|
|
1475
1343
|
listSearchModes,
|
|
1476
1344
|
loadSearchProvider,
|
|
1477
|
-
localGraph,
|
|
1478
1345
|
nativeSearch,
|
|
1479
1346
|
parseAddTarget,
|
|
1480
1347
|
parseArticle,
|