for-humanity 0.4.3 → 0.5.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/CHANGELOG.md +23 -0
- package/README.md +5 -5
- package/dist/browser.js +39 -0
- package/dist/cli.css +372 -299
- package/dist/cli.js +1125 -301
- package/package.json +8 -11
- package/src/component/widget/{shell → cursor-face}/_constant/cursor-face.ts +5 -0
- package/src/component/widget/cursor-face/wg-cursor-face.css +15 -0
- package/src/component/widget/cursor-face/wg-cursor-face.tsx +153 -0
- package/src/component/widget/navigation/_constant/navigation-data-schema.ts +35 -0
- package/src/component/widget/navigation/_constant/navigation.ts +9 -0
- package/src/component/widget/navigation/_function/restore-navigation-scroll.ts +59 -0
- package/src/{content → component/widget/navigation/_function}/to-doc-groups/_to-doc-branches.ts +2 -2
- package/src/{content → component/widget/navigation/_function}/to-doc-groups/_to-doc-group-branches.ts +3 -3
- package/src/{content → component/widget/navigation/_function}/to-doc-groups/to-doc-groups.ts +1 -1
- package/src/component/widget/navigation/_function/to-navigation-branch-id.ts +6 -0
- package/src/component/widget/navigation/_function/to-navigation-data/_to-navigation-document.ts +14 -0
- package/src/component/widget/navigation/_function/to-navigation-data/_to-navigation-group.ts +14 -0
- package/src/component/widget/navigation/_function/to-navigation-data/to-navigation-data.ts +25 -0
- package/src/component/widget/navigation/_function/to-navigation-json.ts +8 -0
- package/src/component/widget/{shell → navigation}/_function/to-toc-groups.ts +2 -2
- package/src/{type → component/widget/navigation/_type}/doc-group.ts +1 -1
- package/src/component/widget/navigation/_type/navigation-data.ts +83 -0
- package/src/component/widget/navigation/_type/navigation-focus-snapshot.ts +21 -0
- package/src/component/widget/navigation/_wg-navigation-branch-toggle.css +28 -0
- package/src/component/widget/navigation/_wg-navigation-branch-toggle.tsx +48 -0
- package/src/component/widget/{shell/_wg-shell-nav-list.css → navigation/_wg-navigation-nav-list.css} +24 -16
- package/src/component/widget/navigation/_wg-navigation-nav-list.tsx +106 -0
- package/src/component/widget/{shell/_wg-shell-nav.css → navigation/_wg-navigation-nav.css} +9 -3
- package/src/component/widget/navigation/_wg-navigation-nav.tsx +43 -0
- package/src/component/widget/navigation/_wg-navigation-scroll.tsx +117 -0
- package/src/component/widget/{shell/_wg-shell-toc.css → navigation/_wg-navigation-toc.css} +43 -26
- package/src/component/widget/navigation/_wg-navigation-toc.tsx +155 -0
- package/src/component/widget/navigation/wg-navigation.css +282 -0
- package/src/component/widget/navigation/wg-navigation.tsx +479 -0
- package/src/component/widget/prose/_function/rehype-sections/rehype-sections.ts +1 -1
- package/src/component/widget/shell/wg-shell.css +13 -309
- package/src/component/widget/shell/wg-shell.tsx +16 -75
- package/src/component/widget/shell-controls/wg-shell-controls.css +4 -0
- package/src/component/widget/shell-controls/wg-shell-controls.tsx +170 -0
- package/src/constant/asset.ts +0 -5
- package/src/entry/browser/browser.tsx +22 -0
- package/src/{app.tsx → entry/cli/_function/create-app.tsx} +6 -6
- package/src/{content → entry/cli/_function/create-processor}/create-processor.ts +3 -3
- package/src/{content → entry/cli/_function}/read-docs.ts +1 -1
- package/src/{content → entry/cli/_function}/read-home.ts +1 -1
- package/src/{content/read-docs.test.ts → entry/cli/cli.test.ts} +105 -30
- package/src/{cli.ts → entry/cli/cli.ts} +10 -11
- package/src/store/navigation/_constant/tree.ts +6 -0
- package/src/store/navigation/create-navigation-stores.test.ts +92 -0
- package/src/store/navigation/create-navigation-stores.ts +73 -0
- package/src/store/navigation/navigation-state.ts +46 -0
- package/src/store/navigation/navigation-storage.ts +14 -0
- package/src/store/navigation/to-navigation-scroll-state.ts +42 -0
- package/src/store/navigation/to-navigation-tree-state.ts +19 -0
- package/src/store/navigation/use-navigation-tree-store.ts +12 -0
- package/src/style/token.css +4 -2
- package/src/type/doc-content.ts +1 -1
- package/src/type/doc-file-data.ts +1 -1
- package/src/{component/widget/shell/_type → type}/doc-outline.ts +1 -1
- package/src/type/site-assets.ts +2 -2
- package/dist/client.js +0 -6
- package/src/client.ts +0 -335
- package/src/component/widget/shell/_constant/navigation.ts +0 -9
- package/src/component/widget/shell/_function/bind-mobile-navigation.ts +0 -140
- package/src/component/widget/shell/_function/bind-navigation-scroll.ts +0 -123
- package/src/component/widget/shell/_wg-shell-nav-list.tsx +0 -87
- package/src/component/widget/shell/_wg-shell-nav.tsx +0 -49
- package/src/component/widget/shell/_wg-shell-toc.tsx +0 -57
- /package/src/{constant → component/widget/navigation/_constant}/locale.ts +0 -0
- /package/src/component/widget/{shell → navigation}/_constant/reading-line.ts +0 -0
- /package/src/{type → component/widget/navigation/_type}/doc-branch.ts +0 -0
- /package/src/component/widget/{shell → navigation}/_type/toc-group.ts +0 -0
- /package/src/{constant → entry/cli/_constant}/cli.ts +0 -0
- /package/src/{dev.ts → entry/cli/_function/create-dev-app.ts} +0 -0
- /package/src/{content/rehype-assets.ts → entry/cli/_function/create-processor/_rehype-assets.ts} +0 -0
- /package/src/{content/rehype-heading-ids.ts → entry/cli/_function/create-processor/_rehype-heading-ids.ts} +0 -0
- /package/src/{content/remark-report.ts → entry/cli/_function/create-processor/_remark-report.ts} +0 -0
- /package/src/{component/widget/prose/_type → type}/doc-section.ts +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// src/cli.ts
|
|
3
|
+
// src/entry/cli/cli.ts
|
|
4
4
|
import { EventEmitter } from "node:events";
|
|
5
|
-
import { existsSync as existsSync3, watch } from "node:fs";
|
|
5
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, watch } from "node:fs";
|
|
6
6
|
import { copyFile, mkdir, rm, writeFile } from "node:fs/promises";
|
|
7
7
|
import { basename as basename2, dirname as dirname4, extname as extname4, join as join4, relative as relative4, resolve as resolve3, sep as sep3 } from "node:path";
|
|
8
8
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
@@ -12,118 +12,31 @@ import { debounce } from "es-toolkit";
|
|
|
12
12
|
import { Hono as Hono3 } from "hono";
|
|
13
13
|
import { toSSG } from "hono/ssg";
|
|
14
14
|
|
|
15
|
-
// src/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
// src/component/widget/shell/_function/to-toc-groups.ts
|
|
37
|
-
import { takeWhile } from "es-toolkit/array";
|
|
38
|
-
|
|
39
|
-
// src/component/widget/prose/_constant/section.ts
|
|
40
|
-
var section_heading_depth = {
|
|
41
|
-
section: 2,
|
|
42
|
-
sub: 3
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
// src/component/widget/shell/_function/to-toc-groups.ts
|
|
46
|
-
var toTocGroups = (outline) => {
|
|
47
|
-
const entries = outline.headings.filter((heading) => heading.depth === section_heading_depth.section || heading.depth === section_heading_depth.sub).map((heading, index) => ({ heading, section: outline.sections[index] }));
|
|
48
|
-
const sections = entries.flatMap(
|
|
49
|
-
(entry, index) => entry.heading.depth === section_heading_depth.section ? [
|
|
50
|
-
{
|
|
51
|
-
heading: entry.heading,
|
|
52
|
-
part: entry.section.part,
|
|
53
|
-
subs: takeWhile(entries.slice(index + 1), (sub) => sub.heading.depth !== section_heading_depth.section).map((sub) => ({
|
|
54
|
-
heading: sub.heading
|
|
55
|
-
}))
|
|
56
|
-
}
|
|
57
|
-
] : []
|
|
58
|
-
);
|
|
59
|
-
return sections.flatMap(
|
|
60
|
-
(section, index) => index === 0 || section.part !== void 0 ? [
|
|
61
|
-
{
|
|
62
|
-
part: section.part,
|
|
63
|
-
sections: [section, ...takeWhile(sections.slice(index + 1), (next) => next.part === void 0)]
|
|
64
|
-
}
|
|
65
|
-
] : []
|
|
66
|
-
);
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
// src/component/widget/shell/_wg-shell-nav.tsx
|
|
70
|
-
import clsx3 from "clsx";
|
|
71
|
-
|
|
72
|
-
// src/component/widget/shell/_wg-shell-nav-list.tsx
|
|
73
|
-
import clsx2 from "clsx";
|
|
74
|
-
import { Fragment } from "react";
|
|
75
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
76
|
-
var WgShellNavList = (props) => {
|
|
77
|
-
const currentAncestors = new Set(props.currentDoc?.ancestors);
|
|
78
|
-
const entries = [
|
|
79
|
-
...props.group.docs.map((doc) => {
|
|
80
|
-
const active = doc.id === props.currentDoc?.id;
|
|
81
|
-
return { kind: "document", key: `doc:${doc.id}`, doc, active, current: active || currentAncestors.has(doc.id) };
|
|
82
|
-
}),
|
|
83
|
-
...props.group.groups.map((group) => ({
|
|
84
|
-
kind: "group",
|
|
85
|
-
key: `group:${JSON.stringify(group.path)}`,
|
|
86
|
-
group,
|
|
87
|
-
current: group.path.every((name, index) => name === props.currentDoc?.data.group[index])
|
|
88
|
-
}))
|
|
89
|
-
];
|
|
90
|
-
const currentIndex = entries.findIndex((entry) => entry.current);
|
|
91
|
-
return /* @__PURE__ */ jsx2("ul", { className: clsx2("wg_shellNavList__root"), "aria-label": props.group.name, children: entries.map((entry, index) => /* @__PURE__ */ jsxs2(
|
|
92
|
-
"li",
|
|
93
|
-
{
|
|
94
|
-
className: clsx2("wg_shellNavList__item", {
|
|
95
|
-
"wg_shellNavList__item--trail": index < currentIndex,
|
|
96
|
-
"wg_shellNavList__item--current": entry.current
|
|
97
|
-
}),
|
|
98
|
-
children: [
|
|
99
|
-
entry.kind === "document" && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
100
|
-
/* @__PURE__ */ jsx2(
|
|
101
|
-
"a",
|
|
102
|
-
{
|
|
103
|
-
className: clsx2("wg_shellNavList__link", { "wg_shellNavList__link--active": entry.active }),
|
|
104
|
-
href: `/${entry.doc.id}/`,
|
|
105
|
-
title: entry.doc.data.label,
|
|
106
|
-
"aria-current": entry.active ? "page" : void 0,
|
|
107
|
-
children: entry.doc.data.name
|
|
108
|
-
}
|
|
109
|
-
),
|
|
110
|
-
entry.doc.children !== void 0 && /* @__PURE__ */ jsx2(
|
|
111
|
-
WgShellNavList,
|
|
112
|
-
{
|
|
113
|
-
group: { name: entry.doc.data.name, path: entry.doc.data.group, docs: entry.doc.children, groups: [] },
|
|
114
|
-
currentDoc: props.currentDoc
|
|
115
|
-
}
|
|
116
|
-
)
|
|
117
|
-
] }),
|
|
118
|
-
entry.kind === "group" && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
119
|
-
/* @__PURE__ */ jsx2("span", { className: clsx2("wg_shellNavList__branch"), children: entry.group.name }),
|
|
120
|
-
/* @__PURE__ */ jsx2(WgShellNavList, { group: entry.group, currentDoc: props.currentDoc })
|
|
121
|
-
] })
|
|
122
|
-
]
|
|
123
|
-
},
|
|
124
|
-
entry.key
|
|
125
|
-
)) });
|
|
15
|
+
// src/constant/asset.ts
|
|
16
|
+
var asset_dir = "_fh";
|
|
17
|
+
var asset_style_path = `/${asset_dir}/style.css`;
|
|
18
|
+
var asset_font_dir = `/${asset_dir}/fonts`;
|
|
19
|
+
var asset_reload_path = `/${asset_dir}/reload`;
|
|
20
|
+
var asset_favicon_path = "/favicon.svg";
|
|
21
|
+
var asset_content_types = {
|
|
22
|
+
".css": "text/css; charset=utf-8",
|
|
23
|
+
".js": "text/javascript; charset=utf-8",
|
|
24
|
+
".woff2": "font/woff2",
|
|
25
|
+
".svg": "image/svg+xml",
|
|
26
|
+
".png": "image/png",
|
|
27
|
+
".jpg": "image/jpeg",
|
|
28
|
+
".jpeg": "image/jpeg",
|
|
29
|
+
".gif": "image/gif",
|
|
30
|
+
".webp": "image/webp",
|
|
31
|
+
".avif": "image/avif",
|
|
32
|
+
".pdf": "application/pdf",
|
|
33
|
+
".csv": "text/csv; charset=utf-8",
|
|
34
|
+
".txt": "text/plain; charset=utf-8",
|
|
35
|
+
".zip": "application/zip"
|
|
126
36
|
};
|
|
37
|
+
var asset_content_type_default = "application/octet-stream";
|
|
38
|
+
var asset_media_dir = `/${asset_dir}/media`;
|
|
39
|
+
var asset_media_extensions = /* @__PURE__ */ new Set([".svg", ".png", ".jpg", ".jpeg", ".gif", ".webp", ".avif", ".pdf", ".csv", ".txt", ".zip"]);
|
|
127
40
|
|
|
128
41
|
// src/constant/copy.ts
|
|
129
42
|
var copy_site_title_default = "for humanity";
|
|
@@ -152,11 +65,52 @@ var copy_warn_broken_link = "\uC5C6\uB294 \uBB38\uC11C\uB85C \uAC74 \uB9C1\uD06C
|
|
|
152
65
|
var copy_warn_unknown_status = "\uC124\uC815\uC5D0 \uC5C6\uB294 \uC0C1\uD0DC \uBB38\uAD6C\uB2E4";
|
|
153
66
|
var copy_error_asset = "\uC790\uC6D0\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uB2E4";
|
|
154
67
|
|
|
155
|
-
// src/constant/
|
|
68
|
+
// src/constant/font.ts
|
|
69
|
+
var font_sans_css = "src/asset/font/pretendard/pretendardvariable-dynamic-subset.css";
|
|
70
|
+
var font_mono_css = "src/asset/font/jetbrains-mono/jetbrains-mono.css";
|
|
71
|
+
var font_brand_css = "src/asset/font/architects-daughter/architects-daughter.css";
|
|
72
|
+
var font_sans_preload_file = "PretendardVariable.subset.91.woff2";
|
|
73
|
+
var font_display_strategy = "optional";
|
|
74
|
+
var font_hash_length = 12;
|
|
75
|
+
var font_cache_control = "public, max-age=31536000, immutable";
|
|
76
|
+
|
|
77
|
+
// src/constant/site.ts
|
|
78
|
+
var site_config_absent = {};
|
|
79
|
+
var site_navigation_default = [];
|
|
80
|
+
|
|
81
|
+
// src/entry/cli/_constant/cli.ts
|
|
82
|
+
var cli_default_command = "dev";
|
|
83
|
+
var cli_default_docs_dir = ".";
|
|
84
|
+
var cli_config_file_name = "for-humanity.config.mjs";
|
|
85
|
+
var cli_dev_port = 4321;
|
|
86
|
+
var cli_reload_delay_ms = 150;
|
|
87
|
+
|
|
88
|
+
// src/entry/cli/_function/create-app.tsx
|
|
89
|
+
import { Hono } from "hono";
|
|
90
|
+
import { html } from "hono/html";
|
|
91
|
+
import { ssgParams } from "hono/ssg";
|
|
92
|
+
|
|
93
|
+
// src/component/widget/prose/wg-prose.tsx
|
|
94
|
+
import clsx from "clsx";
|
|
95
|
+
import { jsx, jsxs } from "hono/jsx/jsx-runtime";
|
|
96
|
+
var WgProse = (props) => {
|
|
97
|
+
if (props.html !== void 0) {
|
|
98
|
+
return /* @__PURE__ */ jsx("article", { className: clsx("wg_prose__root"), dangerouslySetInnerHTML: { __html: props.html } });
|
|
99
|
+
}
|
|
100
|
+
return /* @__PURE__ */ jsx("article", { className: clsx("wg_prose__root"), children: props.head !== void 0 && /* @__PURE__ */ jsxs("header", { className: clsx("wg_prose__head"), children: [
|
|
101
|
+
/* @__PURE__ */ jsx("h1", { children: props.head.title }),
|
|
102
|
+
props.head.lead !== void 0 && /* @__PURE__ */ jsx("p", { children: props.head.lead })
|
|
103
|
+
] }) });
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// src/component/widget/shell/wg-shell.tsx
|
|
107
|
+
import clsx10 from "clsx";
|
|
108
|
+
|
|
109
|
+
// src/component/widget/navigation/_constant/locale.ts
|
|
156
110
|
var locale_doc_name = "en";
|
|
157
111
|
var locale_doc_group = "ko";
|
|
158
112
|
|
|
159
|
-
// src/
|
|
113
|
+
// src/component/widget/navigation/_function/to-doc-groups/_to-doc-branches.ts
|
|
160
114
|
var toDocBranches = (options) => {
|
|
161
115
|
return options.docs.toSorted((a, b) => a.data.order - b.data.order || a.data.name.localeCompare(b.data.name, locale_doc_name) || a.id.localeCompare(b.id, locale_doc_name)).map((doc) => {
|
|
162
116
|
const children = options.children.get(doc.id);
|
|
@@ -164,7 +118,7 @@ var toDocBranches = (options) => {
|
|
|
164
118
|
});
|
|
165
119
|
};
|
|
166
120
|
|
|
167
|
-
// src/
|
|
121
|
+
// src/component/widget/navigation/_function/to-doc-groups/_to-doc-group-branches.ts
|
|
168
122
|
var toDocGroupBranches = (options) => {
|
|
169
123
|
return [
|
|
170
124
|
...Map.groupBy(
|
|
@@ -198,174 +152,1086 @@ var toDocGroupBranches = (options) => {
|
|
|
198
152
|
});
|
|
199
153
|
};
|
|
200
154
|
|
|
201
|
-
// src/
|
|
155
|
+
// src/component/widget/navigation/_function/to-doc-groups/to-doc-groups.ts
|
|
202
156
|
var toDocGroups = (options) => {
|
|
203
157
|
const positions = new Map(options.navigation.flatMap((path, index) => path.map((_name, depth) => [JSON.stringify(path.slice(0, depth + 1)), index])).toReversed());
|
|
204
158
|
const children = Map.groupBy(options.docs, (doc) => doc.data.parent);
|
|
205
159
|
return toDocGroupBranches({ docs: options.docs, children, path: [], positions, unlistedPosition: options.navigation.length });
|
|
206
160
|
};
|
|
207
161
|
|
|
208
|
-
// src/component/widget/
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
162
|
+
// src/component/widget/navigation/_function/to-navigation-data/_to-navigation-document.ts
|
|
163
|
+
var toNavigationDocument = (options) => ({
|
|
164
|
+
id: options.doc.id,
|
|
165
|
+
name: options.doc.data.name,
|
|
166
|
+
label: options.doc.data.label,
|
|
167
|
+
active: options.doc.id === options.current,
|
|
168
|
+
current: options.doc.id === options.current || options.ancestors.has(options.doc.id),
|
|
169
|
+
children: options.doc.children === void 0 ? [] : options.doc.children.map((doc) => toNavigationDocument({ ...options, doc }))
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// src/component/widget/navigation/_function/to-navigation-data/_to-navigation-group.ts
|
|
173
|
+
var toNavigationGroup = (options) => ({
|
|
174
|
+
name: options.group.name,
|
|
175
|
+
path: options.group.path,
|
|
176
|
+
current: options.group.path.every((name, index) => name === options.currentGroup?.[index]),
|
|
177
|
+
docs: options.group.docs.map((doc) => toNavigationDocument({ doc, current: options.current, ancestors: options.ancestors })),
|
|
178
|
+
groups: options.group.groups.map((group) => toNavigationGroup({ ...options, group }))
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// src/component/widget/navigation/_function/to-toc-groups.ts
|
|
182
|
+
import { takeWhile } from "es-toolkit/array";
|
|
183
|
+
|
|
184
|
+
// src/component/widget/prose/_constant/section.ts
|
|
185
|
+
var section_heading_depth = {
|
|
186
|
+
section: 2,
|
|
187
|
+
sub: 3
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// src/component/widget/navigation/_function/to-toc-groups.ts
|
|
191
|
+
var toTocGroups = (outline) => {
|
|
192
|
+
const entries = outline.headings.filter((heading) => heading.depth === section_heading_depth.section || heading.depth === section_heading_depth.sub).map((heading, index) => ({ heading, section: outline.sections[index] }));
|
|
193
|
+
const sections = entries.flatMap(
|
|
194
|
+
(entry, index) => entry.heading.depth === section_heading_depth.section ? [
|
|
195
|
+
{
|
|
196
|
+
heading: entry.heading,
|
|
197
|
+
part: entry.section.part,
|
|
198
|
+
subs: takeWhile(entries.slice(index + 1), (sub) => sub.heading.depth !== section_heading_depth.section).map((sub) => ({
|
|
199
|
+
heading: sub.heading
|
|
200
|
+
}))
|
|
201
|
+
}
|
|
202
|
+
] : []
|
|
203
|
+
);
|
|
204
|
+
return sections.flatMap(
|
|
205
|
+
(section, index) => index === 0 || section.part !== void 0 ? [
|
|
206
|
+
{
|
|
207
|
+
part: section.part,
|
|
208
|
+
sections: [section, ...takeWhile(sections.slice(index + 1), (next) => next.part === void 0)]
|
|
209
|
+
}
|
|
210
|
+
] : []
|
|
211
|
+
);
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// src/component/widget/navigation/_function/to-navigation-data/to-navigation-data.ts
|
|
215
|
+
var toNavigationData = (options) => {
|
|
216
|
+
const currentDoc = options.docs.find((doc) => doc.id === options.current);
|
|
217
|
+
const ancestors = new Set(currentDoc?.ancestors);
|
|
218
|
+
return {
|
|
219
|
+
title: options.site.title,
|
|
220
|
+
groups: toDocGroups({ docs: options.docs, navigation: options.site.navigation }).map(
|
|
221
|
+
(group) => toNavigationGroup({ group, current: options.current, ancestors, currentGroup: currentDoc?.data.group })
|
|
222
|
+
),
|
|
223
|
+
outline: options.outline === void 0 ? [] : toTocGroups(options.outline),
|
|
224
|
+
pageId: options.current === void 0 ? "/" : options.current,
|
|
225
|
+
home: options.current === void 0
|
|
226
|
+
};
|
|
217
227
|
};
|
|
218
228
|
|
|
219
|
-
// src/component/widget/
|
|
229
|
+
// src/component/widget/navigation/_function/to-navigation-json.ts
|
|
230
|
+
var toNavigationJson = (data) => {
|
|
231
|
+
return JSON.stringify(data).replaceAll("<", "\\u003c").replaceAll("\u2028", "\\u2028").replaceAll("\u2029", "\\u2029");
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// src/component/widget/shell-controls/wg-shell-controls.tsx
|
|
235
|
+
import clsx9 from "clsx";
|
|
236
|
+
import { Fragment as Fragment3, useEffect, useLayoutEffect as useLayoutEffect5, useRef as useRef4 } from "hono/jsx";
|
|
237
|
+
|
|
238
|
+
// src/component/widget/cursor-face/wg-cursor-face.tsx
|
|
239
|
+
import clsx2 from "clsx";
|
|
240
|
+
import { useLayoutEffect, useRef } from "hono/jsx";
|
|
241
|
+
|
|
242
|
+
// src/component/widget/cursor-face/_constant/cursor-face.ts
|
|
243
|
+
var cursor_face_offset_px = 16;
|
|
244
|
+
var cursor_face_size_px = 24;
|
|
245
|
+
var cursor_face_storage_key = "fh-cursor-face";
|
|
246
|
+
|
|
247
|
+
// src/component/widget/cursor-face/wg-cursor-face.tsx
|
|
248
|
+
import { jsx as jsx2 } from "hono/jsx/jsx-runtime";
|
|
249
|
+
var WgCursorFace = (props) => {
|
|
250
|
+
const faceRef = useRef(null);
|
|
251
|
+
const mediaRef = useRef(null);
|
|
252
|
+
const positionRef = useRef({ x: 0, y: 0, frame: 0 });
|
|
253
|
+
const handleCursorHide = () => {
|
|
254
|
+
cancelAnimationFrame(positionRef.current.frame);
|
|
255
|
+
positionRef.current.frame = 0;
|
|
256
|
+
faceRef.current?.classList.remove("wg_cursorFace__root--visible");
|
|
257
|
+
};
|
|
258
|
+
const handleCursorMediaChange = () => {
|
|
259
|
+
if (!mediaRef.current?.matches) handleCursorHide();
|
|
260
|
+
};
|
|
261
|
+
const renderCursorFace = () => {
|
|
262
|
+
if (positionRef.current.frame !== 0) return;
|
|
263
|
+
positionRef.current.frame = requestAnimationFrame(() => {
|
|
264
|
+
positionRef.current.frame = 0;
|
|
265
|
+
const face = faceRef.current;
|
|
266
|
+
if (face === null) return;
|
|
267
|
+
face.style.transform = `translate3d(
|
|
268
|
+
${Math.max(0, Math.min(positionRef.current.x + cursor_face_offset_px, document.documentElement.clientWidth - face.width - cursor_face_offset_px))}px,
|
|
269
|
+
${Math.max(0, Math.min(positionRef.current.y + cursor_face_offset_px, document.documentElement.clientHeight - face.height - cursor_face_offset_px))}px,
|
|
270
|
+
0
|
|
271
|
+
)`;
|
|
272
|
+
face.classList.add("wg_cursorFace__root--visible");
|
|
273
|
+
});
|
|
274
|
+
};
|
|
275
|
+
const handleDocumentPointer = (event) => {
|
|
276
|
+
if (!mediaRef.current?.matches || event.pointerType !== "mouse") {
|
|
277
|
+
handleCursorHide();
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
positionRef.current.x = event.clientX;
|
|
281
|
+
positionRef.current.y = event.clientY;
|
|
282
|
+
renderCursorFace();
|
|
283
|
+
};
|
|
284
|
+
const handleCursorResize = () => {
|
|
285
|
+
if (faceRef.current?.classList.contains("wg_cursorFace__root--visible")) renderCursorFace();
|
|
286
|
+
};
|
|
287
|
+
const handlePageHide = () => {
|
|
288
|
+
if (!faceRef.current?.classList.contains("wg_cursorFace__root--visible")) return;
|
|
289
|
+
try {
|
|
290
|
+
sessionStorage.setItem(cursor_face_storage_key, JSON.stringify({ x: positionRef.current.x, y: positionRef.current.y }));
|
|
291
|
+
} catch {
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
const handlePageShow = () => {
|
|
295
|
+
try {
|
|
296
|
+
const stored = sessionStorage.getItem(cursor_face_storage_key);
|
|
297
|
+
sessionStorage.removeItem(cursor_face_storage_key);
|
|
298
|
+
if (stored === null || !mediaRef.current?.matches) return;
|
|
299
|
+
const point = JSON.parse(stored);
|
|
300
|
+
if (typeof point === "object" && point !== null && "x" in point && "y" in point && typeof point.x === "number" && typeof point.y === "number" && Number.isFinite(point.x) && Number.isFinite(point.y)) {
|
|
301
|
+
positionRef.current.x = point.x;
|
|
302
|
+
positionRef.current.y = point.y;
|
|
303
|
+
renderCursorFace();
|
|
304
|
+
}
|
|
305
|
+
} catch {
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
useLayoutEffect(() => {
|
|
309
|
+
if (!props.ready) return;
|
|
310
|
+
const lifetime = new AbortController();
|
|
311
|
+
const media = matchMedia("(hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference)");
|
|
312
|
+
mediaRef.current = media;
|
|
313
|
+
handlePageShow();
|
|
314
|
+
document.addEventListener("pointermove", handleDocumentPointer, { passive: true, signal: lifetime.signal });
|
|
315
|
+
document.addEventListener("pointerdown", handleDocumentPointer, { passive: true, signal: lifetime.signal });
|
|
316
|
+
document.documentElement.addEventListener("pointerleave", handleCursorHide, { signal: lifetime.signal });
|
|
317
|
+
addEventListener("blur", handleCursorHide, { signal: lifetime.signal });
|
|
318
|
+
addEventListener("resize", handleCursorResize, { signal: lifetime.signal });
|
|
319
|
+
addEventListener("pagehide", handlePageHide, { signal: lifetime.signal });
|
|
320
|
+
addEventListener("pageshow", handlePageShow, { signal: lifetime.signal });
|
|
321
|
+
media.addEventListener("change", handleCursorMediaChange, { signal: lifetime.signal });
|
|
322
|
+
return () => {
|
|
323
|
+
lifetime.abort();
|
|
324
|
+
mediaRef.current = null;
|
|
325
|
+
handleCursorHide();
|
|
326
|
+
};
|
|
327
|
+
}, [props.ready]);
|
|
328
|
+
return /* @__PURE__ */ jsx2(
|
|
329
|
+
"img",
|
|
330
|
+
{
|
|
331
|
+
ref: props.ready ? faceRef : void 0,
|
|
332
|
+
className: clsx2("wg_cursorFace__root"),
|
|
333
|
+
src: asset_favicon_path,
|
|
334
|
+
width: cursor_face_size_px,
|
|
335
|
+
height: cursor_face_size_px,
|
|
336
|
+
alt: "",
|
|
337
|
+
"aria-hidden": "true",
|
|
338
|
+
draggable: false,
|
|
339
|
+
"data-cursor-face": ""
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
// src/component/widget/navigation/wg-navigation.tsx
|
|
345
|
+
import clsx8 from "clsx";
|
|
346
|
+
import { Fragment as Fragment2, useLayoutEffect as useLayoutEffect4, useRef as useRef3, useState as useState3 } from "hono/jsx";
|
|
347
|
+
import { flushSync } from "hono/jsx/dom";
|
|
348
|
+
|
|
349
|
+
// src/component/widget/navigation/_constant/navigation.ts
|
|
350
|
+
var navigation_mobile_query = "(width < 1024px)";
|
|
351
|
+
var navigation_wide_query = "(width >= 1536px)";
|
|
352
|
+
|
|
353
|
+
// src/component/widget/navigation/_function/restore-navigation-scroll.ts
|
|
354
|
+
var restoreNavigationScroll = (options) => {
|
|
355
|
+
const navigation = document.querySelector("[data-navigation]");
|
|
356
|
+
const documents = document.querySelector('[data-navigation-scroll="documents"]');
|
|
357
|
+
const outline = document.querySelector('[data-navigation-scroll="outline"]');
|
|
358
|
+
if (!navigation || !documents || !outline) return;
|
|
359
|
+
navigation.dataset.navigationLayout = options.layout;
|
|
360
|
+
try {
|
|
361
|
+
const value = sessionStorage.getItem(options.key);
|
|
362
|
+
const stored = value === null ? void 0 : JSON.parse(value);
|
|
363
|
+
const state = typeof stored === "object" && stored !== null && "version" in stored && stored.version === options.version && "state" in stored ? options.toState(stored.state) : { positions: {} };
|
|
364
|
+
const legacy = sessionStorage.getItem(`${options.key}:${options.layout === "drawer" ? "drawer" : "desktop"}`);
|
|
365
|
+
const previous = state.positions[options.layout] === void 0 && legacy !== null ? options.toState({ positions: { [options.layout]: JSON.parse(legacy) } }).positions[options.layout] : void 0;
|
|
366
|
+
const position = state.positions[options.layout] ?? previous;
|
|
367
|
+
const signature = [...navigation.querySelectorAll(".wg_navigationNav__root a[href]")].map((link) => `${link.pathname}:${link.textContent}`).join("\n");
|
|
368
|
+
if (position === void 0 || position.navigation !== signature) return;
|
|
369
|
+
documents.scrollTop = position.documents;
|
|
370
|
+
if (position.pathname === location.pathname) outline.scrollTop = position.outline;
|
|
371
|
+
} catch {
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
// src/component/widget/navigation/_wg-navigation-nav.tsx
|
|
376
|
+
import clsx5 from "clsx";
|
|
377
|
+
|
|
378
|
+
// src/component/widget/navigation/_wg-navigation-branch-toggle.tsx
|
|
379
|
+
import clsx3 from "clsx";
|
|
380
|
+
|
|
381
|
+
// src/component/widget/navigation/_function/to-navigation-branch-id.ts
|
|
382
|
+
var toNavigationBranchId = (key) => {
|
|
383
|
+
return `fh-branch-${encodeURIComponent(key)}`;
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
// src/component/widget/navigation/_wg-navigation-branch-toggle.tsx
|
|
387
|
+
import { jsx as jsx3 } from "hono/jsx/jsx-runtime";
|
|
388
|
+
var WgNavigationBranchToggle = (props) => {
|
|
389
|
+
const handleToggleClick = () => props.onToggle?.(props.branchKey);
|
|
390
|
+
return /* @__PURE__ */ jsx3(
|
|
391
|
+
"button",
|
|
392
|
+
{
|
|
393
|
+
className: clsx3("wg_navigationBranchToggle__root"),
|
|
394
|
+
type: "button",
|
|
395
|
+
"aria-label": `${props.collapsed[props.branchKey] === true ? "Expand" : "Collapse"} ${props.label}`,
|
|
396
|
+
"aria-expanded": String(props.collapsed[props.branchKey] !== true),
|
|
397
|
+
"aria-controls": toNavigationBranchId(props.branchKey),
|
|
398
|
+
"data-navigation-toggle": props.branchKey,
|
|
399
|
+
"data-navigation-label": props.label,
|
|
400
|
+
hidden: props.onToggle === void 0,
|
|
401
|
+
onClick: handleToggleClick,
|
|
402
|
+
children: props.collapsed[props.branchKey] === true ? "+" : "\u2212"
|
|
403
|
+
}
|
|
404
|
+
);
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
// src/component/widget/navigation/_wg-navigation-nav-list.tsx
|
|
220
408
|
import clsx4 from "clsx";
|
|
221
|
-
import { Fragment
|
|
222
|
-
import { jsx as jsx4, jsxs as
|
|
223
|
-
var
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
409
|
+
import { Fragment } from "hono/jsx";
|
|
410
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "hono/jsx/jsx-runtime";
|
|
411
|
+
var WgNavigationNavList = (props) => {
|
|
412
|
+
const entries = [
|
|
413
|
+
...props.group.docs.map((doc) => {
|
|
414
|
+
const active = doc.active;
|
|
415
|
+
return { kind: "document", key: `doc:${doc.id}`, doc, active, current: doc.current };
|
|
416
|
+
}),
|
|
417
|
+
...props.group.groups.map((group) => ({
|
|
418
|
+
kind: "group",
|
|
419
|
+
key: `group:${JSON.stringify(group.path)}`,
|
|
420
|
+
group,
|
|
421
|
+
current: group.current
|
|
422
|
+
}))
|
|
423
|
+
];
|
|
424
|
+
const currentIndex = entries.findIndex((entry) => entry.current);
|
|
425
|
+
return /* @__PURE__ */ jsx4(
|
|
426
|
+
"ul",
|
|
427
|
+
{
|
|
428
|
+
className: clsx4("wg_navigationNavList__root"),
|
|
429
|
+
"aria-label": props.group.name,
|
|
430
|
+
id: toNavigationBranchId(props.branchKey),
|
|
431
|
+
hidden: props.collapsed[props.branchKey] === true,
|
|
432
|
+
children: entries.map((entry, index) => /* @__PURE__ */ jsxs2(
|
|
433
|
+
"li",
|
|
434
|
+
{
|
|
435
|
+
className: clsx4("wg_navigationNavList__item", {
|
|
436
|
+
"wg_navigationNavList__item--trail": index < currentIndex,
|
|
437
|
+
"wg_navigationNavList__item--current": entry.current
|
|
438
|
+
}),
|
|
439
|
+
children: [
|
|
440
|
+
entry.kind === "document" && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
441
|
+
/* @__PURE__ */ jsx4(
|
|
442
|
+
"a",
|
|
443
|
+
{
|
|
444
|
+
className: clsx4("wg_navigationNavList__link", { "wg_navigationNavList__link--active": entry.active }),
|
|
445
|
+
href: `/${entry.doc.id}/`,
|
|
446
|
+
title: entry.doc.label,
|
|
447
|
+
"aria-current": entry.active ? "page" : void 0,
|
|
448
|
+
children: entry.doc.name
|
|
449
|
+
}
|
|
450
|
+
),
|
|
451
|
+
entry.doc.children.length > 0 && /* @__PURE__ */ jsx4(WgNavigationBranchToggle, { branchKey: entry.key, label: entry.doc.name, collapsed: props.collapsed, onToggle: props.onToggle }),
|
|
452
|
+
entry.doc.children.length > 0 && /* @__PURE__ */ jsx4(
|
|
453
|
+
WgNavigationNavList,
|
|
454
|
+
{
|
|
455
|
+
group: { name: entry.doc.name, path: props.group.path, current: entry.current, docs: entry.doc.children, groups: [] },
|
|
456
|
+
collapsed: props.collapsed,
|
|
457
|
+
onToggle: props.onToggle,
|
|
458
|
+
branchKey: entry.key
|
|
459
|
+
}
|
|
460
|
+
)
|
|
461
|
+
] }),
|
|
462
|
+
entry.kind === "group" && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
463
|
+
/* @__PURE__ */ jsx4("span", { className: clsx4("wg_navigationNavList__branch"), children: entry.group.name }),
|
|
464
|
+
/* @__PURE__ */ jsx4(WgNavigationBranchToggle, { branchKey: entry.key, label: entry.group.name, collapsed: props.collapsed, onToggle: props.onToggle }),
|
|
465
|
+
/* @__PURE__ */ jsx4(WgNavigationNavList, { group: entry.group, collapsed: props.collapsed, onToggle: props.onToggle, branchKey: entry.key })
|
|
466
|
+
] })
|
|
467
|
+
]
|
|
468
|
+
},
|
|
469
|
+
entry.key
|
|
470
|
+
))
|
|
471
|
+
}
|
|
472
|
+
);
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
// src/component/widget/navigation/_wg-navigation-nav.tsx
|
|
476
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "hono/jsx/jsx-runtime";
|
|
477
|
+
var WgNavigationNav = (props) => {
|
|
478
|
+
return /* @__PURE__ */ jsx5("nav", { className: clsx5("wg_navigationNav__root"), "aria-label": copy_nav_aria_label, children: /* @__PURE__ */ jsx5("div", { className: clsx5("wg_navigationNav__docs"), children: props.groups.map((group) => /* @__PURE__ */ jsxs3("section", { className: clsx5("wg_navigationNav__docGroup"), "aria-label": group.name, children: [
|
|
479
|
+
/* @__PURE__ */ jsx5("div", { className: clsx5("wg_navigationNav__group"), children: group.name }),
|
|
480
|
+
/* @__PURE__ */ jsx5(WgNavigationBranchToggle, { branchKey: `group:${JSON.stringify(group.path)}`, label: group.name, collapsed: props.collapsed, onToggle: props.onToggle }),
|
|
481
|
+
/* @__PURE__ */ jsx5(WgNavigationNavList, { group, branchKey: `group:${JSON.stringify(group.path)}`, collapsed: props.collapsed, onToggle: props.onToggle })
|
|
482
|
+
] }, JSON.stringify(group.path))) }) });
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
// src/component/widget/navigation/_wg-navigation-scroll.tsx
|
|
486
|
+
import clsx6 from "clsx";
|
|
487
|
+
import { useLayoutEffect as useLayoutEffect2, useRef as useRef2, useState } from "hono/jsx";
|
|
488
|
+
import { jsx as jsx6 } from "hono/jsx/jsx-runtime";
|
|
489
|
+
var WgNavigationScroll = (props) => {
|
|
490
|
+
const [overflow, setOverflow] = useState({ above: false, below: false });
|
|
491
|
+
const frameRef = useRef2(0);
|
|
492
|
+
const updateOverflow = () => {
|
|
493
|
+
frameRef.current = 0;
|
|
494
|
+
if (props.portRef.current === null) return;
|
|
495
|
+
const above = props.portRef.current.scrollTop > 1;
|
|
496
|
+
const below = props.portRef.current.scrollHeight - props.portRef.current.clientHeight - props.portRef.current.scrollTop > 1;
|
|
497
|
+
setOverflow((state) => state.above === above && state.below === below ? state : { above, below });
|
|
498
|
+
};
|
|
499
|
+
const scheduleOverflow = () => {
|
|
500
|
+
if (frameRef.current === 0) frameRef.current = requestAnimationFrame(updateOverflow);
|
|
501
|
+
};
|
|
502
|
+
const handlePortScroll = (_event) => {
|
|
503
|
+
props.onScroll?.();
|
|
504
|
+
scheduleOverflow();
|
|
505
|
+
};
|
|
506
|
+
useLayoutEffect2(() => {
|
|
507
|
+
if (!props.ready || props.portRef.current === null) return;
|
|
508
|
+
const observer = new ResizeObserver(scheduleOverflow);
|
|
509
|
+
observer.observe(props.portRef.current);
|
|
510
|
+
if (props.portRef.current.firstElementChild !== null) observer.observe(props.portRef.current.firstElementChild);
|
|
511
|
+
let active = true;
|
|
512
|
+
addEventListener("pageshow", scheduleOverflow);
|
|
513
|
+
if (props.portRef.current.isConnected) {
|
|
514
|
+
updateOverflow();
|
|
515
|
+
} else {
|
|
516
|
+
queueMicrotask(() => {
|
|
517
|
+
if (active) updateOverflow();
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
return () => {
|
|
521
|
+
active = false;
|
|
522
|
+
observer.disconnect();
|
|
523
|
+
removeEventListener("pageshow", scheduleOverflow);
|
|
524
|
+
cancelAnimationFrame(frameRef.current);
|
|
525
|
+
frameRef.current = 0;
|
|
526
|
+
};
|
|
527
|
+
}, [props.portRef, props.ready]);
|
|
528
|
+
useLayoutEffect2(() => {
|
|
529
|
+
if (props.ready && props.portRef.current?.isConnected) updateOverflow();
|
|
530
|
+
}, [props.children, props.ready]);
|
|
531
|
+
return (
|
|
532
|
+
// biome-ignore lint/a11y/noStaticElementInteractions lint/a11y/useKeyWithClickEvents: 부모의 링크 이벤트 위임이며 자식 a·button의 네이티브 키보드 동작을 그대로 소비한다
|
|
533
|
+
/* @__PURE__ */ jsx6(
|
|
534
|
+
"div",
|
|
535
|
+
{
|
|
536
|
+
ref: props.ready ? props.portRef : void 0,
|
|
537
|
+
className: clsx6(
|
|
538
|
+
"wg_navigation__scroll",
|
|
539
|
+
props.kind === "documents" && "wg_navigation__documents",
|
|
540
|
+
props.kind === "outline" && "wg_navigation__headings",
|
|
541
|
+
props.ready && "wg_navigation__scroll--ready",
|
|
542
|
+
props.ready && overflow.above && "wg_navigation__scroll--above",
|
|
543
|
+
props.ready && overflow.below && "wg_navigation__scroll--below"
|
|
544
|
+
),
|
|
545
|
+
"data-navigation-scroll": props.kind,
|
|
546
|
+
onClick: props.onClick,
|
|
547
|
+
onScroll: handlePortScroll,
|
|
548
|
+
children: props.children
|
|
549
|
+
}
|
|
550
|
+
)
|
|
551
|
+
);
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
// src/component/widget/navigation/_wg-navigation-toc.tsx
|
|
555
|
+
import clsx7 from "clsx";
|
|
556
|
+
import { useLayoutEffect as useLayoutEffect3, useState as useState2 } from "hono/jsx";
|
|
557
|
+
|
|
558
|
+
// src/component/widget/navigation/_constant/reading-line.ts
|
|
559
|
+
var reading_line_slack_px = 1;
|
|
560
|
+
|
|
561
|
+
// src/util/dom/find-hash-target.ts
|
|
562
|
+
var findHashTarget = (hash) => {
|
|
563
|
+
if (!hash) {
|
|
564
|
+
return null;
|
|
565
|
+
}
|
|
566
|
+
try {
|
|
567
|
+
return document.getElementById(decodeURIComponent(hash.slice(1)));
|
|
568
|
+
} catch (error) {
|
|
569
|
+
if (error instanceof URIError) {
|
|
570
|
+
return null;
|
|
571
|
+
}
|
|
572
|
+
throw error;
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
// src/component/widget/navigation/_wg-navigation-toc.tsx
|
|
577
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "hono/jsx/jsx-runtime";
|
|
578
|
+
var WgNavigationToc = (props) => {
|
|
579
|
+
const [currentSlug, setCurrentSlug] = useState2();
|
|
580
|
+
useLayoutEffect3(() => {
|
|
581
|
+
const sections = props.groups.flatMap((group) => group.sections);
|
|
582
|
+
const headings = sections.flatMap((section) => [section.heading, ...section.subs.map((sub) => sub.heading)]);
|
|
583
|
+
const frame = { id: 0 };
|
|
584
|
+
const updateCurrentHeading = () => {
|
|
585
|
+
frame.id = 0;
|
|
586
|
+
const visible = headings.flatMap((heading) => {
|
|
587
|
+
const target = findHashTarget(`#${heading.slug}`);
|
|
588
|
+
return target?.checkVisibility() ? [{ slug: heading.slug, top: target.getBoundingClientRect().top - Number.parseFloat(getComputedStyle(target).scrollMarginTop) }] : [];
|
|
589
|
+
});
|
|
590
|
+
setCurrentSlug(visible.findLast((heading) => heading.top <= reading_line_slack_px)?.slug ?? visible[0]?.slug);
|
|
591
|
+
};
|
|
592
|
+
const handleReadingPositionChange = () => {
|
|
593
|
+
if (frame.id === 0) frame.id = requestAnimationFrame(updateCurrentHeading);
|
|
594
|
+
};
|
|
595
|
+
addEventListener("scroll", handleReadingPositionChange, { passive: true });
|
|
596
|
+
addEventListener("resize", handleReadingPositionChange);
|
|
597
|
+
addEventListener("toggle", handleReadingPositionChange, true);
|
|
598
|
+
addEventListener("pageshow", handleReadingPositionChange);
|
|
599
|
+
document.addEventListener("DOMContentLoaded", handleReadingPositionChange);
|
|
600
|
+
if (document.readyState !== "loading") updateCurrentHeading();
|
|
601
|
+
return () => {
|
|
602
|
+
cancelAnimationFrame(frame.id);
|
|
603
|
+
removeEventListener("scroll", handleReadingPositionChange);
|
|
604
|
+
removeEventListener("resize", handleReadingPositionChange);
|
|
605
|
+
removeEventListener("toggle", handleReadingPositionChange, true);
|
|
606
|
+
removeEventListener("pageshow", handleReadingPositionChange);
|
|
607
|
+
document.removeEventListener("DOMContentLoaded", handleReadingPositionChange);
|
|
608
|
+
};
|
|
609
|
+
}, [props.groups]);
|
|
610
|
+
return /* @__PURE__ */ jsxs4("nav", { className: clsx7("wg_navigationToc__root"), "aria-label": copy_nav_toc_label, children: [
|
|
611
|
+
/* @__PURE__ */ jsx7("div", { className: clsx7("wg_navigationToc__label"), children: copy_nav_toc_label }),
|
|
612
|
+
props.groups.map((group) => {
|
|
613
|
+
const currentIndex = group.sections.findIndex((section) => section.heading.slug === currentSlug || section.subs.some((sub) => sub.heading.slug === currentSlug));
|
|
614
|
+
const partKey = `outline:${props.pageId}:part:${group.sections[0].heading.slug}`;
|
|
615
|
+
return /* @__PURE__ */ jsxs4(
|
|
616
|
+
"div",
|
|
617
|
+
{
|
|
618
|
+
className: clsx7("wg_navigationToc__groupSection", { "wg_navigationToc__groupSection--named": group.part !== void 0 }),
|
|
619
|
+
children: [
|
|
620
|
+
group.part !== void 0 && /* @__PURE__ */ jsx7("div", { className: clsx7("wg_navigationToc__group"), children: group.part }),
|
|
621
|
+
group.part !== void 0 && /* @__PURE__ */ jsx7(WgNavigationBranchToggle, { branchKey: partKey, label: group.part, collapsed: props.collapsed, onToggle: props.onToggle }),
|
|
622
|
+
/* @__PURE__ */ jsx7("ul", { className: clsx7("wg_navigationToc__list"), id: toNavigationBranchId(partKey), hidden: props.collapsed[partKey] === true, children: group.sections.map((section, index) => {
|
|
623
|
+
const currentSubIndex = section.subs.findIndex((sub) => sub.heading.slug === currentSlug);
|
|
624
|
+
const sectionKey = `outline:${props.pageId}:heading:${section.heading.slug}`;
|
|
625
|
+
return /* @__PURE__ */ jsxs4(
|
|
626
|
+
"li",
|
|
627
|
+
{
|
|
628
|
+
className: clsx7("wg_navigationToc__item", {
|
|
629
|
+
"wg_navigationToc__item--trail": index < currentIndex,
|
|
630
|
+
"wg_navigationToc__item--current": index === currentIndex
|
|
631
|
+
}),
|
|
632
|
+
children: [
|
|
633
|
+
/* @__PURE__ */ jsx7(
|
|
634
|
+
"a",
|
|
635
|
+
{
|
|
636
|
+
className: clsx7("wg_navigationToc__link", { "wg_navigationToc__link--active": section.heading.slug === currentSlug }),
|
|
637
|
+
href: `#${section.heading.slug}`,
|
|
638
|
+
"data-toc-link": "",
|
|
639
|
+
"aria-current": section.heading.slug === currentSlug ? "location" : void 0,
|
|
640
|
+
children: section.heading.text
|
|
641
|
+
}
|
|
642
|
+
),
|
|
643
|
+
section.subs.length > 0 && /* @__PURE__ */ jsx7(WgNavigationBranchToggle, { branchKey: sectionKey, label: section.heading.text, collapsed: props.collapsed, onToggle: props.onToggle }),
|
|
644
|
+
section.subs.length > 0 && /* @__PURE__ */ jsx7("ul", { className: clsx7("wg_navigationToc__sub"), id: toNavigationBranchId(sectionKey), hidden: props.collapsed[sectionKey] === true, children: section.subs.map((sub, subIndex) => /* @__PURE__ */ jsx7(
|
|
645
|
+
"li",
|
|
646
|
+
{
|
|
647
|
+
className: clsx7("wg_navigationToc__subItem", {
|
|
648
|
+
"wg_navigationToc__subItem--trail": subIndex < currentSubIndex,
|
|
649
|
+
"wg_navigationToc__subItem--current": subIndex === currentSubIndex
|
|
650
|
+
}),
|
|
651
|
+
children: /* @__PURE__ */ jsx7(
|
|
652
|
+
"a",
|
|
653
|
+
{
|
|
654
|
+
className: clsx7("wg_navigationToc__subLink", { "wg_navigationToc__subLink--active": sub.heading.slug === currentSlug }),
|
|
655
|
+
href: `#${sub.heading.slug}`,
|
|
656
|
+
"data-toc-sub-link": "",
|
|
657
|
+
"aria-current": sub.heading.slug === currentSlug ? "location" : void 0,
|
|
658
|
+
children: sub.heading.text
|
|
659
|
+
}
|
|
660
|
+
)
|
|
661
|
+
},
|
|
662
|
+
sub.heading.slug
|
|
663
|
+
)) })
|
|
664
|
+
]
|
|
665
|
+
},
|
|
666
|
+
section.heading.slug
|
|
667
|
+
);
|
|
668
|
+
}) })
|
|
669
|
+
]
|
|
670
|
+
},
|
|
671
|
+
group.sections[0].heading.slug
|
|
672
|
+
);
|
|
673
|
+
})
|
|
233
674
|
] });
|
|
234
675
|
};
|
|
235
676
|
|
|
236
|
-
// src/
|
|
237
|
-
var
|
|
238
|
-
var
|
|
239
|
-
var
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
var
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
"
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
677
|
+
// src/store/navigation/navigation-storage.ts
|
|
678
|
+
var navigation_tree_storage_key = "for-humanity:navigation-tree";
|
|
679
|
+
var navigation_storage_version = 1;
|
|
680
|
+
var navigation_scroll_storage_key = "for-humanity:navigation-scroll";
|
|
681
|
+
|
|
682
|
+
// src/store/navigation/to-navigation-scroll-state.ts
|
|
683
|
+
var toNavigationScrollState = (value) => {
|
|
684
|
+
const toPosition = (position) => {
|
|
685
|
+
if (typeof position !== "object" || position === null || !("navigation" in position) || typeof position.navigation !== "string" || !("pathname" in position) || typeof position.pathname !== "string" || !("documents" in position) || typeof position.documents !== "number" || !Number.isFinite(position.documents) || position.documents < 0 || !("outline" in position) || typeof position.outline !== "number" || !Number.isFinite(position.outline) || position.outline < 0) {
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
return { navigation: position.navigation, pathname: position.pathname, documents: position.documents, outline: position.outline };
|
|
689
|
+
};
|
|
690
|
+
if (typeof value !== "object" || value === null || !("positions" in value) || typeof value.positions !== "object" || value.positions === null) {
|
|
691
|
+
return { positions: {} };
|
|
692
|
+
}
|
|
693
|
+
const positions = {
|
|
694
|
+
wide: toPosition("wide" in value.positions ? value.positions.wide : void 0),
|
|
695
|
+
desktop: toPosition("desktop" in value.positions ? value.positions.desktop : void 0),
|
|
696
|
+
drawer: toPosition("drawer" in value.positions ? value.positions.drawer : void 0)
|
|
697
|
+
};
|
|
698
|
+
return { positions: Object.fromEntries(Object.entries(positions).filter((entry) => entry[1] !== void 0)) };
|
|
258
699
|
};
|
|
259
|
-
var asset_content_type_default = "application/octet-stream";
|
|
260
|
-
var asset_media_dir = `/${asset_dir}/media`;
|
|
261
|
-
var asset_media_extensions = /* @__PURE__ */ new Set([".svg", ".png", ".jpg", ".jpeg", ".gif", ".webp", ".avif", ".pdf", ".csv", ".txt", ".zip"]);
|
|
262
700
|
|
|
263
|
-
// src/
|
|
264
|
-
import {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
701
|
+
// src/store/navigation/use-navigation-tree-store.ts
|
|
702
|
+
import { useSyncExternalStore } from "hono/jsx";
|
|
703
|
+
|
|
704
|
+
// src/store/navigation/_constant/tree.ts
|
|
705
|
+
var tree_server_state = { collapsed: {} };
|
|
706
|
+
|
|
707
|
+
// src/store/navigation/use-navigation-tree-store.ts
|
|
708
|
+
var useNavigationTreeStore = (tree) => {
|
|
709
|
+
const subscribe = tree === void 0 ? () => () => {
|
|
710
|
+
} : tree.subscribe;
|
|
711
|
+
const getSnapshot = tree === void 0 ? () => tree_server_state : tree.getState;
|
|
712
|
+
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
// src/util/dom/reveal-hash-target.ts
|
|
716
|
+
var revealHashTarget = (hash) => {
|
|
717
|
+
const target = findHashTarget(hash);
|
|
718
|
+
for (let fold = target?.closest("details"); fold; fold = fold.parentElement?.closest("details")) {
|
|
719
|
+
fold.open = true;
|
|
720
|
+
}
|
|
721
|
+
return target;
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
// src/component/widget/navigation/wg-navigation.tsx
|
|
725
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "hono/jsx/jsx-runtime";
|
|
726
|
+
var WgNavigation = (props) => {
|
|
727
|
+
const navigationTreeStore = useNavigationTreeStore(props.stores?.tree);
|
|
728
|
+
const [layout, setLayout] = useState3(() => {
|
|
729
|
+
if (props.stores === void 0) return "desktop";
|
|
730
|
+
if (matchMedia(navigation_mobile_query).matches) return "drawer";
|
|
731
|
+
return matchMedia(navigation_wide_query).matches ? "wide" : "desktop";
|
|
732
|
+
});
|
|
733
|
+
const [drawerOpen, setDrawerOpen] = useState3(false);
|
|
734
|
+
const navigationRef = useRef3(null);
|
|
735
|
+
const documentsRef = useRef3(null);
|
|
736
|
+
const drawerNavigationRef = useRef3(null);
|
|
737
|
+
const drawerDocumentsRef = useRef3(null);
|
|
738
|
+
const outlineRef = useRef3(null);
|
|
739
|
+
const dialogRef = useRef3(null);
|
|
740
|
+
const openButtonRef = useRef3(null);
|
|
741
|
+
const brandRef = useRef3(null);
|
|
742
|
+
const mobileRef = useRef3(null);
|
|
743
|
+
const wideRef = useRef3(null);
|
|
744
|
+
const layoutRef = useRef3(layout);
|
|
745
|
+
const focusRef = useRef3(null);
|
|
746
|
+
const restorePendingRef = useRef3(true);
|
|
747
|
+
const getNavigationLayout = () => {
|
|
748
|
+
if (mobileRef.current === null || wideRef.current === null) return layoutRef.current;
|
|
749
|
+
if (mobileRef.current.matches) return "drawer";
|
|
750
|
+
return wideRef.current.matches ? "wide" : "desktop";
|
|
751
|
+
};
|
|
752
|
+
const getNavigationPort = () => {
|
|
753
|
+
return layoutRef.current === "drawer" ? drawerNavigationRef.current : navigationRef.current;
|
|
754
|
+
};
|
|
755
|
+
const getDocumentsPort = () => {
|
|
756
|
+
return layoutRef.current === "drawer" ? drawerDocumentsRef.current : documentsRef.current;
|
|
757
|
+
};
|
|
758
|
+
const getNavigationSignature = () => {
|
|
759
|
+
const navigation = getNavigationPort();
|
|
760
|
+
if (navigation === null) return void 0;
|
|
761
|
+
return [...navigation.querySelectorAll(".wg_navigationNav__root a[href]")].map((link) => `${link.pathname}:${link.textContent}`).join("\n");
|
|
762
|
+
};
|
|
763
|
+
const saveScroll = () => {
|
|
764
|
+
const documents = getDocumentsPort();
|
|
765
|
+
if (props.stores === void 0 || documents === null || outlineRef.current === null || restorePendingRef.current || layoutRef.current !== getNavigationLayout() || layoutRef.current === "drawer" && dialogRef.current?.open !== true) {
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
const signature = getNavigationSignature();
|
|
769
|
+
if (signature === void 0) return;
|
|
770
|
+
const navigationPosition = {
|
|
771
|
+
navigation: signature,
|
|
772
|
+
pathname: location.pathname,
|
|
773
|
+
documents: documents.scrollTop,
|
|
774
|
+
outline: outlineRef.current.scrollTop
|
|
775
|
+
};
|
|
776
|
+
props.stores.scroll.setState((state) => ({
|
|
777
|
+
positions: {
|
|
778
|
+
...state.positions,
|
|
779
|
+
[layoutRef.current]: navigationPosition
|
|
780
|
+
}
|
|
781
|
+
}));
|
|
782
|
+
};
|
|
783
|
+
const restoreScroll = () => {
|
|
784
|
+
layoutRef.current = getNavigationLayout();
|
|
785
|
+
const documents = getDocumentsPort();
|
|
786
|
+
const navigation = getNavigationPort();
|
|
787
|
+
if (props.stores === void 0 || documents === null || outlineRef.current === null || navigation === null) return;
|
|
788
|
+
if (layoutRef.current === "drawer" && dialogRef.current?.open !== true) return;
|
|
789
|
+
const signature = getNavigationSignature();
|
|
790
|
+
if (signature === void 0) return;
|
|
791
|
+
const position = props.stores.scroll.getState().positions[layoutRef.current];
|
|
792
|
+
documents.scrollTop = 0;
|
|
793
|
+
outlineRef.current.scrollTop = 0;
|
|
794
|
+
if (position === void 0) {
|
|
795
|
+
restoreNavigationScroll({ key: navigation_scroll_storage_key, version: navigation_storage_version, layout: layoutRef.current, toState: toNavigationScrollState });
|
|
796
|
+
} else if (position.navigation === signature) {
|
|
797
|
+
documents.scrollTop = position.documents;
|
|
798
|
+
if (position.pathname === location.pathname) outlineRef.current.scrollTop = position.outline;
|
|
799
|
+
}
|
|
800
|
+
navigation.dataset.navigationLayout = layoutRef.current;
|
|
801
|
+
restorePendingRef.current = false;
|
|
802
|
+
saveScroll();
|
|
803
|
+
documents.dispatchEvent(new Event("scroll"));
|
|
804
|
+
outlineRef.current.dispatchEvent(new Event("scroll"));
|
|
805
|
+
};
|
|
806
|
+
const handleBranchToggle = (key) => {
|
|
807
|
+
props.stores?.tree.setState((state) => ({ collapsed: { ...state.collapsed, [key]: state.collapsed[key] !== true } }));
|
|
808
|
+
};
|
|
809
|
+
const handleDrawerClose = (_event) => {
|
|
810
|
+
if (dialogRef.current?.open === true) return;
|
|
811
|
+
document.body.classList.remove("wg_shell__root--drawerOpen");
|
|
812
|
+
setDrawerOpen(false);
|
|
813
|
+
};
|
|
814
|
+
const closeNavigation = () => {
|
|
815
|
+
saveScroll();
|
|
816
|
+
dialogRef.current?.close();
|
|
817
|
+
document.body.classList.remove("wg_shell__root--drawerOpen");
|
|
818
|
+
setDrawerOpen(false);
|
|
819
|
+
};
|
|
820
|
+
const handleOpenButtonClick = (_event) => {
|
|
821
|
+
if (getNavigationLayout() !== "drawer" || dialogRef.current === null || dialogRef.current.open) return;
|
|
822
|
+
dialogRef.current.showModal();
|
|
823
|
+
document.body.classList.add("wg_shell__root--drawerOpen");
|
|
824
|
+
setDrawerOpen(true);
|
|
825
|
+
restoreScroll();
|
|
826
|
+
};
|
|
827
|
+
const handleCloseButtonClick = (_event) => {
|
|
828
|
+
closeNavigation();
|
|
829
|
+
};
|
|
830
|
+
const handleDrawerCancel = (event) => {
|
|
831
|
+
event.preventDefault();
|
|
832
|
+
closeNavigation();
|
|
833
|
+
};
|
|
834
|
+
const handleDrawerClick = (event) => {
|
|
835
|
+
if (dialogRef.current === null || event.target !== dialogRef.current) return;
|
|
836
|
+
const bounds = dialogRef.current.getBoundingClientRect();
|
|
837
|
+
if (event.clientX < bounds.left || event.clientX > bounds.right || event.clientY < bounds.top || event.clientY > bounds.bottom) closeNavigation();
|
|
838
|
+
};
|
|
839
|
+
const handleNavigationClick = (event) => {
|
|
840
|
+
saveScroll();
|
|
841
|
+
if (dialogRef.current?.open !== true || event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || !(event.target instanceof Element)) {
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
const link = event.target.closest("a[href]");
|
|
845
|
+
if (!(link instanceof HTMLAnchorElement) || link.target !== "" && link.target !== "_self" || link.hasAttribute("download")) return;
|
|
846
|
+
closeNavigation();
|
|
847
|
+
if (link.origin === location.origin && link.pathname === location.pathname && link.search === location.search && link.hash) {
|
|
848
|
+
const target = revealHashTarget(link.hash);
|
|
849
|
+
if (target !== null) {
|
|
850
|
+
target.tabIndex = -1;
|
|
851
|
+
target.focus({ preventScroll: true });
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
};
|
|
855
|
+
const handleLayoutChange = () => {
|
|
856
|
+
const nextLayout = getNavigationLayout();
|
|
857
|
+
if (nextLayout === layoutRef.current) return;
|
|
858
|
+
if (document.activeElement instanceof HTMLElement) {
|
|
859
|
+
focusRef.current = {
|
|
860
|
+
navigation: document.activeElement.closest("[data-navigation]") !== null,
|
|
861
|
+
drawer: document.activeElement === openButtonRef.current || document.activeElement.closest("[data-navigation-drawer]") !== null,
|
|
862
|
+
branch: document.activeElement.getAttribute("data-navigation-toggle"),
|
|
863
|
+
href: document.activeElement.getAttribute("href")
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
if (nextLayout !== "drawer") closeNavigation();
|
|
867
|
+
restorePendingRef.current = true;
|
|
868
|
+
layoutRef.current = nextLayout;
|
|
869
|
+
flushSync(() => setLayout(nextLayout));
|
|
870
|
+
};
|
|
871
|
+
const handlePageShow = (event) => {
|
|
872
|
+
if (!event.persisted || props.stores === void 0) return;
|
|
873
|
+
restorePendingRef.current = true;
|
|
874
|
+
flushSync(() => {
|
|
875
|
+
props.stores?.tree.persist.rehydrate();
|
|
876
|
+
props.stores?.scroll.persist.rehydrate();
|
|
877
|
+
});
|
|
878
|
+
handleLayoutChange();
|
|
879
|
+
restoreScroll();
|
|
880
|
+
};
|
|
881
|
+
const handleStorageChange = (event) => {
|
|
882
|
+
if (event.key === navigation_tree_storage_key || event.key === null) {
|
|
883
|
+
flushSync(() => props.stores?.tree.persist.rehydrate());
|
|
884
|
+
}
|
|
885
|
+
};
|
|
886
|
+
const handleTreeChange = (state) => {
|
|
887
|
+
if (!(document.activeElement instanceof HTMLElement)) return;
|
|
888
|
+
for (const button of document.querySelectorAll("[data-navigation-toggle]")) {
|
|
889
|
+
const key = button.dataset.navigationToggle;
|
|
890
|
+
const controls = button.getAttribute("aria-controls");
|
|
891
|
+
if (key === void 0 || controls === null || state.collapsed[key] !== true) continue;
|
|
892
|
+
const branch = document.getElementById(controls);
|
|
893
|
+
if (branch?.contains(document.activeElement)) button.focus({ preventScroll: true });
|
|
894
|
+
}
|
|
895
|
+
};
|
|
896
|
+
useLayoutEffect4(() => {
|
|
897
|
+
if (props.stores === void 0) return;
|
|
898
|
+
mobileRef.current = matchMedia(navigation_mobile_query);
|
|
899
|
+
wideRef.current = matchMedia(navigation_wide_query);
|
|
900
|
+
mobileRef.current.addEventListener("change", handleLayoutChange);
|
|
901
|
+
wideRef.current.addEventListener("change", handleLayoutChange);
|
|
902
|
+
addEventListener("pagehide", saveScroll);
|
|
903
|
+
addEventListener("pageshow", handlePageShow);
|
|
904
|
+
addEventListener("storage", handleStorageChange);
|
|
905
|
+
const unsubscribeTree = props.stores.tree.subscribe(handleTreeChange);
|
|
906
|
+
return () => {
|
|
907
|
+
mobileRef.current?.removeEventListener("change", handleLayoutChange);
|
|
908
|
+
wideRef.current?.removeEventListener("change", handleLayoutChange);
|
|
909
|
+
mobileRef.current = null;
|
|
910
|
+
wideRef.current = null;
|
|
911
|
+
removeEventListener("pagehide", saveScroll);
|
|
912
|
+
removeEventListener("pageshow", handlePageShow);
|
|
913
|
+
removeEventListener("storage", handleStorageChange);
|
|
914
|
+
unsubscribeTree();
|
|
915
|
+
document.body.classList.remove("wg_shell__root--drawerOpen");
|
|
916
|
+
};
|
|
917
|
+
}, [props.stores]);
|
|
918
|
+
useLayoutEffect4(() => {
|
|
919
|
+
if (props.stores === void 0) return;
|
|
920
|
+
let active = true;
|
|
921
|
+
const restoreNavigation = () => {
|
|
922
|
+
if (!active) return;
|
|
923
|
+
restoreScroll();
|
|
924
|
+
if (focusRef.current === null) return;
|
|
925
|
+
const navigation = getNavigationPort();
|
|
926
|
+
if (layout === "drawer") {
|
|
927
|
+
if (focusRef.current.navigation) openButtonRef.current?.focus({ preventScroll: true });
|
|
928
|
+
} else if (focusRef.current.navigation && navigation !== null) {
|
|
929
|
+
const target = [...navigation.querySelectorAll("a[href], button")].find((element) => {
|
|
930
|
+
if (focusRef.current === null) return false;
|
|
931
|
+
return focusRef.current.branch !== null ? element.getAttribute("data-navigation-toggle") === focusRef.current.branch : focusRef.current.href !== null && element.getAttribute("href") === focusRef.current.href;
|
|
932
|
+
});
|
|
933
|
+
target?.focus({ preventScroll: true });
|
|
934
|
+
} else if (focusRef.current.drawer) {
|
|
935
|
+
brandRef.current?.focus({ preventScroll: true });
|
|
936
|
+
}
|
|
937
|
+
focusRef.current = null;
|
|
938
|
+
};
|
|
939
|
+
if (getDocumentsPort()?.isConnected) {
|
|
940
|
+
restoreNavigation();
|
|
941
|
+
} else {
|
|
942
|
+
queueMicrotask(restoreNavigation);
|
|
943
|
+
}
|
|
944
|
+
return () => {
|
|
945
|
+
active = false;
|
|
946
|
+
};
|
|
947
|
+
}, [layout, props.stores]);
|
|
948
|
+
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
949
|
+
/* @__PURE__ */ jsxs5("div", { className: clsx8("wg_navigation__sidebar", props.stores !== void 0 && "wg_navigation__sidebar--navigationReady"), children: [
|
|
950
|
+
/* @__PURE__ */ jsxs5("div", { className: clsx8("wg_navigation__brandRow"), children: [
|
|
951
|
+
/* @__PURE__ */ jsx8(
|
|
952
|
+
"a",
|
|
953
|
+
{
|
|
954
|
+
ref: props.stores === void 0 ? void 0 : brandRef,
|
|
955
|
+
className: clsx8("wg_navigation__brand"),
|
|
956
|
+
href: "/",
|
|
957
|
+
"aria-current": props.data.home ? "page" : void 0,
|
|
958
|
+
children: props.data.title
|
|
959
|
+
}
|
|
960
|
+
),
|
|
961
|
+
/* @__PURE__ */ jsx8(
|
|
962
|
+
"button",
|
|
963
|
+
{
|
|
964
|
+
ref: props.stores === void 0 ? void 0 : openButtonRef,
|
|
965
|
+
className: clsx8("wg_navigation__menuToggle", props.stores !== void 0 && layout === "drawer" && "wg_navigation__menuToggle--visible"),
|
|
966
|
+
type: "button",
|
|
967
|
+
"aria-label": copy_nav_open,
|
|
968
|
+
"aria-controls": "fh-navigation-drawer",
|
|
969
|
+
"aria-expanded": String(drawerOpen),
|
|
970
|
+
"data-navigation-open": "",
|
|
971
|
+
onClick: handleOpenButtonClick,
|
|
972
|
+
children: /* @__PURE__ */ jsx8("svg", { className: clsx8("wg_navigation__menuIcon"), viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx8("path", { d: "M4 6h16M4 12h16M4 18h16" }) })
|
|
973
|
+
}
|
|
974
|
+
)
|
|
975
|
+
] }),
|
|
976
|
+
layout !== "drawer" && /* @__PURE__ */ jsx8("div", { ref: props.stores === void 0 ? void 0 : navigationRef, className: clsx8("wg_navigation__navigation"), "data-navigation": "", children: /* @__PURE__ */ jsx8(WgNavigationScroll, { portRef: documentsRef, kind: "documents", ready: props.stores !== void 0, onScroll: saveScroll, onClick: handleNavigationClick, children: /* @__PURE__ */ jsx8(
|
|
977
|
+
WgNavigationNav,
|
|
978
|
+
{
|
|
979
|
+
groups: props.data.groups,
|
|
980
|
+
collapsed: navigationTreeStore.collapsed,
|
|
981
|
+
onToggle: props.stores === void 0 ? void 0 : handleBranchToggle
|
|
982
|
+
}
|
|
983
|
+
) }) })
|
|
280
984
|
] }),
|
|
281
|
-
/* @__PURE__ */
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
985
|
+
/* @__PURE__ */ jsx8("aside", { className: clsx8("wg_navigation__tocRail"), "data-navigation-rail": "", children: /* @__PURE__ */ jsx8("div", { className: clsx8("wg_navigation__outline"), "data-navigation-outline": "", children: /* @__PURE__ */ jsx8(WgNavigationScroll, { portRef: outlineRef, kind: "outline", ready: props.stores !== void 0, onScroll: saveScroll, onClick: handleNavigationClick, children: props.data.outline.length > 0 && /* @__PURE__ */ jsx8(
|
|
986
|
+
WgNavigationToc,
|
|
987
|
+
{
|
|
988
|
+
groups: props.data.outline,
|
|
989
|
+
pageId: props.data.pageId,
|
|
990
|
+
collapsed: navigationTreeStore.collapsed,
|
|
991
|
+
onToggle: props.stores === void 0 ? void 0 : handleBranchToggle
|
|
992
|
+
}
|
|
993
|
+
) }) }) }),
|
|
994
|
+
/* @__PURE__ */ jsxs5(
|
|
995
|
+
"dialog",
|
|
996
|
+
{
|
|
997
|
+
ref: props.stores === void 0 ? void 0 : dialogRef,
|
|
998
|
+
className: clsx8("wg_navigation__drawer"),
|
|
999
|
+
id: "fh-navigation-drawer",
|
|
1000
|
+
"aria-labelledby": "fh-navigation-title",
|
|
1001
|
+
"data-navigation-drawer": "",
|
|
1002
|
+
onClose: handleDrawerClose,
|
|
1003
|
+
onCancel: handleDrawerCancel,
|
|
1004
|
+
onClick: handleDrawerClick,
|
|
1005
|
+
children: [
|
|
1006
|
+
/* @__PURE__ */ jsxs5("div", { className: clsx8("wg_navigation__drawerHeader"), children: [
|
|
1007
|
+
/* @__PURE__ */ jsx8("h2", { className: clsx8("wg_navigation__drawerTitle"), id: "fh-navigation-title", children: copy_nav_title }),
|
|
1008
|
+
/* @__PURE__ */ jsx8("button", { className: clsx8("wg_navigation__drawerClose"), type: "button", "aria-label": copy_nav_close, "data-navigation-close": "", onClick: handleCloseButtonClick, children: /* @__PURE__ */ jsx8("svg", { className: clsx8("wg_navigation__menuIcon"), viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx8("path", { d: "m6 6 12 12M18 6 6 18" }) }) })
|
|
1009
|
+
] }),
|
|
1010
|
+
/* @__PURE__ */ jsx8("div", { className: clsx8("wg_navigation__drawerContent"), "data-navigation-content": "", children: layout === "drawer" && /* @__PURE__ */ jsx8("div", { ref: props.stores === void 0 ? void 0 : drawerNavigationRef, className: clsx8("wg_navigation__navigation"), "data-navigation": "", children: /* @__PURE__ */ jsx8(
|
|
1011
|
+
WgNavigationScroll,
|
|
287
1012
|
{
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
1013
|
+
portRef: drawerDocumentsRef,
|
|
1014
|
+
kind: "documents",
|
|
1015
|
+
ready: props.stores !== void 0,
|
|
1016
|
+
onScroll: saveScroll,
|
|
1017
|
+
onClick: handleNavigationClick,
|
|
1018
|
+
children: /* @__PURE__ */ jsx8(
|
|
1019
|
+
WgNavigationNav,
|
|
1020
|
+
{
|
|
1021
|
+
groups: props.data.groups,
|
|
1022
|
+
collapsed: navigationTreeStore.collapsed,
|
|
1023
|
+
onToggle: props.stores === void 0 ? void 0 : handleBranchToggle
|
|
1024
|
+
}
|
|
1025
|
+
)
|
|
295
1026
|
}
|
|
296
|
-
)
|
|
297
|
-
]
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
1027
|
+
) }) })
|
|
1028
|
+
]
|
|
1029
|
+
}
|
|
1030
|
+
)
|
|
1031
|
+
] });
|
|
1032
|
+
};
|
|
1033
|
+
|
|
1034
|
+
// src/component/widget/prose/_constant/heading-highlight.ts
|
|
1035
|
+
var heading_highlight_hold_ms = 3e3;
|
|
1036
|
+
|
|
1037
|
+
// src/component/widget/shell-controls/wg-shell-controls.tsx
|
|
1038
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "hono/jsx/jsx-runtime";
|
|
1039
|
+
var WgShellControls = (props) => {
|
|
1040
|
+
const headingRef = useRef4(null);
|
|
1041
|
+
const timerRef = useRef4(0);
|
|
1042
|
+
const arrivalRef = useRef4(null);
|
|
1043
|
+
const lifetimeRef = useRef4(null);
|
|
1044
|
+
const userScrollRef = useRef4(null);
|
|
1045
|
+
const clearHeadingHighlight = () => {
|
|
1046
|
+
clearTimeout(timerRef.current);
|
|
1047
|
+
timerRef.current = 0;
|
|
1048
|
+
arrivalRef.current?.abort();
|
|
1049
|
+
arrivalRef.current = null;
|
|
1050
|
+
headingRef.current?.classList.remove("wg_prose__headingText--highlighted");
|
|
1051
|
+
headingRef.current = null;
|
|
1052
|
+
};
|
|
1053
|
+
const handleHighlightArrival = (event) => {
|
|
1054
|
+
if (event.target !== document) return;
|
|
1055
|
+
clearTimeout(timerRef.current);
|
|
1056
|
+
arrivalRef.current?.abort();
|
|
1057
|
+
arrivalRef.current = null;
|
|
1058
|
+
timerRef.current = window.setTimeout(clearHeadingHighlight, heading_highlight_hold_ms);
|
|
1059
|
+
};
|
|
1060
|
+
const highlightHeading = (target) => {
|
|
1061
|
+
clearHeadingHighlight();
|
|
1062
|
+
headingRef.current = target === null ? null : target.querySelector(".wg_prose__headingText");
|
|
1063
|
+
if (headingRef.current === null) return;
|
|
1064
|
+
headingRef.current.classList.add("wg_prose__headingText--highlighted");
|
|
1065
|
+
timerRef.current = window.setTimeout(clearHeadingHighlight, heading_highlight_hold_ms);
|
|
1066
|
+
arrivalRef.current = new AbortController();
|
|
1067
|
+
document.addEventListener("scrollend", handleHighlightArrival, { signal: arrivalRef.current.signal });
|
|
1068
|
+
};
|
|
1069
|
+
const handleHashClick = (event) => {
|
|
1070
|
+
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
|
|
1071
|
+
const link = event.target instanceof Element ? event.target.closest("a[href]") : null;
|
|
1072
|
+
if (link instanceof HTMLAnchorElement && (link.target === "" || link.target === "_self") && !link.hasAttribute("download") && link.origin === location.origin && link.pathname === location.pathname && link.search === location.search && link.hash) {
|
|
1073
|
+
const target = revealHashTarget(link.hash);
|
|
1074
|
+
if (link.hash === location.hash) highlightHeading(target);
|
|
1075
|
+
}
|
|
1076
|
+
};
|
|
1077
|
+
const handleHashChange = () => {
|
|
1078
|
+
const target = revealHashTarget(location.hash);
|
|
1079
|
+
target?.scrollIntoView();
|
|
1080
|
+
highlightHeading(target);
|
|
1081
|
+
};
|
|
1082
|
+
const handleUserScroll = () => {
|
|
1083
|
+
userScrollRef.current?.abort();
|
|
1084
|
+
};
|
|
1085
|
+
const handlePageLoad = async () => {
|
|
1086
|
+
const lifetime = lifetimeRef.current;
|
|
1087
|
+
const hash = location.hash;
|
|
1088
|
+
const target = revealHashTarget(hash);
|
|
1089
|
+
await document.fonts.ready;
|
|
1090
|
+
if (lifetime === null || lifetime.signal.aborted) return;
|
|
1091
|
+
if (target !== null && !userScrollRef.current?.signal.aborted && hash === location.hash) {
|
|
1092
|
+
target.scrollIntoView({ behavior: "instant" });
|
|
1093
|
+
highlightHeading(target);
|
|
1094
|
+
}
|
|
1095
|
+
document.documentElement.style.removeProperty("scroll-behavior");
|
|
1096
|
+
};
|
|
1097
|
+
const handleBodyReady = () => {
|
|
1098
|
+
revealHashTarget(location.hash);
|
|
1099
|
+
if (document.readyState === "complete") void handlePageLoad();
|
|
1100
|
+
};
|
|
1101
|
+
useLayoutEffect5(() => {
|
|
1102
|
+
const lifetime = new AbortController();
|
|
1103
|
+
lifetimeRef.current = lifetime;
|
|
1104
|
+
userScrollRef.current = new AbortController();
|
|
1105
|
+
document.documentElement.style.scrollBehavior = "auto";
|
|
1106
|
+
document.addEventListener("click", handleHashClick, { signal: lifetime.signal });
|
|
1107
|
+
addEventListener("hashchange", handleHashChange, { signal: lifetime.signal });
|
|
1108
|
+
addEventListener("load", handlePageLoad, { once: true, signal: lifetime.signal });
|
|
1109
|
+
for (const type of ["wheel", "touchmove", "keydown", "mousedown"]) {
|
|
1110
|
+
addEventListener(type, handleUserScroll, { once: true, passive: true, signal: lifetime.signal });
|
|
1111
|
+
}
|
|
1112
|
+
if (document.readyState === "loading") {
|
|
1113
|
+
document.addEventListener("DOMContentLoaded", handleBodyReady, { once: true, signal: lifetime.signal });
|
|
1114
|
+
} else {
|
|
1115
|
+
handleBodyReady();
|
|
1116
|
+
}
|
|
1117
|
+
return () => {
|
|
1118
|
+
lifetime.abort();
|
|
1119
|
+
lifetimeRef.current = null;
|
|
1120
|
+
userScrollRef.current?.abort();
|
|
1121
|
+
userScrollRef.current = null;
|
|
1122
|
+
clearHeadingHighlight();
|
|
1123
|
+
document.documentElement.style.removeProperty("scroll-behavior");
|
|
1124
|
+
};
|
|
1125
|
+
}, []);
|
|
1126
|
+
useEffect(() => {
|
|
1127
|
+
if (!props.reload || lifetimeRef.current === null) return;
|
|
1128
|
+
const source = new EventSource(asset_reload_path);
|
|
1129
|
+
source.onmessage = () => location.reload();
|
|
1130
|
+
return () => source.close();
|
|
1131
|
+
}, [props.reload]);
|
|
1132
|
+
return /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
1133
|
+
/* @__PURE__ */ jsx9("div", { className: clsx9("wg_shellControls__navigation"), children: /* @__PURE__ */ jsx9(WgNavigation, { data: props.data, stores: props.stores }) }),
|
|
1134
|
+
/* @__PURE__ */ jsx9(WgCursorFace, { ready: props.stores !== void 0 })
|
|
1135
|
+
] });
|
|
1136
|
+
};
|
|
1137
|
+
|
|
1138
|
+
// src/component/widget/shell/wg-shell.tsx
|
|
1139
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "hono/jsx/jsx-runtime";
|
|
1140
|
+
var WgShell = (props) => {
|
|
1141
|
+
const navigationData = toNavigationData({ site: props.site, docs: props.docs, current: props.current, outline: props.outline });
|
|
1142
|
+
return /* @__PURE__ */ jsxs7("html", { lang: "ko", children: [
|
|
1143
|
+
/* @__PURE__ */ jsxs7("head", { children: [
|
|
1144
|
+
/* @__PURE__ */ jsx10("meta", { charSet: "utf-8" }),
|
|
1145
|
+
/* @__PURE__ */ jsx10("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }),
|
|
1146
|
+
props.site.description !== void 0 && /* @__PURE__ */ jsx10("meta", { name: "description", content: props.site.description }),
|
|
1147
|
+
/* @__PURE__ */ jsx10("title", { children: props.title === void 0 ? props.site.title : `${props.title} \xB7 ${props.site.title}` }),
|
|
1148
|
+
/* @__PURE__ */ jsx10("link", { rel: "icon", href: asset_favicon_path, type: "image/svg+xml" }),
|
|
1149
|
+
/* @__PURE__ */ jsx10("style", { dangerouslySetInnerHTML: { __html: props.assets.fontCss } }),
|
|
1150
|
+
props.assets.preload.map((href) => /* @__PURE__ */ jsx10("link", { rel: "preload", href, as: "font", type: "font/woff2", crossOrigin: "" }, href)),
|
|
1151
|
+
/* @__PURE__ */ jsx10("link", { rel: "stylesheet", href: props.assets.stylePath })
|
|
1152
|
+
] }),
|
|
1153
|
+
/* @__PURE__ */ jsxs7("body", { className: clsx10("wg_shell__root"), children: [
|
|
1154
|
+
/* @__PURE__ */ jsx10("div", { className: clsx10("wg_shell__browserRoot"), "data-shell-browser-root": "", "data-shell-reload": props.assets.reload ? "" : void 0, children: /* @__PURE__ */ jsx10(WgShellControls, { data: navigationData, reload: props.assets.reload }) }),
|
|
1155
|
+
/* @__PURE__ */ jsx10("script", { type: "application/json", id: "fh-navigation-data", dangerouslySetInnerHTML: { __html: toNavigationJson(navigationData) } }),
|
|
1156
|
+
/* @__PURE__ */ jsx10("script", { dangerouslySetInnerHTML: { __html: props.assets.browserScript } }),
|
|
1157
|
+
/* @__PURE__ */ jsx10("main", { className: clsx10("wg_shell__main"), children: props.children })
|
|
313
1158
|
] })
|
|
314
1159
|
] });
|
|
315
1160
|
};
|
|
316
1161
|
|
|
317
1162
|
// src/page/doc/pg-doc.tsx
|
|
318
|
-
import { jsx as
|
|
1163
|
+
import { jsx as jsx11 } from "hono/jsx/jsx-runtime";
|
|
319
1164
|
var PgDoc = (props) => {
|
|
320
|
-
return /* @__PURE__ */
|
|
1165
|
+
return /* @__PURE__ */ jsx11(WgShell, { site: props.site, docs: props.docs, assets: props.assets, title: props.doc.data.name, current: props.doc.id, outline: props.doc.outline, children: /* @__PURE__ */ jsx11(WgProse, { html: props.doc.html }) });
|
|
321
1166
|
};
|
|
322
1167
|
|
|
323
1168
|
// src/page/home/pg-home.tsx
|
|
324
|
-
import { jsx as
|
|
1169
|
+
import { jsx as jsx12 } from "hono/jsx/jsx-runtime";
|
|
325
1170
|
var PgHome = (props) => {
|
|
326
|
-
return /* @__PURE__ */
|
|
1171
|
+
return /* @__PURE__ */ jsx12(WgShell, { site: props.site, docs: props.docs, assets: props.assets, outline: props.home?.outline, children: props.home === void 0 ? /* @__PURE__ */ jsx12(WgProse, { head: { title: props.site.title, lead: copy_home_missing } }) : /* @__PURE__ */ jsx12(WgProse, { html: props.home.html }) });
|
|
327
1172
|
};
|
|
328
1173
|
|
|
329
|
-
// src/app.tsx
|
|
330
|
-
import { jsx as
|
|
1174
|
+
// src/entry/cli/_function/create-app.tsx
|
|
1175
|
+
import { jsx as jsx13 } from "hono/jsx/jsx-runtime";
|
|
331
1176
|
var toHtml = (page) => {
|
|
332
|
-
return `<!DOCTYPE html>${
|
|
1177
|
+
return html`<!DOCTYPE html>${page}`;
|
|
333
1178
|
};
|
|
334
1179
|
var createApp = (options) => {
|
|
335
1180
|
const app = new Hono();
|
|
336
|
-
app.get("/", (c) => c.html(toHtml(/* @__PURE__ */
|
|
1181
|
+
app.get("/", (c) => c.html(toHtml(/* @__PURE__ */ jsx13(PgHome, { site: options.site, docs: options.store.docs, assets: options.assets, home: options.store.home }))));
|
|
337
1182
|
app.get(
|
|
338
1183
|
"/:slug{.+}/",
|
|
339
1184
|
ssgParams(() => options.store.docs.map((doc) => ({ slug: doc.id }))),
|
|
340
1185
|
(c) => {
|
|
341
1186
|
const doc = options.store.docs.find((entry) => entry.id === c.req.param("slug"));
|
|
342
|
-
return doc === void 0 ? c.notFound() : c.html(toHtml(/* @__PURE__ */
|
|
1187
|
+
return doc === void 0 ? c.notFound() : c.html(toHtml(/* @__PURE__ */ jsx13(PgDoc, { site: options.site, docs: options.store.docs, assets: options.assets, doc })));
|
|
343
1188
|
}
|
|
344
1189
|
);
|
|
345
1190
|
return app;
|
|
346
1191
|
};
|
|
347
1192
|
|
|
348
|
-
// src/
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
var
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
1193
|
+
// src/entry/cli/_function/create-dev-app.ts
|
|
1194
|
+
import { readFile } from "node:fs/promises";
|
|
1195
|
+
import { extname } from "node:path";
|
|
1196
|
+
import { Hono as Hono2 } from "hono";
|
|
1197
|
+
import { streamSSE } from "hono/streaming";
|
|
1198
|
+
var createDevApp = (options) => {
|
|
1199
|
+
const app = new Hono2();
|
|
1200
|
+
const handleAsset = async (c) => {
|
|
1201
|
+
const file = options.files.get(c.req.path);
|
|
1202
|
+
if (file === void 0) {
|
|
1203
|
+
return c.notFound();
|
|
1204
|
+
}
|
|
1205
|
+
c.header("content-type", asset_content_types[extname(file).toLowerCase()] ?? asset_content_type_default);
|
|
1206
|
+
if (extname(file) === ".woff2") {
|
|
1207
|
+
c.header("Cache-Control", font_cache_control);
|
|
1208
|
+
}
|
|
1209
|
+
return c.body(await readFile(file));
|
|
1210
|
+
};
|
|
1211
|
+
app.get(
|
|
1212
|
+
asset_reload_path,
|
|
1213
|
+
(c) => streamSSE(
|
|
1214
|
+
c,
|
|
1215
|
+
(stream) => new Promise((done) => {
|
|
1216
|
+
const handleChange = async () => {
|
|
1217
|
+
await stream.writeSSE({ data: "change" });
|
|
1218
|
+
done();
|
|
1219
|
+
};
|
|
1220
|
+
options.reload.once("change", handleChange);
|
|
1221
|
+
stream.onAbort(() => {
|
|
1222
|
+
options.reload.off("change", handleChange);
|
|
1223
|
+
done();
|
|
1224
|
+
});
|
|
1225
|
+
})
|
|
1226
|
+
)
|
|
1227
|
+
);
|
|
1228
|
+
app.get(`/${asset_dir}/*`, handleAsset);
|
|
1229
|
+
app.get(asset_favicon_path, handleAsset);
|
|
1230
|
+
app.all("/*", (c) => options.pages.fetch(c.req.raw, c.env));
|
|
1231
|
+
return app;
|
|
1232
|
+
};
|
|
367
1233
|
|
|
368
|
-
// src/
|
|
1234
|
+
// src/entry/cli/_function/create-processor/create-processor.ts
|
|
369
1235
|
import rehypeShiki from "@shikijs/rehype";
|
|
370
1236
|
import rehypeRaw from "rehype-raw";
|
|
371
1237
|
import rehypeStringify from "rehype-stringify";
|
|
@@ -983,9 +1849,9 @@ var remarkUnknownDirectives = () => (tree, file) => {
|
|
|
983
1849
|
});
|
|
984
1850
|
};
|
|
985
1851
|
|
|
986
|
-
// src/
|
|
1852
|
+
// src/entry/cli/_function/create-processor/_rehype-assets.ts
|
|
987
1853
|
import { existsSync as existsSync2, realpathSync, statSync } from "node:fs";
|
|
988
|
-
import { dirname as dirname2, extname, isAbsolute, relative as relative2, resolve as resolve2, sep } from "node:path";
|
|
1854
|
+
import { dirname as dirname2, extname as extname2, isAbsolute, relative as relative2, resolve as resolve2, sep } from "node:path";
|
|
989
1855
|
import { visit as visit7 } from "unist-util-visit";
|
|
990
1856
|
|
|
991
1857
|
// src/util/file/to-asset-path.ts
|
|
@@ -997,7 +1863,7 @@ var toAssetPath = (options) => {
|
|
|
997
1863
|
return `${posix2.dirname(options.path)}/${posix2.basename(options.path, extension)}.${createHash("sha256").update(readFileSync(options.file)).digest("hex")}${extension}`;
|
|
998
1864
|
};
|
|
999
1865
|
|
|
1000
|
-
// src/
|
|
1866
|
+
// src/entry/cli/_function/create-processor/_rehype-assets.ts
|
|
1001
1867
|
var rehypeAssets = (options) => (tree, file) => {
|
|
1002
1868
|
visit7(tree, "element", (node) => {
|
|
1003
1869
|
const property = node.tagName === "img" ? "src" : "href";
|
|
@@ -1010,7 +1876,7 @@ var rehypeAssets = (options) => (tree, file) => {
|
|
|
1010
1876
|
return;
|
|
1011
1877
|
}
|
|
1012
1878
|
const path = decodeURIComponent(match[1]);
|
|
1013
|
-
const extension =
|
|
1879
|
+
const extension = extname2(path).toLowerCase();
|
|
1014
1880
|
if (!asset_media_extensions.has(extension)) {
|
|
1015
1881
|
if (node.tagName === "img") {
|
|
1016
1882
|
file.fail(`${copy_error_asset}: \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC774\uBBF8\uC9C0 \uD615\uC2DD \xB7 ${url}`, node);
|
|
@@ -1018,8 +1884,8 @@ var rehypeAssets = (options) => (tree, file) => {
|
|
|
1018
1884
|
return;
|
|
1019
1885
|
}
|
|
1020
1886
|
const target = resolve2(dirname2(file.path), path);
|
|
1021
|
-
const
|
|
1022
|
-
if (
|
|
1887
|
+
const location2 = relative2(options.root, target);
|
|
1888
|
+
if (location2 === ".." || location2.startsWith(`..${sep}`) || isAbsolute(location2)) {
|
|
1023
1889
|
file.fail(`${copy_error_asset}: \uBB38\uC11C \uD3F4\uB354 \uBC16 \xB7 ${url}`, node);
|
|
1024
1890
|
}
|
|
1025
1891
|
if (!existsSync2(target)) {
|
|
@@ -1036,7 +1902,7 @@ var rehypeAssets = (options) => (tree, file) => {
|
|
|
1036
1902
|
});
|
|
1037
1903
|
};
|
|
1038
1904
|
|
|
1039
|
-
// src/
|
|
1905
|
+
// src/entry/cli/_function/create-processor/_rehype-heading-ids.ts
|
|
1040
1906
|
import Slugger from "github-slugger";
|
|
1041
1907
|
import { toString as toPlainText3 } from "hast-util-to-string";
|
|
1042
1908
|
import { visit as visit8 } from "unist-util-visit";
|
|
@@ -1058,7 +1924,7 @@ var rehypeHeadingIds = () => (tree, file) => {
|
|
|
1058
1924
|
}
|
|
1059
1925
|
};
|
|
1060
1926
|
|
|
1061
|
-
// src/
|
|
1927
|
+
// src/entry/cli/_function/create-processor/_remark-report.ts
|
|
1062
1928
|
import { relative as relative3 } from "node:path";
|
|
1063
1929
|
var remarkReport = (options) => (_tree, file) => {
|
|
1064
1930
|
const path = relative3(options.root, file.path);
|
|
@@ -1067,13 +1933,13 @@ var remarkReport = (options) => (_tree, file) => {
|
|
|
1067
1933
|
}
|
|
1068
1934
|
};
|
|
1069
1935
|
|
|
1070
|
-
// src/
|
|
1936
|
+
// src/entry/cli/_function/create-processor/create-processor.ts
|
|
1071
1937
|
var createProcessor = (options) => {
|
|
1072
1938
|
return unified().use(remarkParse).use(remarkFrontmatter, ["yaml"]).use(remarkGfm).use(remarkSmartypants).use(remarkDirective).use(remarkBlocks).use(remarkParts).use(remarkFlow).use(remarkStatus, { status: options.site.status }).use(remarkSwatch).use(remarkLinks, { root: options.root }).use(remarkUnknownDirectives).use(remarkReport, { root: options.root }).use(remarkRehype, { allowDangerousHtml: true }).use(rehypeShiki, { theme: createCssVariablesTheme({ name: "for-humanity", variablePrefix: "--app-code-" }) }).use(rehypeHead).use(rehypeHeadingIds).use(rehypeSections).use(rehypeTables).use(rehypeRaw).use(rehypeAssets, { root: options.root, files: options.files ?? /* @__PURE__ */ new Map() }).use(rehypeStringify, { allowDangerousHtml: true });
|
|
1073
1939
|
};
|
|
1074
1940
|
|
|
1075
|
-
// src/
|
|
1076
|
-
import { readdir, readFile } from "node:fs/promises";
|
|
1941
|
+
// src/entry/cli/_function/read-docs.ts
|
|
1942
|
+
import { readdir, readFile as readFile2 } from "node:fs/promises";
|
|
1077
1943
|
import { join, posix as posix3, sep as sep2 } from "node:path";
|
|
1078
1944
|
import { VFile } from "vfile";
|
|
1079
1945
|
import { parse as parseYaml } from "yaml";
|
|
@@ -1120,7 +1986,7 @@ var docDataSchema = z2.object({
|
|
|
1120
1986
|
order: z2.number().int().nonnegative().default(doc_order_default)
|
|
1121
1987
|
});
|
|
1122
1988
|
|
|
1123
|
-
// src/
|
|
1989
|
+
// src/entry/cli/_function/read-docs.ts
|
|
1124
1990
|
var readDocs = async (options) => {
|
|
1125
1991
|
const paths = (await readdir(options.root, { recursive: true })).filter(
|
|
1126
1992
|
(path) => /\.mdx?$/i.test(path) && !/^(readme|agents|claude)\.md$/i.test(path) && !path.split(sep2).includes("node_modules") && !path.startsWith(`dist${sep2}`)
|
|
@@ -1132,7 +1998,7 @@ var readDocs = async (options) => {
|
|
|
1132
1998
|
if (segments.some((segment) => segment === "" || segment === "." || segment === ".." || segment === "index.html") || /[#?%*:\\]/.test(id) || /[\p{Cc}]/u.test(id) || segments[0] === asset_dir || segments[0] === asset_favicon_path.slice(1)) {
|
|
1133
1999
|
throw new Error(`${copy_error_doc_id}: ${path}`);
|
|
1134
2000
|
}
|
|
1135
|
-
const source = await
|
|
2001
|
+
const source = await readFile2(join(options.root, path), "utf8");
|
|
1136
2002
|
const file = new VFile({ value: source.replace(/^\uFEFF/, ""), path: join(options.root, path) });
|
|
1137
2003
|
const tree = options.processor.parse(file);
|
|
1138
2004
|
const frontmatter = tree.children[0];
|
|
@@ -1182,8 +2048,8 @@ var readDocs = async (options) => {
|
|
|
1182
2048
|
});
|
|
1183
2049
|
};
|
|
1184
2050
|
|
|
1185
|
-
// src/
|
|
1186
|
-
import { readdir as readdir2, readFile as
|
|
2051
|
+
// src/entry/cli/_function/read-home.ts
|
|
2052
|
+
import { readdir as readdir2, readFile as readFile3 } from "node:fs/promises";
|
|
1187
2053
|
import { join as join2 } from "node:path";
|
|
1188
2054
|
import { VFile as VFile2 } from "vfile";
|
|
1189
2055
|
var readHome = async (options) => {
|
|
@@ -1196,52 +2062,11 @@ var readHome = async (options) => {
|
|
|
1196
2062
|
}
|
|
1197
2063
|
const path = join2(options.root, paths[0]);
|
|
1198
2064
|
const fh = { headings: [], sections: [] };
|
|
1199
|
-
const file = new VFile2({ value: (await
|
|
2065
|
+
const file = new VFile2({ value: (await readFile3(path, "utf8")).replace(/^\uFEFF/, ""), path, data: { fh } });
|
|
1200
2066
|
await options.processor.process(file);
|
|
1201
2067
|
return { html: String(file), outline: { headings: fh.headings, sections: fh.sections } };
|
|
1202
2068
|
};
|
|
1203
2069
|
|
|
1204
|
-
// src/dev.ts
|
|
1205
|
-
import { readFile as readFile3 } from "node:fs/promises";
|
|
1206
|
-
import { extname as extname2 } from "node:path";
|
|
1207
|
-
import { Hono as Hono2 } from "hono";
|
|
1208
|
-
import { streamSSE } from "hono/streaming";
|
|
1209
|
-
var createDevApp = (options) => {
|
|
1210
|
-
const app = new Hono2();
|
|
1211
|
-
const handleAsset = async (c) => {
|
|
1212
|
-
const file = options.files.get(c.req.path);
|
|
1213
|
-
if (file === void 0) {
|
|
1214
|
-
return c.notFound();
|
|
1215
|
-
}
|
|
1216
|
-
c.header("content-type", asset_content_types[extname2(file).toLowerCase()] ?? asset_content_type_default);
|
|
1217
|
-
if (extname2(file) === ".woff2") {
|
|
1218
|
-
c.header("Cache-Control", font_cache_control);
|
|
1219
|
-
}
|
|
1220
|
-
return c.body(await readFile3(file));
|
|
1221
|
-
};
|
|
1222
|
-
app.get(
|
|
1223
|
-
asset_reload_path,
|
|
1224
|
-
(c) => streamSSE(
|
|
1225
|
-
c,
|
|
1226
|
-
(stream) => new Promise((done) => {
|
|
1227
|
-
const handleChange = async () => {
|
|
1228
|
-
await stream.writeSSE({ data: "change" });
|
|
1229
|
-
done();
|
|
1230
|
-
};
|
|
1231
|
-
options.reload.once("change", handleChange);
|
|
1232
|
-
stream.onAbort(() => {
|
|
1233
|
-
options.reload.off("change", handleChange);
|
|
1234
|
-
done();
|
|
1235
|
-
});
|
|
1236
|
-
})
|
|
1237
|
-
)
|
|
1238
|
-
);
|
|
1239
|
-
app.get(`/${asset_dir}/*`, handleAsset);
|
|
1240
|
-
app.get(asset_favicon_path, handleAsset);
|
|
1241
|
-
app.all("/*", (c) => options.pages.fetch(c.req.raw, c.env));
|
|
1242
|
-
return app;
|
|
1243
|
-
};
|
|
1244
|
-
|
|
1245
2070
|
// src/type/site-config.ts
|
|
1246
2071
|
import { z as z3 } from "zod";
|
|
1247
2072
|
|
|
@@ -1343,7 +2168,7 @@ var toFontCss = (options) => {
|
|
|
1343
2168
|
return { css, files };
|
|
1344
2169
|
};
|
|
1345
2170
|
|
|
1346
|
-
// src/cli.ts
|
|
2171
|
+
// src/entry/cli/cli.ts
|
|
1347
2172
|
var commands = ["dev", "build", "preview"];
|
|
1348
2173
|
var [command = cli_default_command, docsDir = cli_default_docs_dir] = process.argv.slice(2);
|
|
1349
2174
|
var main = async () => {
|
|
@@ -1384,10 +2209,9 @@ var main = async () => {
|
|
|
1384
2209
|
}
|
|
1385
2210
|
const fontCss = [sans.css, mono.css, brand.css].join("\n");
|
|
1386
2211
|
const stylePath = toAssetPath({ path: asset_style_path, file: join4(kitRoot, "dist/cli.css") });
|
|
1387
|
-
const
|
|
2212
|
+
const browserScript = readFileSync3(join4(kitRoot, "dist/browser.js"), "utf8");
|
|
1388
2213
|
const kitFiles = new Map([
|
|
1389
2214
|
[stylePath, join4(kitRoot, "dist/cli.css")],
|
|
1390
|
-
[clientPath, join4(kitRoot, "dist/client.js")],
|
|
1391
2215
|
[asset_favicon_path, join4(kitRoot, "src/asset/favicon.svg")],
|
|
1392
2216
|
...sans.files,
|
|
1393
2217
|
...mono.files,
|
|
@@ -1400,7 +2224,7 @@ var main = async () => {
|
|
|
1400
2224
|
const app = createApp({
|
|
1401
2225
|
site: siteConfig,
|
|
1402
2226
|
store,
|
|
1403
|
-
assets: { stylePath,
|
|
2227
|
+
assets: { stylePath, browserScript, fontCss, preload: [...brand.files.keys(), sansPreload[0], ...mono.files.keys()], reload: command === "dev" }
|
|
1404
2228
|
});
|
|
1405
2229
|
if (command === "build") {
|
|
1406
2230
|
await rm(outDir, { recursive: true, force: true });
|