for-humanity 0.6.0 → 0.7.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 (140) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +1 -1
  3. package/README.md +3 -3
  4. package/dist/browser.js +9 -9
  5. package/dist/cli.css +25 -310
  6. package/dist/cli.js +120 -314
  7. package/package.json +4 -3
  8. package/src/asset/font/{jetbrains-mono/LICENSE → monoplex-kr/LICENSE.md} +61 -8
  9. package/src/asset/font/monoplex-kr/MonoplexKR-Regular.woff2 +0 -0
  10. package/src/asset/font/monoplex-kr/MonoplexKR-SemiBold.woff2 +0 -0
  11. package/src/asset/font/monoplex-kr/monoplex-kr.css +20 -0
  12. package/src/component/widget/navigation/_constant/navigation-data-schema.ts +0 -3
  13. package/src/component/widget/navigation/_function/to-navigation-data/_to-navigation-document.ts +2 -3
  14. package/src/component/widget/navigation/_function/to-navigation-data/_to-navigation-group.ts +3 -4
  15. package/src/component/widget/navigation/_function/to-navigation-data/to-navigation-data.ts +6 -14
  16. package/src/component/widget/navigation/_type/navigation-data.ts +0 -12
  17. package/src/component/widget/navigation/_type/navigation-focus-snapshot.ts +0 -4
  18. package/src/component/widget/navigation/_wg-navigation-nav-list.css +5 -136
  19. package/src/component/widget/navigation/_wg-navigation-nav-list.tsx +10 -55
  20. package/src/component/widget/navigation/_wg-navigation-nav.css +2 -8
  21. package/src/component/widget/navigation/_wg-navigation-nav.tsx +1 -11
  22. package/src/component/widget/navigation/_wg-navigation-toc.css +12 -207
  23. package/src/component/widget/navigation/_wg-navigation-toc.tsx +39 -80
  24. package/src/component/widget/navigation/wg-navigation.tsx +10 -69
  25. package/src/component/widget/prose/wg-prose.css +0 -3
  26. package/src/component/widget/shell/wg-shell.css +1 -1
  27. package/src/constant/copy.ts +0 -5
  28. package/src/constant/font.ts +2 -12
  29. package/src/entry/browser/browser.tsx +1 -1
  30. package/src/entry/cli/cli.test.ts +6 -8
  31. package/src/entry/cli/cli.ts +6 -18
  32. package/src/store/navigation/create-navigation-stores.test.ts +10 -28
  33. package/src/store/navigation/create-navigation-stores.ts +4 -18
  34. package/src/store/navigation/navigation-state.ts +0 -10
  35. package/src/store/navigation/navigation-storage.ts +0 -5
  36. package/src/style/token.css +11 -14
  37. package/src/util/font/to-font-css.test.ts +2 -2
  38. package/src/util/mermaid/render-flow.js +2 -2
  39. package/src/asset/font/jetbrains-mono/jetbrains-mono-latin-wght-normal.woff2 +0 -0
  40. package/src/asset/font/jetbrains-mono/jetbrains-mono.css +0 -11
  41. package/src/asset/font/pretendard/LICENSE.txt +0 -94
  42. package/src/asset/font/pretendard/pretendardvariable-dynamic-subset.css +0 -1008
  43. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.0.woff2 +0 -0
  44. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.1.woff2 +0 -0
  45. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.10.woff2 +0 -0
  46. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.11.woff2 +0 -0
  47. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.12.woff2 +0 -0
  48. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.13.woff2 +0 -0
  49. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.14.woff2 +0 -0
  50. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.15.woff2 +0 -0
  51. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.16.woff2 +0 -0
  52. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.17.woff2 +0 -0
  53. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.18.woff2 +0 -0
  54. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.19.woff2 +0 -0
  55. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.2.woff2 +0 -0
  56. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.20.woff2 +0 -0
  57. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.21.woff2 +0 -0
  58. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.22.woff2 +0 -0
  59. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.23.woff2 +0 -0
  60. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.24.woff2 +0 -0
  61. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.25.woff2 +0 -0
  62. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.26.woff2 +0 -0
  63. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.27.woff2 +0 -0
  64. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.28.woff2 +0 -0
  65. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.29.woff2 +0 -0
  66. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.3.woff2 +0 -0
  67. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.30.woff2 +0 -0
  68. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.31.woff2 +0 -0
  69. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.32.woff2 +0 -0
  70. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.33.woff2 +0 -0
  71. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.34.woff2 +0 -0
  72. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.35.woff2 +0 -0
  73. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.36.woff2 +0 -0
  74. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.37.woff2 +0 -0
  75. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.38.woff2 +0 -0
  76. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.39.woff2 +0 -0
  77. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.4.woff2 +0 -0
  78. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.40.woff2 +0 -0
  79. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.41.woff2 +0 -0
  80. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.42.woff2 +0 -0
  81. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.43.woff2 +0 -0
  82. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.44.woff2 +0 -0
  83. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.45.woff2 +0 -0
  84. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.46.woff2 +0 -0
  85. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.47.woff2 +0 -0
  86. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.48.woff2 +0 -0
  87. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.49.woff2 +0 -0
  88. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.5.woff2 +0 -0
  89. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.50.woff2 +0 -0
  90. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.51.woff2 +0 -0
  91. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.52.woff2 +0 -0
  92. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.53.woff2 +0 -0
  93. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.54.woff2 +0 -0
  94. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.55.woff2 +0 -0
  95. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.56.woff2 +0 -0
  96. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.57.woff2 +0 -0
  97. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.58.woff2 +0 -0
  98. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.59.woff2 +0 -0
  99. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.6.woff2 +0 -0
  100. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.60.woff2 +0 -0
  101. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.61.woff2 +0 -0
  102. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.62.woff2 +0 -0
  103. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.63.woff2 +0 -0
  104. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.64.woff2 +0 -0
  105. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.65.woff2 +0 -0
  106. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.66.woff2 +0 -0
  107. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.67.woff2 +0 -0
  108. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.68.woff2 +0 -0
  109. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.69.woff2 +0 -0
  110. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.7.woff2 +0 -0
  111. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.70.woff2 +0 -0
  112. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.71.woff2 +0 -0
  113. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.72.woff2 +0 -0
  114. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.73.woff2 +0 -0
  115. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.74.woff2 +0 -0
  116. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.75.woff2 +0 -0
  117. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.76.woff2 +0 -0
  118. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.77.woff2 +0 -0
  119. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.78.woff2 +0 -0
  120. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.79.woff2 +0 -0
  121. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.8.woff2 +0 -0
  122. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.80.woff2 +0 -0
  123. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.81.woff2 +0 -0
  124. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.82.woff2 +0 -0
  125. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.83.woff2 +0 -0
  126. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.84.woff2 +0 -0
  127. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.85.woff2 +0 -0
  128. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.86.woff2 +0 -0
  129. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.87.woff2 +0 -0
  130. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.88.woff2 +0 -0
  131. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.89.woff2 +0 -0
  132. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.9.woff2 +0 -0
  133. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.90.woff2 +0 -0
  134. package/src/asset/font/pretendard/woff2-dynamic-subset/PretendardVariable.subset.91.woff2 +0 -0
  135. package/src/component/widget/navigation/_function/to-navigation-branch-id.ts +0 -6
  136. package/src/component/widget/navigation/_wg-navigation-branch-toggle.css +0 -28
  137. package/src/component/widget/navigation/_wg-navigation-branch-toggle.tsx +0 -48
  138. package/src/store/navigation/_constant/tree.ts +0 -6
  139. package/src/store/navigation/to-navigation-tree-state.ts +0 -19
  140. package/src/store/navigation/use-navigation-tree-store.ts +0 -12
