@pruddiman/mdmirror 0.1.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/README.md +1 -0
- package/dist/build/builder.d.ts +41 -0
- package/dist/build/builder.js +108 -0
- package/dist/build/builder.js.map +1 -0
- package/dist/cli/build.d.ts +14 -0
- package/dist/cli/build.js +116 -0
- package/dist/cli/build.js.map +1 -0
- package/dist/cli/index.d.ts +6 -0
- package/dist/cli/index.js +104 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/serve.d.ts +15 -0
- package/dist/cli/serve.js +233 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/core/discovery.d.ts +12 -0
- package/dist/core/discovery.js +91 -0
- package/dist/core/discovery.js.map +1 -0
- package/dist/core/navigation.d.ts +12 -0
- package/dist/core/navigation.js +155 -0
- package/dist/core/navigation.js.map +1 -0
- package/dist/core/slug.d.ts +47 -0
- package/dist/core/slug.js +132 -0
- package/dist/core/slug.js.map +1 -0
- package/dist/core/title.d.ts +22 -0
- package/dist/core/title.js +43 -0
- package/dist/core/title.js.map +1 -0
- package/dist/render/highlight.d.ts +23 -0
- package/dist/render/highlight.js +36 -0
- package/dist/render/highlight.js.map +1 -0
- package/dist/render/mermaid.d.ts +13 -0
- package/dist/render/mermaid.js +66 -0
- package/dist/render/mermaid.js.map +1 -0
- package/dist/render/pipeline.d.ts +32 -0
- package/dist/render/pipeline.js +141 -0
- package/dist/render/pipeline.js.map +1 -0
- package/dist/search/index.d.ts +19 -0
- package/dist/search/index.js +43 -0
- package/dist/search/index.js.map +1 -0
- package/dist/server/reload.d.ts +23 -0
- package/dist/server/reload.js +80 -0
- package/dist/server/reload.js.map +1 -0
- package/dist/server/server.d.ts +22 -0
- package/dist/server/server.js +137 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/watcher.d.ts +24 -0
- package/dist/server/watcher.js +62 -0
- package/dist/server/watcher.js.map +1 -0
- package/dist/theme/index.d.ts +8 -0
- package/dist/theme/index.js +19 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/layout.d.ts +37 -0
- package/dist/theme/layout.js +141 -0
- package/dist/theme/layout.js.map +1 -0
- package/dist/theme/scripts.d.ts +29 -0
- package/dist/theme/scripts.js +159 -0
- package/dist/theme/scripts.js.map +1 -0
- package/dist/theme/styles.css +462 -0
- package/dist/types.d.ts +99 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File system watcher module.
|
|
3
|
+
* Uses chokidar to watch the source folder for .md and .txt file changes.
|
|
4
|
+
* Emits debounced events for add, change, unlink.
|
|
5
|
+
*/
|
|
6
|
+
import { watch } from "chokidar";
|
|
7
|
+
/**
|
|
8
|
+
* Start watching a source folder for markdown/text file changes.
|
|
9
|
+
* Returns the watcher instance for cleanup.
|
|
10
|
+
*/
|
|
11
|
+
export function startWatcher(options) {
|
|
12
|
+
const { sourcePath, debounceMs = 300, onChange } = options;
|
|
13
|
+
let pendingEvents = [];
|
|
14
|
+
let debounceTimer = null;
|
|
15
|
+
function scheduleFlush() {
|
|
16
|
+
if (debounceTimer) {
|
|
17
|
+
clearTimeout(debounceTimer);
|
|
18
|
+
}
|
|
19
|
+
debounceTimer = setTimeout(() => {
|
|
20
|
+
const events = pendingEvents;
|
|
21
|
+
pendingEvents = [];
|
|
22
|
+
debounceTimer = null;
|
|
23
|
+
if (events.length > 0) {
|
|
24
|
+
onChange(events);
|
|
25
|
+
}
|
|
26
|
+
}, debounceMs);
|
|
27
|
+
}
|
|
28
|
+
function handleEvent(type, path) {
|
|
29
|
+
pendingEvents.push({ type, path });
|
|
30
|
+
scheduleFlush();
|
|
31
|
+
}
|
|
32
|
+
const watcher = watch(sourcePath, {
|
|
33
|
+
ignoreInitial: true,
|
|
34
|
+
ignored: [
|
|
35
|
+
/(^|[/\\])\../, // Hidden files/dirs
|
|
36
|
+
/node_modules/,
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
// Only watch supported file types
|
|
40
|
+
watcher
|
|
41
|
+
.on("add", (path) => {
|
|
42
|
+
if (isSupportedFile(path)) {
|
|
43
|
+
handleEvent("add", path);
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
.on("change", (path) => {
|
|
47
|
+
if (isSupportedFile(path)) {
|
|
48
|
+
handleEvent("change", path);
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
.on("unlink", (path) => {
|
|
52
|
+
if (isSupportedFile(path)) {
|
|
53
|
+
handleEvent("unlink", path);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
return watcher;
|
|
57
|
+
}
|
|
58
|
+
function isSupportedFile(filePath) {
|
|
59
|
+
const lower = filePath.toLowerCase();
|
|
60
|
+
return lower.endsWith(".md") || lower.endsWith(".txt");
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/server/watcher.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAkB,MAAM,UAAU,CAAC;AAkBjD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,OAAuB;IAClD,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,GAAG,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAE3D,IAAI,aAAa,GAAiB,EAAE,CAAC;IACrC,IAAI,aAAa,GAAyC,IAAI,CAAC;IAE/D,SAAS,aAAa;QACpB,IAAI,aAAa,EAAE,CAAC;YAClB,YAAY,CAAC,aAAa,CAAC,CAAC;QAC9B,CAAC;QACD,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,MAAM,MAAM,GAAG,aAAa,CAAC;YAC7B,aAAa,GAAG,EAAE,CAAC;YACnB,aAAa,GAAG,IAAI,CAAC;YACrB,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,QAAQ,CAAC,MAAM,CAAC,CAAC;YACnB,CAAC;QACH,CAAC,EAAE,UAAU,CAAC,CAAC;IACjB,CAAC;IAED,SAAS,WAAW,CAAC,IAAoB,EAAE,IAAY;QACrD,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnC,aAAa,EAAE,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,EAAE;QAChC,aAAa,EAAE,IAAI;QACnB,OAAO,EAAE;YACP,cAAc,EAAE,oBAAoB;YACpC,cAAc;SACf;KACF,CAAC,CAAC;IAEH,kCAAkC;IAClC,OAAO;SACJ,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE;QAClB,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC;SACD,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;QACrB,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC,CAAC;SACD,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;QACrB,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme module.
|
|
3
|
+
* Provides access to the default theme's stylesheet and assets.
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
import { resolve, dirname } from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
let cachedStylesheet = null;
|
|
10
|
+
/**
|
|
11
|
+
* Get the default theme stylesheet content.
|
|
12
|
+
*/
|
|
13
|
+
export function getStylesheet() {
|
|
14
|
+
if (!cachedStylesheet) {
|
|
15
|
+
cachedStylesheet = readFileSync(resolve(__dirname, "styles.css"), "utf-8");
|
|
16
|
+
}
|
|
17
|
+
return cachedStylesheet;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,IAAI,gBAAgB,GAAkB,IAAI,CAAC;AAE3C;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,gBAAgB,GAAG,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default HTML layout template.
|
|
3
|
+
* Generates a complete HTML page with sidebar navigation and content area.
|
|
4
|
+
*/
|
|
5
|
+
import type { NavigationTree } from "../types.js";
|
|
6
|
+
export interface LayoutOptions {
|
|
7
|
+
/** Page title */
|
|
8
|
+
title: string;
|
|
9
|
+
/** Short description for the meta description tag (from front matter) */
|
|
10
|
+
description?: string;
|
|
11
|
+
/** Canonical URL for Open Graph / SEO (optional, build mode only) */
|
|
12
|
+
canonicalUrl?: string;
|
|
13
|
+
/** Rendered HTML content */
|
|
14
|
+
content: string;
|
|
15
|
+
/** Navigation tree */
|
|
16
|
+
navigation: NavigationTree;
|
|
17
|
+
/** Current page slug */
|
|
18
|
+
currentSlug: string;
|
|
19
|
+
/** CSS content */
|
|
20
|
+
stylesheet: string;
|
|
21
|
+
/** "serve" or "build" mode */
|
|
22
|
+
mode: "serve" | "build";
|
|
23
|
+
/** Optional live reload script (injected in serve mode) */
|
|
24
|
+
liveReloadScript?: string;
|
|
25
|
+
/** URL path to the Mermaid UMD bundle (e.g. "/assets/mermaid.min.js" or "assets/mermaid.min.js") */
|
|
26
|
+
mermaidBundleSrc?: string;
|
|
27
|
+
/** Inline script to initialize Mermaid after the bundle loads */
|
|
28
|
+
mermaidInitScript?: string;
|
|
29
|
+
/** Optional navigation interactivity script */
|
|
30
|
+
navigationScript?: string;
|
|
31
|
+
/** Optional search UI script */
|
|
32
|
+
searchScript?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generate the complete HTML page.
|
|
36
|
+
*/
|
|
37
|
+
export declare function renderLayout(options: LayoutOptions): string;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default HTML layout template.
|
|
3
|
+
* Generates a complete HTML page with sidebar navigation and content area.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Render a navigation node and its children as HTML list items.
|
|
7
|
+
* In build mode, uses relative paths instead of absolute.
|
|
8
|
+
*/
|
|
9
|
+
function renderNavNode(node, currentSlug, mode) {
|
|
10
|
+
const isActive = node.slug === currentSlug;
|
|
11
|
+
const activeClass = isActive ? ' class="active"' : "";
|
|
12
|
+
const href = mode === "build" ? buildRelativeHref(currentSlug, node.slug) : `/${node.slug}`;
|
|
13
|
+
if (node.type === "page") {
|
|
14
|
+
return `<li${activeClass}><a href="${href}">${escapeHtml(node.label)}</a></li>`;
|
|
15
|
+
}
|
|
16
|
+
// Section node
|
|
17
|
+
const hasActiveChild = containsActiveSlug(node, currentSlug);
|
|
18
|
+
const openAttr = hasActiveChild || isActive ? " open" : "";
|
|
19
|
+
const sectionLink = node.indexDocument
|
|
20
|
+
? `<a href="${href}">${escapeHtml(node.label)}</a>`
|
|
21
|
+
: `<span>${escapeHtml(node.label)}</span>`;
|
|
22
|
+
const childrenHtml = node.children
|
|
23
|
+
.map((child) => renderNavNode(child, currentSlug, mode))
|
|
24
|
+
.join("\n");
|
|
25
|
+
return `<li class="section${isActive ? " active" : ""}">
|
|
26
|
+
<details${openAttr}>
|
|
27
|
+
<summary>${sectionLink}</summary>
|
|
28
|
+
<ul>
|
|
29
|
+
${childrenHtml}
|
|
30
|
+
</ul>
|
|
31
|
+
</details>
|
|
32
|
+
</li>`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Build a relative href from the current page slug to a target slug.
|
|
36
|
+
* Since build mode writes each page as slug/index.html, we compute
|
|
37
|
+
* the relative path between directories.
|
|
38
|
+
*/
|
|
39
|
+
function buildRelativeHref(currentSlug, targetSlug) {
|
|
40
|
+
// Both slugs map to directories containing index.html
|
|
41
|
+
// Current page is at: <currentSlug>/index.html (or root index.html if "")
|
|
42
|
+
// Target page is at: <targetSlug>/index.html
|
|
43
|
+
const currentParts = currentSlug === "" ? [] : currentSlug.split("/");
|
|
44
|
+
const targetParts = targetSlug === "" ? [] : targetSlug.split("/");
|
|
45
|
+
// Navigate up from current directory
|
|
46
|
+
const ups = currentParts.length;
|
|
47
|
+
const upPath = ups > 0 ? "../".repeat(ups) : "./";
|
|
48
|
+
if (targetSlug === "") {
|
|
49
|
+
return upPath || "./";
|
|
50
|
+
}
|
|
51
|
+
return upPath + targetParts.join("/") + "/";
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if a navigation node or any of its descendants matches the current slug.
|
|
55
|
+
*/
|
|
56
|
+
function containsActiveSlug(node, currentSlug) {
|
|
57
|
+
if (node.slug === currentSlug)
|
|
58
|
+
return true;
|
|
59
|
+
return node.children.some((child) => containsActiveSlug(child, currentSlug));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Escape HTML special characters.
|
|
63
|
+
*/
|
|
64
|
+
function escapeHtml(text) {
|
|
65
|
+
return text
|
|
66
|
+
.replace(/&/g, "&")
|
|
67
|
+
.replace(/</g, "<")
|
|
68
|
+
.replace(/>/g, ">")
|
|
69
|
+
.replace(/"/g, """);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Generate the complete HTML page.
|
|
73
|
+
*/
|
|
74
|
+
export function renderLayout(options) {
|
|
75
|
+
const { title, description, canonicalUrl, content, navigation, currentSlug, stylesheet, mode, liveReloadScript, mermaidBundleSrc, mermaidInitScript, navigationScript, searchScript, } = options;
|
|
76
|
+
// Render navigation items
|
|
77
|
+
const navItems = navigation.root
|
|
78
|
+
.map((node) => renderNavNode(node, currentSlug, mode))
|
|
79
|
+
.join("\n");
|
|
80
|
+
// Find the root index page for the site title link
|
|
81
|
+
const rootPage = navigation.flatPages.find((p) => p.slug === "");
|
|
82
|
+
const siteTitle = rootPage ? rootPage.title : "Documentation";
|
|
83
|
+
const homeHref = mode === "build" ? buildRelativeHref(currentSlug, "") : "/";
|
|
84
|
+
// Build scripts section
|
|
85
|
+
const scriptParts = [];
|
|
86
|
+
if (mode === "serve" && liveReloadScript) {
|
|
87
|
+
scriptParts.push(`<script>${liveReloadScript}</script>`);
|
|
88
|
+
}
|
|
89
|
+
if (mermaidBundleSrc) {
|
|
90
|
+
// Compute the correct src for this page
|
|
91
|
+
const src = mode === "build"
|
|
92
|
+
? buildRelativeHref(currentSlug, "").replace(/\/$/, "/") + mermaidBundleSrc
|
|
93
|
+
: mermaidBundleSrc;
|
|
94
|
+
scriptParts.push(`<script src="${src}"></script>`);
|
|
95
|
+
}
|
|
96
|
+
if (mermaidInitScript) {
|
|
97
|
+
scriptParts.push(`<script>${mermaidInitScript}</script>`);
|
|
98
|
+
}
|
|
99
|
+
if (navigationScript) {
|
|
100
|
+
scriptParts.push(`<script>${navigationScript}</script>`);
|
|
101
|
+
}
|
|
102
|
+
if (searchScript) {
|
|
103
|
+
scriptParts.push(`<script>${searchScript}</script>`);
|
|
104
|
+
}
|
|
105
|
+
const scripts = scriptParts.join("\n ");
|
|
106
|
+
return `<!DOCTYPE html>
|
|
107
|
+
<html lang="en">
|
|
108
|
+
<head>
|
|
109
|
+
<meta charset="UTF-8">
|
|
110
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
111
|
+
<title>${escapeHtml(title)}</title>${description ? `\n <meta name="description" content="${escapeHtml(description)}">` : ""}${canonicalUrl ? `\n <link rel="canonical" href="${escapeHtml(canonicalUrl)}">` : ""}${canonicalUrl
|
|
112
|
+
? `\n <meta property="og:title" content="${escapeHtml(title)}">
|
|
113
|
+
<meta property="og:type" content="article">${description ? `\n <meta property="og:description" content="${escapeHtml(description)}">` : ""}
|
|
114
|
+
<meta property="og:url" content="${escapeHtml(canonicalUrl)}">`
|
|
115
|
+
: ""}
|
|
116
|
+
<style>${stylesheet}</style>
|
|
117
|
+
</head>
|
|
118
|
+
<body>
|
|
119
|
+
<aside class="sidebar">
|
|
120
|
+
<div class="sidebar-header">
|
|
121
|
+
<a href="${homeHref}" class="site-title">${escapeHtml(siteTitle)}</a>
|
|
122
|
+
<button class="menu-toggle" aria-label="Toggle navigation">
|
|
123
|
+
<span></span><span></span><span></span>
|
|
124
|
+
</button>
|
|
125
|
+
</div>
|
|
126
|
+
<nav>
|
|
127
|
+
<ul>
|
|
128
|
+
${navItems}
|
|
129
|
+
</ul>
|
|
130
|
+
</nav>
|
|
131
|
+
</aside>
|
|
132
|
+
<main class="content">
|
|
133
|
+
<article>
|
|
134
|
+
${content}
|
|
135
|
+
</article>
|
|
136
|
+
</main>
|
|
137
|
+
${scripts}
|
|
138
|
+
</body>
|
|
139
|
+
</html>`;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/theme/layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side scripts for the mdmirror theme.
|
|
3
|
+
* Mermaid initialization, navigation interactivity, and search.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Get the URL for the Mermaid UMD bundle.
|
|
7
|
+
* In serve mode, returns an absolute path served by the dev server.
|
|
8
|
+
* In build mode, returns a relative path (caller must adjust for page depth).
|
|
9
|
+
*/
|
|
10
|
+
export declare function getMermaidBundleSrc(mode: "serve" | "build"): string;
|
|
11
|
+
/**
|
|
12
|
+
* Mermaid client-side initialization script.
|
|
13
|
+
* Runs after the UMD bundle has loaded and set window.mermaid.
|
|
14
|
+
* Includes error handling for invalid syntax.
|
|
15
|
+
*/
|
|
16
|
+
export declare const MERMAID_INIT_SCRIPT: string;
|
|
17
|
+
/**
|
|
18
|
+
* Client-side search script.
|
|
19
|
+
* Fetches the pre-built search index and uses MiniSearch for fuzzy search.
|
|
20
|
+
* The search box is injected into the sidebar header.
|
|
21
|
+
* @param searchIndexSrc URL path to the search.json index file
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildSearchScript(searchIndexSrc: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Navigation interactivity script.
|
|
26
|
+
* Handles sidebar expand/collapse, active page highlighting,
|
|
27
|
+
* and mobile menu toggle.
|
|
28
|
+
*/
|
|
29
|
+
export declare const NAVIGATION_SCRIPT: string;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side scripts for the mdmirror theme.
|
|
3
|
+
* Mermaid initialization, navigation interactivity, and search.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Get the URL for the Mermaid UMD bundle.
|
|
7
|
+
* In serve mode, returns an absolute path served by the dev server.
|
|
8
|
+
* In build mode, returns a relative path (caller must adjust for page depth).
|
|
9
|
+
*/
|
|
10
|
+
export function getMermaidBundleSrc(mode) {
|
|
11
|
+
if (mode === "serve") {
|
|
12
|
+
return "/assets/mermaid.min.js";
|
|
13
|
+
}
|
|
14
|
+
// Build mode: relative path resolved at runtime isn't needed here —
|
|
15
|
+
// layout.ts computes the relative path per-page.
|
|
16
|
+
return "assets/mermaid.min.js";
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Mermaid client-side initialization script.
|
|
20
|
+
* Runs after the UMD bundle has loaded and set window.mermaid.
|
|
21
|
+
* Includes error handling for invalid syntax.
|
|
22
|
+
*/
|
|
23
|
+
export const MERMAID_INIT_SCRIPT = `
|
|
24
|
+
(function() {
|
|
25
|
+
if (typeof mermaid === 'undefined') return;
|
|
26
|
+
mermaid.initialize({ startOnLoad: false, theme: 'default' });
|
|
27
|
+
mermaid.run({ querySelector: '.mermaid' }).then(function() {
|
|
28
|
+
document.querySelectorAll('.mermaid').forEach(function(el) {
|
|
29
|
+
el.style.visibility = 'visible';
|
|
30
|
+
});
|
|
31
|
+
}).catch(function(e) {
|
|
32
|
+
console.warn('Mermaid rendering error:', e);
|
|
33
|
+
document.querySelectorAll('.mermaid').forEach(function(el) {
|
|
34
|
+
el.style.visibility = 'visible';
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
})();
|
|
38
|
+
`.trim();
|
|
39
|
+
/**
|
|
40
|
+
* Client-side search script.
|
|
41
|
+
* Fetches the pre-built search index and uses MiniSearch for fuzzy search.
|
|
42
|
+
* The search box is injected into the sidebar header.
|
|
43
|
+
* @param searchIndexSrc URL path to the search.json index file
|
|
44
|
+
*/
|
|
45
|
+
export function buildSearchScript(searchIndexSrc) {
|
|
46
|
+
return `
|
|
47
|
+
(function() {
|
|
48
|
+
var indexUrl = ${JSON.stringify(searchIndexSrc)};
|
|
49
|
+
var sidebar = document.querySelector('.sidebar nav');
|
|
50
|
+
if (!sidebar) return;
|
|
51
|
+
|
|
52
|
+
// Inject search box above the nav list
|
|
53
|
+
var searchContainer = document.createElement('div');
|
|
54
|
+
searchContainer.className = 'search-container';
|
|
55
|
+
searchContainer.innerHTML = '<input type="search" class="search-input" placeholder="Search..." aria-label="Search docs">' +
|
|
56
|
+
'<ul class="search-results" role="listbox" aria-label="Search results"></ul>';
|
|
57
|
+
sidebar.insertAdjacentElement('beforebegin', searchContainer);
|
|
58
|
+
|
|
59
|
+
var input = searchContainer.querySelector('.search-input');
|
|
60
|
+
var results = searchContainer.querySelector('.search-results');
|
|
61
|
+
var index = null;
|
|
62
|
+
|
|
63
|
+
// Lazy-load the search index
|
|
64
|
+
function loadIndex() {
|
|
65
|
+
if (index !== null) return Promise.resolve();
|
|
66
|
+
return fetch(indexUrl)
|
|
67
|
+
.then(function(r) { return r.json(); })
|
|
68
|
+
.then(function(docs) {
|
|
69
|
+
// Build a simple in-memory index
|
|
70
|
+
index = docs;
|
|
71
|
+
})
|
|
72
|
+
.catch(function() { index = []; });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function search(query) {
|
|
76
|
+
if (!index || !query.trim()) {
|
|
77
|
+
results.innerHTML = '';
|
|
78
|
+
results.style.display = 'none';
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
var q = query.toLowerCase();
|
|
82
|
+
var matches = index.filter(function(doc) {
|
|
83
|
+
return doc.title.toLowerCase().includes(q) || doc.excerpt.toLowerCase().includes(q);
|
|
84
|
+
}).slice(0, 10);
|
|
85
|
+
|
|
86
|
+
if (matches.length === 0) {
|
|
87
|
+
results.innerHTML = '<li class="search-no-results">No results</li>';
|
|
88
|
+
} else {
|
|
89
|
+
results.innerHTML = matches.map(function(doc) {
|
|
90
|
+
var href = doc.slug === '__root__' ? '/' : '/' + doc.slug + '/';
|
|
91
|
+
return '<li><a href="' + href + '">' + doc.title + '</a></li>';
|
|
92
|
+
}).join('');
|
|
93
|
+
}
|
|
94
|
+
results.style.display = 'block';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
input.addEventListener('focus', function() { loadIndex(); });
|
|
98
|
+
input.addEventListener('input', function() { loadIndex().then(function() { search(input.value); }); });
|
|
99
|
+
|
|
100
|
+
document.addEventListener('click', function(e) {
|
|
101
|
+
if (!searchContainer.contains(e.target)) {
|
|
102
|
+
results.style.display = 'none';
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
})();
|
|
106
|
+
`.trim();
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Navigation interactivity script.
|
|
110
|
+
* Handles sidebar expand/collapse, active page highlighting,
|
|
111
|
+
* and mobile menu toggle.
|
|
112
|
+
*/
|
|
113
|
+
export const NAVIGATION_SCRIPT = `
|
|
114
|
+
(function() {
|
|
115
|
+
// Mobile menu toggle
|
|
116
|
+
var toggle = document.querySelector('.menu-toggle');
|
|
117
|
+
var sidebar = document.querySelector('.sidebar');
|
|
118
|
+
|
|
119
|
+
if (toggle && sidebar) {
|
|
120
|
+
toggle.addEventListener('click', function() {
|
|
121
|
+
sidebar.classList.toggle('open');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Close sidebar when clicking outside on mobile
|
|
125
|
+
document.addEventListener('click', function(e) {
|
|
126
|
+
if (window.innerWidth <= 768 &&
|
|
127
|
+
sidebar.classList.contains('open') &&
|
|
128
|
+
!sidebar.contains(e.target) &&
|
|
129
|
+
e.target !== toggle &&
|
|
130
|
+
!toggle.contains(e.target)) {
|
|
131
|
+
sidebar.classList.remove('open');
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Highlight active page based on current URL
|
|
137
|
+
var currentPath = window.location.pathname.replace(/\\/$/, '') || '/';
|
|
138
|
+
var links = document.querySelectorAll('.sidebar nav a');
|
|
139
|
+
|
|
140
|
+
links.forEach(function(link) {
|
|
141
|
+
var linkPath = link.getAttribute('href');
|
|
142
|
+
if (!linkPath) return;
|
|
143
|
+
linkPath = linkPath.replace(/\\/$/, '') || '/';
|
|
144
|
+
|
|
145
|
+
if (linkPath === currentPath) {
|
|
146
|
+
var li = link.closest('li');
|
|
147
|
+
if (li) li.classList.add('active');
|
|
148
|
+
|
|
149
|
+
// Open parent details elements
|
|
150
|
+
var parent = li;
|
|
151
|
+
while (parent) {
|
|
152
|
+
parent = parent.parentElement?.closest('details');
|
|
153
|
+
if (parent) parent.setAttribute('open', '');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
})();
|
|
158
|
+
`.trim();
|
|
159
|
+
//# sourceMappingURL=scripts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripts.js","sourceRoot":"","sources":["../../src/theme/scripts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAuB;IACzD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,wBAAwB,CAAC;IAClC,CAAC;IACD,oEAAoE;IACpE,iDAAiD;IACjD,OAAO,uBAAuB,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;CAelC,CAAC,IAAI,EAAE,CAAC;AAET;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,cAAsB;IACtD,OAAO;;mBAEU,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DhD,CAAC,IAAI,EAAE,CAAC;AACT,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6ChC,CAAC,IAAI,EAAE,CAAC"}
|