for-humanity 0.12.0 → 0.13.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.
Files changed (226) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +16 -9
  3. package/dist/browser.js +16 -16
  4. package/dist/cli.css +2 -968
  5. package/dist/cli.js +92 -2318
  6. package/dist/config.js +1 -0
  7. package/dist/constant/copy.d.ts +100 -0
  8. package/dist/constant/site.d.ts +20 -0
  9. package/dist/constant/status.d.ts +19 -0
  10. package/dist/copy-C1uzvEnr.js +103 -0
  11. package/dist/group-path-XAThmzvC.js +10 -0
  12. package/dist/load-site-CbpLEhwu.js +2379 -0
  13. package/dist/logger-Dv1i9xSV.js +9 -0
  14. package/dist/mermaid/THIRD-PARTY-NOTICES.txt +3134 -0
  15. package/dist/mermaid/chunk--TN-qHgG.js +2 -0
  16. package/dist/mermaid/chunk-0kM1Lv4D.js +2 -0
  17. package/dist/mermaid/chunk-3FHei3pH.js +2001 -0
  18. package/dist/mermaid/chunk-3_2p2GqN.js +2 -0
  19. package/dist/mermaid/chunk-6HLei9i0.js +84 -0
  20. package/dist/mermaid/chunk-7Sz3kAwl.js +2214 -0
  21. package/dist/mermaid/chunk-7Tarqbpa.js +18047 -0
  22. package/dist/mermaid/chunk-9kkt8lzL.js +10 -0
  23. package/dist/mermaid/chunk-B--pNBQF.js +884 -0
  24. package/dist/mermaid/chunk-B4F-pysn.js +4241 -0
  25. package/dist/mermaid/chunk-B58sEIY_.js +14 -0
  26. package/dist/mermaid/chunk-B9_UWzSH.js +1517 -0
  27. package/dist/mermaid/chunk-BB8uZHwY.js +75 -0
  28. package/dist/mermaid/chunk-BFfk0LEc.js +717 -0
  29. package/dist/mermaid/chunk-BKri0qr7.js +89 -0
  30. package/dist/mermaid/chunk-BL404pH5.js +26 -0
  31. package/dist/mermaid/chunk-BLeiQSWo.js +354 -0
  32. package/dist/mermaid/chunk-BOmH_UFd.js +2 -0
  33. package/dist/mermaid/chunk-BSej9Nhy.js +1361 -0
  34. package/dist/mermaid/chunk-BYzrzvCI.js +12 -0
  35. package/dist/mermaid/chunk-BariMtWr.js +3020 -0
  36. package/dist/mermaid/chunk-BcrBoMwH.js +2352 -0
  37. package/dist/mermaid/chunk-Bok8z-Yo.js +67 -0
  38. package/dist/mermaid/chunk-BpTHLKQM.js +1970 -0
  39. package/dist/mermaid/chunk-BqjuxRsC.js +733 -0
  40. package/dist/mermaid/chunk-BuvPd-s5.js +1073 -0
  41. package/dist/mermaid/chunk-BvVehae3.js +5069 -0
  42. package/dist/mermaid/chunk-C-JABYpd.js +3075 -0
  43. package/dist/mermaid/chunk-C9XlTm4w.js +2 -0
  44. package/dist/mermaid/chunk-CApNbSU9.js +6 -0
  45. package/dist/mermaid/chunk-CCM2AH-C.js +9 -0
  46. package/dist/mermaid/chunk-CD1E0F_N.js +2 -0
  47. package/dist/mermaid/chunk-CDWvKG7D.js +2 -0
  48. package/dist/mermaid/chunk-CEVPpC1F.js +34 -0
  49. package/dist/mermaid/chunk-CLDr12lf.js +47504 -0
  50. package/dist/mermaid/chunk-CLVYqOBI.js +61 -0
  51. package/dist/mermaid/chunk-CLeOkFb5.js +15 -0
  52. package/dist/mermaid/chunk-CLgRAtOz.js +37 -0
  53. package/dist/mermaid/chunk-CMqFNUBl.js +134 -0
  54. package/dist/mermaid/chunk-CTPaBJXB.js +2 -0
  55. package/dist/mermaid/chunk-CVi6IGBL.js +2 -0
  56. package/dist/mermaid/chunk-CWV_EN-4.js +4745 -0
  57. package/dist/mermaid/chunk-CZ0dAs3g.js +2 -0
  58. package/dist/mermaid/chunk-C_YGy4Fn.js +236 -0
  59. package/dist/mermaid/chunk-CcVH22Yt.js +100 -0
  60. package/dist/mermaid/chunk-CgG6CD9_.js +7175 -0
  61. package/dist/mermaid/chunk-CgOP6IDB.js +3397 -0
  62. package/dist/mermaid/chunk-Cgg2UTSf.js +13 -0
  63. package/dist/mermaid/chunk-ChJfJJ1A.js +214 -0
  64. package/dist/mermaid/chunk-Ck5XRA46.js +447 -0
  65. package/dist/mermaid/chunk-Ckuw16cl.js +203 -0
  66. package/dist/mermaid/chunk-CpAbRCbF.js +1880 -0
  67. package/dist/mermaid/chunk-CuYekbSv.js +2 -0
  68. package/dist/mermaid/chunk-CwS4wZ5a.js +2 -0
  69. package/dist/mermaid/chunk-D-bcrBO3.js +82 -0
  70. package/dist/mermaid/chunk-D3IEAkCW.js +76 -0
  71. package/dist/mermaid/chunk-D8XfBJ_K.js +645 -0
  72. package/dist/mermaid/chunk-D9Ddd9y4.js +2228 -0
  73. package/dist/mermaid/chunk-DBh1mIbK.js +12 -0
  74. package/dist/mermaid/chunk-DD6Df6Ic.js +5 -0
  75. package/dist/mermaid/chunk-DGVDaXjx.js +8 -0
  76. package/dist/mermaid/chunk-DK9KqIXj.js +632 -0
  77. package/dist/mermaid/chunk-DORnIAsy.js +4487 -0
  78. package/dist/mermaid/chunk-DU69_VcF.js +363 -0
  79. package/dist/mermaid/chunk-DVNvSFoz.js +2144 -0
  80. package/dist/mermaid/chunk-DZe-4kde.js +20 -0
  81. package/dist/mermaid/chunk-D_a06Rz4.js +287 -0
  82. package/dist/mermaid/chunk-DfyFJJi2.js +972 -0
  83. package/dist/mermaid/chunk-DhKYPp1Z.js +2 -0
  84. package/dist/mermaid/chunk-DjFqgNTG.js +94 -0
  85. package/dist/mermaid/chunk-DmbDDrr-.js +65 -0
  86. package/dist/mermaid/chunk-DpuxlyL_.js +696 -0
  87. package/dist/mermaid/chunk-DqGhppWe.js +2 -0
  88. package/dist/mermaid/chunk-DqPZxHXa.js +5 -0
  89. package/dist/mermaid/chunk-Dt_1Jyif.js +293 -0
  90. package/dist/mermaid/chunk-DyQBE_NW.js +1935 -0
  91. package/dist/mermaid/chunk-JckyC4mW.js +1009 -0
  92. package/dist/mermaid/chunk-K7Myuj2-.js +1334 -0
  93. package/dist/mermaid/chunk-KuPYb48V.js +275 -0
  94. package/dist/mermaid/chunk-MFVRUoO0.js +4020 -0
  95. package/dist/mermaid/chunk-MbInCS_6.js +28 -0
  96. package/dist/mermaid/chunk-MexOLyKV.js +355 -0
  97. package/dist/mermaid/chunk-NnbDtJzg.js +21856 -0
  98. package/dist/mermaid/chunk-SGpOYZbI.js +2139 -0
  99. package/dist/mermaid/chunk-TbxLDlcU.js +198 -0
  100. package/dist/mermaid/chunk-TftHqGLg.js +490 -0
  101. package/dist/mermaid/chunk-UjQ8vA_Z.js +4138 -0
  102. package/dist/mermaid/chunk-YgmVTKqc.js +16 -0
  103. package/dist/mermaid/chunk-_a9EZE1v.js +1798 -0
  104. package/dist/mermaid/chunk-dTb8jqeP.js +2 -0
  105. package/dist/mermaid/chunk-fFdMfF8S.js +2240 -0
  106. package/dist/mermaid/chunk-feYbMzBj.js +1267 -0
  107. package/dist/mermaid/chunk-g3Pn8DkW.js +46 -0
  108. package/dist/mermaid/chunk-hM77LvCb.js +19832 -0
  109. package/dist/mermaid/chunk-hUDb-eAW.js +527 -0
  110. package/dist/mermaid/chunk-tpABtZ-3.js +4252 -0
  111. package/dist/mermaid/chunk-xIbz3oFK.js +59 -0
  112. package/dist/mermaid/chunk-yBz-vst0.js +976 -0
  113. package/dist/mermaid/mermaid-BhtR3wyB.js +1145 -0
  114. package/dist/run-site-command-C80YoNOe.js +129 -0
  115. package/dist/site-config-bllORGpm.js +90 -0
  116. package/dist/site.js +1 -0
  117. package/dist/start-dev-server-C4_Lu1nZ.js +176 -0
  118. package/dist/to-change-queue-DbEnZGNK.js +34 -0
  119. package/dist/to-error-message-pF6_7wGK.js +16 -0
  120. package/dist/type/group-path.d.ts +7 -0
  121. package/dist/type/site-config.d.ts +57 -0
  122. package/package.json +34 -17
  123. package/src/component/widget/cursor-face/_constant/cursor-face.ts +0 -14
  124. package/src/component/widget/cursor-face/wg-cursor-face.css +0 -15
  125. package/src/component/widget/cursor-face/wg-cursor-face.tsx +0 -153
  126. package/src/component/widget/navigation/_constant/locale.ts +0 -9
  127. package/src/component/widget/navigation/_constant/navigation-data-schema.ts +0 -33
  128. package/src/component/widget/navigation/_constant/navigation.ts +0 -9
  129. package/src/component/widget/navigation/_constant/reading-line.ts +0 -4
  130. package/src/component/widget/navigation/_function/restore-navigation-scroll.ts +0 -59
  131. package/src/component/widget/navigation/_function/to-doc-groups/_to-doc-branches.ts +0 -15
  132. package/src/component/widget/navigation/_function/to-doc-groups/_to-doc-group-branches.ts +0 -70
  133. package/src/component/widget/navigation/_function/to-doc-groups/to-doc-groups.ts +0 -15
  134. package/src/component/widget/navigation/_function/to-navigation-data/_to-navigation-document.ts +0 -13
  135. package/src/component/widget/navigation/_function/to-navigation-data/_to-navigation-group.ts +0 -13
  136. package/src/component/widget/navigation/_function/to-navigation-data/to-navigation-data.ts +0 -18
  137. package/src/component/widget/navigation/_function/to-navigation-json.ts +0 -8
  138. package/src/component/widget/navigation/_function/to-toc-groups.ts +0 -38
  139. package/src/component/widget/navigation/_type/doc-branch.ts +0 -11
  140. package/src/component/widget/navigation/_type/doc-group.ts +0 -24
  141. package/src/component/widget/navigation/_type/navigation-data.ts +0 -75
  142. package/src/component/widget/navigation/_type/navigation-focus-snapshot.ts +0 -17
  143. package/src/component/widget/navigation/_type/toc-group.ts +0 -39
  144. package/src/component/widget/navigation/_wg-navigation-nav-list.css +0 -48
  145. package/src/component/widget/navigation/_wg-navigation-nav-list.tsx +0 -61
  146. package/src/component/widget/navigation/_wg-navigation-nav.css +0 -21
  147. package/src/component/widget/navigation/_wg-navigation-nav.tsx +0 -33
  148. package/src/component/widget/navigation/_wg-navigation-scroll.tsx +0 -117
  149. package/src/component/widget/navigation/_wg-navigation-toc.css +0 -91
  150. package/src/component/widget/navigation/_wg-navigation-toc.tsx +0 -114
  151. package/src/component/widget/navigation/wg-navigation.css +0 -282
  152. package/src/component/widget/navigation/wg-navigation.tsx +0 -420
  153. package/src/component/widget/prose/_constant/heading-highlight.ts +0 -4
  154. package/src/component/widget/prose/_constant/section.ts +0 -7
  155. package/src/component/widget/prose/_constant/status.ts +0 -9
  156. package/src/component/widget/prose/_function/has-block-content.ts +0 -30
  157. package/src/component/widget/prose/_function/rehype-head.ts +0 -31
  158. package/src/component/widget/prose/_function/rehype-sections/_to-section-headings.ts +0 -20
  159. package/src/component/widget/prose/_function/rehype-sections/rehype-sections.ts +0 -21
  160. package/src/component/widget/prose/_function/rehype-tables.ts +0 -22
  161. package/src/component/widget/prose/_function/remark-blocks.ts +0 -112
  162. package/src/component/widget/prose/_function/remark-flow.ts +0 -26
  163. package/src/component/widget/prose/_function/remark-links.ts +0 -33
  164. package/src/component/widget/prose/_function/remark-parts.ts +0 -26
  165. package/src/component/widget/prose/_function/remark-status.ts +0 -59
  166. package/src/component/widget/prose/_function/remark-swatch.ts +0 -16
  167. package/src/component/widget/prose/_function/remark-unknown-directives.ts +0 -25
  168. package/src/component/widget/prose/wg-prose.css +0 -484
  169. package/src/component/widget/prose/wg-prose.tsx +0 -43
  170. package/src/component/widget/shell/wg-shell.css +0 -63
  171. package/src/component/widget/shell/wg-shell.tsx +0 -88
  172. package/src/component/widget/shell-controls/wg-shell-controls.css +0 -4
  173. package/src/component/widget/shell-controls/wg-shell-controls.tsx +0 -170
  174. package/src/constant/asset.ts +0 -63
  175. package/src/constant/copy.ts +0 -133
  176. package/src/constant/doc.ts +0 -13
  177. package/src/constant/font.ts +0 -34
  178. package/src/constant/site.ts +0 -24
  179. package/src/constant/status.ts +0 -15
  180. package/src/entry/browser/browser.tsx +0 -22
  181. package/src/entry/cli/_constant/cli.ts +0 -19
  182. package/src/entry/cli/_constant/crawling.ts +0 -14
  183. package/src/entry/cli/_constant/snippet.ts +0 -21
  184. package/src/entry/cli/_function/create-app.tsx +0 -57
  185. package/src/entry/cli/_function/create-dev-app.ts +0 -87
  186. package/src/entry/cli/_function/create-processor/_rehype-assets.ts +0 -70
  187. package/src/entry/cli/_function/create-processor/_rehype-heading-ids.ts +0 -34
  188. package/src/entry/cli/_function/create-processor/_remark-report.ts +0 -15
  189. package/src/entry/cli/_function/create-processor/_remark-snippets.ts +0 -117
  190. package/src/entry/cli/_function/create-processor/_shiki-transformers.ts +0 -91
  191. package/src/entry/cli/_function/create-processor/create-processor.ts +0 -64
  192. package/src/entry/cli/_function/read-docs.ts +0 -128
  193. package/src/entry/cli/_function/read-home.ts +0 -32
  194. package/src/entry/cli/_function/to-crawling-app.ts +0 -42
  195. package/src/entry/cli/cli.test.ts +0 -804
  196. package/src/entry/cli/cli.ts +0 -206
  197. package/src/env.d.ts +0 -6
  198. package/src/page/doc/pg-doc.tsx +0 -35
  199. package/src/page/home/pg-home.tsx +0 -40
  200. package/src/store/navigation/create-navigation-stores.test.ts +0 -74
  201. package/src/store/navigation/create-navigation-stores.ts +0 -59
  202. package/src/store/navigation/navigation-state.ts +0 -36
  203. package/src/store/navigation/navigation-storage.ts +0 -9
  204. package/src/store/navigation/to-navigation-scroll-state.ts +0 -42
  205. package/src/style/base.css +0 -28
  206. package/src/style/token.css +0 -188
  207. package/src/type/doc-content.ts +0 -15
  208. package/src/type/doc-data.ts +0 -38
  209. package/src/type/doc-file-data.ts +0 -21
  210. package/src/type/doc-heading.ts +0 -17
  211. package/src/type/doc-outline.ts +0 -16
  212. package/src/type/doc-section.ts +0 -9
  213. package/src/type/doc.ts +0 -20
  214. package/src/type/group-path.ts +0 -7
  215. package/src/type/site-assets.ts +0 -25
  216. package/src/type/site-config.ts +0 -73
  217. package/src/type/vfile-data.d.ts +0 -10
  218. package/src/util/async/to-change-queue.test.ts +0 -58
  219. package/src/util/async/to-change-queue.ts +0 -43
  220. package/src/util/dom/find-hash-target.ts +0 -18
  221. package/src/util/dom/reveal-hash-target.ts +0 -15
  222. package/src/util/error/to-error-message.ts +0 -10
  223. package/src/util/file/to-asset-path.ts +0 -26
  224. package/src/util/font/to-font-css.test.ts +0 -41
  225. package/src/util/font/to-font-css.ts +0 -28
  226. package/src/util/mermaid/render-flow.js +0 -321