@@ -1,5 +1,5 @@
1
1
  /*
2
- * 와이드 화면의 오른쪽 목차 · 회색 제목·묶음과 본문 글색의 이동 대상 구분
2
+ * 와이드 화면의 오른쪽 목차 · 라벨·묶음은 문서 탐색의 묶음과 같은 표현
3
3
  */
4
4
  .wg_navigationToc__root {
5
5
  font-size: var(--app-font-size-dense);
@@ -7,166 +7,55 @@
7
7
  }
8
8
 
9
9
  .wg_navigationToc__label {
10
- margin-bottom: var(--app-space-inline);
10
+ margin: 0 0 var(--app-space-tree-label);
11
11
  color: var(--app-color-text-muted);
12
- font-size: var(--app-font-size-label);
13
- font-weight: var(--app-font-weight-strong);
14
- letter-spacing: var(--app-letter-spacing-label);
12
+ font-size: var(--app-font-size-group);
13
+ line-height: calc(var(--app-font-size-dense) * var(--app-line-height-tight));
14
+ text-box: trim-start cap alphabetic;
15
15
  }
16
16
 
17
17
  .wg_navigationToc__group {
18
- margin: 0 0 4px;
19
- padding-inline-end: calc(var(--app-size-tree-toggle) + var(--app-space-inline));
18
+ margin: 0 0 var(--app-space-tree-label);
20
19
  color: var(--app-color-text-muted);
21
20
  font-size: var(--app-font-size-group);
22
21
  line-height: calc(var(--app-font-size-dense) * var(--app-line-height-tight));
23
- }
24
-
25
- .wg_navigationToc__groupSection {
26
- /* 가름 제목과 그 하위 목록을 하나의 접힘 대상으로 연결 */
27
- position: relative;
28
- display: flow-root;
22
+ text-box: trim-start cap alphabetic;
29
23
  }
