for-humanity 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/LICENSE +21 -0
- package/README.md +118 -0
- package/dist/cli.css +962 -0
- package/dist/cli.js +1241 -0
- package/dist/client.js +5 -0
- package/package.json +92 -0
- package/src/app.tsx +57 -0
- package/src/asset/favicon.svg +5 -0
- package/src/asset/font/architects-daughter/LICENSE.txt +93 -0
- package/src/asset/font/architects-daughter/architects-daughter-latin-400-normal.woff2 +0 -0
- package/src/asset/font/architects-daughter/architects-daughter.css +10 -0
- package/src/asset/font/jetbrains-mono/LICENSE +93 -0
- package/src/asset/font/jetbrains-mono/jetbrains-mono-latin-wght-normal.woff2 +0 -0
- package/src/asset/font/jetbrains-mono/jetbrains-mono.css +11 -0
- package/src/asset/font/pretendard/LICENSE.txt +94 -0
- package/src/asset/font/pretendard/pretendardvariable-dynamic-subset.css +1008 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.0.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.1.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.10.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.11.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.12.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.13.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.14.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.15.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.16.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.17.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.18.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.19.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.2.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.20.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.21.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.22.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.23.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.24.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.25.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.26.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.27.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.28.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.29.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.3.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.30.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.31.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.32.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.33.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.34.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.35.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.36.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.37.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.38.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.39.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.4.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.40.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.41.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.42.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.43.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.44.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.45.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.46.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.47.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.48.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.49.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.5.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.50.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.51.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.52.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.53.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.54.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.55.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.56.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.57.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.58.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.59.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.6.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.60.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.61.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.62.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.63.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.64.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.65.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.66.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.67.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.68.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.69.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.7.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.70.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.71.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.72.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.73.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.74.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.75.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.76.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.77.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.78.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.79.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.8.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.80.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.81.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.82.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.83.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.84.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.85.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.86.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.87.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.88.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.89.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.9.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.90.woff2 +0 -0
- package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.91.woff2 +0 -0
- package/src/cli.ts +162 -0
- package/src/client.ts +322 -0
- package/src/component/widget/prose/_constant/heading-highlight.ts +4 -0
- package/src/component/widget/prose/_constant/section.ts +7 -0
- package/src/component/widget/prose/_constant/status.ts +9 -0
- package/src/component/widget/prose/_function/has-block-content.ts +30 -0
- package/src/component/widget/prose/_function/rehype-head.ts +31 -0
- package/src/component/widget/prose/_function/rehype-sections/_to-section-headings.ts +20 -0
- package/src/component/widget/prose/_function/rehype-sections/rehype-sections.ts +21 -0
- package/src/component/widget/prose/_function/rehype-tables.ts +22 -0
- package/src/component/widget/prose/_function/remark-blocks.ts +112 -0
- package/src/component/widget/prose/_function/remark-flow.ts +26 -0
- package/src/component/widget/prose/_function/remark-links.ts +33 -0
- package/src/component/widget/prose/_function/remark-parts.ts +26 -0
- package/src/component/widget/prose/_function/remark-status.ts +59 -0
- package/src/component/widget/prose/_function/remark-swatch.ts +16 -0
- package/src/component/widget/prose/_function/remark-unknown-directives.ts +25 -0
- package/src/component/widget/prose/_type/doc-section.ts +9 -0
- package/src/component/widget/prose/wg-prose.css +381 -0
- package/src/component/widget/prose/wg-prose.tsx +43 -0
- package/src/component/widget/shell/_constant/cursor-face.ts +9 -0
- package/src/component/widget/shell/_constant/navigation.ts +4 -0
- package/src/component/widget/shell/_constant/reading-line.ts +4 -0
- package/src/component/widget/shell/_function/bind-mobile-navigation.ts +140 -0
- package/src/component/widget/shell/_function/to-toc-groups.ts +38 -0
- package/src/component/widget/shell/_type/doc-outline.ts +16 -0
- package/src/component/widget/shell/_type/toc-group.ts +39 -0
- package/src/component/widget/shell/_wg-shell-nav.css +134 -0
- package/src/component/widget/shell/_wg-shell-nav.tsx +75 -0
- package/src/component/widget/shell/_wg-shell-toc.css +268 -0
- package/src/component/widget/shell/_wg-shell-toc.tsx +57 -0
- package/src/component/widget/shell/wg-shell.css +261 -0
- package/src/component/widget/shell/wg-shell.tsx +147 -0
- package/src/constant/asset.ts +48 -0
- package/src/constant/cli.ts +19 -0
- package/src/constant/copy.ts +108 -0
- package/src/constant/doc.ts +13 -0
- package/src/constant/font.ts +39 -0
- package/src/constant/locale.ts +9 -0
- package/src/constant/site.ts +9 -0
- package/src/constant/status.ts +15 -0
- package/src/content/create-processor.ts +59 -0
- package/src/content/read-docs.test.ts +242 -0
- package/src/content/read-docs.ts +75 -0
- package/src/content/read-home.ts +32 -0
- package/src/content/rehype-heading-ids.ts +34 -0
- package/src/content/remark-report.ts +15 -0
- package/src/content/to-doc-groups.ts +18 -0
- package/src/dev.ts +79 -0
- package/src/env.d.ts +6 -0
- package/src/page/doc/pg-doc.tsx +35 -0
- package/src/page/home/pg-home.tsx +40 -0
- package/src/style/base.css +28 -0
- package/src/style/token.css +162 -0
- package/src/type/doc-content.ts +15 -0
- package/src/type/doc-data.ts +33 -0
- package/src/type/doc-file-data.ts +21 -0
- package/src/type/doc-heading.ts +17 -0
- package/src/type/doc.ts +16 -0
- package/src/type/site-assets.ts +17 -0
- package/src/type/site-config.ts +55 -0
- package/src/type/vfile-data.d.ts +10 -0
- package/src/util/dom/find-hash-target.ts +18 -0
- package/src/util/dom/reveal-hash-target.ts +15 -0
- package/src/util/error/to-error-message.ts +10 -0
- package/src/util/font/to-font-css.test.ts +41 -0
- package/src/util/font/to-font-css.ts +28 -0
- package/src/util/mermaid/render-flow.js +321 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,1241 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli.ts
|
|
4
|
+
import { EventEmitter } from "node:events";
|
|
5
|
+
import { existsSync as existsSync2, watch } from "node:fs";
|
|
6
|
+
import { copyFile, mkdir, rm, writeFile } from "node:fs/promises";
|
|
7
|
+
import { basename as basename2, dirname as dirname3, join as join4, relative as relative3, resolve as resolve2 } from "node:path";
|
|
8
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
9
|
+
import { serve } from "@hono/node-server";
|
|
10
|
+
import { serveStatic } from "@hono/node-server/serve-static";
|
|
11
|
+
import { Hono as Hono3 } from "hono";
|
|
12
|
+
import { toSSG } from "hono/ssg";
|
|
13
|
+
|
|
14
|
+
// src/app.tsx
|
|
15
|
+
import { Hono } from "hono";
|
|
16
|
+
import { ssgParams } from "hono/ssg";
|
|
17
|
+
import { renderToStaticMarkup } from "react-dom/server";
|
|
18
|
+
|
|
19
|
+
// src/component/widget/prose/wg-prose.tsx
|
|
20
|
+
import clsx from "clsx";
|
|
21
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
22
|
+
var WgProse = (props) => {
|
|
23
|
+
if (props.html !== void 0) {
|
|
24
|
+
return /* @__PURE__ */ jsx("article", { className: clsx("wg_prose__root"), dangerouslySetInnerHTML: { __html: props.html } });
|
|
25
|
+
}
|
|
26
|
+
return /* @__PURE__ */ jsx("article", { className: clsx("wg_prose__root"), children: props.head !== void 0 && /* @__PURE__ */ jsxs("header", { className: clsx("wg_prose__head"), children: [
|
|
27
|
+
/* @__PURE__ */ jsx("h1", { children: props.head.title }),
|
|
28
|
+
props.head.lead !== void 0 && /* @__PURE__ */ jsx("p", { children: props.head.lead })
|
|
29
|
+
] }) });
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// src/component/widget/shell/wg-shell.tsx
|
|
33
|
+
import clsx4 from "clsx";
|
|
34
|
+
|
|
35
|
+
// src/component/widget/shell/_function/to-toc-groups.ts
|
|
36
|
+
import { takeWhile } from "es-toolkit/array";
|
|
37
|
+
|
|
38
|
+
// src/component/widget/prose/_constant/section.ts
|
|
39
|
+
var section_heading_depth = {
|
|
40
|
+
section: 2,
|
|
41
|
+
sub: 3
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// src/component/widget/shell/_function/to-toc-groups.ts
|
|
45
|
+
var toTocGroups = (outline) => {
|
|
46
|
+
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] }));
|
|
47
|
+
const sections = entries.flatMap(
|
|
48
|
+
(entry, index) => entry.heading.depth === section_heading_depth.section ? [
|
|
49
|
+
{
|
|
50
|
+
heading: entry.heading,
|
|
51
|
+
part: entry.section.part,
|
|
52
|
+
subs: takeWhile(entries.slice(index + 1), (sub) => sub.heading.depth !== section_heading_depth.section).map((sub) => ({
|
|
53
|
+
heading: sub.heading
|
|
54
|
+
}))
|
|
55
|
+
}
|
|
56
|
+
] : []
|
|
57
|
+
);
|
|
58
|
+
return sections.flatMap(
|
|
59
|
+
(section, index) => index === 0 || section.part !== void 0 ? [
|
|
60
|
+
{
|
|
61
|
+
part: section.part,
|
|
62
|
+
sections: [section, ...takeWhile(sections.slice(index + 1), (next) => next.part === void 0)]
|
|
63
|
+
}
|
|
64
|
+
] : []
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// src/component/widget/shell/_wg-shell-nav.tsx
|
|
69
|
+
import clsx2 from "clsx";
|
|
70
|
+
|
|
71
|
+
// src/constant/copy.ts
|
|
72
|
+
var copy_site_title_default = "for humanity";
|
|
73
|
+
var copy_nav_aria_label = "Document navigation";
|
|
74
|
+
var copy_nav_open = "Open navigation";
|
|
75
|
+
var copy_nav_close = "Close navigation";
|
|
76
|
+
var copy_nav_title = "Navigation";
|
|
77
|
+
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.";
|
|
78
|
+
var copy_nav_toc_label = "Contents";
|
|
79
|
+
var copy_error_home_clash = "\uD648 README\uAC00 \uACB9\uCE5C\uB2E4";
|
|
80
|
+
var copy_error_prefix = "for-humanity";
|
|
81
|
+
var copy_error_font_preload = "Missing bundled font for preload";
|
|
82
|
+
var copy_error_unknown_command = "\uBAA8\uB974\uB294 \uBA85\uB839\uC774\uB2E4";
|
|
83
|
+
var copy_error_config = "\uC124\uC815\uC774 \uD2C0\uB838\uB2E4";
|
|
84
|
+
var copy_error_frontmatter = "frontmatter\uAC00 \uC62C\uBC14\uB974\uC9C0 \uC54A\uB2E4";
|
|
85
|
+
var copy_error_navigation_clash = "navigation\uC758 \uBB36\uC74C\uC774 \uACB9\uCE5C\uB2E4";
|
|
86
|
+
var copy_error_doc_id = "\uBB38\uC11C id\uC5D0 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uB294 \uACBD\uB85C";
|
|
87
|
+
var copy_error_doc_id_clash = "\uBB38\uC11C id\uAC00 \uACB9\uCE5C\uB2E4";
|
|
88
|
+
var copy_error_flow = "\uD750\uB984\uB3C4\uB97C \uADF8\uB9AC\uC9C0 \uBABB\uD588\uB2E4";
|
|
89
|
+
var copy_error_unknown_directive = "\uBAA8\uB974\uB294 \uBD80\uD488\uC774\uB2E4";
|
|
90
|
+
var copy_error_directive_syntax = "\uBD80\uD488 \uBB38\uBC95\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uB2E4";
|
|
91
|
+
var copy_warn_broken_link = "\uC5C6\uB294 \uBB38\uC11C\uB85C \uAC74 \uB9C1\uD06C\uB2E4";
|
|
92
|
+
var copy_warn_unknown_status = "\uC124\uC815\uC5D0 \uC5C6\uB294 \uC0C1\uD0DC \uBB38\uAD6C\uB2E4";
|
|
93
|
+
|
|
94
|
+
// src/constant/locale.ts
|
|
95
|
+
var locale_doc_name = "en";
|
|
96
|
+
var locale_doc_group = "ko";
|
|
97
|
+
|
|
98
|
+
// src/content/to-doc-groups.ts
|
|
99
|
+
var toDocGroups = (options) => {
|
|
100
|
+
const positions = new Map(options.navigation.map((name, index) => [name, index]));
|
|
101
|
+
return [...Map.groupBy(options.docs, (doc) => doc.data.group)].toSorted((a, b) => (positions.get(a[0]) ?? options.navigation.length) - (positions.get(b[0]) ?? options.navigation.length) || a[0].localeCompare(b[0], locale_doc_group)).map(([name, docs]) => ({
|
|
102
|
+
name,
|
|
103
|
+
docs: 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))
|
|
104
|
+
}));
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// src/component/widget/shell/_wg-shell-nav.tsx
|
|
108
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
109
|
+
var WgShellNav = (props) => {
|
|
110
|
+
const docGroups = toDocGroups({ docs: props.docs, navigation: props.site.navigation });
|
|
111
|
+
return /* @__PURE__ */ jsx2("nav", { className: clsx2("wg_shellNav__root"), "aria-label": copy_nav_aria_label, children: /* @__PURE__ */ jsx2("div", { className: clsx2("wg_shellNav__docs"), children: docGroups.map((group) => {
|
|
112
|
+
const currentIndex = group.docs.findIndex((doc) => doc.id === props.current);
|
|
113
|
+
return /* @__PURE__ */ jsxs2("section", { className: clsx2("wg_shellNav__docGroup"), "aria-label": group.name, children: [
|
|
114
|
+
/* @__PURE__ */ jsx2("div", { className: clsx2("wg_shellNav__group"), children: group.name }),
|
|
115
|
+
/* @__PURE__ */ jsx2("ul", { className: clsx2("wg_shellNav__list"), children: group.docs.map((doc, index) => /* @__PURE__ */ jsx2(
|
|
116
|
+
"li",
|
|
117
|
+
{
|
|
118
|
+
className: clsx2("wg_shellNav__item", {
|
|
119
|
+
"wg_shellNav__item--trail": index < currentIndex,
|
|
120
|
+
"wg_shellNav__item--current": index === currentIndex
|
|
121
|
+
}),
|
|
122
|
+
children: /* @__PURE__ */ jsx2(
|
|
123
|
+
"a",
|
|
124
|
+
{
|
|
125
|
+
className: clsx2("wg_shellNav__link", {
|
|
126
|
+
"wg_shellNav__link--active": index === currentIndex
|
|
127
|
+
}),
|
|
128
|
+
href: `/${doc.id}/`,
|
|
129
|
+
title: doc.data.label,
|
|
130
|
+
"aria-current": index === currentIndex ? "page" : void 0,
|
|
131
|
+
children: doc.data.name
|
|
132
|
+
}
|
|
133
|
+
)
|
|
134
|
+
},
|
|
135
|
+
doc.id
|
|
136
|
+
)) })
|
|
137
|
+
] }, group.name);
|
|
138
|
+
}) }) });
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// src/component/widget/shell/_wg-shell-toc.tsx
|
|
142
|
+
import clsx3 from "clsx";
|
|
143
|
+
import { Fragment } from "react";
|
|
144
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
145
|
+
var WgShellToc = (props) => {
|
|
146
|
+
return /* @__PURE__ */ jsxs3("nav", { className: clsx3("wg_shellToc__root"), "aria-label": copy_nav_toc_label, children: [
|
|
147
|
+
/* @__PURE__ */ jsx3("div", { className: clsx3("wg_shellToc__label"), children: copy_nav_toc_label }),
|
|
148
|
+
props.groups.map((group) => /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
149
|
+
group.part !== void 0 && /* @__PURE__ */ jsx3("div", { className: clsx3("wg_shellToc__group"), children: group.part }),
|
|
150
|
+
/* @__PURE__ */ jsx3("ul", { className: clsx3("wg_shellToc__list"), children: group.sections.map((section) => /* @__PURE__ */ jsxs3("li", { className: clsx3("wg_shellToc__item"), children: [
|
|
151
|
+
/* @__PURE__ */ jsx3("a", { className: clsx3("wg_shellToc__link"), href: `#${section.heading.slug}`, "data-toc-link": "", children: section.heading.text }),
|
|
152
|
+
section.subs.length > 0 && /* @__PURE__ */ jsx3("ul", { className: clsx3("wg_shellToc__sub"), children: section.subs.map((sub) => /* @__PURE__ */ jsx3("li", { className: clsx3("wg_shellToc__subItem"), children: /* @__PURE__ */ jsx3("a", { className: clsx3("wg_shellToc__subLink"), href: `#${sub.heading.slug}`, "data-toc-sub-link": "", children: sub.heading.text }) }, sub.heading.slug)) })
|
|
153
|
+
] }, section.heading.slug)) })
|
|
154
|
+
] }, group.sections[0].heading.slug))
|
|
155
|
+
] });
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// src/constant/asset.ts
|
|
159
|
+
var asset_dir = "_fh";
|
|
160
|
+
var asset_style_path = `/${asset_dir}/style.css`;
|
|
161
|
+
var asset_client_path = `/${asset_dir}/client.js`;
|
|
162
|
+
var asset_font_dir = `/${asset_dir}/fonts`;
|
|
163
|
+
var asset_reload_path = `/${asset_dir}/reload`;
|
|
164
|
+
var asset_favicon_path = "/favicon.svg";
|
|
165
|
+
var asset_content_types = {
|
|
166
|
+
".css": "text/css; charset=utf-8",
|
|
167
|
+
".js": "text/javascript; charset=utf-8",
|
|
168
|
+
".woff2": "font/woff2",
|
|
169
|
+
".svg": "image/svg+xml"
|
|
170
|
+
};
|
|
171
|
+
var asset_content_type_default = "application/octet-stream";
|
|
172
|
+
|
|
173
|
+
// src/component/widget/shell/wg-shell.tsx
|
|
174
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
175
|
+
var reloadScript = `new EventSource(${JSON.stringify(asset_reload_path)}).onmessage=function(){location.reload()}`;
|
|
176
|
+
var WgShell = (props) => {
|
|
177
|
+
const tocGroups = props.outline === void 0 ? [] : toTocGroups(props.outline);
|
|
178
|
+
return /* @__PURE__ */ jsxs4("html", { lang: "ko", children: [
|
|
179
|
+
/* @__PURE__ */ jsxs4("head", { children: [
|
|
180
|
+
/* @__PURE__ */ jsx4("meta", { charSet: "utf-8" }),
|
|
181
|
+
/* @__PURE__ */ jsx4("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }),
|
|
182
|
+
props.site.description !== void 0 && /* @__PURE__ */ jsx4("meta", { name: "description", content: props.site.description }),
|
|
183
|
+
/* @__PURE__ */ jsx4("title", { children: props.title === void 0 ? props.site.title : `${props.title} \xB7 ${props.site.title}` }),
|
|
184
|
+
/* @__PURE__ */ jsx4("link", { rel: "icon", href: asset_favicon_path, type: "image/svg+xml" }),
|
|
185
|
+
/* @__PURE__ */ jsx4("style", { dangerouslySetInnerHTML: { __html: props.assets.fontCss } }),
|
|
186
|
+
props.assets.preload.map((href) => /* @__PURE__ */ jsx4("link", { rel: "preload", href, as: "font", type: "font/woff2", crossOrigin: "" }, href)),
|
|
187
|
+
/* @__PURE__ */ jsx4("script", { dangerouslySetInnerHTML: { __html: 'document.documentElement.style.scrollBehavior="auto"' } }),
|
|
188
|
+
/* @__PURE__ */ jsx4("link", { rel: "stylesheet", href: asset_style_path }),
|
|
189
|
+
props.assets.reload && /* @__PURE__ */ jsx4("script", { dangerouslySetInnerHTML: { __html: reloadScript } })
|
|
190
|
+
] }),
|
|
191
|
+
/* @__PURE__ */ jsxs4("body", { className: clsx4("wg_shell__root"), children: [
|
|
192
|
+
/* @__PURE__ */ jsxs4("div", { className: clsx4("wg_shell__sidebar"), children: [
|
|
193
|
+
/* @__PURE__ */ jsxs4("div", { className: clsx4("wg_shell__brandRow"), children: [
|
|
194
|
+
/* @__PURE__ */ jsx4("a", { className: clsx4("wg_shell__brand"), href: "/", "aria-current": props.current === void 0 ? "page" : void 0, children: props.site.title }),
|
|
195
|
+
/* @__PURE__ */ jsx4(
|
|
196
|
+
"button",
|
|
197
|
+
{
|
|
198
|
+
className: clsx4("wg_shell__menuToggle"),
|
|
199
|
+
type: "button",
|
|
200
|
+
"aria-label": copy_nav_open,
|
|
201
|
+
"aria-controls": "fh-navigation-drawer",
|
|
202
|
+
"aria-expanded": "false",
|
|
203
|
+
"data-navigation-open": "",
|
|
204
|
+
children: /* @__PURE__ */ jsx4("svg", { className: clsx4("wg_shell__menuIcon"), viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx4("path", { d: "M4 6h16M4 12h16M4 18h16" }) })
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
] }),
|
|
208
|
+
/* @__PURE__ */ jsxs4("div", { className: clsx4("wg_shell__navigation"), "data-navigation": "", children: [
|
|
209
|
+
/* @__PURE__ */ jsx4(WgShellNav, { site: props.site, docs: props.docs, current: props.current }),
|
|
210
|
+
tocGroups.length > 0 && /* @__PURE__ */ jsx4(WgShellToc, { groups: tocGroups })
|
|
211
|
+
] })
|
|
212
|
+
] }),
|
|
213
|
+
/* @__PURE__ */ jsx4("main", { className: clsx4("wg_shell__main"), children: props.children }),
|
|
214
|
+
/* @__PURE__ */ jsxs4("dialog", { className: clsx4("wg_shell__drawer"), id: "fh-navigation-drawer", "aria-labelledby": "fh-navigation-title", "data-navigation-drawer": "", children: [
|
|
215
|
+
/* @__PURE__ */ jsxs4("div", { className: clsx4("wg_shell__drawerHeader"), children: [
|
|
216
|
+
/* @__PURE__ */ jsx4("h2", { className: clsx4("wg_shell__drawerTitle"), id: "fh-navigation-title", children: copy_nav_title }),
|
|
217
|
+
/* @__PURE__ */ jsx4("button", { className: clsx4("wg_shell__drawerClose"), type: "button", "aria-label": copy_nav_close, "data-navigation-close": "", children: /* @__PURE__ */ jsx4("svg", { className: clsx4("wg_shell__menuIcon"), viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx4("path", { d: "m6 6 12 12M18 6 6 18" }) }) })
|
|
218
|
+
] }),
|
|
219
|
+
/* @__PURE__ */ jsx4("div", { className: clsx4("wg_shell__drawerContent"), "data-navigation-content": "" })
|
|
220
|
+
] }),
|
|
221
|
+
/* @__PURE__ */ jsx4("img", { className: clsx4("wg_shell__cursorFace"), src: asset_favicon_path, width: "24", height: "24", alt: "", "aria-hidden": "true", draggable: false, "data-cursor-face": "" }),
|
|
222
|
+
/* @__PURE__ */ jsx4("script", { type: "module", src: asset_client_path })
|
|
223
|
+
] })
|
|
224
|
+
] });
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// src/page/doc/pg-doc.tsx
|
|
228
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
229
|
+
var PgDoc = (props) => {
|
|
230
|
+
return /* @__PURE__ */ jsx5(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__ */ jsx5(WgProse, { html: props.doc.html }) });
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// src/page/home/pg-home.tsx
|
|
234
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
235
|
+
var PgHome = (props) => {
|
|
236
|
+
return /* @__PURE__ */ jsx6(WgShell, { site: props.site, docs: props.docs, assets: props.assets, outline: props.home?.outline, children: props.home === void 0 ? /* @__PURE__ */ jsx6(WgProse, { head: { title: props.site.title, lead: copy_home_missing } }) : /* @__PURE__ */ jsx6(WgProse, { html: props.home.html }) });
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// src/app.tsx
|
|
240
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
241
|
+
var toHtml = (page) => {
|
|
242
|
+
return `<!DOCTYPE html>${renderToStaticMarkup(page)}`;
|
|
243
|
+
};
|
|
244
|
+
var createApp = (options) => {
|
|
245
|
+
const app = new Hono();
|
|
246
|
+
app.get("/", (c) => c.html(toHtml(/* @__PURE__ */ jsx7(PgHome, { site: options.site, docs: options.store.docs, assets: options.assets, home: options.store.home }))));
|
|
247
|
+
app.get(
|
|
248
|
+
"/:slug{.+}/",
|
|
249
|
+
ssgParams(() => options.store.docs.map((doc) => ({ slug: doc.id }))),
|
|
250
|
+
(c) => {
|
|
251
|
+
const doc = options.store.docs.find((entry) => entry.id === c.req.param("slug"));
|
|
252
|
+
return doc === void 0 ? c.notFound() : c.html(toHtml(/* @__PURE__ */ jsx7(PgDoc, { site: options.site, docs: options.store.docs, assets: options.assets, doc })));
|
|
253
|
+
}
|
|
254
|
+
);
|
|
255
|
+
return app;
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// src/constant/cli.ts
|
|
259
|
+
var cli_default_command = "dev";
|
|
260
|
+
var cli_default_docs_dir = ".";
|
|
261
|
+
var cli_config_file_name = "for-humanity.config.mjs";
|
|
262
|
+
var cli_dev_port = 4321;
|
|
263
|
+
|
|
264
|
+
// src/constant/font.ts
|
|
265
|
+
var font_sans_css = "src/asset/font/pretendard/pretendardvariable-dynamic-subset.css";
|
|
266
|
+
var font_mono_css = "src/asset/font/jetbrains-mono/jetbrains-mono.css";
|
|
267
|
+
var font_brand_css = "src/asset/font/architects-daughter/architects-daughter.css";
|
|
268
|
+
var font_sans_preload_file = "PretendardVariable.subset.91.woff2";
|
|
269
|
+
var font_display_strategy = "optional";
|
|
270
|
+
var font_hash_length = 12;
|
|
271
|
+
var font_cache_control = "public, max-age=31536000, immutable";
|
|
272
|
+
|
|
273
|
+
// src/constant/site.ts
|
|
274
|
+
var site_config_absent = {};
|
|
275
|
+
var site_navigation_default = [];
|
|
276
|
+
|
|
277
|
+
// src/content/create-processor.ts
|
|
278
|
+
import rehypeShiki from "@shikijs/rehype";
|
|
279
|
+
import rehypeRaw from "rehype-raw";
|
|
280
|
+
import rehypeStringify from "rehype-stringify";
|
|
281
|
+
import remarkDirective from "remark-directive";
|
|
282
|
+
import remarkFrontmatter from "remark-frontmatter";
|
|
283
|
+
import remarkGfm from "remark-gfm";
|
|
284
|
+
import remarkParse from "remark-parse";
|
|
285
|
+
import remarkRehype from "remark-rehype";
|
|
286
|
+
import remarkSmartypants from "remark-smartypants";
|
|
287
|
+
import { createCssVariablesTheme } from "shiki";
|
|
288
|
+
import { unified } from "unified";
|
|
289
|
+
|
|
290
|
+
// src/component/widget/prose/_function/rehype-head.ts
|
|
291
|
+
var rehypeHead = () => (tree, file) => {
|
|
292
|
+
const frontmatter = file.data.fh?.frontmatter;
|
|
293
|
+
const firstSection = tree.children.findIndex((node) => node.type === "element" && node.tagName === `h${section_heading_depth.section}`);
|
|
294
|
+
const leadEnd = firstSection === -1 ? tree.children.length : firstSection;
|
|
295
|
+
if (frontmatter === void 0 && leadEnd === 0) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
tree.children = [
|
|
299
|
+
{
|
|
300
|
+
type: "element",
|
|
301
|
+
tagName: "header",
|
|
302
|
+
properties: { className: ["wg_prose__head"] },
|
|
303
|
+
children: [...tree.children.slice(0, leadEnd).filter((node) => node.type !== "doctype")]
|
|
304
|
+
},
|
|
305
|
+
...tree.children.slice(leadEnd)
|
|
306
|
+
];
|
|
307
|
+
if (frontmatter !== void 0 && tree.children[0].type === "element") {
|
|
308
|
+
tree.children[0].children.unshift({ type: "element", tagName: "h1", properties: {}, children: [{ type: "text", value: frontmatter.name }] });
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
// src/component/widget/prose/_function/rehype-sections/_to-section-headings.ts
|
|
313
|
+
var toSectionHeadings = (node) => {
|
|
314
|
+
return node.children.flatMap((child) => {
|
|
315
|
+
if (child.type !== "element") {
|
|
316
|
+
return [];
|
|
317
|
+
}
|
|
318
|
+
if (child.tagName === `h${section_heading_depth.section}` || child.tagName === `h${section_heading_depth.sub}`) {
|
|
319
|
+
return [child];
|
|
320
|
+
}
|
|
321
|
+
return toSectionHeadings(child);
|
|
322
|
+
});
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
// src/component/widget/prose/_function/rehype-sections/rehype-sections.ts
|
|
326
|
+
var rehypeSections = () => (tree, file) => {
|
|
327
|
+
if (file.data.fh === void 0) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
file.data.fh.sections = toSectionHeadings(tree).map(
|
|
331
|
+
(heading) => ({
|
|
332
|
+
part: typeof heading.properties.dataPart === "string" ? heading.properties.dataPart : void 0
|
|
333
|
+
})
|
|
334
|
+
);
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
// src/component/widget/prose/_function/rehype-tables.ts
|
|
338
|
+
import { SKIP, visit } from "unist-util-visit";
|
|
339
|
+
var rehypeTables = () => (tree) => {
|
|
340
|
+
visit(tree, "element", (node, index, parent) => {
|
|
341
|
+
if (node.tagName !== "table" || parent === void 0 || index === void 0) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
parent.children[index] = {
|
|
345
|
+
type: "element",
|
|
346
|
+
tagName: "div",
|
|
347
|
+
properties: { className: ["wg_prose__table"] },
|
|
348
|
+
children: [node]
|
|
349
|
+
};
|
|
350
|
+
return [SKIP, index + 1];
|
|
351
|
+
});
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
// src/component/widget/prose/_function/remark-blocks.ts
|
|
355
|
+
import { toString as toPlainText } from "mdast-util-to-string";
|
|
356
|
+
import { visit as visit2 } from "unist-util-visit";
|
|
357
|
+
|
|
358
|
+
// src/component/widget/prose/_function/has-block-content.ts
|
|
359
|
+
var hasBlockContent = (node) => {
|
|
360
|
+
if (node.type === "definition") {
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
if (node.type === "html") {
|
|
364
|
+
return node.value.replace(/<!--(?:>|->|[\s\S]*?(?:--!?>|$))/g, "").trim() !== "";
|
|
365
|
+
}
|
|
366
|
+
if ("value" in node) {
|
|
367
|
+
return node.value.trim() !== "";
|
|
368
|
+
}
|
|
369
|
+
if (node.type === "table" || node.type === "textDirective") {
|
|
370
|
+
return true;
|
|
371
|
+
}
|
|
372
|
+
if ("children" in node) {
|
|
373
|
+
return node.children.some(hasBlockContent);
|
|
374
|
+
}
|
|
375
|
+
return true;
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
// src/component/widget/prose/_function/remark-blocks.ts
|
|
379
|
+
var remarkBlocks = () => (tree, file) => {
|
|
380
|
+
const source = String(file.value);
|
|
381
|
+
visit2(tree, (node, _index, parent) => {
|
|
382
|
+
if (node.type === "leafDirective" && node.name === "part" && parent?.type !== "root") {
|
|
383
|
+
file.fail(`${copy_error_directive_syntax}: part \xB7 \uBB38\uC11C \uCD5C\uC0C1\uC704\uC5D0 \uC791\uC131`, node);
|
|
384
|
+
}
|
|
385
|
+
if (node.type !== "containerDirective" && node.type !== "leafDirective" && node.type !== "textDirective") {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
if (node.name !== "note" && node.name !== "details") {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (node.type !== "containerDirective") {
|
|
392
|
+
file.fail(`${copy_error_directive_syntax}: ${node.name} \xB7 ::: \uBE14\uB85D\uC73C\uB85C \uC791\uC131`, node);
|
|
393
|
+
}
|
|
394
|
+
const label = node.children.at(0);
|
|
395
|
+
if (label?.type !== "paragraph" || label.data?.directiveLabel !== true || label.children.some((child) => child.type !== "text")) {
|
|
396
|
+
file.fail(`${copy_error_directive_syntax}: ${node.name} \xB7 \uC77C\uBC18 \uD14D\uC2A4\uD2B8 \uC81C\uBAA9 \uD544\uC218`, node);
|
|
397
|
+
}
|
|
398
|
+
const title = toPlainText(label).trim();
|
|
399
|
+
if (title === "") {
|
|
400
|
+
file.fail(`${copy_error_directive_syntax}: ${node.name} \xB7 \uBE44\uC5B4 \uC788\uC9C0 \uC54A\uC740 \uC81C\uBAA9 \uD544\uC218`, node);
|
|
401
|
+
}
|
|
402
|
+
if (!node.children.slice(1).some(hasBlockContent)) {
|
|
403
|
+
file.fail(`${copy_error_directive_syntax}: ${node.name} \xB7 \uBCF8\uBB38 \uD544\uC218`, node);
|
|
404
|
+
}
|
|
405
|
+
const unsupported = node.attributes ? Object.keys(node.attributes).find((key) => node.name !== "details" || key !== "open") : void 0;
|
|
406
|
+
if (unsupported !== void 0) {
|
|
407
|
+
file.fail(`${copy_error_directive_syntax}: ${node.name} \xB7 \uBBF8\uC9C0\uC6D0 \uC18D\uC131 ${unsupported}`, node);
|
|
408
|
+
}
|
|
409
|
+
const open = node.attributes?.open;
|
|
410
|
+
const attributeSource = source.slice(label.position?.end.offset, node.position?.end.offset).split(/\r?\n/, 1)[0].trim();
|
|
411
|
+
if (attributeSource !== "" && (node.name !== "details" || !/^\{[ \t]*open[ \t]*\}$/.test(attributeSource))) {
|
|
412
|
+
file.fail(`${copy_error_directive_syntax}: ${node.name} \xB7 \uD5C8\uC6A9 \uC18D\uC131\uC740 Details\uC758 {open}, \uB098\uBA38\uC9C0\uB294 \uC0DD\uB7B5`, node);
|
|
413
|
+
}
|
|
414
|
+
const original = source.slice(node.position?.start.offset, node.position?.end.offset);
|
|
415
|
+
const opening = /^(:{3,})/.exec(original);
|
|
416
|
+
const closing = /(?:^|\n)[ \t>]*(:{3,})[ \t]*\r?$/.exec(original);
|
|
417
|
+
if (opening === null || closing === null || closing.index + closing[0].length !== original.length || closing[1].length < opening[1].length || node.position?.end.offset === node.children.at(-1)?.position?.end.offset) {
|
|
418
|
+
file.fail(`${copy_error_directive_syntax}: ${node.name} \xB7 \uBE14\uB85D\uC744 \uB2EB\uB294 fence \uD544\uC218`, node);
|
|
419
|
+
}
|
|
420
|
+
visit2(node, "heading", (heading) => {
|
|
421
|
+
if (heading.depth <= section_heading_depth.section) {
|
|
422
|
+
file.fail(`${copy_error_directive_syntax}: ${node.name} \xB7 #\xB7## \uC81C\uBAA9\uC740 \uBD80\uD488 \uBC16\uC5D0 \uC791\uC131`, heading);
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
visit2(node, "code", (code) => {
|
|
426
|
+
const originalCode = source.slice(code.position?.start.offset, code.position?.end.offset);
|
|
427
|
+
const codeOpening = /^ {0,3}(`{3,}|~{3,})/.exec(originalCode);
|
|
428
|
+
const codeClosing = /(?:^|\n)[ \t>]*(`{3,}|~{3,})[ \t]*\r?$/.exec(originalCode);
|
|
429
|
+
if (codeOpening !== null && (codeClosing === null || codeClosing.index + codeClosing[0].length !== originalCode.length || codeClosing[1][0] !== codeOpening[1][0] || codeClosing[1].length < codeOpening[1].length)) {
|
|
430
|
+
file.fail(`${copy_error_directive_syntax}: ${node.name} \xB7 \uCF54\uB4DC fence\uB97C \uB2EB\uACE0, \uCF54\uB4DC \uC548\uC758 :\uBCF4\uB2E4 \uAE34 \uBC14\uAE65 fence \uC0AC\uC6A9`, code);
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
label.children = [{ type: "text", value: title }];
|
|
434
|
+
label.data = {
|
|
435
|
+
...label.data,
|
|
436
|
+
hName: node.name === "note" ? "strong" : "summary",
|
|
437
|
+
hProperties: { className: [node.name === "note" ? "wg_prose__noteTitle" : "wg_prose__detailsSummary"] }
|
|
438
|
+
};
|
|
439
|
+
node.data = {
|
|
440
|
+
...node.data,
|
|
441
|
+
hName: node.name === "note" ? "aside" : "details",
|
|
442
|
+
hProperties: node.name === "note" ? { className: ["wg_prose__note"], ariaLabel: title } : { className: ["wg_prose__details"], open: open === "" }
|
|
443
|
+
};
|
|
444
|
+
});
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
// src/component/widget/prose/_function/remark-flow.ts
|
|
448
|
+
import { visit as visit3 } from "unist-util-visit";
|
|
449
|
+
|
|
450
|
+
// src/util/mermaid/render-flow.js
|
|
451
|
+
import { renderMermaidASCII } from "beautiful-mermaid";
|
|
452
|
+
var esc = (s) => String(s == null ? "" : s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
453
|
+
var ASCII_OPT = { paddingX: 3, paddingY: 2, boxBorderPadding: 1, colorMode: "none" };
|
|
454
|
+
var WIDE = /[ᄀ-ᇿ -〿-가-一-鿿-ヿ-⦆]/;
|
|
455
|
+
var ZW = "\u200B";
|
|
456
|
+
var widenCjk = (src) => src.replace(new RegExp(WIDE.source, "g"), (c) => c + ZW);
|
|
457
|
+
var LINES = {
|
|
458
|
+
"\u2500": "LR",
|
|
459
|
+
"\u2502": "UD",
|
|
460
|
+
"\u250C": "RD",
|
|
461
|
+
"\u2510": "LD",
|
|
462
|
+
"\u2514": "RU",
|
|
463
|
+
"\u2518": "LU",
|
|
464
|
+
"\u251C": "UDR",
|
|
465
|
+
"\u2524": "UDL",
|
|
466
|
+
"\u252C": "LRD",
|
|
467
|
+
"\u2534": "LRU",
|
|
468
|
+
"\u253C": "LRUD",
|
|
469
|
+
"\u256D": "RDr",
|
|
470
|
+
"\u256E": "LDr",
|
|
471
|
+
"\u2570": "RUr",
|
|
472
|
+
"\u256F": "LUr",
|
|
473
|
+
"\u2550": "LRb",
|
|
474
|
+
"\u2551": "UDb",
|
|
475
|
+
"\u2554": "RDb",
|
|
476
|
+
"\u2557": "LDb",
|
|
477
|
+
"\u255A": "RUb",
|
|
478
|
+
"\u255D": "LUb",
|
|
479
|
+
"\u255F": "UDRb",
|
|
480
|
+
"\u2562": "UDLb",
|
|
481
|
+
"\u254C": "LRd",
|
|
482
|
+
"\u254E": "UDd"
|
|
483
|
+
};
|
|
484
|
+
var ARROWS = { "\u25BA": "R", "\u25C4": "L", "\u25BC": "D", "\u25B2": "U", "\u25B6": "R", "\u25C0": "L" };
|
|
485
|
+
var isWall = (chr) => chr === "\u2502" || chr === "\u25C7" || chr === "\u251C" || chr === "\u2524";
|
|
486
|
+
var isHBorder = (chr) => chr !== void 0 && chr !== " " && chr !== ZW && (LINES[chr] !== void 0 || chr === "\u25C7");
|
|
487
|
+
function widenLabelGaps(rows) {
|
|
488
|
+
const width = Math.max.apply(null, rows.map((r) => r.length));
|
|
489
|
+
let grid = rows.map((r) => r.padEnd(width));
|
|
490
|
+
const H = new Set("\u2500\u252C\u2534\u251C\u2524\u253C\u25C7\u250C\u2510\u2514\u2518\u256D\u256E\u2570\u256F\u2550\u254C\u25BA\u25C4\u25B6\u25C0\u2554\u2557\u255A\u255D\u255F\u2562".split(""));
|
|
491
|
+
const ANCHOR = new Set("\u251C\u2524\u252C\u2534\u253C\u2514\u2518\u250C\u2510\u256D\u256E\u2570\u256F".split(""));
|
|
492
|
+
const END = new Set("\u25BA\u25B6\u25C4\u25C0\u2524\u251C\u252C\u2534\u253C\u2510\u2518\u250C\u2514\u256E\u256F\u256D\u2570\u2502".split(""));
|
|
493
|
+
const isTxt = (chr) => chr !== void 0 && chr !== " " && chr !== ZW && chr !== "\u2502" && !H.has(chr);
|
|
494
|
+
const txtish = (chr) => isTxt(chr) || chr === ZW;
|
|
495
|
+
const splittable = (col) => grid.every((r) => !(txtish(r[col - 1]) && txtish(r[col])));
|
|
496
|
+
const filler = (r, col) => {
|
|
497
|
+
const l = r[col - 1], rt = r[col];
|
|
498
|
+
if (l === void 0 || rt === void 0) return " ";
|
|
499
|
+
if ((H.has(l) || txtish(l)) && (H.has(rt) || rt === "\u2502" || txtish(rt)) && !(txtish(l) && txtish(rt))) {
|
|
500
|
+
if (!(H.has(l) || H.has(rt))) return " ";
|
|
501
|
+
return l === "\u254C" || rt === "\u254C" ? "\u254C" : "\u2500";
|
|
502
|
+
}
|
|
503
|
+
return " ";
|
|
504
|
+
};
|
|
505
|
+
const runs = (row) => {
|
|
506
|
+
const out = [];
|
|
507
|
+
for (const m of row.matchAll(/(─*)((?:[가-힣A-Za-z0-9]?)+)(─*)/g)) {
|
|
508
|
+
if (m[2].length === 0) continue;
|
|
509
|
+
const before = row[m.index - 1], after = row[m.index + m[0].length];
|
|
510
|
+
const leftOk = m[1].length > 0 || ANCHOR.has(before);
|
|
511
|
+
const rightOk = m[3].length > 0 || END.has(after);
|
|
512
|
+
if (leftOk && rightOk && (m[1].length + m[3].length > 0 || ANCHOR.has(before) && END.has(after))) {
|
|
513
|
+
out.push({ start: m.index, label: m[2], left: m[1].length, right: m[3].length, end: m.index + m[0].length });
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return out;
|
|
517
|
+
};
|
|
518
|
+
const want = 6;
|
|
519
|
+
const inserts = [];
|
|
520
|
+
grid.forEach((row) => {
|
|
521
|
+
for (const run of runs(row)) {
|
|
522
|
+
const missing = want - (run.left + run.right);
|
|
523
|
+
if (missing > 0) inserts.push({ at: run.end, alt: run.start + run.left, n: missing });
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
inserts.sort((x, y) => y.at - x.at);
|
|
527
|
+
for (const ins of inserts) {
|
|
528
|
+
const candidates = [ins.at, ins.at + 1, ins.at + 2, ins.alt, ins.alt - 1];
|
|
529
|
+
const col = candidates.find((c) => c > 0 && c < width + 40 && splittable(c));
|
|
530
|
+
if (col === void 0) continue;
|
|
531
|
+
grid = grid.map((r) => r.slice(0, col) + filler(r, col).repeat(ins.n) + r.slice(col));
|
|
532
|
+
}
|
|
533
|
+
return grid.map((row) => {
|
|
534
|
+
let out = row;
|
|
535
|
+
for (const run of runs(row).reverse()) {
|
|
536
|
+
const total = run.left + run.right, l = Math.floor(total / 2), rgt = total - l;
|
|
537
|
+
out = out.slice(0, run.start) + "\u2500".repeat(l) + run.label + "\u2500".repeat(rgt) + out.slice(run.end);
|
|
538
|
+
}
|
|
539
|
+
return out;
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
function gridToSvg(ascii) {
|
|
543
|
+
const cw = 7.2, ch = 17, fs = 12;
|
|
544
|
+
const rows = widenLabelGaps(ascii.replace(/\s+$/, "").split("\n"));
|
|
545
|
+
const cols = Math.max.apply(null, rows.map((r) => r.length));
|
|
546
|
+
const f = (n) => n.toFixed(1);
|
|
547
|
+
let path = "", bold = "", dashed = "", arcs = "", tris = "", marks = "", dots = "", texts = "";
|
|
548
|
+
const isText = (chr) => chr !== void 0 && chr !== " " && chr !== ZW && LINES[chr] === void 0 && ARROWS[chr] === void 0 && chr !== "\u25C7";
|
|
549
|
+
const center = (c) => c * cw + cw / 2;
|
|
550
|
+
const textWidth = (chars) => chars.reduce((w, chr) => w + (WIDE.test(chr) ? fs : cw), 0);
|
|
551
|
+
rows.forEach((row, r) => {
|
|
552
|
+
const cy = r * ch + ch / 2, y0 = r * ch, y1 = y0 + ch;
|
|
553
|
+
let run = null;
|
|
554
|
+
const skip = /* @__PURE__ */ new Set();
|
|
555
|
+
for (let c = 0; c < row.length; c++) {
|
|
556
|
+
if (!isText(row[c]) || skip.has(c)) continue;
|
|
557
|
+
let e = c;
|
|
558
|
+
while (e < row.length && (isText(row[e]) || row[e] === ZW || row[e] === " " && isText(row[e + 1]))) e++;
|
|
559
|
+
if (row[c - 1] === "\u2500" && row[e] === "\u2500") {
|
|
560
|
+
const below = rows[r + 1] || "", above = rows[r - 1] || "";
|
|
561
|
+
let exit = null;
|
|
562
|
+
for (let k = c - 2; k < e + 2 && exit === null; k++) {
|
|
563
|
+
if (below[k] === "\u2502" || below[k] === "\u25BC") exit = { k, dir: 1 };
|
|
564
|
+
else if (above[k] === "\u2502" || above[k] === "\u25B2") exit = { k, dir: -1 };
|
|
565
|
+
}
|
|
566
|
+
if (exit) {
|
|
567
|
+
const kx = center(exit.k), chars2 = row.slice(c, e).split("").filter((chr) => chr !== ZW);
|
|
568
|
+
path += "M" + f(c * cw) + " " + f(cy) + "H" + f(e * cw) + " ";
|
|
569
|
+
path += "M" + f(kx) + " " + f(cy) + "V" + f(exit.dir > 0 ? y1 : y0) + " ";
|
|
570
|
+
texts += '<text x="' + f(kx + cw * 0.8 + textWidth(chars2) / 2) + '" y="' + f(cy + exit.dir * ch + fs * 0.35) + '">' + esc(chars2.join("")) + "</text>";
|
|
571
|
+
for (let k = c; k < e; k++) skip.add(k);
|
|
572
|
+
c = e - 1;
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
let l = c - 1, rr = e;
|
|
577
|
+
while (l >= 0 && row[l] === " ") l--;
|
|
578
|
+
while (rr < row.length && row[rr] === " ") rr++;
|
|
579
|
+
const onLine = (row[l] === "\u2500" || row[l] === "\u251C") && (row[rr] === "\u2500" || ARROWS[row[rr]] !== void 0 || row[rr] === "\u2524");
|
|
580
|
+
if (!onLine) {
|
|
581
|
+
c = e - 1;
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
let L = l;
|
|
585
|
+
while (L - 1 >= 0 && row[L - 1] === "\u2500") L--;
|
|
586
|
+
let segStart = L * cw, drawStart = L * cw;
|
|
587
|
+
if (row[L] === "\u251C" || row[L - 1] === "\u251C") {
|
|
588
|
+
const j = row[L] === "\u251C" ? L : L - 1;
|
|
589
|
+
const above = rows[r - 1] ? rows[r - 1][j] : " ", below = rows[r + 1] ? rows[r + 1][j] : " ";
|
|
590
|
+
const junction = above !== void 0 && LINES[above] !== void 0 && /[UD]/.test(LINES[above]) || below !== void 0 && LINES[below] !== void 0 && /[UD]/.test(LINES[below]);
|
|
591
|
+
if (junction) {
|
|
592
|
+
segStart = center(j);
|
|
593
|
+
drawStart = center(j);
|
|
594
|
+
for (let m = j + 1; m < L; m++) skip.add(m);
|
|
595
|
+
} else {
|
|
596
|
+
let k = j - 1;
|
|
597
|
+
while (k >= 0 && row[k] === " ") k--;
|
|
598
|
+
segStart = isWall(row[k]) ? center(k) : center(j);
|
|
599
|
+
drawStart = segStart;
|
|
600
|
+
for (let m = j; m < L; m++) skip.add(m);
|
|
601
|
+
}
|
|
602
|
+
} else if (LINES[row[L - 1]] !== void 0 || isWall(row[L - 1])) {
|
|
603
|
+
segStart = center(L - 1);
|
|
604
|
+
}
|
|
605
|
+
let R = rr;
|
|
606
|
+
while (R + 1 < row.length && row[R + 1] === "\u2500") R++;
|
|
607
|
+
let segEnd = (R + 1) * cw, drawEnd = (R + 1) * cw;
|
|
608
|
+
if (ARROWS[row[R]] !== void 0) {
|
|
609
|
+
drawEnd = R * cw;
|
|
610
|
+
segEnd = isWall(row[R + 1]) ? center(R + 1) : center(R) + cw * 0.45;
|
|
611
|
+
R--;
|
|
612
|
+
} else if (ARROWS[row[R + 1]] !== void 0) {
|
|
613
|
+
drawEnd = (R + 1) * cw;
|
|
614
|
+
segEnd = isWall(row[R + 2]) ? center(R + 2) : center(R + 1) + cw * 0.45;
|
|
615
|
+
} else if (LINES[row[R + 1]] !== void 0 || isWall(row[R + 1])) {
|
|
616
|
+
segEnd = center(R + 1);
|
|
617
|
+
}
|
|
618
|
+
const chars = row.slice(c, e).split("").filter((chr) => chr !== ZW);
|
|
619
|
+
const mid = (segStart + segEnd) / 2, half = textWidth(chars) / 2 + 5;
|
|
620
|
+
path += "M" + f(drawStart) + " " + f(cy) + "H" + f(mid - half) + " ";
|
|
621
|
+
path += "M" + f(mid + half) + " " + f(cy) + "H" + f(drawEnd) + " ";
|
|
622
|
+
texts += '<text x="' + f(mid) + '" y="' + f(cy + fs * 0.35) + '">' + esc(chars.join("")) + "</text>";
|
|
623
|
+
for (let k = L; k <= R; k++) skip.add(k);
|
|
624
|
+
c = e - 1;
|
|
625
|
+
}
|
|
626
|
+
const wall = (chr) => chr === "\u2502" || chr === "\u25C7" || chr === "\u251C" || chr === "\u2524";
|
|
627
|
+
const walls = (from, to) => {
|
|
628
|
+
let l = from - 1, rgt = to;
|
|
629
|
+
while (l >= 0 && (row[l] === " " || row[l] === ZW)) l--;
|
|
630
|
+
while (rgt < row.length && (row[rgt] === " " || row[rgt] === ZW)) rgt++;
|
|
631
|
+
return wall(row[l] || "") && wall(row[rgt] || "") ? [l, rgt] : null;
|
|
632
|
+
};
|
|
633
|
+
const lift = (box) => {
|
|
634
|
+
const col = run.start;
|
|
635
|
+
let top = r - 1, bottom = r + 1;
|
|
636
|
+
while (top >= 0 && !isHBorder((rows[top] || "")[col])) top--;
|
|
637
|
+
while (bottom < rows.length && !isHBorder((rows[bottom] || "")[col])) bottom++;
|
|
638
|
+
const corner = (chr) => chr !== void 0 && chr !== "\u2500" && chr !== "\u2550" && chr !== "\u254C" && (LINES[chr] !== void 0 || chr === "\u25C7");
|
|
639
|
+
if (top < 0 || bottom >= rows.length || !corner((rows[top] || "")[box[0]]) || !corner((rows[bottom] || "")[box[0]])) return 0;
|
|
640
|
+
let labelRows = 0;
|
|
641
|
+
for (let k = top + 1; k < bottom; k++) {
|
|
642
|
+
const inner = (rows[k] || "").slice(box[0] + 1, box[1]).split(ZW).join("").trim();
|
|
643
|
+
if (inner.length > 0) labelRows++;
|
|
644
|
+
}
|
|
645
|
+
return (bottom - top - 1 - labelRows) % 2 === 1 ? -ch / 2 : 0;
|
|
646
|
+
};
|
|
647
|
+
const flush = () => {
|
|
648
|
+
if (!run) return;
|
|
649
|
+
const box = walls(run.start, run.end);
|
|
650
|
+
const y = f(cy + fs * 0.35 + (box ? lift(box) : 0));
|
|
651
|
+
const x = box ? f(((box[0] + 1) * cw + box[1] * cw) / 2) : run.wide ? f((run.start * cw + run.end * cw) / 2) : run.xs.join(" ");
|
|
652
|
+
texts += '<text x="' + x + '" y="' + y + '">' + esc(run.chars.join("")) + "</text>";
|
|
653
|
+
run = null;
|
|
654
|
+
};
|
|
655
|
+
for (let c = 0; c < row.length; c++) {
|
|
656
|
+
const chr = row[c];
|
|
657
|
+
const cx = c * cw + cw / 2, x0 = c * cw, x1 = x0 + cw;
|
|
658
|
+
if (skip.has(c)) {
|
|
659
|
+
flush();
|
|
660
|
+
continue;
|
|
661
|
+
}
|
|
662
|
+
if (chr === ZW) {
|
|
663
|
+
if (run) run.end = c + 1;
|
|
664
|
+
continue;
|
|
665
|
+
}
|
|
666
|
+
if (chr === " ") {
|
|
667
|
+
const next = row[c + 1];
|
|
668
|
+
const joins = run && next !== void 0 && next !== " " && next !== ZW && !LINES[next] && !ARROWS[next] && next !== "\u25C7";
|
|
669
|
+
if (!joins) {
|
|
670
|
+
flush();
|
|
671
|
+
continue;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
const above = rows[r - 1] ? rows[r - 1][c] : " ", below = rows[r + 1] ? rows[r + 1][c] : " ";
|
|
675
|
+
const vertical = (v) => v !== void 0 && LINES[v] !== void 0 && /[UD]/.test(LINES[v]) || v === "\u25C7";
|
|
676
|
+
if ((chr === "\u251C" || chr === "\u2524") && !vertical(above) && !vertical(below)) {
|
|
677
|
+
flush();
|
|
678
|
+
let l = c - 1, rgt = c + 1;
|
|
679
|
+
while (l >= 0 && row[l] === " ") l--;
|
|
680
|
+
while (rgt < row.length && row[rgt] === " ") rgt++;
|
|
681
|
+
const gapL = isWall(row[l]) ? l * cw + cw / 2 : x0;
|
|
682
|
+
const gapR = isWall(row[rgt]) ? rgt * cw + cw / 2 : x1;
|
|
683
|
+
path += "M" + f(gapL) + " " + f(cy) + "H" + f(gapR) + " ";
|
|
684
|
+
continue;
|
|
685
|
+
}
|
|
686
|
+
const ln = LINES[chr];
|
|
687
|
+
if (ln) {
|
|
688
|
+
flush();
|
|
689
|
+
if (ln.indexOf("r") >= 0) {
|
|
690
|
+
const ax = ln.indexOf("L") >= 0 ? x0 : x1, by = ln.indexOf("U") >= 0 ? y0 : y1;
|
|
691
|
+
arcs += "M" + f(ax) + " " + f(cy) + "Q" + f(cx) + " " + f(cy) + " " + f(cx) + " " + f(by) + " ";
|
|
692
|
+
} else {
|
|
693
|
+
let seg = "";
|
|
694
|
+
if (ln.indexOf("L") >= 0) seg += "M" + f(isWall(row[c - 1]) ? x0 - cw / 2 : x0) + " " + f(cy) + "H" + f(cx) + " ";
|
|
695
|
+
if (ln.indexOf("R") >= 0) seg += "M" + f(cx) + " " + f(cy) + "H" + f(isWall(row[c + 1]) ? x1 + cw / 2 : x1) + " ";
|
|
696
|
+
if (ln.indexOf("U") >= 0) seg += "M" + f(cx) + " " + f(y0) + "V" + f(cy) + " ";
|
|
697
|
+
if (ln.indexOf("D") >= 0) seg += "M" + f(cx) + " " + f(cy) + "V" + f(y1) + " ";
|
|
698
|
+
if (ln.indexOf("b") >= 0) bold += seg;
|
|
699
|
+
else if (ln.indexOf("d") >= 0) dashed += seg;
|
|
700
|
+
else path += seg;
|
|
701
|
+
}
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
const ar = ARROWS[chr];
|
|
705
|
+
if (ar) {
|
|
706
|
+
flush();
|
|
707
|
+
const w = cw * 0.9, h = ch * 0.42;
|
|
708
|
+
const tipR = isWall(row[c + 1]) ? x1 + cw / 2 : cx + w / 2, tipL = isWall(row[c - 1]) ? x0 - cw / 2 : cx - w / 2;
|
|
709
|
+
const tipD = isHBorder(below) ? y1 + ch / 2 : cy + h / 2, tipU = isHBorder(above) ? y0 - ch / 2 : cy - h / 2;
|
|
710
|
+
if (ar === "R") {
|
|
711
|
+
path += "M" + f(x0) + " " + f(cy) + "H" + f(tipR - w) + " ";
|
|
712
|
+
tris += "M" + f(tipR - w) + " " + f(cy - h / 2) + "L" + f(tipR) + " " + f(cy) + "L" + f(tipR - w) + " " + f(cy + h / 2) + "Z ";
|
|
713
|
+
}
|
|
714
|
+
if (ar === "L") {
|
|
715
|
+
path += "M" + f(tipL + w) + " " + f(cy) + "H" + f(x1) + " ";
|
|
716
|
+
tris += "M" + f(tipL + w) + " " + f(cy - h / 2) + "L" + f(tipL) + " " + f(cy) + "L" + f(tipL + w) + " " + f(cy + h / 2) + "Z ";
|
|
717
|
+
}
|
|
718
|
+
if (ar === "D") {
|
|
719
|
+
path += "M" + f(cx) + " " + f(y0) + "V" + f(tipD - h) + " ";
|
|
720
|
+
tris += "M" + f(cx - w / 2) + " " + f(tipD - h) + "L" + f(cx + w / 2) + " " + f(tipD - h) + "L" + f(cx) + " " + f(tipD) + "Z ";
|
|
721
|
+
}
|
|
722
|
+
if (ar === "U") {
|
|
723
|
+
path += "M" + f(cx) + " " + f(tipU + h) + "V" + f(y1) + " ";
|
|
724
|
+
tris += "M" + f(cx - w / 2) + " " + f(tipU + h) + "L" + f(cx + w / 2) + " " + f(tipU + h) + "L" + f(cx) + " " + f(tipU) + "Z ";
|
|
725
|
+
}
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
728
|
+
if (chr === "\u25C7") {
|
|
729
|
+
flush();
|
|
730
|
+
const w = cw * 0.8, h = ch * 0.4;
|
|
731
|
+
marks += "M" + f(cx) + " " + f(cy - h / 2) + "L" + f(cx + w / 2) + " " + f(cy) + "L" + f(cx) + " " + f(cy + h / 2) + "L" + f(cx - w / 2) + " " + f(cy) + "Z ";
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
if (chr === "\u25CF") {
|
|
735
|
+
flush();
|
|
736
|
+
const rr = cw * 0.45;
|
|
737
|
+
dots += "M" + f(cx - rr) + " " + f(cy) + "a" + f(rr) + " " + f(rr) + " 0 1 0 " + f(rr * 2) + " 0a" + f(rr) + " " + f(rr) + " 0 1 0 " + f(-rr * 2) + " 0Z ";
|
|
738
|
+
continue;
|
|
739
|
+
}
|
|
740
|
+
if (chr === "\u25B3") {
|
|
741
|
+
flush();
|
|
742
|
+
const w = cw * 0.9, h = ch * 0.42;
|
|
743
|
+
marks += "M" + f(cx) + " " + f(cy - h / 2) + "L" + f(cx + w / 2) + " " + f(cy + h / 2) + "L" + f(cx - w / 2) + " " + f(cy + h / 2) + "Z ";
|
|
744
|
+
path += "M" + f(cx) + " " + f(cy + h / 2) + "V" + f(y1) + " ";
|
|
745
|
+
continue;
|
|
746
|
+
}
|
|
747
|
+
if (!run) run = { start: c, end: c + 1, xs: [], chars: [], wide: false };
|
|
748
|
+
run.end = c + 1;
|
|
749
|
+
run.xs.push(f(cx));
|
|
750
|
+
run.chars.push(chr);
|
|
751
|
+
if (WIDE.test(chr)) run.wide = true;
|
|
752
|
+
}
|
|
753
|
+
flush();
|
|
754
|
+
});
|
|
755
|
+
const W = f(cols * cw), H = f(rows.length * ch);
|
|
756
|
+
return '<svg xmlns="http://www.w3.org/2000/svg" class="ascii-flow" viewBox="0 0 ' + W + " " + H + '" width="' + W + '" height="' + H + '"><path d="' + path + '" fill="none" stroke="var(--app-color-text-muted)" stroke-width="1"/><path d="' + bold + '" fill="none" stroke="var(--app-color-text-muted)" stroke-width="2"/><path d="' + dashed + '" fill="none" stroke="var(--app-color-text-muted)" stroke-width="1" stroke-dasharray="3 3"/><path d="' + arcs + '" fill="none" stroke="var(--app-color-text-muted)" stroke-width="1"/><path d="' + tris + '" fill="var(--app-color-text-muted)"/><path d="' + dots + '" fill="var(--app-color-text-muted)"/><path d="' + marks + '" fill="var(--app-color-surface)" stroke="var(--app-color-text-muted)" stroke-width="1"/><g font-family="var(--app-font-mono)" font-size="' + fs + '" text-anchor="middle" fill="var(--app-color-text)">' + texts + "</g></svg>";
|
|
757
|
+
}
|
|
758
|
+
var renderFlow = (source) => gridToSvg(renderMermaidASCII(widenCjk(source), ASCII_OPT));
|
|
759
|
+
|
|
760
|
+
// src/component/widget/prose/_function/remark-flow.ts
|
|
761
|
+
var remarkFlow = () => (tree, file) => {
|
|
762
|
+
visit3(tree, "code", (node, index, parent) => {
|
|
763
|
+
if (node.lang !== "mermaid" || parent === void 0 || index === void 0) {
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
try {
|
|
767
|
+
parent.children[index] = {
|
|
768
|
+
type: "html",
|
|
769
|
+
value: `<div class="wg_prose__flow">${renderFlow(node.value)}</div>`
|
|
770
|
+
};
|
|
771
|
+
} catch (error) {
|
|
772
|
+
file.fail(`${copy_error_flow}: ${error instanceof Error ? error.message : String(error)}`, node);
|
|
773
|
+
}
|
|
774
|
+
});
|
|
775
|
+
};
|
|
776
|
+
|
|
777
|
+
// src/component/widget/prose/_function/remark-links.ts
|
|
778
|
+
import { existsSync } from "node:fs";
|
|
779
|
+
import { dirname, posix, relative, resolve } from "node:path";
|
|
780
|
+
import { visit as visit4 } from "unist-util-visit";
|
|
781
|
+
var remarkLinks = (options) => (tree, file) => {
|
|
782
|
+
const here = dirname(relative(options.root, file.path));
|
|
783
|
+
visit4(tree, (node) => {
|
|
784
|
+
if (node.type !== "link" && node.type !== "definition") {
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
const match = /^(?![a-z]+:|\/|#)([^#?]+)(\.mdx?)([?#].*|)$/i.exec(node.url);
|
|
788
|
+
if (match) {
|
|
789
|
+
if (!existsSync(resolve(dirname(file.path), `${match[1]}${match[2]}`))) {
|
|
790
|
+
file.message(`${copy_warn_broken_link}: ${node.url}`, node);
|
|
791
|
+
}
|
|
792
|
+
const target = posix.join(here, `${match[1]}${match[2]}`).toLowerCase();
|
|
793
|
+
node.url = target === "readme.md" ? `/${match[3]}` : `/${posix.join(here, match[1]).toLowerCase()}/${match[3]}`;
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
};
|
|
797
|
+
|
|
798
|
+
// src/component/widget/prose/_function/remark-parts.ts
|
|
799
|
+
import { toString as toPlainText2 } from "mdast-util-to-string";
|
|
800
|
+
var remarkParts = () => (tree) => {
|
|
801
|
+
for (const [index, node] of tree.children.entries()) {
|
|
802
|
+
if (node.type !== "leafDirective" || node.name !== "part") {
|
|
803
|
+
continue;
|
|
804
|
+
}
|
|
805
|
+
const section = tree.children.slice(index + 1).find((next) => next.type === "heading" && next.depth === section_heading_depth.section);
|
|
806
|
+
node.data = { hName: "div", hProperties: { className: ["wg_prose__part"] } };
|
|
807
|
+
if (section) {
|
|
808
|
+
section.data = {
|
|
809
|
+
...section.data,
|
|
810
|
+
hProperties: { ...section.data?.hProperties, dataPart: toPlainText2(node).trim() }
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
|
|
816
|
+
// src/component/widget/prose/_function/remark-status.ts
|
|
817
|
+
import { escape as escapeHtml, escapeRegExp } from "es-toolkit/string";
|
|
818
|
+
import { findAndReplace } from "mdast-util-find-and-replace";
|
|
819
|
+
|
|
820
|
+
// src/component/widget/prose/_constant/status.ts
|
|
821
|
+
var status_date_pattern = String.raw`\d{4}-\d{2}-\d{2}`;
|
|
822
|
+
var status_candidate_pattern = new RegExp(String.raw`\([^()\n]*${status_date_pattern}\)`, "g");
|
|
823
|
+
|
|
824
|
+
// src/component/widget/prose/_function/remark-status.ts
|
|
825
|
+
var remarkStatus = (options) => {
|
|
826
|
+
const statuses = options.status.toSorted((a, b) => b.phrase.length - a.phrase.length);
|
|
827
|
+
const phrases = statuses.map((item) => [escapeRegExp(item.phrase), ...item.date ? [`(?: ${status_date_pattern})?`] : []].join("")).join("|");
|
|
828
|
+
const pattern = new RegExp(String.raw`\((${phrases})\)|(${phrases})`, "g");
|
|
829
|
+
const ignore = ["link", "linkReference", "heading"];
|
|
830
|
+
return (tree, file) => {
|
|
831
|
+
findAndReplace(
|
|
832
|
+
tree,
|
|
833
|
+
[
|
|
834
|
+
pattern,
|
|
835
|
+
(_match, inParens, bare) => {
|
|
836
|
+
const text = inParens ?? bare;
|
|
837
|
+
const item = statuses.find((status) => text?.startsWith(status.phrase));
|
|
838
|
+
if (text === void 0 || item === void 0) {
|
|
839
|
+
return false;
|
|
840
|
+
}
|
|
841
|
+
return {
|
|
842
|
+
type: "html",
|
|
843
|
+
value: `<span class="wg_prose__pill wg_prose__pill--${item.kind}">${escapeHtml(text)}</span>`
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
],
|
|
847
|
+
{ ignore }
|
|
848
|
+
);
|
|
849
|
+
findAndReplace(
|
|
850
|
+
tree,
|
|
851
|
+
[
|
|
852
|
+
status_candidate_pattern,
|
|
853
|
+
(match, info) => {
|
|
854
|
+
file.message(
|
|
855
|
+
`${copy_warn_unknown_status}: ${match}`,
|
|
856
|
+
info.stack.findLast((node) => node.position !== void 0)
|
|
857
|
+
);
|
|
858
|
+
return false;
|
|
859
|
+
}
|
|
860
|
+
],
|
|
861
|
+
{ ignore }
|
|
862
|
+
);
|
|
863
|
+
};
|
|
864
|
+
};
|
|
865
|
+
|
|
866
|
+
// src/component/widget/prose/_function/remark-swatch.ts
|
|
867
|
+
import { visit as visit5 } from "unist-util-visit";
|
|
868
|
+
var remarkSwatch = () => (tree) => {
|
|
869
|
+
visit5(tree, "inlineCode", (node) => {
|
|
870
|
+
if (/^#[0-9a-f]{3,8}$/i.test(node.value.trim())) {
|
|
871
|
+
node.data = {
|
|
872
|
+
hProperties: { className: ["wg_prose__color"], style: `--wg-prose-chip-color: ${node.value.trim()}` }
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
});
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
// src/component/widget/prose/_function/remark-unknown-directives.ts
|
|
879
|
+
import { SKIP as SKIP2, visit as visit6 } from "unist-util-visit";
|
|
880
|
+
var remarkUnknownDirectives = () => (tree, file) => {
|
|
881
|
+
visit6(tree, (node, index, parent) => {
|
|
882
|
+
if (node.type === "textDirective" && parent !== void 0 && index !== void 0) {
|
|
883
|
+
parent.children[index] = {
|
|
884
|
+
type: "text",
|
|
885
|
+
value: String(file.value).slice(node.position?.start.offset, node.position?.end.offset)
|
|
886
|
+
};
|
|
887
|
+
return SKIP2;
|
|
888
|
+
}
|
|
889
|
+
if ((node.type === "leafDirective" || node.type === "containerDirective") && node.data?.hName === void 0) {
|
|
890
|
+
file.fail(`${copy_error_unknown_directive}: ${node.name}`, node);
|
|
891
|
+
}
|
|
892
|
+
});
|
|
893
|
+
};
|
|
894
|
+
|
|
895
|
+
// src/content/rehype-heading-ids.ts
|
|
896
|
+
import Slugger from "github-slugger";
|
|
897
|
+
import { toString as toPlainText3 } from "hast-util-to-string";
|
|
898
|
+
import { visit as visit7 } from "unist-util-visit";
|
|
899
|
+
var rehypeHeadingIds = () => (tree, file) => {
|
|
900
|
+
const slugger = new Slugger();
|
|
901
|
+
const headings = [];
|
|
902
|
+
visit7(tree, "element", (node) => {
|
|
903
|
+
const depth = /^h([1-6])$/.exec(node.tagName)?.[1];
|
|
904
|
+
if (depth === void 0) {
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
const text = toPlainText3(node);
|
|
908
|
+
node.properties.id = typeof node.properties.id === "string" ? node.properties.id : slugger.slug(text);
|
|
909
|
+
headings.push({ depth: Number(depth), slug: node.properties.id, text });
|
|
910
|
+
node.children = [{ type: "element", tagName: "span", properties: { className: ["wg_prose__headingText"] }, children: node.children }];
|
|
911
|
+
});
|
|
912
|
+
if (file.data.fh) {
|
|
913
|
+
file.data.fh.headings = headings;
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
|
|
917
|
+
// src/content/remark-report.ts
|
|
918
|
+
import { relative as relative2 } from "node:path";
|
|
919
|
+
var remarkReport = (options) => (_tree, file) => {
|
|
920
|
+
const path = relative2(options.root, file.path);
|
|
921
|
+
for (const message of file.messages) {
|
|
922
|
+
console.warn(`${message.line === void 0 ? path : `${path}:${message.line}`} ${message.reason}`);
|
|
923
|
+
}
|
|
924
|
+
};
|
|
925
|
+
|
|
926
|
+
// src/content/create-processor.ts
|
|
927
|
+
var createProcessor = (options) => {
|
|
928
|
+
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 });
|
|
929
|
+
};
|
|
930
|
+
|
|
931
|
+
// src/content/read-docs.ts
|
|
932
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
933
|
+
import { join, sep } from "node:path";
|
|
934
|
+
import { VFile } from "vfile";
|
|
935
|
+
import { parse as parseYaml } from "yaml";
|
|
936
|
+
|
|
937
|
+
// src/type/doc-data.ts
|
|
938
|
+
import { z } from "zod";
|
|
939
|
+
|
|
940
|
+
// src/constant/doc.ts
|
|
941
|
+
var doc_type = {
|
|
942
|
+
document: "document",
|
|
943
|
+
blueprint: "blueprint"
|
|
944
|
+
};
|
|
945
|
+
var doc_order_default = Number.MAX_SAFE_INTEGER;
|
|
946
|
+
|
|
947
|
+
// src/type/doc-data.ts
|
|
948
|
+
var docDataSchema = z.object({
|
|
949
|
+
/**
|
|
950
|
+
* 문서 이름 · 제목·목록 · 같은 첫 글자 허용
|
|
951
|
+
*/
|
|
952
|
+
name: z.string().trim().min(1),
|
|
953
|
+
/**
|
|
954
|
+
* 짧은 문서 설명 · 사이드바 툴팁
|
|
955
|
+
*/
|
|
956
|
+
label: z.string(),
|
|
957
|
+
/**
|
|
958
|
+
* 문서 종류 · blueprint 전용 표현 미구현
|
|
959
|
+
*/
|
|
960
|
+
type: z.enum(doc_type).default(doc_type.document),
|
|
961
|
+
/**
|
|
962
|
+
* 사이드바의 문서 묶음
|
|
963
|
+
*/
|
|
964
|
+
group: z.string().trim().min(1),
|
|
965
|
+
/**
|
|
966
|
+
* 묶음 안의 읽는 순서 · 미지정 문서는 뒤에서 이름순
|
|
967
|
+
*/
|
|
968
|
+
order: z.number().int().nonnegative().default(doc_order_default)
|
|
969
|
+
});
|
|
970
|
+
|
|
971
|
+
// src/content/read-docs.ts
|
|
972
|
+
var readDocs = async (options) => {
|
|
973
|
+
const paths = (await readdir(options.root, { recursive: true })).filter(
|
|
974
|
+
(path) => /\.mdx?$/i.test(path) && !/^(readme|agents|claude)\.md$/i.test(path) && !path.split(sep).includes("node_modules") && !path.startsWith(`dist${sep}`)
|
|
975
|
+
);
|
|
976
|
+
const docs = await Promise.all(
|
|
977
|
+
paths.map(async (path) => {
|
|
978
|
+
const id = path.replace(/\.mdx?$/i, "").split(sep).join("/").toLowerCase();
|
|
979
|
+
const segments = id.split("/");
|
|
980
|
+
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)) {
|
|
981
|
+
throw new Error(`${copy_error_doc_id}: ${path}`);
|
|
982
|
+
}
|
|
983
|
+
const source = await readFile(join(options.root, path), "utf8");
|
|
984
|
+
const file = new VFile({ value: source.replace(/^\uFEFF/, ""), path: join(options.root, path) });
|
|
985
|
+
const tree = options.processor.parse(file);
|
|
986
|
+
const frontmatter = tree.children[0];
|
|
987
|
+
const parsed = docDataSchema.safeParse(frontmatter?.type === "yaml" ? parseYaml(frontmatter.value) : {});
|
|
988
|
+
if (!parsed.success) {
|
|
989
|
+
throw new Error(`${copy_error_frontmatter}: ${path}: ${parsed.error.issues.map((issue) => `${issue.path.join(".")} ${issue.message}`).join(", ")}`);
|
|
990
|
+
}
|
|
991
|
+
const fh = { frontmatter: parsed.data, headings: [], sections: [] };
|
|
992
|
+
file.data.fh = fh;
|
|
993
|
+
tree.children = tree.children.filter((node) => node.type !== "yaml");
|
|
994
|
+
const rendered = await options.processor.run(tree, file);
|
|
995
|
+
return {
|
|
996
|
+
id,
|
|
997
|
+
data: parsed.data,
|
|
998
|
+
html: options.processor.stringify(rendered, file),
|
|
999
|
+
outline: { headings: fh.headings, sections: fh.sections }
|
|
1000
|
+
};
|
|
1001
|
+
})
|
|
1002
|
+
);
|
|
1003
|
+
const duplicateIds = [...Map.groupBy(docs, (doc) => doc.id)].filter((entry) => entry[1].length > 1);
|
|
1004
|
+
if (duplicateIds.length > 0) {
|
|
1005
|
+
throw new Error(`${copy_error_doc_id_clash}: ${duplicateIds.map((entry) => entry[0]).join(", ")}`);
|
|
1006
|
+
}
|
|
1007
|
+
return docs;
|
|
1008
|
+
};
|
|
1009
|
+
|
|
1010
|
+
// src/content/read-home.ts
|
|
1011
|
+
import { readdir as readdir2, readFile as readFile2 } from "node:fs/promises";
|
|
1012
|
+
import { join as join2 } from "node:path";
|
|
1013
|
+
import { VFile as VFile2 } from "vfile";
|
|
1014
|
+
var readHome = async (options) => {
|
|
1015
|
+
const paths = (await readdir2(options.root)).filter((path2) => path2.toLowerCase() === "readme.md");
|
|
1016
|
+
if (paths.length > 1) {
|
|
1017
|
+
throw new Error(`${copy_error_home_clash}: ${paths.join(", ")}`);
|
|
1018
|
+
}
|
|
1019
|
+
if (paths.length === 0) {
|
|
1020
|
+
return void 0;
|
|
1021
|
+
}
|
|
1022
|
+
const path = join2(options.root, paths[0]);
|
|
1023
|
+
const fh = { headings: [], sections: [] };
|
|
1024
|
+
const file = new VFile2({ value: (await readFile2(path, "utf8")).replace(/^\uFEFF/, ""), path, data: { fh } });
|
|
1025
|
+
await options.processor.process(file);
|
|
1026
|
+
return { html: String(file), outline: { headings: fh.headings, sections: fh.sections } };
|
|
1027
|
+
};
|
|
1028
|
+
|
|
1029
|
+
// src/dev.ts
|
|
1030
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
1031
|
+
import { extname } from "node:path";
|
|
1032
|
+
import { Hono as Hono2 } from "hono";
|
|
1033
|
+
import { streamSSE } from "hono/streaming";
|
|
1034
|
+
var createDevApp = (options) => {
|
|
1035
|
+
const app = new Hono2();
|
|
1036
|
+
const handleAsset = async (c) => {
|
|
1037
|
+
const file = options.files.get(c.req.path);
|
|
1038
|
+
if (file === void 0) {
|
|
1039
|
+
return c.notFound();
|
|
1040
|
+
}
|
|
1041
|
+
c.header("content-type", asset_content_types[extname(file)] ?? asset_content_type_default);
|
|
1042
|
+
if (extname(file) === ".woff2") {
|
|
1043
|
+
c.header("Cache-Control", font_cache_control);
|
|
1044
|
+
}
|
|
1045
|
+
return c.body(await readFile3(file));
|
|
1046
|
+
};
|
|
1047
|
+
app.get(
|
|
1048
|
+
asset_reload_path,
|
|
1049
|
+
(c) => streamSSE(
|
|
1050
|
+
c,
|
|
1051
|
+
(stream) => new Promise((done) => {
|
|
1052
|
+
const handleChange = async () => {
|
|
1053
|
+
await stream.writeSSE({ data: "change" });
|
|
1054
|
+
done();
|
|
1055
|
+
};
|
|
1056
|
+
options.reload.once("change", handleChange);
|
|
1057
|
+
stream.onAbort(() => {
|
|
1058
|
+
options.reload.off("change", handleChange);
|
|
1059
|
+
done();
|
|
1060
|
+
});
|
|
1061
|
+
})
|
|
1062
|
+
)
|
|
1063
|
+
);
|
|
1064
|
+
app.get(`/${asset_dir}/*`, handleAsset);
|
|
1065
|
+
app.get(asset_favicon_path, handleAsset);
|
|
1066
|
+
app.all("/*", (c) => options.pages.fetch(c.req.raw, c.env));
|
|
1067
|
+
return app;
|
|
1068
|
+
};
|
|
1069
|
+
|
|
1070
|
+
// src/type/site-config.ts
|
|
1071
|
+
import { z as z2 } from "zod";
|
|
1072
|
+
|
|
1073
|
+
// src/constant/status.ts
|
|
1074
|
+
var status_kind = {
|
|
1075
|
+
verified: "verified",
|
|
1076
|
+
unverified: "unverified"
|
|
1077
|
+
};
|
|
1078
|
+
var status_default_phrases = [
|
|
1079
|
+
{ phrase: "\uD655\uC778\uB428", kind: status_kind.verified, date: true },
|
|
1080
|
+
{ phrase: "\uD655\uC778\uB418\uC9C0 \uC54A\uC558\uB2E4", kind: status_kind.unverified }
|
|
1081
|
+
];
|
|
1082
|
+
|
|
1083
|
+
// src/type/site-config.ts
|
|
1084
|
+
var siteConfigSchema = z2.object({
|
|
1085
|
+
/**
|
|
1086
|
+
* 사이드바 이름과 탭 제목
|
|
1087
|
+
*/
|
|
1088
|
+
title: z2.string().default(copy_site_title_default),
|
|
1089
|
+
/**
|
|
1090
|
+
* HTML 설명 메타데이터 · 선택
|
|
1091
|
+
*/
|
|
1092
|
+
description: z2.string().optional(),
|
|
1093
|
+
/**
|
|
1094
|
+
* 탐색 묶음의 읽는 순서 · 미지정 묶음은 뒤에서 이름순
|
|
1095
|
+
*/
|
|
1096
|
+
navigation: z2.array(z2.string().trim().min(1)).refine((groups) => new Set(groups).size === groups.length, copy_error_navigation_clash).default([...site_navigation_default]),
|
|
1097
|
+
/**
|
|
1098
|
+
* 본문에서 상태 표지로 표시할 문구
|
|
1099
|
+
*/
|
|
1100
|
+
status: z2.array(
|
|
1101
|
+
z2.object({
|
|
1102
|
+
/**
|
|
1103
|
+
* 찾을 문구 원문
|
|
1104
|
+
*/
|
|
1105
|
+
phrase: z2.string().min(1).refine((phrase) => phrase.trim().length > 0),
|
|
1106
|
+
/**
|
|
1107
|
+
* 상태 표지의 색 종류
|
|
1108
|
+
*/
|
|
1109
|
+
kind: z2.enum(status_kind),
|
|
1110
|
+
/**
|
|
1111
|
+
* 문구 뒤의 YYYY-MM-DD 날짜 포함 여부
|
|
1112
|
+
*/
|
|
1113
|
+
date: z2.boolean().optional()
|
|
1114
|
+
})
|
|
1115
|
+
).default(status_default_phrases)
|
|
1116
|
+
});
|
|
1117
|
+
|
|
1118
|
+
// src/util/error/to-error-message.ts
|
|
1119
|
+
var toErrorMessage = (error) => {
|
|
1120
|
+
if (error instanceof Error && "file" in error && typeof error.file === "string" && "line" in error && typeof error.line === "number") {
|
|
1121
|
+
return `${error.file}:${error.line}: ${error.message}`;
|
|
1122
|
+
}
|
|
1123
|
+
return error instanceof Error ? error.message : String(error);
|
|
1124
|
+
};
|
|
1125
|
+
|
|
1126
|
+
// src/util/font/to-font-css.ts
|
|
1127
|
+
import { createHash } from "node:crypto";
|
|
1128
|
+
import { readFileSync } from "node:fs";
|
|
1129
|
+
import { basename, dirname as dirname2, extname as extname2, join as join3 } from "node:path";
|
|
1130
|
+
var toFontCss = (options) => {
|
|
1131
|
+
const files = /* @__PURE__ */ new Map();
|
|
1132
|
+
const css = [...readFileSync(options.css, "utf8").matchAll(/@font-face\s*\{[^}]*\}/g)].map(
|
|
1133
|
+
(match) => match[0].replace(/font-display:\s*[^;]+;/g, `font-display: ${font_display_strategy};`).replace(/url\(([^)]+)\)/g, (_match, relativeUrl) => {
|
|
1134
|
+
const file = join3(dirname2(options.css), relativeUrl);
|
|
1135
|
+
const extension = extname2(file);
|
|
1136
|
+
const hash = createHash("sha256").update(readFileSync(file)).digest("hex").slice(0, font_hash_length);
|
|
1137
|
+
const url = `${options.fontDir}/${basename(file, extension)}.${hash}${extension}`;
|
|
1138
|
+
files.set(url, file);
|
|
1139
|
+
return `url(${url})`;
|
|
1140
|
+
})
|
|
1141
|
+
).join("\n");
|
|
1142
|
+
return { css, files };
|
|
1143
|
+
};
|
|
1144
|
+
|
|
1145
|
+
// src/cli.ts
|
|
1146
|
+
var commands = ["dev", "build", "preview"];
|
|
1147
|
+
var [command = cli_default_command, docsDir = cli_default_docs_dir] = process.argv.slice(2);
|
|
1148
|
+
var main = async () => {
|
|
1149
|
+
if (!commands.includes(command)) {
|
|
1150
|
+
throw new Error(`${copy_error_unknown_command}: ${command} (${commands.join(", ")})`);
|
|
1151
|
+
}
|
|
1152
|
+
const kitRoot = fileURLToPath(new URL("../", import.meta.url));
|
|
1153
|
+
const docsRoot = resolve2(docsDir);
|
|
1154
|
+
const outDir = join4(docsRoot, "dist");
|
|
1155
|
+
if (command === "preview") {
|
|
1156
|
+
const app2 = new Hono3();
|
|
1157
|
+
app2.use(
|
|
1158
|
+
"/*",
|
|
1159
|
+
serveStatic({
|
|
1160
|
+
root: relative3(process.cwd(), outDir),
|
|
1161
|
+
onFound: (_path, c) => {
|
|
1162
|
+
if (c.req.path.startsWith(`${asset_font_dir}/`)) {
|
|
1163
|
+
c.header("Cache-Control", font_cache_control);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
})
|
|
1167
|
+
);
|
|
1168
|
+
serve({ fetch: app2.fetch, port: cli_dev_port }, (info) => console.log(`http://localhost:${info.port}/`));
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
const configFile = join4(docsRoot, cli_config_file_name);
|
|
1172
|
+
const parsedConfig = siteConfigSchema.safeParse(existsSync2(configFile) ? (await import(pathToFileURL(configFile).href)).default : site_config_absent);
|
|
1173
|
+
if (!parsedConfig.success) {
|
|
1174
|
+
throw new Error(`${copy_error_config}: ${parsedConfig.error.issues.map((issue) => `${issue.path.join(".")} ${issue.message}`).join(", ")}`);
|
|
1175
|
+
}
|
|
1176
|
+
const siteConfig = parsedConfig.data;
|
|
1177
|
+
const sans = toFontCss({ css: join4(kitRoot, font_sans_css), fontDir: asset_font_dir });
|
|
1178
|
+
const mono = toFontCss({ css: join4(kitRoot, font_mono_css), fontDir: asset_font_dir });
|
|
1179
|
+
const brand = toFontCss({ css: join4(kitRoot, font_brand_css), fontDir: asset_font_dir });
|
|
1180
|
+
const sansPreload = [...sans.files].find((entry) => basename2(entry[1]) === font_sans_preload_file);
|
|
1181
|
+
if (sansPreload === void 0) {
|
|
1182
|
+
throw new Error(`${copy_error_font_preload}: ${font_sans_preload_file}`);
|
|
1183
|
+
}
|
|
1184
|
+
const fontCss = [sans.css, mono.css, brand.css].join("\n");
|
|
1185
|
+
const files = new Map([
|
|
1186
|
+
[asset_style_path, join4(kitRoot, "dist/cli.css")],
|
|
1187
|
+
[asset_client_path, join4(kitRoot, "dist/client.js")],
|
|
1188
|
+
[asset_favicon_path, join4(kitRoot, "src/asset/favicon.svg")],
|
|
1189
|
+
...sans.files,
|
|
1190
|
+
...mono.files,
|
|
1191
|
+
...brand.files
|
|
1192
|
+
]);
|
|
1193
|
+
const processor = createProcessor({ site: siteConfig, root: docsRoot });
|
|
1194
|
+
const [docs, home] = await Promise.all([readDocs({ root: docsRoot, processor }), readHome({ root: docsRoot, processor })]);
|
|
1195
|
+
const store = { docs, home };
|
|
1196
|
+
const app = createApp({
|
|
1197
|
+
site: siteConfig,
|
|
1198
|
+
store,
|
|
1199
|
+
assets: { fontCss, preload: [...brand.files.keys(), sansPreload[0], ...mono.files.keys()], reload: command === "dev" }
|
|
1200
|
+
});
|
|
1201
|
+
if (command === "build") {
|
|
1202
|
+
await rm(outDir, { recursive: true, force: true });
|
|
1203
|
+
const result = await toSSG(app, { writeFile, mkdir }, { dir: outDir });
|
|
1204
|
+
if (!result.success) {
|
|
1205
|
+
throw result.error;
|
|
1206
|
+
}
|
|
1207
|
+
for (const [url, file] of files) {
|
|
1208
|
+
await mkdir(dirname3(join4(outDir, url)), { recursive: true });
|
|
1209
|
+
await copyFile(file, join4(outDir, url));
|
|
1210
|
+
}
|
|
1211
|
+
console.log(`${result.files.length} pages, ${files.size} assets \u2192 ${relative3(process.cwd(), outDir)}`);
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
1214
|
+
const reload = new EventEmitter();
|
|
1215
|
+
let generation = 0;
|
|
1216
|
+
serve({ fetch: createDevApp({ pages: app, files, reload }).fetch, port: cli_dev_port }, (info) => console.log(`http://localhost:${info.port}/`));
|
|
1217
|
+
const handleDocsChange = async (_event, filename) => {
|
|
1218
|
+
if (filename !== null && !/\.mdx?$/i.test(filename)) {
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
const currentGeneration = ++generation;
|
|
1222
|
+
try {
|
|
1223
|
+
const [docs2, home2] = await Promise.all([readDocs({ root: docsRoot, processor }), readHome({ root: docsRoot, processor })]);
|
|
1224
|
+
if (currentGeneration !== generation) {
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
store.docs = docs2;
|
|
1228
|
+
store.home = home2;
|
|
1229
|
+
reload.emit("change");
|
|
1230
|
+
} catch (error) {
|
|
1231
|
+
console.error(`${copy_error_prefix}: ${toErrorMessage(error)}`);
|
|
1232
|
+
}
|
|
1233
|
+
};
|
|
1234
|
+
watch(docsRoot, { recursive: true }, handleDocsChange);
|
|
1235
|
+
};
|
|
1236
|
+
try {
|
|
1237
|
+
await main();
|
|
1238
|
+
} catch (error) {
|
|
1239
|
+
console.error(`${copy_error_prefix}: ${toErrorMessage(error)}`);
|
|
1240
|
+
process.exit(1);
|
|
1241
|
+
}
|