for-humanity 0.2.0 → 0.3.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.
@@ -1,4 +1,5 @@
1
- import {locale_doc_group, locale_doc_name} from "@/constant/locale";
1
+ import {locale_doc_group} from "@/constant/locale";
2
+ import {toDocBranches} from "@/content/to-doc-groups/_to-doc-branches";
2
3
  import type {Doc} from "@/type/doc";
3
4
  import type {DocGroup} from "@/type/doc-group";
4
5
 
@@ -10,6 +11,10 @@ interface DocGroupBranchesOptions {
10
11
  * 부모 경로에 속한 문서
11
12
  */
12
13
  docs: readonly Doc[];
14
+ /**
15
+ * 검증된 부모 id별 문서 · 자손을 각 단계에서 다시 수집하지 않음
16
+ */
17
+ children: ReadonlyMap<Doc["data"]["parent"], Doc[]>;
13
18
  /**
14
19
  * 부모까지의 경로 · 최상위는 빈 배열
15
20
  */
@@ -49,10 +54,17 @@ export const toDocGroupBranches = (options: DocGroupBranchesOptions): DocGroup[]
49
54
  return {
50
55
  name: group.name,
51
56
  path: group.path,
52
- docs: group.docs
53
- .filter((doc) => doc.data.group.length === group.path.length)
54
- .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)),
55
- groups: toDocGroupBranches({docs: group.docs, path: group.path, positions: options.positions, unlistedPosition: options.unlistedPosition}),
57
+ docs: toDocBranches({
58
+ docs: group.docs.filter((doc) => doc.data.group.length === group.path.length && doc.data.parent === undefined),
59
+ children: options.children,
60
+ }),
61
+ groups: toDocGroupBranches({
62
+ docs: group.docs,
63
+ children: options.children,
64
+ path: group.path,
65
+ positions: options.positions,
66
+ unlistedPosition: options.unlistedPosition,
67
+ }),
56
68
  };
57
69
  });
58
70
  };