30
24
 
31
25
  .wg_navigationToc__groupSection--named {
32
- margin-top: var(--app-space-stack);
26
+ margin-top: var(--app-space-tree-group);
33
27
  }
34
28
 
35
29
  .wg_navigationToc__list {
36
- margin: 0 0 0 var(--app-space-tree-inset);
30
+ margin: 0;
37
31
  padding: 0;
38
32
  list-style: none;
39
33
  }
40
34
 
41
35
  .wg_navigationToc__link {
42
- /* 가로 가지는 링크 첫 줄 기준 · 여러 줄 제목에서도 연결 위치 유지 */
43
- position: relative;
44
36
  display: block;
45
- padding: var(--app-space-tree-row) 0 var(--app-space-tree-row) calc(var(--app-space-tree-indent) + var(--app-space-inline));
37
+ padding: var(--app-space-tree-row) 0;
46
38
  color: var(--app-color-text);
47
39
  font-size: var(--app-font-size-dense);
48
40
  line-height: var(--app-line-height-tight);
49
41
  text-decoration: none;
50
42
 
51
- &::before {
52
- position: absolute;
53
- top: calc(0.5lh + var(--app-space-tree-row));
54
- left: 0;
55
- width: var(--app-space-tree-indent);
56
- border-top: 1px solid var(--app-color-border-soft);
57
- content: "";
58
- pointer-events: none;
59
- }
60
-
61
43
  &:where(:hover) {
62
44
  color: var(--app-color-text-strong);
63
45
  text-decoration: underline;
64
46
  }
65
47
 
66
- &:where(:hover)::before {
67
- border-top-color: currentcolor;
68
- }
69
-
70
- /* 박스 대신 hover와 같은 진한 글·밑줄·가지선으로 키보드 위치 표시 */
48
+ /* 박스 대신 hover와 같은 진한 글·밑줄로 키보드 위치 표시 */
71
49
  &:where(:focus-visible) {
72
50
  outline: none;
73
51
  color: var(--app-color-text-strong);
74
52
  text-decoration: underline;
75
53
  }
76
-
77
- &:where(:focus-visible)::before {
78
- border-top-color: currentcolor;
79
- }
80
54
  }
81
55
 
82
56
  .wg_navigationToc__link--active {
83
57
  color: var(--app-color-text-strong);
84
58
  font-weight: var(--app-font-weight-active);
85
-
86
- &::before {
87
- border-top-color: currentcolor;
88
- }
89
- }
90
-
91
- .wg_navigationToc__item {
92
- /* 하위 목록의 margin을 포함해 다음 항목까지 줄기 연결 */
93
- display: flow-root;
94
-
95
- /* 세로 줄기는 항목 전체 기준 · 중간 항목의 소제목 옆에서도 연결 */
96
- position: relative;
97
-
98
- &:has(> .wg_navigationBranchToggle__root) > .wg_navigationToc__link {
99
- padding-inline-end: calc(var(--app-size-tree-toggle) + var(--app-space-inline));
100
- }
101
-
102
- &::before {
103
- position: absolute;
104
- top: 0;
105
- bottom: 0;
106
- left: 0;
107
- border-left: 1px solid var(--app-color-border-soft);
108
- content: "";
109
- pointer-events: none;
110
- }
111
-
112
- &:where(:last-child)::before {
113
- bottom: auto;
114
- height: calc(0.5lh + var(--app-space-tree-row));
115
- }
116
-
117
- /* hover·키보드 포커스의 도착점 · 첫 줄 아래는 기본 줄기 유지 */
118
- &::after {
119
- position: absolute;
120
- top: 0;
121
- left: 0;
122
- height: calc(0.5lh + var(--app-space-tree-row));
123
- border-left: 1px solid transparent;
124
- content: "";
125
- pointer-events: none;
126
- }
127
-
128
- &:where(:hover)::after {
129
- border-left-color: var(--app-color-text-strong);
130
- }
131
-
132
- &:where(:has(:focus-visible))::after {
133
- border-left-color: var(--app-color-text-strong);
134
- }
135
-
136
- /* 뒤 항목까지의 세로 경로 · 같은 목록의 형제 안에서만 연결 */
137
- &:where(:has(~ .wg_navigationToc__item:hover))::before {
138
- border-left-color: var(--app-color-text-strong);
139
- }
140
-
141
- &:where(:has(~ .wg_navigationToc__item :focus-visible))::before {
142
- border-left-color: var(--app-color-text-strong);
143
- }
144
-
145
- /* 하위 제목을 탐색할 때 상위 절의 가지도 연결 */
146
- &:where(:hover) > .wg_navigationToc__link::before {
147
- border-top-color: var(--app-color-text-strong);
148
- }
149
-
150
- &:where(:has(:focus-visible)) > .wg_navigationToc__link::before {
151
- border-top-color: var(--app-color-text-strong);
152
- }
153
- }
154
-
155
- .wg_navigationToc__item--trail {
156
- &::before {
157
- border-left-color: var(--app-color-text-strong);
158
- }
159
- }
160
-
161
- .wg_navigationToc__item--current {
162
- &::after {
163
- border-left-color: var(--app-color-text-strong);
164
- }
165
-
166
- /* 현재 소제목의 상위 절은 글 강조 없이 경로의 가로 가지 연결 */
167
- & > .wg_navigationToc__link::before {
168
- border-top-color: var(--app-color-text-strong);
169
- }
170
59
  }
