@dooc-dev/dooc 0.0.0-stage → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -2
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +244 -0
- package/dist/code.global.js +285 -0
- package/dist/compiler/bundle-urls.d.ts +3 -0
- package/dist/compiler/bundle-urls.js +294 -0
- package/dist/compiler/bundle.d.ts +2 -0
- package/dist/compiler/bundle.js +100 -0
- package/dist/compiler/check-prose.d.ts +11 -0
- package/dist/compiler/check-prose.js +138 -0
- package/dist/compiler/check-types.d.ts +44 -0
- package/dist/compiler/check-types.js +1 -0
- package/dist/compiler/check.d.ts +5 -0
- package/dist/compiler/check.js +450 -0
- package/dist/compiler/code-blocks.d.ts +17 -0
- package/dist/compiler/code-blocks.js +198 -0
- package/dist/compiler/code-languages.d.ts +10 -0
- package/dist/compiler/code-languages.js +109 -0
- package/dist/compiler/compile.d.ts +95 -0
- package/dist/compiler/compile.js +410 -0
- package/dist/compiler/config.d.ts +7 -0
- package/dist/compiler/config.js +52 -0
- package/dist/compiler/dialect.d.ts +24 -0
- package/dist/compiler/dialect.js +198 -0
- package/dist/compiler/drawio.d.ts +26 -0
- package/dist/compiler/drawio.js +176 -0
- package/dist/compiler/figures.d.ts +14 -0
- package/dist/compiler/figures.js +221 -0
- package/dist/compiler/file-cache.d.ts +14 -0
- package/dist/compiler/file-cache.js +61 -0
- package/dist/compiler/files.d.ts +29 -0
- package/dist/compiler/files.js +431 -0
- package/dist/compiler/fonts.d.ts +10 -0
- package/dist/compiler/fonts.js +54 -0
- package/dist/compiler/format.d.ts +1 -0
- package/dist/compiler/format.js +42 -0
- package/dist/compiler/from-mdast.d.ts +16 -0
- package/dist/compiler/from-mdast.js +142 -0
- package/dist/compiler/icons.d.ts +14 -0
- package/dist/compiler/icons.js +85 -0
- package/dist/compiler/language-codes.d.ts +7 -0
- package/dist/compiler/language-codes.js +17 -0
- package/dist/compiler/locales.d.ts +7 -0
- package/dist/compiler/locales.js +67 -0
- package/dist/compiler/manifest.d.ts +6 -0
- package/dist/compiler/manifest.js +30 -0
- package/dist/compiler/ops.d.ts +44 -0
- package/dist/compiler/ops.js +362 -0
- package/dist/compiler/public-file.d.ts +2 -0
- package/dist/compiler/public-file.js +93 -0
- package/dist/compiler/serialize.d.ts +3 -0
- package/dist/compiler/serialize.js +16 -0
- package/dist/compiler/terms.d.ts +9 -0
- package/dist/compiler/terms.js +44 -0
- package/dist/compiler/textfile-remote.d.ts +12 -0
- package/dist/compiler/textfile-remote.js +124 -0
- package/dist/compiler/textfile.d.ts +9 -0
- package/dist/compiler/textfile.js +113 -0
- package/dist/compiler/theme-variants.d.ts +4 -0
- package/dist/compiler/theme-variants.js +22 -0
- package/dist/compiler/zip.d.ts +6 -0
- package/dist/compiler/zip.js +48 -0
- package/dist/core/blocks.d.ts +99 -0
- package/dist/core/blocks.js +29 -0
- package/dist/core/code-file.d.ts +12 -0
- package/dist/core/code-file.js +68 -0
- package/dist/core/content-metadata.d.ts +48 -0
- package/dist/core/content-metadata.js +264 -0
- package/dist/core/content-types.d.ts +45 -0
- package/dist/core/content-types.js +1 -0
- package/dist/core/figure-frame.d.ts +12 -0
- package/dist/core/figure-frame.js +108 -0
- package/dist/core/file-embed.d.ts +13 -0
- package/dist/core/file-embed.js +43 -0
- package/dist/core/files.d.ts +15 -0
- package/dist/core/files.js +59 -0
- package/dist/core/flow-base-css.generated.d.ts +1 -0
- package/dist/core/flow-base-css.generated.js +4 -0
- package/dist/core/flow-css.d.ts +9 -0
- package/dist/core/flow-css.js +54 -0
- package/dist/core/graph-common.d.ts +32 -0
- package/dist/core/graph-common.js +113 -0
- package/dist/core/graph.d.ts +117 -0
- package/dist/core/graph.js +480 -0
- package/dist/core/html.d.ts +29 -0
- package/dist/core/html.js +444 -0
- package/dist/core/icons.d.ts +1 -0
- package/dist/core/icons.js +1 -0
- package/dist/core/inline.d.ts +27 -0
- package/dist/core/inline.js +42 -0
- package/dist/core/language.d.ts +41 -0
- package/dist/core/language.js +44 -0
- package/dist/core/languages/ja.d.ts +2 -0
- package/dist/core/languages/ja.js +5 -0
- package/dist/core/markdown.d.ts +27 -0
- package/dist/core/markdown.js +154 -0
- package/dist/core/previewers.d.ts +37 -0
- package/dist/core/previewers.js +103 -0
- package/dist/core/routing.d.ts +20 -0
- package/dist/core/routing.js +64 -0
- package/dist/core/schema-comments.d.ts +14 -0
- package/dist/core/schema-comments.js +52 -0
- package/dist/core/schema-graph-flow.d.ts +9 -0
- package/dist/core/schema-graph-flow.js +379 -0
- package/dist/core/schema-graph-mount.d.ts +9 -0
- package/dist/core/schema-graph-mount.js +105 -0
- package/dist/core/schema-graph.d.ts +254 -0
- package/dist/core/schema-graph.js +981 -0
- package/dist/core/table-ui.d.ts +2 -0
- package/dist/core/table-ui.js +180 -0
- package/dist/core/taxonomy.d.ts +12 -0
- package/dist/core/taxonomy.js +49 -0
- package/dist/core/term-reference.d.ts +5 -0
- package/dist/core/term-reference.js +19 -0
- package/dist/core/terms-ui.d.ts +6 -0
- package/dist/core/terms-ui.js +22 -0
- package/dist/core/textfile.d.ts +10 -0
- package/dist/core/textfile.js +39 -0
- package/dist/core/theme-variants.d.ts +3 -0
- package/dist/core/theme-variants.js +37 -0
- package/dist/core/toc-ui.d.ts +2 -0
- package/dist/core/toc-ui.js +161 -0
- package/dist/core/video-ui.d.ts +2 -0
- package/dist/core/video-ui.js +253 -0
- package/dist/core/workspace.d.ts +15 -0
- package/dist/core/workspace.js +28 -0
- package/dist/edit.global.js +305 -0
- package/dist/flow.global.js +4959 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +31 -0
- package/dist/mcp.d.ts +24 -0
- package/dist/mcp.js +467 -0
- package/dist/plugins/actions.d.ts +45 -0
- package/dist/plugins/actions.js +125 -0
- package/dist/plugins/blocks.d.ts +92 -0
- package/dist/plugins/blocks.js +99 -0
- package/dist/plugins/index.d.ts +4 -0
- package/dist/plugins/index.js +1 -0
- package/dist/plugins/oauth.d.ts +14 -0
- package/dist/plugins/oauth.js +164 -0
- package/dist/plugins/runtime.d.ts +24 -0
- package/dist/plugins/runtime.js +339 -0
- package/dist/plugins/types.d.ts +56 -0
- package/dist/plugins/types.js +1 -0
- package/dist/plugins/view.d.ts +29 -0
- package/dist/plugins/view.js +60 -0
- package/dist/ui.global.js +77 -0
- package/dist/viewer/assets.d.ts +2 -0
- package/dist/viewer/assets.js +3 -0
- package/dist/viewer/build.d.ts +12 -0
- package/dist/viewer/build.js +55 -0
- package/dist/viewer/bundle-network.d.ts +2 -0
- package/dist/viewer/bundle-network.js +88 -0
- package/dist/viewer/code-file.d.ts +20 -0
- package/dist/viewer/code-file.js +42 -0
- package/dist/viewer/editor-tools.d.ts +38 -0
- package/dist/viewer/editor-tools.js +211 -0
- package/dist/viewer/file-references.d.ts +14 -0
- package/dist/viewer/file-references.js +38 -0
- package/dist/viewer/font-picker.d.ts +4 -0
- package/dist/viewer/font-picker.js +145 -0
- package/dist/viewer/font-settings.d.ts +11 -0
- package/dist/viewer/font-settings.js +50 -0
- package/dist/viewer/fonts/LICENSE.txt +119 -0
- package/dist/viewer/fonts/udev-gothic-regular.woff2 +0 -0
- package/dist/viewer/fonts.d.ts +2 -0
- package/dist/viewer/fonts.js +13 -0
- package/dist/viewer/git-diff.d.ts +3 -0
- package/dist/viewer/git-diff.js +33 -0
- package/dist/viewer/git-types.d.ts +73 -0
- package/dist/viewer/git-types.js +1 -0
- package/dist/viewer/git.d.ts +5 -0
- package/dist/viewer/git.js +337 -0
- package/dist/viewer/hmr.d.ts +53 -0
- package/dist/viewer/hmr.js +335 -0
- package/dist/viewer/i18n.d.ts +6 -0
- package/dist/viewer/i18n.js +65 -0
- package/dist/viewer/ja-lint.d.ts +3 -0
- package/dist/viewer/ja-lint.js +44 -0
- package/dist/viewer/language-picker.d.ts +2 -0
- package/dist/viewer/language-picker.js +233 -0
- package/dist/viewer/languages.d.ts +11 -0
- package/dist/viewer/languages.js +20 -0
- package/dist/viewer/locales/eng.json +294 -0
- package/dist/viewer/locales/jpn.json +294 -0
- package/dist/viewer/locales/zho.json +294 -0
- package/dist/viewer/nav-focus.d.ts +2 -0
- package/dist/viewer/nav-focus.js +64 -0
- package/dist/viewer/plugin-blocks.d.ts +3 -0
- package/dist/viewer/plugin-blocks.js +115 -0
- package/dist/viewer/plugin-config.d.ts +35 -0
- package/dist/viewer/plugin-config.js +57 -0
- package/dist/viewer/plugin-view.d.ts +3 -0
- package/dist/viewer/plugin-view.js +28 -0
- package/dist/viewer/plugins.d.ts +8 -0
- package/dist/viewer/plugins.js +214 -0
- package/dist/viewer/resize.d.ts +4 -0
- package/dist/viewer/resize.js +238 -0
- package/dist/viewer/resource-library.d.ts +29 -0
- package/dist/viewer/resource-library.js +104 -0
- package/dist/viewer/search.d.ts +16 -0
- package/dist/viewer/search.js +358 -0
- package/dist/viewer/serve.d.ts +206 -0
- package/dist/viewer/serve.js +3233 -0
- package/dist/viewer/site-icon.d.ts +8 -0
- package/dist/viewer/site-icon.js +56 -0
- package/dist/viewer/textfile.d.ts +9 -0
- package/dist/viewer/textfile.js +50 -0
- package/dist/viewer/theme-picker.d.ts +2 -0
- package/dist/viewer/theme-picker.js +135 -0
- package/dist/viewer/workspace.d.ts +4 -0
- package/dist/viewer/workspace.js +47 -0
- package/package.json +127 -5
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/** Shared by editor, preview, and published pages; keep this function self-contained. */
|
|
2
|
+
export const mountPanelResize = () => {
|
|
3
|
+
const sidebar = document.getElementById("sidebar");
|
|
4
|
+
const editor = document.getElementById("panel");
|
|
5
|
+
const closed = () => document.body.classList.contains("sidebar-closed");
|
|
6
|
+
const contentWidth = () => Math.min(240, Math.max(0, window.innerWidth - (closed() ? 52 : 200) - (editor ? 320 : 0)));
|
|
7
|
+
const panels = [
|
|
8
|
+
{
|
|
9
|
+
element: sidebar,
|
|
10
|
+
handle: "sidebar-resize",
|
|
11
|
+
key: "docs:sidebar-width",
|
|
12
|
+
min: 200,
|
|
13
|
+
max: 480,
|
|
14
|
+
direction: 1,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
element: editor,
|
|
18
|
+
handle: "resize",
|
|
19
|
+
key: "docs-edit:panelw",
|
|
20
|
+
min: 320,
|
|
21
|
+
max: 960,
|
|
22
|
+
direction: -1,
|
|
23
|
+
},
|
|
24
|
+
].flatMap((options) => {
|
|
25
|
+
const element = options.element;
|
|
26
|
+
const handle = document.getElementById(options.handle);
|
|
27
|
+
if (!element || !handle)
|
|
28
|
+
return [];
|
|
29
|
+
let preferred;
|
|
30
|
+
try {
|
|
31
|
+
const saved = Number(localStorage.getItem(options.key));
|
|
32
|
+
if (Number.isFinite(saved) && saved > 0)
|
|
33
|
+
preferred = saved;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
/* Width persistence is optional. */
|
|
37
|
+
}
|
|
38
|
+
const property = options.direction === 1 ? "--sidebar-width" : "--panel-width";
|
|
39
|
+
const requested = () => preferred ?? (options.direction === 1 ? 260 : Math.min(760, window.innerWidth * 0.52));
|
|
40
|
+
const apply = (width) => {
|
|
41
|
+
const other = options.direction === 1 ? editor : sidebar;
|
|
42
|
+
const max = Math.max(0, Math.min(options.max, window.innerWidth -
|
|
43
|
+
(other?.getBoundingClientRect().width ?? 0) -
|
|
44
|
+
contentWidth()));
|
|
45
|
+
const min = Math.min(options.min, max);
|
|
46
|
+
const value = Math.round(Math.max(min, Math.min(width, max)));
|
|
47
|
+
element.style.setProperty(property, `${value}px`);
|
|
48
|
+
handle.setAttribute("aria-valuemin", String(min));
|
|
49
|
+
handle.setAttribute("aria-valuemax", String(max));
|
|
50
|
+
handle.setAttribute("aria-valuenow", String(value));
|
|
51
|
+
};
|
|
52
|
+
const persist = () => {
|
|
53
|
+
preferred = element.getBoundingClientRect().width;
|
|
54
|
+
try {
|
|
55
|
+
localStorage.setItem(options.key, String(preferred));
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
/* Optional. */
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
let drag;
|
|
62
|
+
handle.addEventListener("pointerdown", (event) => {
|
|
63
|
+
if (event.button !== 0 || drag)
|
|
64
|
+
return;
|
|
65
|
+
event.preventDefault();
|
|
66
|
+
handle.focus();
|
|
67
|
+
drag = {
|
|
68
|
+
id: event.pointerId,
|
|
69
|
+
x: event.clientX,
|
|
70
|
+
width: element.getBoundingClientRect().width,
|
|
71
|
+
};
|
|
72
|
+
handle.setPointerCapture(event.pointerId);
|
|
73
|
+
handle.classList.add("drag");
|
|
74
|
+
document.body.classList.add("resizing");
|
|
75
|
+
});
|
|
76
|
+
handle.addEventListener("pointermove", (event) => {
|
|
77
|
+
if (drag?.id !== event.pointerId)
|
|
78
|
+
return;
|
|
79
|
+
apply(drag.width + options.direction * (event.clientX - drag.x));
|
|
80
|
+
});
|
|
81
|
+
const stop = (event) => {
|
|
82
|
+
if (drag?.id !== event.pointerId)
|
|
83
|
+
return;
|
|
84
|
+
drag = undefined;
|
|
85
|
+
handle.classList.remove("drag");
|
|
86
|
+
document.body.classList.remove("resizing");
|
|
87
|
+
persist();
|
|
88
|
+
};
|
|
89
|
+
handle.addEventListener("pointerup", stop);
|
|
90
|
+
handle.addEventListener("pointercancel", stop);
|
|
91
|
+
handle.addEventListener("lostpointercapture", stop);
|
|
92
|
+
handle.addEventListener("dblclick", () => {
|
|
93
|
+
preferred = undefined;
|
|
94
|
+
try {
|
|
95
|
+
localStorage.removeItem(options.key);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
/* Optional. */
|
|
99
|
+
}
|
|
100
|
+
apply(requested());
|
|
101
|
+
});
|
|
102
|
+
handle.addEventListener("keydown", (event) => {
|
|
103
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight")
|
|
104
|
+
return;
|
|
105
|
+
event.preventDefault();
|
|
106
|
+
apply(element.getBoundingClientRect().width +
|
|
107
|
+
options.direction * (event.key === "ArrowRight" ? 20 : -20));
|
|
108
|
+
persist();
|
|
109
|
+
});
|
|
110
|
+
return [{ ...options, element, apply, requested, persist, property }];
|
|
111
|
+
});
|
|
112
|
+
const layout = () => {
|
|
113
|
+
// On a smaller viewport, make room for the navigation before clamping both panels.
|
|
114
|
+
const right = panels.find((panel) => panel.direction === -1);
|
|
115
|
+
if (right) {
|
|
116
|
+
const available = Math.max(0, window.innerWidth - (closed() ? 52 : 200) - contentWidth());
|
|
117
|
+
right.element.style.setProperty(right.property, `${Math.min(right.requested(), available)}px`);
|
|
118
|
+
}
|
|
119
|
+
for (const panel of panels) {
|
|
120
|
+
if (panel.direction === 1 && closed())
|
|
121
|
+
continue;
|
|
122
|
+
panel.apply(panel.requested());
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
window.addEventListener("resize", layout);
|
|
126
|
+
document.getElementById("sidebar-toggle")?.addEventListener("click", layout);
|
|
127
|
+
window.addEventListener("keydown", (event) => {
|
|
128
|
+
if (event.defaultPrevented || !(event.ctrlKey || event.metaKey) || !event.altKey)
|
|
129
|
+
return;
|
|
130
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight")
|
|
131
|
+
return;
|
|
132
|
+
const right = panels.find((panel) => panel.direction === -1);
|
|
133
|
+
if (!right)
|
|
134
|
+
return;
|
|
135
|
+
event.preventDefault();
|
|
136
|
+
right.apply(right.element.getBoundingClientRect().width + (event.key === "ArrowLeft" ? 40 : -40));
|
|
137
|
+
right.persist();
|
|
138
|
+
});
|
|
139
|
+
layout();
|
|
140
|
+
};
|
|
141
|
+
/** The navigation is replaced on refresh; keep listeners and height on its stable sidebar. */
|
|
142
|
+
export const mountToolsResize = () => {
|
|
143
|
+
const sidebar = document.getElementById("sidebar");
|
|
144
|
+
if (!sidebar || !document.getElementById("nav-tools"))
|
|
145
|
+
return () => { };
|
|
146
|
+
const key = "docs:tools-height";
|
|
147
|
+
let preferred;
|
|
148
|
+
try {
|
|
149
|
+
const saved = Number(localStorage.getItem(key));
|
|
150
|
+
if (Number.isFinite(saved) && saved > 0)
|
|
151
|
+
preferred = saved;
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
/* Persistence is optional. */
|
|
155
|
+
}
|
|
156
|
+
const apply = (height = preferred ?? Math.min(220, innerHeight * 0.4)) => {
|
|
157
|
+
const handle = document.getElementById("tools-resize");
|
|
158
|
+
if (!handle)
|
|
159
|
+
return;
|
|
160
|
+
const max = Math.max(80, sidebar.clientHeight - 100);
|
|
161
|
+
const min = Math.min(144, max);
|
|
162
|
+
const value = Math.round(Math.max(min, Math.min(height, max)));
|
|
163
|
+
sidebar.style.setProperty("--tools-height", `${value}px`);
|
|
164
|
+
handle.setAttribute("aria-valuemin", String(min));
|
|
165
|
+
handle.setAttribute("aria-valuemax", String(max));
|
|
166
|
+
handle.setAttribute("aria-valuenow", String(value));
|
|
167
|
+
};
|
|
168
|
+
const persist = () => {
|
|
169
|
+
preferred = Number.parseFloat(sidebar.style.getPropertyValue("--tools-height"));
|
|
170
|
+
try {
|
|
171
|
+
localStorage.setItem(key, String(preferred));
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
/* Optional. */
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
const isHandle = (event) => event.target instanceof Element && !!event.target.closest("#tools-resize");
|
|
178
|
+
const height = () => document.getElementById("nav-tools")?.getBoundingClientRect().height ?? 0;
|
|
179
|
+
let drag;
|
|
180
|
+
sidebar.addEventListener("pointerdown", (event) => {
|
|
181
|
+
if (!isHandle(event) || event.button !== 0 || drag)
|
|
182
|
+
return;
|
|
183
|
+
const handle = document.getElementById("tools-resize");
|
|
184
|
+
if (!handle)
|
|
185
|
+
return;
|
|
186
|
+
event.preventDefault();
|
|
187
|
+
handle.focus({ preventScroll: true });
|
|
188
|
+
drag = { id: event.pointerId, y: event.clientY, height: height(), handle };
|
|
189
|
+
handle.setPointerCapture(event.pointerId);
|
|
190
|
+
document.body.classList.add("resizing-tools");
|
|
191
|
+
});
|
|
192
|
+
sidebar.addEventListener("pointermove", (event) => {
|
|
193
|
+
if (drag?.id === event.pointerId)
|
|
194
|
+
apply(drag.height + drag.y - event.clientY);
|
|
195
|
+
});
|
|
196
|
+
const stop = () => {
|
|
197
|
+
if (!drag)
|
|
198
|
+
return;
|
|
199
|
+
drag = undefined;
|
|
200
|
+
document.body.classList.remove("resizing-tools");
|
|
201
|
+
persist();
|
|
202
|
+
};
|
|
203
|
+
for (const type of ["pointerup", "pointercancel", "lostpointercapture"])
|
|
204
|
+
sidebar.addEventListener(type, (event) => {
|
|
205
|
+
if (drag?.id === event.pointerId)
|
|
206
|
+
stop();
|
|
207
|
+
});
|
|
208
|
+
sidebar.addEventListener("keydown", (event) => {
|
|
209
|
+
if (!isHandle(event) || (event.key !== "ArrowUp" && event.key !== "ArrowDown"))
|
|
210
|
+
return;
|
|
211
|
+
event.preventDefault();
|
|
212
|
+
apply(height() + (event.key === "ArrowUp" ? 20 : -20));
|
|
213
|
+
persist();
|
|
214
|
+
});
|
|
215
|
+
sidebar.addEventListener("dblclick", (event) => {
|
|
216
|
+
if (!isHandle(event))
|
|
217
|
+
return;
|
|
218
|
+
preferred = undefined;
|
|
219
|
+
try {
|
|
220
|
+
localStorage.removeItem(key);
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
/* Optional. */
|
|
224
|
+
}
|
|
225
|
+
apply();
|
|
226
|
+
});
|
|
227
|
+
window.addEventListener("resize", () => apply());
|
|
228
|
+
const restore = () => {
|
|
229
|
+
if (drag && !drag.handle.isConnected)
|
|
230
|
+
stop();
|
|
231
|
+
apply();
|
|
232
|
+
};
|
|
233
|
+
const nav = document.getElementById("nav-groups");
|
|
234
|
+
if (nav)
|
|
235
|
+
new MutationObserver(restore).observe(nav, { childList: true });
|
|
236
|
+
restore();
|
|
237
|
+
return restore;
|
|
238
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { TermEntry } from "../core/content-types.js";
|
|
2
|
+
interface SourceLocation {
|
|
3
|
+
file: string;
|
|
4
|
+
line: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ResourceIndex {
|
|
7
|
+
terms: {
|
|
8
|
+
entry: TermEntry;
|
|
9
|
+
source: SourceLocation;
|
|
10
|
+
}[];
|
|
11
|
+
code: {
|
|
12
|
+
language: string;
|
|
13
|
+
caption: string;
|
|
14
|
+
content: string;
|
|
15
|
+
source: SourceLocation;
|
|
16
|
+
}[];
|
|
17
|
+
urls: {
|
|
18
|
+
url: string;
|
|
19
|
+
host: string;
|
|
20
|
+
sources: SourceLocation[];
|
|
21
|
+
}[];
|
|
22
|
+
errors: string[];
|
|
23
|
+
}
|
|
24
|
+
/** Index authored content, including files not referenced by any document. */
|
|
25
|
+
export declare const resourceIndex: (root: string, files: readonly string[]) => ResourceIndex;
|
|
26
|
+
export type ResourceView = "files" | "dictionary" | "code" | "urls";
|
|
27
|
+
export declare const resourceTabs: (view: ResourceView) => string;
|
|
28
|
+
export declare const resourceLibraryHtml: (index: ResourceIndex, view: Exclude<ResourceView, "files">) => string;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { visit } from "unist-util-visit";
|
|
2
|
+
import { parseTermSource } from "../compiler/terms.js";
|
|
3
|
+
import { readTextfile } from "../compiler/textfile.js";
|
|
4
|
+
import { blocksHtml, escapeHtml } from "../core/html.js";
|
|
5
|
+
import { parseMdast } from "../core/markdown.js";
|
|
6
|
+
/** Index authored content, including files not referenced by any document. */
|
|
7
|
+
export const resourceIndex = (root, files) => {
|
|
8
|
+
const result = { terms: [], code: [], urls: [], errors: [] };
|
|
9
|
+
const urls = new Map();
|
|
10
|
+
const terms = (raw, source) => {
|
|
11
|
+
const parsed = parseTermSource(`${source.file}#L${source.line}`, raw);
|
|
12
|
+
result.terms.push(...parsed.entries.map((entry) => ({ entry, source })));
|
|
13
|
+
result.errors.push(...parsed.errors.map((error) => `${source.file}:L${source.line + error.line}: ${error.message}`));
|
|
14
|
+
};
|
|
15
|
+
const scan = (tree, file, offset = 0) => {
|
|
16
|
+
const definitions = new Map();
|
|
17
|
+
visit(tree, "definition", (node) => {
|
|
18
|
+
definitions.set(node.identifier, node.url);
|
|
19
|
+
});
|
|
20
|
+
visit(tree, (node) => {
|
|
21
|
+
const source = { file, line: offset + (node.position?.start.line ?? 1) };
|
|
22
|
+
if (node.type === "code") {
|
|
23
|
+
const language = node.lang?.toLowerCase() || "text";
|
|
24
|
+
result.code.push({
|
|
25
|
+
language,
|
|
26
|
+
caption: node.meta ?? "",
|
|
27
|
+
content: node.value,
|
|
28
|
+
source,
|
|
29
|
+
});
|
|
30
|
+
if (language === "termth")
|
|
31
|
+
terms(node.value, { ...source, line: source.line + 1 });
|
|
32
|
+
if (language === "callouth")
|
|
33
|
+
scan(parseMdast(node.value), file, source.line);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const target = node.type === "link" || node.type === "image"
|
|
37
|
+
? node.url
|
|
38
|
+
: node.type === "linkReference" || node.type === "imageReference"
|
|
39
|
+
? definitions.get(node.identifier)
|
|
40
|
+
: undefined;
|
|
41
|
+
if (!target)
|
|
42
|
+
return;
|
|
43
|
+
try {
|
|
44
|
+
const url = new URL(target);
|
|
45
|
+
if (!["http:", "https:", "mailto:"].includes(url.protocol))
|
|
46
|
+
return;
|
|
47
|
+
const key = url.href;
|
|
48
|
+
const entry = urls.get(key) ?? {
|
|
49
|
+
url: key,
|
|
50
|
+
host: url.host || url.protocol,
|
|
51
|
+
sources: [],
|
|
52
|
+
};
|
|
53
|
+
entry.sources.push(source);
|
|
54
|
+
urls.set(key, entry);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Local paths and anchors are not external URL resources.
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
for (const file of new Set(files)) {
|
|
62
|
+
if (!/\.(?:md|termth)$/i.test(file))
|
|
63
|
+
continue;
|
|
64
|
+
try {
|
|
65
|
+
const raw = readTextfile(root, file);
|
|
66
|
+
if (/\.termth$/i.test(file))
|
|
67
|
+
terms(raw, { file, line: 1 });
|
|
68
|
+
else
|
|
69
|
+
scan(parseMdast(raw), file);
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
result.errors.push(`${file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
result.terms.sort((a, b) => a.entry.name.localeCompare(b.entry.name, undefined, { numeric: true }));
|
|
76
|
+
result.urls = [...urls.values()].sort((a, b) => a.url.localeCompare(b.url));
|
|
77
|
+
return result;
|
|
78
|
+
};
|
|
79
|
+
export const resourceTabs = (view) => view === "files"
|
|
80
|
+
? ""
|
|
81
|
+
: `<nav class="resource-tabs" aria-label="Resource views" data-i18n-aria-label="Resource views">${[
|
|
82
|
+
["dictionary", "Dictionary"],
|
|
83
|
+
["code", "Code blocks"],
|
|
84
|
+
["urls", "URLs"],
|
|
85
|
+
]
|
|
86
|
+
.map(([key, label]) => `<a href="/_statics${key === "dictionary" ? "" : `/${key}`}"${view === key ? ' aria-current="page"' : ""} data-i18n="${label}">${label}</a>`)
|
|
87
|
+
.join("")}</nav>`;
|
|
88
|
+
const sourceLink = ({ file, line }) => `<a class="resource-source" href="/_files/file/${encodeURIComponent(file)}#L${line}" data-resource-source="${escapeHtml(file)}" data-resource-line="${line}" title="${escapeHtml(file)}:L${line}"><span class="resource-source-file">${escapeHtml(file)}</span><span>L${line}</span></a>`;
|
|
89
|
+
export const resourceLibraryHtml = (index, view) => {
|
|
90
|
+
const groupLabel = view === "code" ? "Code language" : "Domain";
|
|
91
|
+
const groups = view === "dictionary"
|
|
92
|
+
? []
|
|
93
|
+
: [
|
|
94
|
+
...new Set(view === "code"
|
|
95
|
+
? index.code.map((item) => item.language)
|
|
96
|
+
: index.urls.map((item) => item.host)),
|
|
97
|
+
].sort();
|
|
98
|
+
const items = view === "dictionary"
|
|
99
|
+
? index.terms.map(({ entry, source }) => `<details class="resource-item resource-term" data-resource-item><summary><span class="resource-name" title="${escapeHtml(entry.name)}">${escapeHtml(entry.name)}</span>${sourceLink(source)}</summary><div class="resource-body"><p class="term-definition">${escapeHtml(entry.definition)}</p>${entry.description ? `<p class="resource-description">${escapeHtml(entry.description)}</p>` : ""}</div></details>`)
|
|
100
|
+
: view === "code"
|
|
101
|
+
? index.code.map(({ language, caption, content, source }) => `<details class="resource-item resource-code" data-resource-item data-resource-group="${escapeHtml(language)}"><summary><span class="resource-badge">${escapeHtml(language)}</span>${caption ? `<span class="resource-name" title="${escapeHtml(caption)}">${escapeHtml(caption)}</span>` : ""}${sourceLink(source)}</summary><div class="resource-body">${blocksHtml([{ type: "code", lang: language === "mermaid" ? "text" : language, lines: content.split("\n") }])}</div></details>`)
|
|
102
|
+
: index.urls.map(({ url, host, sources }) => `<details class="resource-item resource-url" data-resource-item data-resource-group="${escapeHtml(host)}"><summary><a class="resource-name" href="${escapeHtml(url)}" title="${escapeHtml(url)}" target="_blank" rel="noopener noreferrer">${escapeHtml(url)}</a><span class="resource-usage" title="references" data-i18n-title="references">${sources.length}</span></summary><div class="resource-body resource-sources">${sources.map(sourceLink).join("")}</div></details>`);
|
|
103
|
+
return `<section class="resource-results" data-resource-results><div class="resource-toolbar"><span data-i18n="Name">Name</span><label class="resource-search"><svg width="13" height="13" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M14 14l4 4M15 9a6 6 0 1 1-12 0 6 6 0 0 1 12 0"/></svg><input type="search" data-resource-search placeholder="Search resources" aria-label="Search resources" data-i18n-placeholder="Search resources" data-i18n-aria-label="Search resources"></label>${groups.length ? `<select data-resource-filter aria-label="${groupLabel}" data-i18n-aria-label="${groupLabel}"><option value="" data-i18n="All">All</option>${groups.map((group) => `<option value="${escapeHtml(group)}">${escapeHtml(group)}</option>`).join("")}</select>` : ""}<span class="resource-count" data-resource-count role="status" aria-live="polite">${items.length}</span></div>${index.errors.length ? `<details class="resource-errors"><summary><span data-i18n="Files with errors">Files with errors</span> (${index.errors.length})</summary><ul>${index.errors.map((error) => `<li>${escapeHtml(error)}</li>`).join("")}</ul></details>` : ""}<div class="resource-items resource-${view}">${items.join("")}</div><p class="resource-empty" data-resource-empty${items.length ? " hidden" : ""} data-i18n="No matching resources">No matching resources</p></section>`;
|
|
104
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Site } from "./serve.js";
|
|
2
|
+
export interface SearchSection {
|
|
3
|
+
path: string;
|
|
4
|
+
file: string;
|
|
5
|
+
folder: boolean;
|
|
6
|
+
title: string;
|
|
7
|
+
heading: string;
|
|
8
|
+
anchor: string;
|
|
9
|
+
text: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const searchIndex: (site: Site) => SearchSection[];
|
|
12
|
+
export declare const searchSections: (index: SearchSection[], query: string, currentPath?: string) => (SearchSection & {
|
|
13
|
+
snippet: string;
|
|
14
|
+
})[];
|
|
15
|
+
export declare const SEARCH_LABELS: string[];
|
|
16
|
+
export declare const mountSearch: (initial: SearchSection[], search: typeof searchSections, labels: Record<string, string>, published: boolean) => void;
|