@@ -1,4 +0,0 @@
1
- /**
2
- * 앵커 이동 후 제목 강조 유지 시간 · 이후 CSS로 서서히 해제
3
- */
4
- export const heading_highlight_hold_ms = 3000;
@@ -1,7 +0,0 @@
1
- /**
2
- * 목차 대상 제목 깊이 · h2 절, h3 소제목
3
- */
4
- export const section_heading_depth = {
5
- section: 2,
6
- sub: 3,
7
- } as const;
@@ -1,9 +0,0 @@
1
- /**
2
- * 상태 문구 뒤 날짜 패턴 · YYYY-MM-DD
3
- */
4
- export const status_date_pattern = String.raw`\d{4}-\d{2}-\d{2}`;
5
-
6
- /**
7
- * 미등록 날짜 상태 후보 · 등록 문구 치환 뒤 남은 괄호 문구
8
- */
9
- export const status_candidate_pattern = new RegExp(String.raw`\([^()\n]*${status_date_pattern}\)`, "g");
@@ -1,30 +0,0 @@
1
- import type {Nodes} from "mdast";
2
-
3
- /**
4
- * 부품 본문의 내용 판정 · 참조 정의·주석·빈 텍스트와 빈 구조 제외
5
- * 이미지·표·구분선·주석 외 원시 HTML은 본문 요소
6
- */
7
- export const hasBlockContent = (node: Nodes): boolean => {
8
- if (node.type === "definition") {
9
- return false;
10
- }
11
-
12
- if (node.type === "html") {
13
- // HTML의 빈 주석·대체 닫힘·미종결 주석 포함
14
- return node.value.replace(/<!--(?:>|->|[\s\S]*?(?:--!?>|$))/g, "").trim() !== "";
15
- }
16
-
17
- if ("value" in node) {
18
- return node.value.trim() !== "";
19
- }
20
-
21
- if (node.type === "table" || node.type === "textDirective") {
22
- return true;
23
- }
24
-
25
- if ("children" in node) {
26
- return node.children.some(hasBlockContent);
27
- }
28
-
29
- return true;
30
- };
@@ -1,31 +0,0 @@
1
- import type {Root} from "hast";
2
- import type {VFile} from "vfile";
3
- import {section_heading_depth} from "@/component/widget/prose/_constant/section";
4
-
5
- /**
6
- * name 제목과 첫 절 앞 본문의 공통 머리 · README는 원문의 h1 사용
7
- */
8
- export const rehypeHead = () => (tree: Root, file: VFile) => {
9
- const frontmatter = file.data.fh?.frontmatter;
10
-
11
- const firstSection = tree.children.findIndex((node) => node.type === "element" && node.tagName === `h${section_heading_depth.section}`);
12
- const leadEnd = firstSection === -1 ? tree.children.length : firstSection;
13
-
14
- if (frontmatter === undefined && leadEnd === 0) {
15
- return;
16
- }
17
-
18
- tree.children = [
19
- {
20
- type: "element",
21
- tagName: "header",
22
- properties: {className: ["wg_prose__head"]},
23
- children: [...tree.children.slice(0, leadEnd).filter((node) => node.type !== "doctype")],
24
- },
25
- ...tree.children.slice(leadEnd),
26
- ];
27
-
28
- if (frontmatter !== undefined && tree.children[0].type === "element") {
29
- tree.children[0].children.unshift({type: "element", tagName: "h1", properties: {}, children: [{type: "text", value: frontmatter.name}]});
30
- }
31
- };
@@ -1,20 +0,0 @@
1
- import type {Element, Root} from "hast";
2
- import {section_heading_depth} from "@/component/widget/prose/_constant/section";
3
-
4
- /**
5
- * 목차 대상 h2·h3 · 중첩 블록까지 문서 순서 수집
6
- * rehype-heading-ids의 순회 순서와 일치
7
- */
8
- export const toSectionHeadings = (node: Root | Element): Element[] => {
9
- return node.children.flatMap((child) => {
10
- if (child.type !== "element") {
11
- return [];
12
- }
13
-
14
- if (child.tagName === `h${section_heading_depth.section}` || child.tagName === `h${section_heading_depth.sub}`) {
15
- return [child];
16
- }
17
-
18
- return toSectionHeadings(child);
19
- });
20
- };
@@ -1,21 +0,0 @@
1
- import type {Root} from "hast";
2
- import type {VFile} from "vfile";
3
- import {toSectionHeadings} from "@/component/widget/prose/_function/rehype-sections/_to-section-headings";
4
- import type {DocSection} from "@/type/doc-section";
5
-
6
- /**
7
- * h2·h3의 가름 메타데이터 수집 · 작성한 제목은 그대로 유지
8
- * id·목차 텍스트는 앞 단계의 rehype-heading-ids 소유
9
- * file.data.fh.sections는 headings의 h2·h3 순서와 일치
10
- */
11
- export const rehypeSections = () => (tree: Root, file: VFile) => {
12
- if (file.data.fh === undefined) {
13
- return;
14
- }
15
-
16
- file.data.fh.sections = toSectionHeadings(tree).map(
17
- (heading): DocSection => ({
18
- part: typeof heading.properties.dataPart === "string" ? heading.properties.dataPart : undefined,
19
- }),
20
- );
21
- };
@@ -1,22 +0,0 @@
1
- import type {Root} from "hast";
2
- import {SKIP, visit} from "unist-util-visit";
3
-
4
- /**
5
- * 넓은 표의 내부 가로 스크롤 래퍼
6
- */
7
- export const rehypeTables = () => (tree: Root) => {
8
- visit(tree, "element", (node, index, parent) => {
9
- if (node.tagName !== "table" || parent === undefined || index === undefined) {
10
- return;
11
- }
12
-
13
- parent.children[index] = {
14
- type: "element",
15
- tagName: "div",
16
- properties: {className: ["wg_prose__table"]},
17
- children: [node],
18
- };
19
-
20
- return [SKIP, index + 1];
21
- });
22
- };
@@ -1,112 +0,0 @@
1
- import type {Root} from "mdast";
2
- import {toString as toPlainText} from "mdast-util-to-string";
3
- import {visit} from "unist-util-visit";
4
- import type {VFile} from "vfile";
5
- import {section_heading_depth} from "@/component/widget/prose/_constant/section";
6
- import {hasBlockContent} from "@/component/widget/prose/_function/has-block-content";
7
- import {copy_error_directive_syntax} from "@/constant/copy";
8
-
9
- /**
10
- * Note·Details의 제목·본문·속성·닫힘 계약
11
- * label은 첫 자식 · summary는 Details의 첫 요소 · 원문 위치는 오류 기준
12
- */
13
- export const remarkBlocks = () => (tree: Root, file: VFile) => {
14
- const source = String(file.value);
15
-
16
- visit(tree, (node, _index, parent) => {
17
- if (node.type === "leafDirective" && node.name === "part" && parent?.type !== "root") {
18
- file.fail(`${copy_error_directive_syntax}: part · 문서 최상위에 작성`, node);
19
- }
20
-
21
- if (node.type !== "containerDirective" && node.type !== "leafDirective" && node.type !== "textDirective") {
22
- return;
23
- }
24
-
25
- if (node.name !== "note" && node.name !== "details") {
26
- return;
27
- }
28
-
29
- if (node.type !== "containerDirective") {
30
- file.fail(`${copy_error_directive_syntax}: ${node.name} · ::: 블록으로 작성`, node);
31
- }
32
-
33
- const label = node.children.at(0);
34
-
35
- if (label?.type !== "paragraph" || label.data?.directiveLabel !== true || label.children.some((child) => child.type !== "text")) {
36
- file.fail(`${copy_error_directive_syntax}: ${node.name} · 일반 텍스트 제목 필수`, node);
37
- }
38
-
39
- const title = toPlainText(label).trim();
40
-
41
- if (title === "") {
42
- file.fail(`${copy_error_directive_syntax}: ${node.name} · 비어 있지 않은 제목 필수`, node);
43
- }
44
-
45
- if (!node.children.slice(1).some(hasBlockContent)) {
46
- file.fail(`${copy_error_directive_syntax}: ${node.name} · 본문 필수`, node);
47
- }
48
-
49
- const unsupported = node.attributes ? Object.keys(node.attributes).find((key) => node.name !== "details" || key !== "open") : undefined;
50
-
51
- if (unsupported !== undefined) {
52
- file.fail(`${copy_error_directive_syntax}: ${node.name} · 미지원 속성 ${unsupported}`, node);
53
- }
54
-
55
- const open = node.attributes?.open;
56
- const attributeSource = source.slice(label.position?.end.offset, node.position?.end.offset).split(/\r?\n/, 1)[0].trim();
57
-
58
- // 속성 정규화 이전의 표기 · 중복 open과 open="" 거부
59
- if (attributeSource !== "" && (node.name !== "details" || !/^\{[ \t]*open[ \t]*\}$/.test(attributeSource))) {
60
- file.fail(`${copy_error_directive_syntax}: ${node.name} · 허용 속성은 Details의 {open}, 나머지는 생략`, node);
61
- }
62
-
63
- const original = source.slice(node.position?.start.offset, node.position?.end.offset);
64
- const opening = /^(:{3,})/.exec(original);
65
- const closing = /(?:^|\n)[ \t>]*(:{3,})[ \t]*\r?$/.exec(original);
66
-
67
- if (
68
- opening === null ||
69
- closing === null ||
70
- closing.index + closing[0].length !== original.length ||
71
- closing[1].length < opening[1].length ||
72
- node.position?.end.offset === node.children.at(-1)?.position?.end.offset
73
- ) {
74
- file.fail(`${copy_error_directive_syntax}: ${node.name} · 블록을 닫는 fence 필수`, node);
75
- }
76
-
77
- visit(node, "heading", (heading) => {
78
- if (heading.depth <= section_heading_depth.section) {
79
- file.fail(`${copy_error_directive_syntax}: ${node.name} · #·## 제목은 부품 밖에 작성`, heading);
80
- }
81
- });
82
-
83
- // 코드 안의 :::가 container를 먼저 닫은 경우 · 더 긴 바깥 fence로 구분
84
- visit(node, "code", (code) => {
85
- const originalCode = source.slice(code.position?.start.offset, code.position?.end.offset);
86
- const codeOpening = /^ {0,3}(`{3,}|~{3,})/.exec(originalCode);
87
- const codeClosing = /(?:^|\n)[ \t>]*(`{3,}|~{3,})[ \t]*\r?$/.exec(originalCode);
88
-
89
- if (
90
- codeOpening !== null &&
91
- (codeClosing === null ||
92
- codeClosing.index + codeClosing[0].length !== originalCode.length ||
93
- codeClosing[1][0] !== codeOpening[1][0] ||
94
- codeClosing[1].length < codeOpening[1].length)
95
- ) {
96
- file.fail(`${copy_error_directive_syntax}: ${node.name} · 코드 fence를 닫고, 코드 안의 :보다 긴 바깥 fence 사용`, code);
97
- }
98
- });
99
-
100
- label.children = [{type: "text", value: title}];
101
- label.data = {
102
- ...label.data,
103
- hName: node.name === "note" ? "strong" : "summary",
104
- hProperties: {className: [node.name === "note" ? "wg_prose__noteTitle" : "wg_prose__detailsSummary"]},
105
- };
106
- node.data = {
107
- ...node.data,
108
- hName: node.name === "note" ? "aside" : "details",
109
- hProperties: node.name === "note" ? {className: ["wg_prose__note"], ariaLabel: title} : {className: ["wg_prose__details"], open: open === ""},
110
- };
111
- });
112
- };
@@ -1,26 +0,0 @@
1
- import type {Root} from "mdast";
2
- import {visit} from "unist-util-visit";
3
- import type {VFile} from "vfile";
4
- import {copy_error_flow} from "@/constant/copy";
5
- import {renderFlow} from "@/util/mermaid/render-flow";
6
-
7
- /**
8
- * Mermaid → 격자 SVG · beautiful-mermaid 기반
9
- * 실패 시 파일·줄을 포함한 빌드 오류
10
- */
11
- export const remarkFlow = () => (tree: Root, file: VFile) => {
12
- visit(tree, "code", (node, index, parent) => {
13
- if (node.lang !== "mermaid" || parent === undefined || index === undefined) {
14
- return;
15
- }
16
-
17
- try {
18
- parent.children[index] = {
19
- type: "html",
20
- value: `<div class="wg_prose__flow">${renderFlow(node.value)}</div>`,
21
- };
22
- } catch (error) {
23
- file.fail(`${copy_error_flow}: ${error instanceof Error ? error.message : String(error)}`, node);
24
- }
25
- });
26
- };
@@ -1,33 +0,0 @@
1
- import {existsSync} from "node:fs";
2
- import {dirname, posix, relative, resolve} from "node:path";
3
- import type {Root} from "mdast";
4
- import {visit} from "unist-util-visit";
5
- import type {VFile} from "vfile";
6
- import {copy_warn_broken_link} from "@/constant/copy";
7
-
8
- /**
9
- * 상대 Markdown 링크 → 사이트 URL · query·hash 원문 유지
10
- * 외부·절대 URL과 같은 페이지 hash 유지 · 없는 파일은 터미널 경고
11
- */
12
- export const remarkLinks = (options: {root: string}) => (tree: Root, file: VFile) => {
13
- const here = dirname(relative(options.root, file.path));
14
-
15
- visit(tree, (node) => {
16
- if (node.type !== "link" && node.type !== "definition") {
17
- return;
18
- }
19
-
20
- // 셋째 capture: query·hash 접미사 · 파일 확인과 경로 정규화에서 제외
21
- const match = /^(?![a-z]+:|\/|#)([^#?]+)(\.mdx?)([?#].*|)$/i.exec(node.url);
22
-
23
- if (match) {
24
- if (!existsSync(resolve(dirname(file.path), `${match[1]}${match[2]}`))) {
25
- file.message(`${copy_warn_broken_link}: ${node.url}`, node);
26
- }
27
-
28
- const target = posix.join(here, `${match[1]}${match[2]}`).toLowerCase();
29
-
30
- node.url = target === "readme.md" ? `/${match[3]}` : `/${posix.join(here, match[1]).toLowerCase()}/${match[3]}`;
31
- }
32
- });
33
- };
@@ -1,26 +0,0 @@
1
- import type {Root} from "mdast";
2
- import {toString as toPlainText} from "mdast-util-to-string";
3
- import {section_heading_depth} from "@/component/widget/prose/_constant/section";
4
-
5
- /**
6
- * ::part[이름]의 본문 가름과 다음 h2의 data-part
7
- * rehype-sections에서 같은 지점의 목차 묶음 생성
8
- */
9
- export const remarkParts = () => (tree: Root) => {
10
- for (const [index, node] of tree.children.entries()) {
11
- if (node.type !== "leafDirective" || node.name !== "part") {
12
- continue;
13
- }
14
-
15
- const section = tree.children.slice(index + 1).find((next) => next.type === "heading" && next.depth === section_heading_depth.section);
16
-
17
- node.data = {hName: "div", hProperties: {className: ["wg_prose__part"]}};
18
-
19
- if (section) {
20
- section.data = {
21
- ...section.data,
22
- hProperties: {...section.data?.hProperties, dataPart: toPlainText(node).trim()},
23
- };
24
- }
25
- }
26
- };
@@ -1,59 +0,0 @@
1
- import {escape as escapeHtml, escapeRegExp} from "es-toolkit/string";
2
- import type {Root} from "mdast";
3
- import {findAndReplace, type RegExpMatchObject} from "mdast-util-find-and-replace";
4
- import type {VFile} from "vfile";
5
- import {status_candidate_pattern, status_date_pattern} from "@/component/widget/prose/_constant/status";
6
- import {copy_warn_unknown_status} from "@/constant/copy";
7
- import type {SiteConfig} from "@/type/site-config";
8
-
9
- /**
10
- * 설정 문구의 상태 표지 변환 · 괄호 제거 · 제목·링크 제외
11
- * 미등록 날짜 문구는 파일 경고 · remark-report에서 출력
12
- */
13
- export const remarkStatus = (options: {status: SiteConfig["status"]}) => {
14
- const statuses = options.status.toSorted((a, b) => b.phrase.length - a.phrase.length);
15
- const phrases = statuses.map((item) => [escapeRegExp(item.phrase), ...(item.date ? [`(?: ${status_date_pattern})?`] : [])].join("")).join("|");
16
- const pattern = new RegExp(String.raw`\((${phrases})\)|(${phrases})`, "g");
17
- const ignore = ["link", "linkReference", "heading"];
18
-
19
- return (tree: Root, file: VFile) => {
20
- findAndReplace(
21
- tree,
22
- [
23
- pattern,
24
- (_match: string, inParens: string | undefined, bare: string | undefined) => {
25
- const text = inParens ?? bare;
26
- const item = statuses.find((status) => text?.startsWith(status.phrase));
27
-
28
- // findAndReplace의 false: 원문 유지
29
- if (text === undefined || item === undefined) {
30
- return false;
31
- }
32
-
33
- return {
34
- type: "html",
35
- value: `<span class="wg_prose__pill wg_prose__pill--${item.kind}">${escapeHtml(text)}</span>`,
36
- };
37
- },
38
- ],
39
- {ignore},
40
- );
41
-
42
- findAndReplace(
43
- tree,
44
- [
45
- status_candidate_pattern,
46
- (match: string, info: RegExpMatchObject) => {
47
- // 치환된 텍스트에 position 부재 · 위치가 남은 가까운 조상 기준
48
- file.message(
49
- `${copy_warn_unknown_status}: ${match}`,
50
- info.stack.findLast((node) => node.position !== undefined),
51
- );
52
-
53
- return false;
54
- },
55
- ],
56
- {ignore},
57
- );
58
- };
59
- };
@@ -1,16 +0,0 @@
1
- import type {Root} from "mdast";
2
- import {visit} from "unist-util-visit";
3
-
4
- /**
5
- * 인라인 hex 색 값의 칩 표시
6
- * 문서별 색은 --wg-prose-chip-color로 전달 · 고정 스타일시트 값 불가
7
- */
8
- export const remarkSwatch = () => (tree: Root) => {
9
- visit(tree, "inlineCode", (node) => {
10
- if (/^#[0-9a-f]{3,8}$/i.test(node.value.trim())) {
11
- node.data = {
12
- hProperties: {className: ["wg_prose__color"], style: `--wg-prose-chip-color: ${node.value.trim()}`},
13
- };
14
- }
15
- });
16
- };
@@ -1,25 +0,0 @@
1
- import type {Root} from "mdast";
2
- import {SKIP, visit} from "unist-util-visit";
3
- import type {VFile} from "vfile";
4
- import {copy_error_unknown_directive} from "@/constant/copy";
5
-
6
- /**
7
- * hName 없는 블록 지시문은 작성 오류
8
- * textDirective는 원문 복원 · 예:이것 같은 일반 문장의 오인 방지
9
- */
10
- export const remarkUnknownDirectives = () => (tree: Root, file: VFile) => {
11
- visit(tree, (node, index, parent) => {
12
- if (node.type === "textDirective" && parent !== undefined && index !== undefined) {
13
- parent.children[index] = {
14
- type: "text",
15
- value: String(file.value).slice(node.position?.start.offset, node.position?.end.offset),
16
- };
17
-
18
- return SKIP;
19
- }
20
-
21
- if ((node.type === "leafDirective" || node.type === "containerDirective") && node.data?.hName === undefined) {
22
- file.fail(`${copy_error_unknown_directive}: ${node.name}`, node);
23
- }
24
- });
25
- };