171
60
 
172
61
  .wg_navigationToc__sub {
@@ -175,112 +64,28 @@
175
64
  list-style: none;
176
65
  }
177
66
 
178
- .wg_navigationToc__subItem {
179
- /* 하위 줄기는 소제목 항목 기준 · 마지막 소제목 첫 줄에서 종료 */
180
- position: relative;
181
-
182
- &::before {
183
- position: absolute;
184
- top: 0;
185
- bottom: 0;
186
- left: 0;
187
- border-left: 1px solid var(--app-color-border-soft);
188
- content: "";
189
- pointer-events: none;
190
- }
191
-
192
- &:where(:last-child)::before {
193
- bottom: auto;
194
- height: calc(0.5lh + var(--app-space-tree-row));
195
- }
196
-
197
- /* hover·키보드 포커스의 도착점 · 첫 줄 아래는 기본 줄기 유지 */
198
- &::after {
199
- position: absolute;
200
- top: 0;
201
- left: 0;
202
- height: calc(0.5lh + var(--app-space-tree-row));
203
- border-left: 1px solid transparent;
204
- content: "";
205
- pointer-events: none;
206
- }
207
-
208
- &:where(:hover)::after {
209
- border-left-color: var(--app-color-text-strong);
210
- }
211
-
212
- &:where(:has(:focus-visible))::after {
213
- border-left-color: var(--app-color-text-strong);
214
- }
215
-
216
- /* 뒤 항목까지의 세로 경로 · 같은 목록의 형제 안에서만 연결 */
217
- &:where(:has(~ .wg_navigationToc__subItem:hover))::before {
218
- border-left-color: var(--app-color-text-strong);
219
- }
220
-
221
- &:where(:has(~ .wg_navigationToc__subItem :focus-visible))::before {
222
- border-left-color: var(--app-color-text-strong);
223
- }
224
- }
225
-
226
- .wg_navigationToc__subItem--trail {
227
- &::before {
228
- border-left-color: var(--app-color-text-strong);
229
- }
230
- }
231
-
232
- .wg_navigationToc__subItem--current {
233
- &::after {
234
- border-left-color: var(--app-color-text-strong);
235
- }
236
- }
237
-
238
67
  .wg_navigationToc__subLink {
239
- /* 하위 가지도 링크 첫 줄 기준 · 줄바꿈된 제목 옆으로 선이 늘어나지 않음 */
240
- position: relative;
241
68
  display: block;
242
- padding: var(--app-space-tree-row) 0 var(--app-space-tree-row) calc(var(--app-space-tree-indent) + var(--app-space-inline));
69
+ padding: var(--app-space-tree-row) 0;
243
70
  color: var(--app-color-text);
244
71
  font-size: var(--app-font-size-detail);
245
72
  line-height: var(--app-line-height-tight);
246
73
  text-decoration: none;
247
74
 
248
- &::before {
249
- position: absolute;
250
- top: calc(0.5lh + var(--app-space-tree-row));
251
- left: 0;
252
- width: var(--app-space-tree-indent);
253
- border-top: 1px solid var(--app-color-border-soft);
254
- content: "";
255
- pointer-events: none;
256
- }
257
-
258
75
  &:where(:hover) {
259
76
  color: var(--app-color-text-strong);
260
77
  text-decoration: underline;
261
78
  }
262
79
 
263
- &:where(:hover)::before {
264
- border-top-color: currentcolor;
265
- }
266
-
267
80
  /* 상위 목차와 같은 키보드 표현 */
268
81
  &:where(:focus-visible) {
269
82
  outline: none;
270
83
  color: var(--app-color-text-strong);
271
84
  text-decoration: underline;
272
85
  }
273
-
274
- &:where(:focus-visible)::before {
275
- border-top-color: currentcolor;
276
- }
277
86
  }
278
87
 
279
88
  .wg_navigationToc__subLink--active {
280
89
  color: var(--app-color-text-strong);
281
90
  font-weight: var(--app-font-weight-active);
282
-
283
- &::before {
284
- border-top-color: currentcolor;
285
- }
286
91
  }
@@ -1,33 +1,19 @@
1
1
  import clsx from "clsx";
2
2
  import {useLayoutEffect, useState} from "hono/jsx";
