for-humanity 0.13.0 → 0.14.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 +22 -0
- package/README.md +41 -66
- package/dist/browser.js +4 -6
- package/dist/cli.css +1 -1
- package/dist/cli.js +6 -6
- package/dist/config.js +1 -1
- package/dist/constant/site.d.ts +8 -0
- package/dist/{load-site-CbpLEhwu.js → load-site-CBJGMNfH.js} +388 -252
- package/dist/{run-site-command-C80YoNOe.js → run-site-command-DPG5RNIN.js} +40 -17
- package/dist/{site-config-bllORGpm.js → site-config-FmStUQ2W.js} +44 -0
- package/dist/site.js +1 -1
- package/dist/{start-dev-server-C4_Lu1nZ.js → start-dev-server-x7Ja5uwv.js} +12 -4
- package/dist/type/content-config.d.ts +9 -0
- package/dist/type/site-config.d.ts +9 -0
- package/package.json +4 -3
- package/template/content/README.md +5 -0
- package/template/content/asset/.gitkeep +0 -0
- package/template/content/private/.gitkeep +0 -0
- package/template/content/public/getting-started.md +26 -0
- package/template/for-humanity.config.ts +8 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { d as copy_error_missing_build, n as copy_error_config } from "./copy-C1uzvEnr.js";
|
|
2
2
|
import { t as logger } from "./logger-Dv1i9xSV.js";
|
|
3
|
-
import { n as site_config_absent, t as siteConfigSchema } from "./site-config-
|
|
4
|
-
import { n as font_cache_control, r as asset_font_dir, t as loadSite } from "./load-site-
|
|
3
|
+
import { n as site_config_absent, t as siteConfigSchema } from "./site-config-FmStUQ2W.js";
|
|
4
|
+
import { n as font_cache_control, r as asset_font_dir, t as loadSite } from "./load-site-CBJGMNfH.js";
|
|
5
5
|
import { n as config_file_names, t as toErrorMessage } from "./to-error-message-pF6_7wGK.js";
|
|
6
6
|
import { copyFile, mkdir, rm, writeFile } from "node:fs/promises";
|
|
7
7
|
import { z } from "zod";
|
|
8
|
-
import { existsSync } from "node:fs";
|
|
9
|
-
import { dirname, join, relative, resolve } from "node:path";
|
|
8
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
9
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
10
10
|
import { toSSG } from "hono/ssg";
|
|
11
11
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
12
12
|
import { createJiti } from "jiti";
|
|
13
13
|
//#region src/app/_function/read-site-config.ts
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* 프로젝트 루트의 설정 조회, TypeScript 실행과 스키마 검증
|
|
16
16
|
*
|
|
17
17
|
* - 중복 파일 거부, 실제 적용되는 설정의 모호성 방지
|
|
18
18
|
* - Node의 기본 TypeScript 지원 여부와 무관하게 같은 설정 실행
|
|
@@ -31,6 +31,29 @@ var readSiteConfig = async (root) => {
|
|
|
31
31
|
return parsed.data.default;
|
|
32
32
|
};
|
|
33
33
|
//#endregion
|
|
34
|
+
//#region src/app/_function/read-project.ts
|
|
35
|
+
/**
|
|
36
|
+
* 프로젝트 설정과 문서 루트 해소, 외부·시스템 폴더 symlink 거부
|
|
37
|
+
*/
|
|
38
|
+
var readProject = async (directory) => {
|
|
39
|
+
const projectRoot = realpathSync(resolve(directory));
|
|
40
|
+
const site = await readSiteConfig(projectRoot);
|
|
41
|
+
const root = resolve(projectRoot, site.content.root);
|
|
42
|
+
if (existsSync(root)) {
|
|
43
|
+
const location = relative(projectRoot, realpathSync(root));
|
|
44
|
+
if (location === ".." || location.startsWith(`..${sep}`) || isAbsolute(location)) throw new Error(`content 루트는 프로젝트 내부여야 합니다: ${root}`);
|
|
45
|
+
if (location.split(sep).some((part) => [
|
|
46
|
+
"dist",
|
|
47
|
+
".git",
|
|
48
|
+
"node_modules"
|
|
49
|
+
].includes(part.toLowerCase()))) throw new Error(`content 루트는 dist, .git, node_modules 내부일 수 없습니다: ${root}`);
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
root,
|
|
53
|
+
site
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
//#endregion
|
|
34
57
|
//#region src/entry/preview/to-preview-config.ts
|
|
35
58
|
/**
|
|
36
59
|
* 빌드된 사이트 전용 Vite 설정. 소비 프로젝트의 설정과 환경 파일 자동 로드 제외
|
|
@@ -75,31 +98,31 @@ var toPreviewConfig = (params) => {
|
|
|
75
98
|
*/
|
|
76
99
|
var runSiteCommand = async (params) => {
|
|
77
100
|
try {
|
|
78
|
-
if (params.args._.length > 1) throw new Error("
|
|
101
|
+
if (params.args._.length > 1) throw new Error("프로젝트 폴더는 하나만 지정하세요");
|
|
79
102
|
const kitRoot = fileURLToPath(new URL("../", import.meta.url));
|
|
80
|
-
const
|
|
81
|
-
const outDir = join(
|
|
82
|
-
const siteConfig = await readSiteConfig(docsRoot);
|
|
103
|
+
const project = await readProject(params.args.dir);
|
|
104
|
+
const outDir = join(project.root, "dist");
|
|
83
105
|
if (params.command === "preview") {
|
|
84
106
|
(await (await import("vite")).preview(toPreviewConfig({
|
|
85
|
-
root:
|
|
86
|
-
port:
|
|
107
|
+
root: project.root,
|
|
108
|
+
port: project.site.port
|
|
87
109
|
}))).printUrls();
|
|
88
110
|
return;
|
|
89
111
|
}
|
|
90
112
|
if (params.command === "dev") {
|
|
91
|
-
await (await import("./start-dev-server-
|
|
92
|
-
root:
|
|
113
|
+
await (await import("./start-dev-server-x7Ja5uwv.js")).startDevServer({
|
|
114
|
+
root: project.root,
|
|
93
115
|
kitRoot,
|
|
94
|
-
site:
|
|
95
|
-
source: false
|
|
116
|
+
site: project.site,
|
|
117
|
+
source: false,
|
|
118
|
+
includePrivate: true
|
|
96
119
|
});
|
|
97
120
|
return;
|
|
98
121
|
}
|
|
99
122
|
const snapshot = await loadSite({
|
|
100
|
-
root:
|
|
123
|
+
root: project.root,
|
|
101
124
|
kitRoot,
|
|
102
|
-
site:
|
|
125
|
+
site: project.site
|
|
103
126
|
});
|
|
104
127
|
await rm(outDir, {
|
|
105
128
|
recursive: true,
|
|
@@ -18,6 +18,14 @@ var site_port_default = 4321;
|
|
|
18
18
|
* 포트 번호 상한. TCP
|
|
19
19
|
*/
|
|
20
20
|
var site_port_max = 65535;
|
|
21
|
+
/**
|
|
22
|
+
* 기본 문서 루트와 공개 범위 폴더
|
|
23
|
+
*/
|
|
24
|
+
var content_default = {
|
|
25
|
+
root: "content",
|
|
26
|
+
public: "public",
|
|
27
|
+
private: "private"
|
|
28
|
+
};
|
|
21
29
|
//#endregion
|
|
22
30
|
//#region src/constant/status.ts
|
|
23
31
|
/**
|
|
@@ -39,11 +47,47 @@ var status_default_phrases = [{
|
|
|
39
47
|
kind: status_kind.unverified
|
|
40
48
|
}];
|
|
41
49
|
//#endregion
|
|
50
|
+
//#region src/type/content-config.ts
|
|
51
|
+
/**
|
|
52
|
+
* 프로젝트 내부의 상대 경로, 출력 폴더와 시스템 폴더 제외
|
|
53
|
+
*/
|
|
54
|
+
var contentPathSchema = z.string().trim().min(1).refine((value) => !/^[\\/]|[:?#%*\p{Cc}]/u.test(value) && !value.split(/[\\/]/).some((part) => [
|
|
55
|
+
"..",
|
|
56
|
+
"dist",
|
|
57
|
+
"node_modules",
|
|
58
|
+
".git"
|
|
59
|
+
].includes(part.toLowerCase())), "프로젝트 내부 상대 경로만 사용하세요. dist, node_modules, .git 경로는 사용할 수 없습니다").transform((value) => value.replaceAll("\\", "/").split("/").filter((part) => part !== "" && part !== ".").join("/"));
|
|
60
|
+
/**
|
|
61
|
+
* 공개와 내부 문서 폴더의 상대 경로 계약
|
|
62
|
+
*/
|
|
63
|
+
var contentConfigSchema = z.object({
|
|
64
|
+
/**
|
|
65
|
+
* 프로젝트 루트 기준 문서 폴더, 점 하나는 프로젝트 루트
|
|
66
|
+
*/
|
|
67
|
+
root: contentPathSchema.transform((value) => value === "" ? "." : value).default(content_default.root),
|
|
68
|
+
/**
|
|
69
|
+
* 문서 루트 아래 공개 문서 폴더
|
|
70
|
+
*/
|
|
71
|
+
public: contentPathSchema.refine((value) => value !== "", "공개 문서는 별도 하위 폴더가 필요합니다").default(content_default.public),
|
|
72
|
+
/**
|
|
73
|
+
* 문서 루트 아래 로컬 전용 문서 폴더
|
|
74
|
+
*/
|
|
75
|
+
private: contentPathSchema.refine((value) => value !== "", "내부 문서는 별도 하위 폴더가 필요합니다").default(content_default.private)
|
|
76
|
+
}).refine((value) => {
|
|
77
|
+
const published = value.public.toLowerCase();
|
|
78
|
+
const internal = value.private.toLowerCase();
|
|
79
|
+
return published !== internal && !published.startsWith(`${internal}/`) && !internal.startsWith(`${published}/`);
|
|
80
|
+
}, "공개 문서와 내부 문서 폴더는 같거나 중첩될 수 없습니다");
|
|
81
|
+
//#endregion
|
|
42
82
|
//#region src/type/site-config.ts
|
|
43
83
|
/**
|
|
44
84
|
* 사이트 설정의 입력 검증과 기본값 적용
|
|
45
85
|
*/
|
|
46
86
|
var siteConfigSchema = z.object({
|
|
87
|
+
/**
|
|
88
|
+
* 프로젝트 기준 문서 루트와 공개 범위
|
|
89
|
+
*/
|
|
90
|
+
content: contentConfigSchema.default(content_default),
|
|
47
91
|
/**
|
|
48
92
|
* 사이드바 이름과 탭 제목
|
|
49
93
|
*/
|
package/dist/site.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as loadSite } from "./load-site-
|
|
1
|
+
export { t as loadSite } from "./load-site-CBJGMNfH.js";
|
|
@@ -96,7 +96,9 @@ var toDevConfig = (params) => {
|
|
|
96
96
|
currentSite = nextSite;
|
|
97
97
|
if (generation > 0) server.hot.send({ type: "full-reload" });
|
|
98
98
|
},
|
|
99
|
-
onError: (error) =>
|
|
99
|
+
onError: (error) => {
|
|
100
|
+
return server.config.logger.error(`${copy_error_prefix}: ${toErrorMessage(error)}`);
|
|
101
|
+
}
|
|
100
102
|
});
|
|
101
103
|
const reload = debounce(refresh, 150);
|
|
102
104
|
/**
|
|
@@ -126,7 +128,9 @@ var toDevConfig = (params) => {
|
|
|
126
128
|
};
|
|
127
129
|
prepare = refresh;
|
|
128
130
|
},
|
|
129
|
-
closeBundle: () =>
|
|
131
|
+
closeBundle: () => {
|
|
132
|
+
return dispose?.();
|
|
133
|
+
}
|
|
130
134
|
}, devServer({
|
|
131
135
|
exclude: params.source ? [
|
|
132
136
|
...viteClientPaths,
|
|
@@ -137,13 +141,17 @@ var toDevConfig = (params) => {
|
|
|
137
141
|
/^\/src\/entry\/browser\//
|
|
138
142
|
] : viteClientPaths,
|
|
139
143
|
ignoreWatching: dev_ignored_paths,
|
|
140
|
-
handleHotUpdate: (context) =>
|
|
144
|
+
handleHotUpdate: (context) => {
|
|
145
|
+
return context.file.endsWith(".css") ? void 0 : [];
|
|
146
|
+
},
|
|
141
147
|
loadModule: async () => {
|
|
142
148
|
ready ??= prepare?.();
|
|
143
149
|
await ready;
|
|
144
150
|
if (currentSite === void 0) throw new Error("문서 준비에 실패했습니다. 위 오류를 수정하면 다시 반영합니다.");
|
|
145
151
|
const app = currentSite.app;
|
|
146
|
-
return { fetch: async (request, env) =>
|
|
152
|
+
return { fetch: async (request, env) => {
|
|
153
|
+
return app.fetch(request, env);
|
|
154
|
+
} };
|
|
147
155
|
}
|
|
148
156
|
})]
|
|
149
157
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* 공개와 내부 문서 폴더의 상대 경로 계약
|
|
4
|
+
*/
|
|
5
|
+
export declare const contentConfigSchema: z.ZodObject<{
|
|
6
|
+
root: z.ZodDefault<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodTransform<string, string>>>;
|
|
7
|
+
public: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
8
|
+
private: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
9
|
+
}, z.core.$strip>;
|
|
@@ -3,6 +3,11 @@ import { z } from "zod";
|
|
|
3
3
|
* 사이트 설정의 입력 검증과 기본값 적용
|
|
4
4
|
*/
|
|
5
5
|
export declare const siteConfigSchema: z.ZodObject<{
|
|
6
|
+
content: z.ZodDefault<z.ZodObject<{
|
|
7
|
+
root: z.ZodDefault<z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodTransform<string, string>>>;
|
|
8
|
+
public: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
9
|
+
private: z.ZodDefault<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
10
|
+
}, z.core.$strip>>;
|
|
6
11
|
title: z.ZodDefault<z.ZodString>;
|
|
7
12
|
description: z.ZodOptional<z.ZodString>;
|
|
8
13
|
url: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodURL, z.ZodTransform<URL, string>>, z.ZodTransform<string, URL>>>;
|
|
@@ -26,6 +31,10 @@ export type ResolvedSiteConfig = z.infer<typeof siteConfigSchema>;
|
|
|
26
31
|
* 작성자가 지정하는 사이트 설정, 기본값 적용 전 입력
|
|
27
32
|
*/
|
|
28
33
|
export interface SiteConfig {
|
|
34
|
+
/**
|
|
35
|
+
* 기본 content/public, content/private 구조의 경로 변경
|
|
36
|
+
*/
|
|
37
|
+
content?: z.input<typeof siteConfigSchema>["content"];
|
|
29
38
|
/**
|
|
30
39
|
* 사이드바 이름과 탭 제목, 생략 시 for humanity
|
|
31
40
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "for-humanity",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Documents written for humans to read: a docs kit with a sidebar, parts, sections and Mermaid diagrams, built on Hono JSX",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"files": [
|
|
28
28
|
"dist",
|
|
29
29
|
"src/asset",
|
|
30
|
+
"template",
|
|
30
31
|
"CHANGELOG.md"
|
|
31
32
|
],
|
|
32
33
|
"engines": {
|
|
@@ -37,9 +38,9 @@
|
|
|
37
38
|
"sync:readme": "tsx util/sync-readme.ts",
|
|
38
39
|
"sync:docs": "pnpm sync:readme && tsx util/sync-changelog.ts",
|
|
39
40
|
"dev": "pnpm sync:docs && pnpm build:kit && tsx src/entry/dev/dev.ts",
|
|
40
|
-
"build": "pnpm sync:docs && pnpm build:kit && node dist/cli.js build
|
|
41
|
+
"build": "pnpm sync:docs && pnpm build:kit && node dist/cli.js build .",
|
|
41
42
|
"build:pages": "pnpm build && tsx util/prepare-pages.ts",
|
|
42
|
-
"preview": "node dist/cli.js preview
|
|
43
|
+
"preview": "node dist/cli.js preview .",
|
|
43
44
|
"test": "pnpm build:kit && vitest run",
|
|
44
45
|
"test:watch": "pnpm build:kit && vitest",
|
|
45
46
|
"test:browser": "pnpm build:kit && playwright test",
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Getting started
|
|
3
|
+
label: 문서 작성과 공개 범위
|
|
4
|
+
group: Guide
|
|
5
|
+
order: 10
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Getting started
|
|
9
|
+
|
|
10
|
+
`content/public`은 공개 문서, `content/private`는 로컬 전용 문서입니다.
|
|
11
|
+
공용 이미지와 첨부는 `content/asset`, 내부 자료는 `content/private/asset`에 보관합니다.
|
|
12
|
+
|
|
13
|
+
프로젝트 루트에서 실행합니다.
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
pnpm exec for-humanity dev
|
|
17
|
+
pnpm exec for-humanity build
|
|
18
|
+
pnpm exec for-humanity preview
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`dev`는 전체 문서, `build`와 `preview`는 공개 결과를 제공합니다.
|
|
22
|
+
배포할 폴더는 `content/dist`입니다. `content` 전체를 업로드하지 않습니다.
|
|
23
|
+
`private`는 사이트 배포 제외이며 Git 저장소 접근 제어가 아닙니다.
|
|
24
|
+
|
|
25
|
+
설정은 프로젝트 루트의 `for-humanity.config.ts`, 홈은 `content/README.md`입니다.
|
|
26
|
+
공개 문서의 URL에는 `public`이 붙지 않습니다. 이 문서는 `/getting-started/`에서 확인할 수 있습니다.
|