@@ -10,5 +10,6 @@ export const toDocGroups = (options: {docs: readonly Doc[]; navigation: SiteConf
10
10
  // 같은 조상을 지정한 경로는 최초 navigation 위치를 우선
11
11
  const positions = new Map(options.navigation.flatMap((path, index) => path.map((_name, depth) => [JSON.stringify(path.slice(0, depth + 1)), index] as const)).toReversed());
12
12
 
13
- return toDocGroupBranches({docs: options.docs, path: [], positions, unlistedPosition: options.navigation.length});
13
+ const children = Map.groupBy(options.docs, (doc) => doc.data.parent);
14
+ return toDocGroupBranches({docs: options.docs, children, path: [], positions, unlistedPosition: options.navigation.length});
14
15
  };
@@ -55,7 +55,8 @@
55
55
  --app-font-mono: "JetBrains Mono Variable", var(--app-font-sans);
56
56
  --app-font-brand: "Architects Daughter", var(--app-font-sans);
57
57
 
58
- /* 글자 크기 · 12px 기본과 역할별 제목 크기 */
58
+ /* 글자 크기 · 11px 비상호작용 묶음 · 12px 기본과 역할별 제목 크기 */
59
+ --app-font-size-group: 11px;
59
60
  --app-font-size-label: 12px;
60
61
  --app-font-size-detail: 12px;
61
62
  --app-font-size-dense: 12px;
@@ -65,9 +66,9 @@
65
66
  --app-font-size-section: 14px;
66
67
  --app-font-size-title: 16px;
67
68
 
68
- /* 굵기 · 기본 400 · 현재 위치 500 · 제목·강조 600 */
69
+ /* 굵기 · 기본 400 · 현재 위치·제목·강조 600 */
69
70
  --app-font-weight-mark: 400;
70
- --app-font-weight-active: 500;
71
+ --app-font-weight-active: 600;
71
72
  --app-font-weight-strong: 600;
72
73
  --app-font-weight-title: 600;
73
74
 
@@ -0,0 +1,11 @@
1
+ import type {Doc} from "@/type/doc";
2
+
3
+ /**
4
+ * 문서 탐색의 클릭 가능한 가지 · 원래 URL과 본문을 유지
5
+ */
6
+ export interface DocBranch extends Doc {
7
+ /**
8
+ * 같은 부모 아래의 문서 · order·제목·id 순, 말단 문서는 생략
9
+ */
10
+ children?: DocBranch[];
11
+ }
@@ -22,6 +22,10 @@ export const docDataSchema = z.object({
22
22
  * 사이드바의 문서 묶음 경로 · 문자열도 배열로 정규화
23
23
  */
24
24
  group: groupPathSchema,
25
+ /**
26
+ * 같은 묶음 안의 부모 문서 id · 확장자 제외, ./·../ 상대 경로도 허용
27
+ */
28
+ parent: z.string().trim().min(1).optional(),
25
29
  /**
26
30
  * 묶음 안의 읽는 순서 · 미지정 문서는 뒤에서 이름순
27
31
  */
@@ -1,4 +1,5 @@
1
1
  import type {Doc} from "@/type/doc";
2
+ import type {DocBranch} from "@/type/doc-branch";
2
3
 
3
4
  /**
4
5
  * 사이드바의 문서 묶음 · 같은 이름도 전체 경로로 구분
@@ -13,9 +14,9 @@ export interface DocGroup {
13
14
  */
14
15
  path: Doc["data"]["group"];
15
16
  /**
16
- * 현재 묶음에 직접 속한 문서 · order·제목·id 순
17
+ * 현재 묶음의 부모 없는 문서 · 하위 문서는 각 문서 가지에 포함
17
18
  */
18
- docs: Doc[];
19
+ docs: DocBranch[];
19
20
  /**
20
21
  * 현재 묶음의 하위 묶음 · navigation·이름 순
21
22
  */
package/src/type/doc.ts CHANGED
@@ -13,4 +13,8 @@ export interface Doc extends DocContent {
13
13
  * 검증된 머리말
14
14
  */
15
15
  data: DocData;
16
+ /**
17
+ * 검증된 부모 문서 경로 · 최상위부터 직접 부모까지, 자신은 제외
18
+ */
19
+ ancestors: string[];
16
20
  }
@@ -2,6 +2,14 @@
2
2
  * 모든 페이지가 공유하는 HTML 머리 자원
3
3
  */
4
4
  export interface SiteAssets {
5
+ /**
6
+ * 내용 지문으로 구분한 스타일시트 URL
7
+ */
8
+ stylePath: string;
9
+ /**
10
+ * 내용 지문으로 구분한 브라우저 스크립트 URL
11
+ */
12
+ clientPath: string;
5
13
  /**
6
14
  * 내장 @font-face · head의 style 내용
7
15
  */
@@ -0,0 +1,26 @@
1
+ import {createHash} from "node:crypto";
2
+ import {readFileSync} from "node:fs";
3
+ import {posix} from "node:path";
4
+
5
+ /**
6
+ * 파일 내용으로 자원 URL을 구분하는 입력
7
+ */
8
+ export interface AssetPathOptions {
9
+ /**
10
+ * 사이트 루트 기준 기본 자원 경로
11
+ */
12
+ path: string;
13
+ /**
14
+ * 배포할 실제 파일 경로
15
+ */
16
+ file: string;
17
+ }
18
+
19
+ /**
20
+ * 파일명에 내용 지문 추가 · 같은 내용은 같은 URL, 변경한 내용은 새 캐시 키 사용
21
+ */
22
+ export const toAssetPath = (options: AssetPathOptions) => {
23
+ const extension = posix.extname(options.path);
24
+
25
+ return `${posix.dirname(options.path)}/${posix.basename(options.path, extension)}.${createHash("sha256").update(readFileSync(options.file)).digest("hex")}${extension}`;
26
+ };