3
3
  import {reading_line_slack_px} from "@/component/widget/navigation/_constant/reading-line";
4
- import {toNavigationBranchId} from "@/component/widget/navigation/_function/to-navigation-branch-id";
5
4
  import type {TocGroup} from "@/component/widget/navigation/_type/toc-group";
6
- import {WgNavigationBranchToggle} from "@/component/widget/navigation/_wg-navigation-branch-toggle";
7
5
  import {copy_nav_toc_label} from "@/constant/copy";
8
6
  import {findHashTarget} from "@/util/dom/find-hash-target";
9
7
  import "./_wg-navigation-toc.css";
10
8
 
11
9
  /**
12
- * 현재 문서의 목차 · 읽는 제목 한 항목과 조상 트리선 구분
10
+ * 현재 문서의 목차 · 읽는 제목 한 항목만 강조
13
11
  */
14
12
  export interface WgNavigationTocProps {
15
13
  /**
16
14
  * 본문 순서의 가름·절·소제목
17
15
  */
18
16
  groups: TocGroup[];
19
- /**
20
- * 문서별 접힘 상태의 키
21
- */
22
- pageId: string;
23
- /**
24
- * 사용자가 접은 가지
25
- */
26
- collapsed: Record<string, boolean>;
27
- /**
28
- * 브라우저에서만 제공하는 가지 변경 동작
29
- */
30
- onToggle?: (key: string) => void;
31
17
  }
32
18
 
33
19
  export const WgNavigationToc = (props: WgNavigationTocProps) => {
@@ -85,71 +71,44 @@ export const WgNavigationToc = (props: WgNavigationTocProps) => {
85
71
  {/**
86
72
  * 가름별 제목 이동 · 하위 제목이 현재 위치여도 부모 글씨는 강조하지 않음
87
73
  */}
88
- {props.groups.map((group) => {
89
- const currentIndex = group.sections.findIndex((section) => section.heading.slug === currentSlug || section.subs.some((sub) => sub.heading.slug === currentSlug));
90
- const partKey = `outline:${props.pageId}:part:${group.sections[0].heading.slug}`;
91
- return (
92
- <div
93
- className={clsx("wg_navigationToc__groupSection", {"wg_navigationToc__groupSection--named": group.part !== undefined})}
94
- key={group.sections[0].heading.slug}
95
- >
96
- {group.part !== undefined && <div className={clsx("wg_navigationToc__group")}>{group.part}</div>}
97
- {group.part !== undefined && <WgNavigationBranchToggle branchKey={partKey} label={group.part} collapsed={props.collapsed} onToggle={props.onToggle} />}
98
- <ul className={clsx("wg_navigationToc__list")} id={toNavigationBranchId(partKey)} hidden={props.collapsed[partKey] === true}>
99
- {group.sections.map((section, index) => {
100
- const currentSubIndex = section.subs.findIndex((sub) => sub.heading.slug === currentSlug);
101
- const sectionKey = `outline:${props.pageId}:heading:${section.heading.slug}`;
102
- return (
103
- <li
104
- className={clsx("wg_navigationToc__item", {
105
- "wg_navigationToc__item--trail": index < currentIndex,
106
- "wg_navigationToc__item--current": index === currentIndex,
107
- })}
108
- key={section.heading.slug}
109
- >
110
- <a
111
- className={clsx("wg_navigationToc__link", {"wg_navigationToc__link--active": section.heading.slug === currentSlug})}
112
- href={`#${section.heading.slug}`}
113
- data-toc-link=""
114
- aria-current={section.heading.slug === currentSlug ? "location" : undefined}
115
- >
116
- {section.heading.text}
117
- </a>
118
- {section.subs.length > 0 && (
119
- <WgNavigationBranchToggle branchKey={sectionKey} label={section.heading.text} collapsed={props.collapsed} onToggle={props.onToggle} />
120
- )}
121
- {/**
122
- * 조상과 이전 형제의 트리선은 연결 · 활성 링크는 한 제목만
123
- */}
124
- {section.subs.length > 0 && (
125
- <ul className={clsx("wg_navigationToc__sub")} id={toNavigationBranchId(sectionKey)} hidden={props.collapsed[sectionKey] === true}>
126
- {section.subs.map((sub, subIndex) => (
127
- <li
128
- className={clsx("wg_navigationToc__subItem", {
129
- "wg_navigationToc__subItem--trail": subIndex < currentSubIndex,
130
- "wg_navigationToc__subItem--current": subIndex === currentSubIndex,
131
- })}
132
- key={sub.heading.slug}
133
- >
134
- <a
135
- className={clsx("wg_navigationToc__subLink", {"wg_navigationToc__subLink--active": sub.heading.slug === currentSlug})}
136
- href={`#${sub.heading.slug}`}
137
- data-toc-sub-link=""
138
- aria-current={sub.heading.slug === currentSlug ? "location" : undefined}
139
- >
140
- {sub.heading.text}
141
- </a>
142
- </li>
143
- ))}
144
- </ul>
145
- )}
146
- </li>
147
- );
148
- })}
149
- </ul>
150
- </div>
151
- );
152
- })}
74
+ {props.groups.map((group) => (
75
+ <div className={clsx("wg_navigationToc__groupSection", {"wg_navigationToc__groupSection--named": group.part !== undefined})} key={group.sections[0].heading.slug}>
76
+ {group.part !== undefined && <div className={clsx("wg_navigationToc__group")}>{group.part}</div>}
77
+ <ul className={clsx("wg_navigationToc__list")}>
78
+ {group.sections.map((section) => (
79
+ <li className={clsx("wg_navigationToc__item")} key={section.heading.slug}>
80
+ <a
81
+ className={clsx("wg_navigationToc__link", {"wg_navigationToc__link--active": section.heading.slug === currentSlug})}
82
+ href={`#${section.heading.slug}`}
83
+ data-toc-link=""
84
+ aria-current={section.heading.slug === currentSlug ? "location" : undefined}
85
+ >
86
+ {section.heading.text}
87
+ </a>
88
+ {/**
89
+ * 하위 제목 · 활성 링크는 한 제목만
90
+ */}
91
+ {section.subs.length > 0 && (
92
+ <ul className={clsx("wg_navigationToc__sub")}>
93
+ {section.subs.map((sub) => (
94
+ <li className={clsx("wg_navigationToc__subItem")} key={sub.heading.slug}>
95
+ <a
96
+ className={clsx("wg_navigationToc__subLink", {"wg_navigationToc__subLink--active": sub.heading.slug === currentSlug})}
97
+ href={`#${sub.heading.slug}`}
98
+ data-toc-sub-link=""
99
+ aria-current={sub.heading.slug === currentSlug ? "location" : undefined}
100
+ >
101
+ {sub.heading.text}
102
+ </a>
103
+ </li>
104
+ ))}
105
+ </ul>
106
+ )}
107
+ </li>
108
+ ))}
109
+ </ul>
110
+ </div>
111
+ ))}
153
112
  </nav>
154
113
  );
155
114
  };
