for-humanity 0.2.1 → 0.4.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 +20 -0
- package/README.md +6 -5
- package/dist/cli.css +66 -54
- package/dist/cli.js +183 -55
- package/dist/client.js +2 -2
- package/package.json +1 -1
- package/src/cli.ts +18 -7
- package/src/client.ts +12 -1
- package/src/component/widget/shell/_wg-shell-nav-list.css +70 -57
- package/src/component/widget/shell/_wg-shell-nav-list.tsx +25 -10
- package/src/component/widget/shell/_wg-shell-nav.css +3 -2
- package/src/component/widget/shell/_wg-shell-toc.css +6 -5
- package/src/constant/asset.ts +20 -0
- package/src/constant/copy.ts +21 -1
- package/src/constant/doc.ts +2 -2
- package/src/content/create-processor.ts +3 -1
- package/src/content/read-docs.test.ts +180 -3
- package/src/content/read-docs.ts +39 -5
- package/src/content/rehype-assets.ts +70 -0
- package/src/content/to-doc-groups/_to-doc-branches.ts +15 -0
- package/src/content/to-doc-groups/_to-doc-group-branches.ts +17 -5
- package/src/content/to-doc-groups/to-doc-groups.ts +2 -1
- package/src/dev.ts +1 -1
- package/src/style/token.css +4 -3
- package/src/type/doc-branch.ts +11 -0
- package/src/type/doc-data.ts +5 -1
- package/src/type/doc-group.ts +3 -2
- package/src/type/doc.ts +4 -0
package/dist/cli.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { EventEmitter } from "node:events";
|
|
5
|
-
import { existsSync as
|
|
5
|
+
import { existsSync as existsSync3, watch } from "node:fs";
|
|
6
6
|
import { copyFile, mkdir, rm, writeFile } from "node:fs/promises";
|
|
7
|
-
import { basename as basename2, dirname as
|
|
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";
|
|
9
9
|
import { serve } from "@hono/node-server";
|
|
10
10
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
@@ -73,8 +73,12 @@ import clsx2 from "clsx";
|
|
|
73
73
|
import { Fragment } from "react";
|
|
74
74
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
75
75
|
var WgShellNavList = (props) => {
|
|
76
|
+
const currentAncestors = new Set(props.currentDoc?.ancestors);
|
|
76
77
|
const entries = [
|
|
77
|
-
...props.group.docs.map((doc) =>
|
|
78
|
+
...props.group.docs.map((doc) => {
|
|
79
|
+
const active = doc.id === props.currentDoc?.id;
|
|
80
|
+
return { kind: "document", key: `doc:${doc.id}`, doc, active, current: active || currentAncestors.has(doc.id) };
|
|
81
|
+
}),
|
|
78
82
|
...props.group.groups.map((group) => ({
|
|
79
83
|
kind: "group",
|
|
80
84
|
key: `group:${JSON.stringify(group.path)}`,
|
|
@@ -91,16 +95,25 @@ var WgShellNavList = (props) => {
|
|
|
91
95
|
"wg_shellNavList__item--current": entry.current
|
|
92
96
|
}),
|
|
93
97
|
children: [
|
|
94
|
-
entry.kind === "document" && /* @__PURE__ */
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
entry.kind === "document" && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
99
|
+
/* @__PURE__ */ jsx2(
|
|
100
|
+
"a",
|
|
101
|
+
{
|
|
102
|
+
className: clsx2("wg_shellNavList__link", { "wg_shellNavList__link--active": entry.active }),
|
|
103
|
+
href: `/${entry.doc.id}/`,
|
|
104
|
+
title: entry.doc.data.label,
|
|
105
|
+
"aria-current": entry.active ? "page" : void 0,
|
|
106
|
+
children: entry.doc.data.name
|
|
107
|
+
}
|
|
108
|
+
),
|
|
109
|
+
entry.doc.children !== void 0 && /* @__PURE__ */ jsx2(
|
|
110
|
+
WgShellNavList,
|
|
111
|
+
{
|
|
112
|
+
group: { name: entry.doc.data.name, path: entry.doc.data.group, docs: entry.doc.children, groups: [] },
|
|
113
|
+
currentDoc: props.currentDoc
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
] }),
|
|
104
117
|
entry.kind === "group" && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
105
118
|
/* @__PURE__ */ jsx2("span", { className: clsx2("wg_shellNavList__branch"), children: entry.group.name }),
|
|
106
119
|
/* @__PURE__ */ jsx2(WgShellNavList, { group: entry.group, currentDoc: props.currentDoc })
|
|
@@ -118,7 +131,7 @@ var copy_nav_open = "Open navigation";
|
|
|
118
131
|
var copy_nav_close = "Close navigation";
|
|
119
132
|
var copy_nav_title = "Navigation";
|
|
120
133
|
var copy_home_missing = "\uBB38\uC11C \uD3F4\uB354\uC5D0 README.md\uB97C \uCD94\uAC00\uD558\uBA74 \uC774\uACF3\uC5D0 \uD648 \uD654\uBA74\uC73C\uB85C \uD45C\uC2DC\uB429\uB2C8\uB2E4.";
|
|
121
|
-
var copy_nav_toc_label = "
|
|
134
|
+
var copy_nav_toc_label = "On this page";
|
|
122
135
|
var copy_error_home_clash = "\uD648 README\uAC00 \uACB9\uCE5C\uB2E4";
|
|
123
136
|
var copy_error_prefix = "for-humanity";
|
|
124
137
|
var copy_error_font_preload = "Missing bundled font for preload";
|
|
@@ -128,16 +141,28 @@ var copy_error_frontmatter = "frontmatter\uAC00 \uC62C\uBC14\uB974\uC9C0 \uC54A\
|
|
|
128
141
|
var copy_error_navigation_clash = "navigation\uC758 \uBB36\uC74C\uC774 \uACB9\uCE5C\uB2E4";
|
|
129
142
|
var copy_error_doc_id = "\uBB38\uC11C id\uC5D0 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uB294 \uACBD\uB85C";
|
|
130
143
|
var copy_error_doc_id_clash = "\uBB38\uC11C id\uAC00 \uACB9\uCE5C\uB2E4";
|
|
144
|
+
var copy_error_doc_parent_missing = "\uBD80\uBAA8 \uBB38\uC11C\uAC00 \uC5C6\uB2E4";
|
|
145
|
+
var copy_error_doc_parent_cycle = "\uBB38\uC11C parent\uAC00 \uC21C\uD658\uD55C\uB2E4";
|
|
146
|
+
var copy_error_doc_parent_group = "\uBD80\uBAA8 \uBB38\uC11C\uC640 group\uC774 \uB2E4\uB974\uB2E4";
|
|
131
147
|
var copy_error_flow = "\uD750\uB984\uB3C4\uB97C \uADF8\uB9AC\uC9C0 \uBABB\uD588\uB2E4";
|
|
132
148
|
var copy_error_unknown_directive = "\uBAA8\uB974\uB294 \uBD80\uD488\uC774\uB2E4";
|
|
133
149
|
var copy_error_directive_syntax = "\uBD80\uD488 \uBB38\uBC95\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uB2E4";
|
|
134
150
|
var copy_warn_broken_link = "\uC5C6\uB294 \uBB38\uC11C\uB85C \uAC74 \uB9C1\uD06C\uB2E4";
|
|
135
151
|
var copy_warn_unknown_status = "\uC124\uC815\uC5D0 \uC5C6\uB294 \uC0C1\uD0DC \uBB38\uAD6C\uB2E4";
|
|
152
|
+
var copy_error_asset = "\uC790\uC6D0\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uB2E4";
|
|
136
153
|
|
|
137
154
|
// src/constant/locale.ts
|
|
138
155
|
var locale_doc_name = "en";
|
|
139
156
|
var locale_doc_group = "ko";
|
|
140
157
|
|
|
158
|
+
// src/content/to-doc-groups/_to-doc-branches.ts
|
|
159
|
+
var toDocBranches = (options) => {
|
|
160
|
+
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) => {
|
|
161
|
+
const children = options.children.get(doc.id);
|
|
162
|
+
return { ...doc, children: children === void 0 ? void 0 : toDocBranches({ docs: children, children: options.children }) };
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
|
|
141
166
|
// src/content/to-doc-groups/_to-doc-group-branches.ts
|
|
142
167
|
var toDocGroupBranches = (options) => {
|
|
143
168
|
return [
|
|
@@ -157,8 +182,17 @@ var toDocGroupBranches = (options) => {
|
|
|
157
182
|
return {
|
|
158
183
|
name: group.name,
|
|
159
184
|
path: group.path,
|
|
160
|
-
docs:
|
|
161
|
-
|
|
185
|
+
docs: toDocBranches({
|
|
186
|
+
docs: group.docs.filter((doc) => doc.data.group.length === group.path.length && doc.data.parent === void 0),
|
|
187
|
+
children: options.children
|
|
188
|
+
}),
|
|
189
|
+
groups: toDocGroupBranches({
|
|
190
|
+
docs: group.docs,
|
|
191
|
+
children: options.children,
|
|
192
|
+
path: group.path,
|
|
193
|
+
positions: options.positions,
|
|
194
|
+
unlistedPosition: options.unlistedPosition
|
|
195
|
+
})
|
|
162
196
|
};
|
|
163
197
|
});
|
|
164
198
|
};
|
|
@@ -166,7 +200,8 @@ var toDocGroupBranches = (options) => {
|
|
|
166
200
|
// src/content/to-doc-groups/to-doc-groups.ts
|
|
167
201
|
var toDocGroups = (options) => {
|
|
168
202
|
const positions = new Map(options.navigation.flatMap((path, index) => path.map((_name, depth) => [JSON.stringify(path.slice(0, depth + 1)), index])).toReversed());
|
|
169
|
-
|
|
203
|
+
const children = Map.groupBy(options.docs, (doc) => doc.data.parent);
|
|
204
|
+
return toDocGroupBranches({ docs: options.docs, children, path: [], positions, unlistedPosition: options.navigation.length });
|
|
170
205
|
};
|
|
171
206
|
|
|
172
207
|
// src/component/widget/shell/_wg-shell-nav.tsx
|
|
@@ -208,9 +243,21 @@ var asset_content_types = {
|
|
|
208
243
|
".css": "text/css; charset=utf-8",
|
|
209
244
|
".js": "text/javascript; charset=utf-8",
|
|
210
245
|
".woff2": "font/woff2",
|
|
211
|
-
".svg": "image/svg+xml"
|
|
246
|
+
".svg": "image/svg+xml",
|
|
247
|
+
".png": "image/png",
|
|
248
|
+
".jpg": "image/jpeg",
|
|
249
|
+
".jpeg": "image/jpeg",
|
|
250
|
+
".gif": "image/gif",
|
|
251
|
+
".webp": "image/webp",
|
|
252
|
+
".avif": "image/avif",
|
|
253
|
+
".pdf": "application/pdf",
|
|
254
|
+
".csv": "text/csv; charset=utf-8",
|
|
255
|
+
".txt": "text/plain; charset=utf-8",
|
|
256
|
+
".zip": "application/zip"
|
|
212
257
|
};
|
|
213
258
|
var asset_content_type_default = "application/octet-stream";
|
|
259
|
+
var asset_media_dir = `/${asset_dir}/media`;
|
|
260
|
+
var asset_media_extensions = /* @__PURE__ */ new Set([".svg", ".png", ".jpg", ".jpeg", ".gif", ".webp", ".avif", ".pdf", ".csv", ".txt", ".zip"]);
|
|
214
261
|
|
|
215
262
|
// src/component/widget/shell/wg-shell.tsx
|
|
216
263
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
@@ -934,14 +981,67 @@ var remarkUnknownDirectives = () => (tree, file) => {
|
|
|
934
981
|
});
|
|
935
982
|
};
|
|
936
983
|
|
|
984
|
+
// src/content/rehype-assets.ts
|
|
985
|
+
import { existsSync as existsSync2, realpathSync, statSync } from "node:fs";
|
|
986
|
+
import { dirname as dirname2, extname, isAbsolute, relative as relative2, resolve as resolve2, sep } from "node:path";
|
|
987
|
+
import { visit as visit7 } from "unist-util-visit";
|
|
988
|
+
|
|
989
|
+
// src/util/file/to-asset-path.ts
|
|
990
|
+
import { createHash } from "node:crypto";
|
|
991
|
+
import { readFileSync } from "node:fs";
|
|
992
|
+
import { posix as posix2 } from "node:path";
|
|
993
|
+
var toAssetPath = (options) => {
|
|
994
|
+
const extension = posix2.extname(options.path);
|
|
995
|
+
return `${posix2.dirname(options.path)}/${posix2.basename(options.path, extension)}.${createHash("sha256").update(readFileSync(options.file)).digest("hex")}${extension}`;
|
|
996
|
+
};
|
|
997
|
+
|
|
998
|
+
// src/content/rehype-assets.ts
|
|
999
|
+
var rehypeAssets = (options) => (tree, file) => {
|
|
1000
|
+
visit7(tree, "element", (node) => {
|
|
1001
|
+
const property = node.tagName === "img" ? "src" : "href";
|
|
1002
|
+
const url = node.properties[property];
|
|
1003
|
+
if (node.tagName !== "img" && node.tagName !== "a" || typeof url !== "string" || /^(?:[a-z][a-z\d+.-]*:|\/|#)/i.test(url)) {
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
1006
|
+
const match = /^([^?#]+)([?#].*)?$/.exec(url);
|
|
1007
|
+
if (match === null) {
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
const path = decodeURIComponent(match[1]);
|
|
1011
|
+
const extension = extname(path).toLowerCase();
|
|
1012
|
+
if (!asset_media_extensions.has(extension)) {
|
|
1013
|
+
if (node.tagName === "img") {
|
|
1014
|
+
file.fail(`${copy_error_asset}: \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC774\uBBF8\uC9C0 \uD615\uC2DD \xB7 ${url}`, node);
|
|
1015
|
+
}
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
1018
|
+
const target = resolve2(dirname2(file.path), path);
|
|
1019
|
+
const location = relative2(options.root, target);
|
|
1020
|
+
if (location === ".." || location.startsWith(`..${sep}`) || isAbsolute(location)) {
|
|
1021
|
+
file.fail(`${copy_error_asset}: \uBB38\uC11C \uD3F4\uB354 \uBC16 \xB7 ${url}`, node);
|
|
1022
|
+
}
|
|
1023
|
+
if (!existsSync2(target)) {
|
|
1024
|
+
file.fail(`${copy_error_asset}: \uD30C\uC77C\uC774 \uC5C6\uB2E4 \xB7 ${url}`, node);
|
|
1025
|
+
}
|
|
1026
|
+
const actual = realpathSync(target);
|
|
1027
|
+
const actualLocation = relative2(realpathSync(options.root), actual);
|
|
1028
|
+
if (actualLocation === ".." || actualLocation.startsWith(`..${sep}`) || isAbsolute(actualLocation) || !statSync(actual).isFile()) {
|
|
1029
|
+
file.fail(`${copy_error_asset}: \uBB38\uC11C \uD3F4\uB354 \uBC16\uC774\uAC70\uB098 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2C8\uB2E4 \xB7 ${url}`, node);
|
|
1030
|
+
}
|
|
1031
|
+
const assetUrl = toAssetPath({ path: `${asset_media_dir}/asset${extension}`, file: actual });
|
|
1032
|
+
options.files.set(assetUrl, actual);
|
|
1033
|
+
node.properties[property] = match[2] === void 0 ? assetUrl : `${assetUrl}${match[2]}`;
|
|
1034
|
+
});
|
|
1035
|
+
};
|
|
1036
|
+
|
|
937
1037
|
// src/content/rehype-heading-ids.ts
|
|
938
1038
|
import Slugger from "github-slugger";
|
|
939
1039
|
import { toString as toPlainText3 } from "hast-util-to-string";
|
|
940
|
-
import { visit as
|
|
1040
|
+
import { visit as visit8 } from "unist-util-visit";
|
|
941
1041
|
var rehypeHeadingIds = () => (tree, file) => {
|
|
942
1042
|
const slugger = new Slugger();
|
|
943
1043
|
const headings = [];
|
|
944
|
-
|
|
1044
|
+
visit8(tree, "element", (node) => {
|
|
945
1045
|
const depth = /^h([1-6])$/.exec(node.tagName)?.[1];
|
|
946
1046
|
if (depth === void 0) {
|
|
947
1047
|
return;
|
|
@@ -957,9 +1057,9 @@ var rehypeHeadingIds = () => (tree, file) => {
|
|
|
957
1057
|
};
|
|
958
1058
|
|
|
959
1059
|
// src/content/remark-report.ts
|
|
960
|
-
import { relative as
|
|
1060
|
+
import { relative as relative3 } from "node:path";
|
|
961
1061
|
var remarkReport = (options) => (_tree, file) => {
|
|
962
|
-
const path =
|
|
1062
|
+
const path = relative3(options.root, file.path);
|
|
963
1063
|
for (const message of file.messages) {
|
|
964
1064
|
console.warn(`${message.line === void 0 ? path : `${path}:${message.line}`} ${message.reason}`);
|
|
965
1065
|
}
|
|
@@ -967,12 +1067,12 @@ var remarkReport = (options) => (_tree, file) => {
|
|
|
967
1067
|
|
|
968
1068
|
// src/content/create-processor.ts
|
|
969
1069
|
var createProcessor = (options) => {
|
|
970
|
-
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(rehypeStringify, { allowDangerousHtml: true });
|
|
1070
|
+
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 });
|
|
971
1071
|
};
|
|
972
1072
|
|
|
973
1073
|
// src/content/read-docs.ts
|
|
974
1074
|
import { readdir, readFile } from "node:fs/promises";
|
|
975
|
-
import { join, sep } from "node:path";
|
|
1075
|
+
import { join, posix as posix3, sep as sep2 } from "node:path";
|
|
976
1076
|
import { VFile } from "vfile";
|
|
977
1077
|
import { parse as parseYaml } from "yaml";
|
|
978
1078
|
|
|
@@ -1001,13 +1101,17 @@ var docDataSchema = z2.object({
|
|
|
1001
1101
|
*/
|
|
1002
1102
|
label: z2.string(),
|
|
1003
1103
|
/**
|
|
1004
|
-
*
|
|
1104
|
+
* 기존 type 값 호환 · 생략 권장, 렌더링 차이 없음
|
|
1005
1105
|
*/
|
|
1006
1106
|
type: z2.enum(doc_type).default(doc_type.document),
|
|
1007
1107
|
/**
|
|
1008
1108
|
* 사이드바의 문서 묶음 경로 · 문자열도 배열로 정규화
|
|
1009
1109
|
*/
|
|
1010
1110
|
group: groupPathSchema,
|
|
1111
|
+
/**
|
|
1112
|
+
* 같은 묶음 안의 부모 문서 id · 확장자 제외, ./·../ 상대 경로도 허용
|
|
1113
|
+
*/
|
|
1114
|
+
parent: z2.string().trim().min(1).optional(),
|
|
1011
1115
|
/**
|
|
1012
1116
|
* 묶음 안의 읽는 순서 · 미지정 문서는 뒤에서 이름순
|
|
1013
1117
|
*/
|
|
@@ -1017,11 +1121,11 @@ var docDataSchema = z2.object({
|
|
|
1017
1121
|
// src/content/read-docs.ts
|
|
1018
1122
|
var readDocs = async (options) => {
|
|
1019
1123
|
const paths = (await readdir(options.root, { recursive: true })).filter(
|
|
1020
|
-
(path) => /\.mdx?$/i.test(path) && !/^(readme|agents|claude)\.md$/i.test(path) && !path.split(
|
|
1124
|
+
(path) => /\.mdx?$/i.test(path) && !/^(readme|agents|claude)\.md$/i.test(path) && !path.split(sep2).includes("node_modules") && !path.startsWith(`dist${sep2}`)
|
|
1021
1125
|
);
|
|
1022
1126
|
const docs = await Promise.all(
|
|
1023
1127
|
paths.map(async (path) => {
|
|
1024
|
-
const id = path.replace(/\.mdx?$/i, "").split(
|
|
1128
|
+
const id = path.replace(/\.mdx?$/i, "").split(sep2).join("/").toLowerCase();
|
|
1025
1129
|
const segments = id.split("/");
|
|
1026
1130
|
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)) {
|
|
1027
1131
|
throw new Error(`${copy_error_doc_id}: ${path}`);
|
|
@@ -1034,13 +1138,18 @@ var readDocs = async (options) => {
|
|
|
1034
1138
|
if (!parsed.success) {
|
|
1035
1139
|
throw new Error(`${copy_error_frontmatter}: ${path}: ${parsed.error.issues.map((issue) => `${issue.path.join(".")} ${issue.message}`).join(", ")}`);
|
|
1036
1140
|
}
|
|
1037
|
-
const
|
|
1141
|
+
const data = {
|
|
1142
|
+
...parsed.data,
|
|
1143
|
+
parent: parsed.data.parent !== void 0 && /^\.\.?\//.test(parsed.data.parent) ? posix3.join(posix3.dirname(id), parsed.data.parent) : parsed.data.parent
|
|
1144
|
+
};
|
|
1145
|
+
const fh = { frontmatter: data, headings: [], sections: [] };
|
|
1038
1146
|
file.data.fh = fh;
|
|
1039
1147
|
tree.children = tree.children.filter((node) => node.type !== "yaml");
|
|
1040
1148
|
const rendered = await options.processor.run(tree, file);
|
|
1041
1149
|
return {
|
|
1042
1150
|
id,
|
|
1043
|
-
data
|
|
1151
|
+
data,
|
|
1152
|
+
ancestors: [],
|
|
1044
1153
|
html: options.processor.stringify(rendered, file),
|
|
1045
1154
|
outline: { headings: fh.headings, sections: fh.sections }
|
|
1046
1155
|
};
|
|
@@ -1050,7 +1159,25 @@ var readDocs = async (options) => {
|
|
|
1050
1159
|
if (duplicateIds.length > 0) {
|
|
1051
1160
|
throw new Error(`${copy_error_doc_id_clash}: ${duplicateIds.map((entry) => entry[0]).join(", ")}`);
|
|
1052
1161
|
}
|
|
1053
|
-
|
|
1162
|
+
const docsById = new Map(docs.map((doc) => [doc.id, doc]));
|
|
1163
|
+
return docs.map((doc) => {
|
|
1164
|
+
const ancestors = /* @__PURE__ */ new Set([doc.id]);
|
|
1165
|
+
for (let parentId = doc.data.parent; parentId !== void 0; ) {
|
|
1166
|
+
const parent = docsById.get(parentId);
|
|
1167
|
+
if (parent === void 0) {
|
|
1168
|
+
throw new Error(`${copy_error_doc_parent_missing}: ${doc.id} \u2192 ${parentId}`);
|
|
1169
|
+
}
|
|
1170
|
+
if (ancestors.has(parent.id)) {
|
|
1171
|
+
throw new Error(`${copy_error_doc_parent_cycle}: ${[...ancestors, parent.id].join(" \u2192 ")}`);
|
|
1172
|
+
}
|
|
1173
|
+
if (JSON.stringify(parent.data.group) !== JSON.stringify(doc.data.group)) {
|
|
1174
|
+
throw new Error(`${copy_error_doc_parent_group}: ${doc.id} \u2192 ${parent.id}`);
|
|
1175
|
+
}
|
|
1176
|
+
ancestors.add(parent.id);
|
|
1177
|
+
parentId = parent.data.parent;
|
|
1178
|
+
}
|
|
1179
|
+
return { ...doc, ancestors: [...ancestors].slice(1).toReversed() };
|
|
1180
|
+
});
|
|
1054
1181
|
};
|
|
1055
1182
|
|
|
1056
1183
|
// src/content/read-home.ts
|
|
@@ -1074,7 +1201,7 @@ var readHome = async (options) => {
|
|
|
1074
1201
|
|
|
1075
1202
|
// src/dev.ts
|
|
1076
1203
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
1077
|
-
import { extname } from "node:path";
|
|
1204
|
+
import { extname as extname2 } from "node:path";
|
|
1078
1205
|
import { Hono as Hono2 } from "hono";
|
|
1079
1206
|
import { streamSSE } from "hono/streaming";
|
|
1080
1207
|
var createDevApp = (options) => {
|
|
@@ -1084,8 +1211,8 @@ var createDevApp = (options) => {
|
|
|
1084
1211
|
if (file === void 0) {
|
|
1085
1212
|
return c.notFound();
|
|
1086
1213
|
}
|
|
1087
|
-
c.header("content-type", asset_content_types[
|
|
1088
|
-
if (
|
|
1214
|
+
c.header("content-type", asset_content_types[extname2(file).toLowerCase()] ?? asset_content_type_default);
|
|
1215
|
+
if (extname2(file) === ".woff2") {
|
|
1089
1216
|
c.header("Cache-Control", font_cache_control);
|
|
1090
1217
|
}
|
|
1091
1218
|
return c.body(await readFile3(file));
|
|
@@ -1169,25 +1296,16 @@ var toErrorMessage = (error) => {
|
|
|
1169
1296
|
return error instanceof Error ? error.message : String(error);
|
|
1170
1297
|
};
|
|
1171
1298
|
|
|
1172
|
-
// src/util/file/to-asset-path.ts
|
|
1173
|
-
import { createHash } from "node:crypto";
|
|
1174
|
-
import { readFileSync } from "node:fs";
|
|
1175
|
-
import { posix as posix2 } from "node:path";
|
|
1176
|
-
var toAssetPath = (options) => {
|
|
1177
|
-
const extension = posix2.extname(options.path);
|
|
1178
|
-
return `${posix2.dirname(options.path)}/${posix2.basename(options.path, extension)}.${createHash("sha256").update(readFileSync(options.file)).digest("hex")}${extension}`;
|
|
1179
|
-
};
|
|
1180
|
-
|
|
1181
1299
|
// src/util/font/to-font-css.ts
|
|
1182
1300
|
import { createHash as createHash2 } from "node:crypto";
|
|
1183
1301
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
1184
|
-
import { basename, dirname as
|
|
1302
|
+
import { basename, dirname as dirname3, extname as extname3, join as join3 } from "node:path";
|
|
1185
1303
|
var toFontCss = (options) => {
|
|
1186
1304
|
const files = /* @__PURE__ */ new Map();
|
|
1187
1305
|
const css = [...readFileSync2(options.css, "utf8").matchAll(/@font-face\s*\{[^}]*\}/g)].map(
|
|
1188
1306
|
(match) => match[0].replace(/font-display:\s*[^;]+;/g, `font-display: ${font_display_strategy};`).replace(/url\(([^)]+)\)/g, (_match, relativeUrl) => {
|
|
1189
|
-
const file = join3(
|
|
1190
|
-
const extension =
|
|
1307
|
+
const file = join3(dirname3(options.css), relativeUrl);
|
|
1308
|
+
const extension = extname3(file);
|
|
1191
1309
|
const hash = createHash2("sha256").update(readFileSync2(file)).digest("hex").slice(0, font_hash_length);
|
|
1192
1310
|
const url = `${options.fontDir}/${basename(file, extension)}.${hash}${extension}`;
|
|
1193
1311
|
files.set(url, file);
|
|
@@ -1205,14 +1323,14 @@ var main = async () => {
|
|
|
1205
1323
|
throw new Error(`${copy_error_unknown_command}: ${command} (${commands.join(", ")})`);
|
|
1206
1324
|
}
|
|
1207
1325
|
const kitRoot = fileURLToPath(new URL("../", import.meta.url));
|
|
1208
|
-
const docsRoot =
|
|
1326
|
+
const docsRoot = resolve3(docsDir);
|
|
1209
1327
|
const outDir = join4(docsRoot, "dist");
|
|
1210
1328
|
if (command === "preview") {
|
|
1211
1329
|
const app2 = new Hono3();
|
|
1212
1330
|
app2.use(
|
|
1213
1331
|
"/*",
|
|
1214
1332
|
serveStatic({
|
|
1215
|
-
root:
|
|
1333
|
+
root: relative4(process.cwd(), outDir),
|
|
1216
1334
|
onFound: (_path, c) => {
|
|
1217
1335
|
if (c.req.path.startsWith(`${asset_font_dir}/`)) {
|
|
1218
1336
|
c.header("Cache-Control", font_cache_control);
|
|
@@ -1224,7 +1342,7 @@ var main = async () => {
|
|
|
1224
1342
|
return;
|
|
1225
1343
|
}
|
|
1226
1344
|
const configFile = join4(docsRoot, cli_config_file_name);
|
|
1227
|
-
const parsedConfig = siteConfigSchema.safeParse(
|
|
1345
|
+
const parsedConfig = siteConfigSchema.safeParse(existsSync3(configFile) ? (await import(pathToFileURL(configFile).href)).default : site_config_absent);
|
|
1228
1346
|
if (!parsedConfig.success) {
|
|
1229
1347
|
throw new Error(`${copy_error_config}: ${parsedConfig.error.issues.map((issue) => `${issue.path.join(".")} ${issue.message}`).join(", ")}`);
|
|
1230
1348
|
}
|
|
@@ -1239,7 +1357,7 @@ var main = async () => {
|
|
|
1239
1357
|
const fontCss = [sans.css, mono.css, brand.css].join("\n");
|
|
1240
1358
|
const stylePath = toAssetPath({ path: asset_style_path, file: join4(kitRoot, "dist/cli.css") });
|
|
1241
1359
|
const clientPath = toAssetPath({ path: asset_client_path, file: join4(kitRoot, "dist/client.js") });
|
|
1242
|
-
const
|
|
1360
|
+
const kitFiles = new Map([
|
|
1243
1361
|
[stylePath, join4(kitRoot, "dist/cli.css")],
|
|
1244
1362
|
[clientPath, join4(kitRoot, "dist/client.js")],
|
|
1245
1363
|
[asset_favicon_path, join4(kitRoot, "src/asset/favicon.svg")],
|
|
@@ -1247,7 +1365,8 @@ var main = async () => {
|
|
|
1247
1365
|
...mono.files,
|
|
1248
1366
|
...brand.files
|
|
1249
1367
|
]);
|
|
1250
|
-
const
|
|
1368
|
+
const files = new Map(kitFiles);
|
|
1369
|
+
const processor = createProcessor({ site: siteConfig, root: docsRoot, files });
|
|
1251
1370
|
const [docs, home] = await Promise.all([readDocs({ root: docsRoot, processor }), readHome({ root: docsRoot, processor })]);
|
|
1252
1371
|
const store = { docs, home };
|
|
1253
1372
|
const app = createApp({
|
|
@@ -1262,25 +1381,34 @@ var main = async () => {
|
|
|
1262
1381
|
throw result.error;
|
|
1263
1382
|
}
|
|
1264
1383
|
for (const [url, file] of files) {
|
|
1265
|
-
await mkdir(
|
|
1384
|
+
await mkdir(dirname4(join4(outDir, url)), { recursive: true });
|
|
1266
1385
|
await copyFile(file, join4(outDir, url));
|
|
1267
1386
|
}
|
|
1268
|
-
console.log(`${result.files.length} pages, ${files.size} assets \u2192 ${
|
|
1387
|
+
console.log(`${result.files.length} pages, ${files.size} assets \u2192 ${relative4(process.cwd(), outDir)}`);
|
|
1269
1388
|
return;
|
|
1270
1389
|
}
|
|
1271
1390
|
const reload = new EventEmitter();
|
|
1272
1391
|
let generation = 0;
|
|
1273
1392
|
serve({ fetch: createDevApp({ pages: app, files, reload }).fetch, port: cli_dev_port }, (info) => console.log(`http://localhost:${info.port}/`));
|
|
1274
1393
|
const handleDocsChange = async (_event, filename) => {
|
|
1275
|
-
if (filename !== null
|
|
1276
|
-
|
|
1394
|
+
if (filename !== null) {
|
|
1395
|
+
const segments = filename.split(sep3);
|
|
1396
|
+
if (segments.includes("dist") || segments.includes("node_modules") || !/\.mdx?$/i.test(filename) && !asset_media_extensions.has(extname4(filename).toLowerCase())) {
|
|
1397
|
+
return;
|
|
1398
|
+
}
|
|
1277
1399
|
}
|
|
1278
1400
|
const currentGeneration = ++generation;
|
|
1279
1401
|
try {
|
|
1280
|
-
const
|
|
1402
|
+
const nextFiles = new Map(kitFiles);
|
|
1403
|
+
const nextProcessor = createProcessor({ site: siteConfig, root: docsRoot, files: nextFiles });
|
|
1404
|
+
const [docs2, home2] = await Promise.all([readDocs({ root: docsRoot, processor: nextProcessor }), readHome({ root: docsRoot, processor: nextProcessor })]);
|
|
1281
1405
|
if (currentGeneration !== generation) {
|
|
1282
1406
|
return;
|
|
1283
1407
|
}
|
|
1408
|
+
files.clear();
|
|
1409
|
+
for (const entry of nextFiles) {
|
|
1410
|
+
files.set(...entry);
|
|
1411
|
+
}
|
|
1284
1412
|
store.docs = docs2;
|
|
1285
1413
|
store.home = home2;
|
|
1286
1414
|
reload.emit("change");
|
package/dist/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var L="fh-cursor-face";var
|
|
1
|
+
var L="fh-cursor-face";var k="(width < 1024px)";var p=e=>{if(!e)return null;try{return document.getElementById(decodeURIComponent(e.slice(1)))}catch(t){if(t instanceof URIError)return null;throw t}};var m=e=>{let t=p(e);for(let n=t?.closest("details");n;n=n.parentElement?.closest("details"))n.open=!0;return t};var S=()=>{let e=document.querySelector("[data-navigation]"),t=document.querySelector("[data-navigation-drawer]"),n=document.querySelector("[data-navigation-content]"),i=document.querySelector("[data-navigation-open]"),d=document.querySelector("[data-navigation-close]"),c=e?.parentElement;if(!e||!t||!n||!i||!d||!c)return;let l=matchMedia(k),a=()=>{t.open||(document.body.classList.remove("wg_shell__root--drawerOpen"),i.setAttribute("aria-expanded","false"))},u=()=>{t.close(),a()},h=()=>{!l.matches||t.open||(t.showModal(),document.body.classList.add("wg_shell__root--drawerOpen"),i.setAttribute("aria-expanded","true"))},r=o=>{let s=t.getBoundingClientRect();o.target===t&&(o.clientX<s.left||o.clientX>s.right||o.clientY<s.top||o.clientY>s.bottom)&&u()},q=o=>{if(!t.open||o.defaultPrevented||o.button!==0||o.metaKey||o.ctrlKey||o.shiftKey||o.altKey||!(o.target instanceof Element))return;let s=o.target.closest("a[href]");if(!(!(s instanceof HTMLAnchorElement)||s.target!==""&&s.target!=="_self"||s.hasAttribute("download"))&&(u(),s.origin===location.origin&&s.pathname===location.pathname&&s.search===location.search&&s.hash)){let T=m(s.hash);T&&(T.tabIndex=-1,T.focus({preventScroll:!0}))}},H=()=>{let o=document.activeElement;if(l.matches){i.classList.add("wg_shell__menuToggle--visible"),n.append(e),o instanceof HTMLElement&&e.contains(o)&&i.focus({preventScroll:!0});return}u(),c.append(e),o instanceof HTMLElement&&e.contains(o)?o.focus({preventScroll:!0}):(o===i||o instanceof HTMLElement&&t.contains(o))&&c.querySelector(".wg_shell__brand")?.focus({preventScroll:!0}),i.classList.remove("wg_shell__menuToggle--visible")};i.addEventListener("click",h),d.addEventListener("click",u),t.addEventListener("close",a),t.addEventListener("click",r),e.addEventListener("click",q),l.addEventListener("change",H),H(),c.classList.add("wg_shell__sidebar--navigationReady")};S();var g=document.querySelector("[data-cursor-face]");if(g){let e=matchMedia("(hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference)"),t={x:0,y:0,frame:0},n=()=>{cancelAnimationFrame(t.frame),t.frame=0,g.classList.remove("wg_shell__cursorFace--visible")},i=()=>{e.matches||n()},d=()=>{t.frame===0&&(t.frame=requestAnimationFrame(()=>{t.frame=0,g.style.transform=`translate3d(
|
|
2
2
|
${Math.max(0,Math.min(t.x+16,document.documentElement.clientWidth-g.width-16))}px,
|
|
3
3
|
${Math.max(0,Math.min(t.y+16,document.documentElement.clientHeight-g.height-16))}px,
|
|
4
4
|
0
|
|
5
|
-
)`,g.classList.add("wg_shell__cursorFace--visible")}))},
|
|
5
|
+
)`,g.classList.add("wg_shell__cursorFace--visible")}))},c=h=>{if(!(e.matches&&h.pointerType==="mouse")){n();return}t.x=h.clientX,t.y=h.clientY,d()},l=()=>{g.classList.contains("wg_shell__cursorFace--visible")&&d()},a=()=>{if(g.classList.contains("wg_shell__cursorFace--visible"))try{sessionStorage.setItem(L,JSON.stringify({x:t.x,y:t.y}))}catch{}},u=()=>{try{let h=sessionStorage.getItem(L);if(sessionStorage.removeItem(L),h!==null&&e.matches){let r=JSON.parse(h);typeof r=="object"&&r!==null&&"x"in r&&"y"in r&&typeof r.x=="number"&&typeof r.y=="number"&&Number.isFinite(r.x)&&Number.isFinite(r.y)&&(t.x=r.x,t.y=r.y,d())}}catch{}};u(),document.addEventListener("pointermove",c,{passive:!0}),document.addEventListener("pointerdown",c,{passive:!0}),document.documentElement.addEventListener("pointerleave",n),addEventListener("blur",n),addEventListener("resize",l),addEventListener("pagehide",a),addEventListener("pageshow",u),e.addEventListener("change",i)}var v=m(location.hash),_=null,y=0,f=null,x=()=>{clearTimeout(y),f?.abort(),f=null,_?.classList.remove("wg_prose__headingText--highlighted"),_=null},M=e=>{x(),_=e===null?null:e.querySelector(".wg_prose__headingText"),_!==null&&(_.classList.add("wg_prose__headingText--highlighted"),y=window.setTimeout(x,3e3),f=new AbortController,document.addEventListener("scrollend",B,{signal:f.signal}))},B=e=>{e.target===document&&(clearTimeout(y),f?.abort(),f=null,y=window.setTimeout(x,3e3))},N=e=>{if(!(e.defaultPrevented||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)&&e.currentTarget instanceof HTMLAnchorElement&&(e.currentTarget.target===""||e.currentTarget.target==="_self")&&!e.currentTarget.hasAttribute("download")&&e.currentTarget.origin===location.origin&&e.currentTarget.pathname===location.pathname&&e.currentTarget.search===location.search&&e.currentTarget.hash){let t=m(e.currentTarget.hash);e.currentTarget.hash===location.hash&&M(t)}},K=()=>{let e=m(location.hash);e?.scrollIntoView(),M(e)};for(let e of document.querySelectorAll("a[href]"))e.addEventListener("click",N);addEventListener("hashchange",K);var E=[...document.querySelectorAll("[data-toc-link]")].flatMap(e=>{let t=p(e.hash),n=e.parentElement;return!t||!n?[]:[{heading:t,link:e,item:n,list:n.parentElement,subs:[...n.querySelectorAll("[data-toc-sub-link]")].flatMap(i=>{let d=p(i.hash),c=i.parentElement;return d&&c?[{heading:d,link:i,item:c}]:[]})}]}),w=E.at(0);if(w){let e=()=>{let t=Number.parseFloat(getComputedStyle(w.heading).scrollMarginTop)+1,n=E.findLast(l=>l.heading.checkVisibility()&&l.heading.getBoundingClientRect().top<=t)??w,i=n.subs.findLast(l=>l.heading.checkVisibility()&&l.heading.getBoundingClientRect().top<=t),d=E.indexOf(n),c=i===void 0?-1:n.subs.indexOf(i);for(let[l,a]of E.entries()){let u=a===n&&i===void 0;a.link.classList.toggle("wg_shellToc__link--active",u),u?a.link.setAttribute("aria-current","location"):a.link.removeAttribute("aria-current"),a.item.classList.toggle("wg_shellToc__item--trail",a.list===n.list&&l<d),a.item.classList.toggle("wg_shellToc__item--current",a===n);for(let[h,r]of a.subs.entries())r.link.classList.toggle("wg_shellToc__subLink--active",r===i),r===i?r.link.setAttribute("aria-current","location"):r.link.removeAttribute("aria-current"),r.item.classList.toggle("wg_shellToc__subItem--trail",a===n&&h<c),r.item.classList.toggle("wg_shellToc__subItem--current",r===i)}};addEventListener("scroll",e,{passive:!0}),addEventListener("resize",e),addEventListener("toggle",e,!0),e()}var I=new AbortController;for(let e of["wheel","touchmove","keydown","mousedown"])addEventListener(e,()=>I.abort(),{once:!0,passive:!0});var A=async()=>{await document.fonts.ready,v&&!I.signal.aborted&&(v.scrollIntoView({behavior:"instant"}),M(v)),document.documentElement.style.removeProperty("scroll-behavior")};document.readyState==="complete"?A():addEventListener("load",A,{once:!0});
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
import {EventEmitter} from "node:events";
|
|
8
8
|
import {existsSync, watch} from "node:fs";
|
|
9
9
|
import {copyFile, mkdir, rm, writeFile} from "node:fs/promises";
|
|
10
|
-
import {basename, dirname, join, relative, resolve} from "node:path";
|
|
10
|
+
import {basename, dirname, extname, join, relative, resolve, sep} from "node:path";
|
|
11
11
|
import {fileURLToPath, pathToFileURL} from "node:url";
|
|
12
12
|
import {serve} from "@hono/node-server";
|
|
13
13
|
import {serveStatic} from "@hono/node-server/serve-static";
|
|
14
14
|
import {Hono} from "hono";
|
|
15
15
|
import {toSSG} from "hono/ssg";
|
|
16
16
|
import {createApp} from "@/app";
|
|
17
|
-
import {asset_client_path, asset_favicon_path, asset_font_dir, asset_style_path} from "@/constant/asset";
|
|
17
|
+
import {asset_client_path, asset_favicon_path, asset_font_dir, asset_media_extensions, asset_style_path} from "@/constant/asset";
|
|
18
18
|
import {cli_config_file_name, cli_default_command, cli_default_docs_dir, cli_dev_port} from "@/constant/cli";
|
|
19
19
|
import {copy_error_config, copy_error_font_preload, copy_error_prefix, copy_error_unknown_command} from "@/constant/copy";
|
|
20
20
|
import {font_brand_css, font_cache_control, font_mono_css, font_sans_css, font_sans_preload_file} from "@/constant/font";
|
|
@@ -85,7 +85,7 @@ const main = async () => {
|
|
|
85
85
|
const fontCss = [sans.css, mono.css, brand.css].join("\n");
|
|
86
86
|
const stylePath = toAssetPath({path: asset_style_path, file: join(kitRoot, "dist/cli.css")});
|
|
87
87
|
const clientPath = toAssetPath({path: asset_client_path, file: join(kitRoot, "dist/client.js")});
|
|
88
|
-
const
|
|
88
|
+
const kitFiles = new Map([
|
|
89
89
|
[stylePath, join(kitRoot, "dist/cli.css")],
|
|
90
90
|
[clientPath, join(kitRoot, "dist/client.js")],
|
|
91
91
|
[asset_favicon_path, join(kitRoot, "src/asset/favicon.svg")],
|
|
@@ -93,7 +93,8 @@ const main = async () => {
|
|
|
93
93
|
...mono.files,
|
|
94
94
|
...brand.files,
|
|
95
95
|
]);
|
|
96
|
-
const
|
|
96
|
+
const files = new Map(kitFiles);
|
|
97
|
+
const processor = createProcessor({site: siteConfig, root: docsRoot, files});
|
|
97
98
|
const [docs, home] = await Promise.all([readDocs({root: docsRoot, processor}), readHome({root: docsRoot, processor})]);
|
|
98
99
|
const store = {docs, home};
|
|
99
100
|
const app = createApp({
|
|
@@ -132,20 +133,30 @@ const main = async () => {
|
|
|
132
133
|
* 재처리 실패 시 직전 정상 문서 유지
|
|
133
134
|
*/
|
|
134
135
|
const handleDocsChange = async (_event: string, filename: string | null) => {
|
|
135
|
-
if (filename !== null
|
|
136
|
-
|
|
136
|
+
if (filename !== null) {
|
|
137
|
+
const segments = filename.split(sep);
|
|
138
|
+
// 출력·설치 폴더는 제외 · 실패한 참조의 파일이 뒤늦게 생겨도 다시 처리
|
|
139
|
+
if (segments.includes("dist") || segments.includes("node_modules") || (!/\.mdx?$/i.test(filename) && !asset_media_extensions.has(extname(filename).toLowerCase()))) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
137
142
|
}
|
|
138
143
|
|
|
139
144
|
const currentGeneration = ++generation;
|
|
140
145
|
|
|
141
146
|
try {
|
|
142
|
-
const
|
|
147
|
+
const nextFiles = new Map(kitFiles);
|
|
148
|
+
const nextProcessor = createProcessor({site: siteConfig, root: docsRoot, files: nextFiles});
|
|
149
|
+
const [docs, home] = await Promise.all([readDocs({root: docsRoot, processor: nextProcessor}), readHome({root: docsRoot, processor: nextProcessor})]);
|
|
143
150
|
|
|
144
151
|
// 최신 변경의 처리 결과만 반영
|
|
145
152
|
if (currentGeneration !== generation) {
|
|
146
153
|
return;
|
|
147
154
|
}
|
|
148
155
|
|
|
156
|
+
files.clear();
|
|
157
|
+
for (const entry of nextFiles) {
|
|
158
|
+
files.set(...entry);
|
|
159
|
+
}
|
|
149
160
|
store.docs = docs;
|
|
150
161
|
store.home = home;
|
|
151
162
|
reload.emit("change");
|
package/src/client.ts
CHANGED
|
@@ -275,12 +275,23 @@ if (firstSection) {
|
|
|
275
275
|
const currentSubIndex = sub === undefined ? -1 : current.subs.indexOf(sub);
|
|
276
276
|
|
|
277
277
|
for (const [index, section] of tocSections.entries()) {
|
|
278
|
-
|
|
278
|
+
const active = section === current && sub === undefined;
|
|
279
|
+
section.link.classList.toggle("wg_shellToc__link--active", active);
|
|
280
|
+
if (active) {
|
|
281
|
+
section.link.setAttribute("aria-current", "location");
|
|
282
|
+
} else {
|
|
283
|
+
section.link.removeAttribute("aria-current");
|
|
284
|
+
}
|
|
279
285
|
section.item.classList.toggle("wg_shellToc__item--trail", section.list === current.list && index < currentIndex);
|
|
280
286
|
section.item.classList.toggle("wg_shellToc__item--current", section === current);
|
|
281
287
|
|
|
282
288
|
for (const [subIndex, item] of section.subs.entries()) {
|
|
283
289
|
item.link.classList.toggle("wg_shellToc__subLink--active", item === sub);
|
|
290
|
+
if (item === sub) {
|
|
291
|
+
item.link.setAttribute("aria-current", "location");
|
|
292
|
+
} else {
|
|
293
|
+
item.link.removeAttribute("aria-current");
|
|
294
|
+
}
|
|
284
295
|
item.item.classList.toggle("wg_shellToc__subItem--trail", section === current && subIndex < currentSubIndex);
|
|
285
296
|
item.item.classList.toggle("wg_shellToc__subItem--current", item === sub);
|
|
286
297
|
}
|