@@ -10,10 +10,9 @@ import {WgNavigationScroll} from "@/component/widget/navigation/_wg-navigation-s
10
10
  import {WgNavigationToc} from "@/component/widget/navigation/_wg-navigation-toc";
11
11
  import {copy_nav_close, copy_nav_open, copy_nav_title} from "@/constant/copy";
12
12
  import type {createNavigationStores} from "@/store/navigation/create-navigation-stores";
13
- import type {NavigationLayout, NavigationPosition, NavigationTreeState} from "@/store/navigation/navigation-state";
14
- import {navigation_scroll_storage_key, navigation_storage_version, navigation_tree_storage_key} from "@/store/navigation/navigation-storage";
13
+ import type {NavigationLayout, NavigationPosition} from "@/store/navigation/navigation-state";
14
+ import {navigation_scroll_storage_key, navigation_storage_version} from "@/store/navigation/navigation-storage";
15
15
  import {toNavigationScrollState} from "@/store/navigation/to-navigation-scroll-state";
16
- import {useNavigationTreeStore} from "@/store/navigation/use-navigation-tree-store";
17
16
  import {revealHashTarget} from "@/util/dom/reveal-hash-target";
18
17
  import "./wg-navigation.css";
19
18
 
@@ -32,7 +31,6 @@ export interface WgNavigationProps {
32
31
  }
33
32
 
34
33
  export const WgNavigation = (props: WgNavigationProps) => {
35
- const navigationTreeStore = useNavigationTreeStore(props.stores?.tree);
36
34
  const [layout, setLayout] = useState<NavigationLayout>(() => {
37
35
  if (props.stores === undefined) return "desktop";
38
36
  if (matchMedia(navigation_mobile_query).matches) return "drawer";
@@ -77,7 +75,7 @@ export const WgNavigation = (props: WgNavigationProps) => {
77
75
  };
78
76
 
79
77
  /**
80
- * 접힘과 무관한 모든 링크의 URL·표시명으로 사이트 공통 문서 목록의 동일성 판정
78
+ * 모든 링크의 URL·표시명으로 사이트 공통 문서 목록의 동일성 판정
81
79
  */
82
80
  const getNavigationSignature = () => {
83
81
  const navigation = getNavigationPort();
@@ -144,13 +142,6 @@ export const WgNavigation = (props: WgNavigationProps) => {
144
142
  outlineRef.current.dispatchEvent(new Event("scroll"));
145
143
  };
146
144
 
147
- /**
148
- * 선택 순간의 최신 스토어로 반전 · 직접 클릭과 다른 탭의 선택을 같은 자료로 유지
149
- */
150
- const handleBranchToggle = (key: string) => {
151
- props.stores?.tree.setState((state) => ({collapsed: {...state.collapsed, [key]: state.collapsed[key] !== true}}));
152
- };
153
-
154
145
  /**
155
146
  * 네이티브 close가 이전 열기 이벤트보다 늦게 도착해도 새 모달을 잠금 해제하지 않음
156
147
  */
@@ -241,7 +232,6 @@ export const WgNavigation = (props: WgNavigationProps) => {
241
232
  focusRef.current = {
242
233
  navigation: document.activeElement.closest("[data-navigation]") !== null,
243
234
  drawer: document.activeElement === openButtonRef.current || document.activeElement.closest("[data-navigation-drawer]") !== null,
244
- branch: document.activeElement.getAttribute("data-navigation-toggle"),
245
235
  href: document.activeElement.getAttribute("href"),
246
236
  };
247
237
  }
@@ -252,42 +242,16 @@ export const WgNavigation = (props: WgNavigationProps) => {
252
242
  };
253
243
 
254
244
  /**
255
- * BFCache의 이전 메모리가 다음 문서의 선택·좌표를 덮지 않도록 렌더까지 동기 갱신 후 복원
245
+ * BFCache의 이전 메모리가 다음 문서의 좌표를 덮지 않도록 렌더까지 동기 갱신 후 복원
256
246
  */
257
247
  const handlePageShow = (event: PageTransitionEvent) => {
258
248
  if (!event.persisted || props.stores === undefined) return;
259
249
  restorePendingRef.current = true;
260
- flushSync(() => {
261
- props.stores?.tree.persist.rehydrate();
262
- props.stores?.scroll.persist.rehydrate();
263
- });
250
+ flushSync(() => props.stores?.scroll.persist.rehydrate());
264
251
  handleLayoutChange();
265
252
  restoreScroll();
266
253
  };
267
254
 
268
- /**
269
- * 같은 origin의 다른 탭에서 바꾼 접힘 선택과 저장소 초기화 반영
270
- */
271
- const handleStorageChange = (event: StorageEvent) => {
272
- if (event.key === navigation_tree_storage_key || event.key === null) {
273
- flushSync(() => props.stores?.tree.persist.rehydrate());
274
- }
275
- };
276
-
277
- /**
278
- * 다른 탭·BFCache의 선택이 현재 키보드 위치를 숨기기 전에 가장 바깥 접힘 버튼으로 복원
279
- */
280
- const handleTreeChange = (state: NavigationTreeState) => {
281
- if (!(document.activeElement instanceof HTMLElement)) return;
282
- for (const button of document.querySelectorAll<HTMLButtonElement>("[data-navigation-toggle]")) {
283
- const key = button.dataset.navigationToggle;
284
- const controls = button.getAttribute("aria-controls");
285
- if (key === undefined || controls === null || state.collapsed[key] !== true) continue;
286
- const branch = document.getElementById(controls);
287
- if (branch?.contains(document.activeElement)) button.focus({preventScroll: true});
288
- }
289
- };
290
-
291
255
  /**
292
256
  * Hono 탐색이 전역 구독의 설치·정리를 소유 · 서버 렌더에서는 실행하지 않음
293
257
  */
@@ -299,8 +263,6 @@ export const WgNavigation = (props: WgNavigationProps) => {
299
263
  wideRef.current.addEventListener("change", handleLayoutChange);
300
264
  addEventListener("pagehide", saveScroll);
301
265
  addEventListener("pageshow", handlePageShow);
302
- addEventListener("storage", handleStorageChange);
303
- const unsubscribeTree = props.stores.tree.subscribe(handleTreeChange);
304
266
  return () => {
305
267
  mobileRef.current?.removeEventListener("change", handleLayoutChange);
306
268
  wideRef.current?.removeEventListener("change", handleLayoutChange);
@@ -308,8 +270,6 @@ export const WgNavigation = (props: WgNavigationProps) => {
308
270
  wideRef.current = null;
309
271
  removeEventListener("pagehide", saveScroll);
310
272
  removeEventListener("pageshow", handlePageShow);
311
- removeEventListener("storage", handleStorageChange);
312
- unsubscribeTree();
313
273
  document.body.classList.remove("wg_shell__root--drawerOpen");
314
274
  };
315
275
  }, [props.stores]);
@@ -328,12 +288,8 @@ export const WgNavigation = (props: WgNavigationProps) => {
328
288
  if (layout === "drawer") {
329
289
  if (focusRef.current.navigation) openButtonRef.current?.focus({preventScroll: true});
330
290
  } else if (focusRef.current.navigation && navigation !== null) {
331
- const target = [...navigation.querySelectorAll<HTMLElement>("a[href], button")].find((element) => {
332
- if (focusRef.current === null) return false;
333
- return focusRef.current.branch !== null
334
- ? element.getAttribute("data-navigation-toggle") === focusRef.current.branch
335
- : focusRef.current.href !== null && element.getAttribute("href") === focusRef.current.href;
336
- });
291
+ const href = focusRef.current.href;
292
+ const target = [...navigation.querySelectorAll<HTMLElement>("a[href]")].find((element) => element.getAttribute("href") === href);
337
293
  target?.focus({preventScroll: true});
338
294
  } else if (focusRef.current.drawer) {
339
295
  brandRef.current?.focus({preventScroll: true});
@@ -393,11 +349,7 @@ export const WgNavigation = (props: WgNavigationProps) => {
393
349
  {layout !== "drawer" && (
394
350
  <div ref={props.stores === undefined ? undefined : navigationRef} className={clsx("wg_navigation__navigation")} data-navigation="">
395
351
  <WgNavigationScroll portRef={documentsRef} kind="documents" ready={props.stores !== undefined} onScroll={saveScroll} onClick={handleNavigationClick}>
396
- <WgNavigationNav
397
- groups={props.data.groups}
398
- collapsed={navigationTreeStore.collapsed}
399
- onToggle={props.stores === undefined ? undefined : handleBranchToggle}
400
- />
352
+ <WgNavigationNav groups={props.data.groups} />
401
353
  </WgNavigationScroll>
402
354
  </div>
403
355
  )}
@@ -408,14 +360,7 @@ export const WgNavigation = (props: WgNavigationProps) => {
408
360
  <aside className={clsx("wg_navigation__tocRail")} data-navigation-rail="">
409
361
  <div className={clsx("wg_navigation__outline")} data-navigation-outline="">
410
362
  <WgNavigationScroll portRef={outlineRef} kind="outline" ready={props.stores !== undefined} onScroll={saveScroll} onClick={handleNavigationClick}>
411
- {props.data.outline.length > 0 && (
412
- <WgNavigationToc
413
- groups={props.data.outline}
414
- pageId={props.data.pageId}
415
- collapsed={navigationTreeStore.collapsed}
416
- onToggle={props.stores === undefined ? undefined : handleBranchToggle}
417
- />
418
- )}
363
+ {props.data.outline.length > 0 && <WgNavigationToc groups={props.data.outline} />}
419
364
  </WgNavigationScroll>
420
365
  </div>
421
366
  </aside>
@@ -464,11 +409,7 @@ export const WgNavigation = (props: WgNavigationProps) => {
464
409
  onScroll={saveScroll}
465
410
  onClick={handleNavigationClick}
466
411
  >
467
- <WgNavigationNav
468
- groups={props.data.groups}
469
- collapsed={navigationTreeStore.collapsed}
470
- onToggle={props.stores === undefined ? undefined : handleBranchToggle}
471
- />
412
+ <WgNavigationNav groups={props.data.groups} />
472
413
  </WgNavigationScroll>
473
414
  </div>
474
415
  )}
@@ -130,7 +130,6 @@
130
130
  margin: 4px 0 0;
131
131
  }
132
132
 
133
- /* JetBrains Mono 합자 비활성 · >=, != 원문 구분 */
134
133
  & code {
135
134
  padding: 1px 3px;
136
135
  border-radius: var(--app-radius-inline);
@@ -138,7 +137,6 @@
138
137
  color: var(--app-color-text-strong);
139
138
  font-family: var(--app-font-mono);
140
139
  font-size: 1em;
141
- font-variant-ligatures: none;
142
140
  }
143
141
 
144
142
  /* 코드 블록 · Shiki의 --app-code-* 참조 */
@@ -151,7 +149,6 @@
151
149
  background: var(--app-color-code);
152
150
  font-family: var(--app-font-mono);
153
151
  font-size: var(--app-font-size-detail);
154
- font-variant-ligatures: none;
155
152
  line-height: var(--app-line-height-code);
156
153
  }
157
154
 
@@ -12,7 +12,7 @@
12
12
  );
13
13
  background: var(--app-color-ground);
14
14
  color: var(--app-color-text);
15
- font-family: var(--app-font-sans);
15
+ font-family: var(--app-font-mono);
16
16
  font-size: var(--app-font-size-body);
17
17
  line-height: var(--app-line-height-body);
18
18
 
@@ -47,11 +47,6 @@ export const copy_error_home_clash = "홈 README가 겹친다";
47
47
  */
48
48
  export const copy_error_prefix = "for-humanity";
49
49
 
50
- /**
51
- * 내장 본문 글꼴의 공통 조각이 누락된 패키지 오류
52
- */
53
- export const copy_error_font_preload = "Missing bundled font for preload";
54
-
55
50
  /**
56
51
  * 미지원 명령 오류
57
52
  */