@agentsmd/core 0.1.0 → 0.2.1
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/README.md +1 -1
- package/dist/agents-md.d.ts +30 -0
- package/dist/agents-md.d.ts.map +1 -0
- package/dist/agents-md.js +197 -0
- package/dist/agents-md.js.map +1 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/install-entry-files.d.ts +19 -0
- package/dist/install-entry-files.d.ts.map +1 -0
- package/dist/install-entry-files.js +67 -0
- package/dist/install-entry-files.js.map +1 -0
- package/dist/install.d.ts +7 -1
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +12 -3
- package/dist/install.js.map +1 -1
- package/dist/markdown-sections.d.ts +20 -0
- package/dist/markdown-sections.d.ts.map +1 -0
- package/dist/markdown-sections.js +58 -0
- package/dist/markdown-sections.js.map +1 -0
- package/dist/markdown-table.d.ts +12 -0
- package/dist/markdown-table.d.ts.map +1 -0
- package/dist/markdown-table.js +46 -0
- package/dist/markdown-table.js.map +1 -0
- package/dist/pre-commit-hook.d.ts +8 -0
- package/dist/pre-commit-hook.d.ts.map +1 -0
- package/dist/pre-commit-hook.js +25 -0
- package/dist/pre-commit-hook.js.map +1 -0
- package/dist/preset.d.ts +15 -2
- package/dist/preset.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/resolve-presets.d.ts +0 -9
- package/dist/resolve-presets.d.ts.map +0 -1
- package/dist/resolve-presets.js +0 -26
- package/dist/resolve-presets.js.map +0 -1
package/README.md
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Preset } from "./preset.js";
|
|
2
|
+
/** Claude Code가 AGENTS.md를 읽도록 불러오기만 하는 CLAUDE.md. 규칙이 두 곳으로 갈라지지 않게 한다. */
|
|
3
|
+
export declare const CLAUDE_MD = "@AGENTS.md\n\n<!-- \uADDC\uCE59\uC740 \uC774 \uD30C\uC77C\uC5D0 \uC4F0\uC9C0 \uC54A\uB294\uB2E4. AGENTS.md \uC640 docs/ \uC5D0\uB9CC \uC791\uC131\uD55C\uB2E4. -->\n";
|
|
4
|
+
/** 합치면서 새로 넣은 항목. */
|
|
5
|
+
export interface AgentsMdAdditions {
|
|
6
|
+
/** 문서 지도에 넣은 문서 경로. */
|
|
7
|
+
readonly docs: readonly string[];
|
|
8
|
+
readonly rules: readonly string[];
|
|
9
|
+
readonly verify: readonly string[];
|
|
10
|
+
}
|
|
11
|
+
export interface MergedAgentsMd {
|
|
12
|
+
readonly content: string;
|
|
13
|
+
readonly added: AgentsMdAdditions;
|
|
14
|
+
}
|
|
15
|
+
/** 고른 프리셋들의 문서·규칙·검증 명령으로 새 AGENTS.md를 만든다. */
|
|
16
|
+
export declare function renderAgentsMd(presets: readonly Preset[]): string;
|
|
17
|
+
/**
|
|
18
|
+
* 이미 있는 AGENTS.md에 프리셋의 문서·규칙·검증 명령 가운데 빠진 것만 넣는다.
|
|
19
|
+
*
|
|
20
|
+
* 프리셋을 나눠 설치해도 지도에서 문서가 빠지지 않게 하려는 것이다. 설치 순서와 상관없이 같은 항목이 모이고,
|
|
21
|
+
* 같은 프리셋을 다시 합치면 아무것도 바뀌지 않는다. 사람이 고쳐 둔 줄은 지우거나 바꾸지 않는다.
|
|
22
|
+
*
|
|
23
|
+
* - 문서: 이미 링크된 문서는 건너뛰고, `## 문서 지도` 표 끝에 행을 더한다. 표 정렬은 다시 맞춘다.
|
|
24
|
+
* - 규칙: 같은 문장이 없으면 `## 핵심 규칙` 목록 끝에 이어 붙인다.
|
|
25
|
+
* - 검증: 같은 명령 줄이 없으면 `## 검증` 코드 블록에 더한다.
|
|
26
|
+
*
|
|
27
|
+
* 절이나 표, 목록이 없으면 새로 만든다.
|
|
28
|
+
*/
|
|
29
|
+
export declare function mergeAgentsMd(existing: string, presets: readonly Preset[]): MergedAgentsMd;
|
|
30
|
+
//# sourceMappingURL=agents-md.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents-md.d.ts","sourceRoot":"","sources":["../src/agents-md.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAe,MAAM,EAAE,MAAM,aAAa,CAAC;AAGvD,4EAA4E;AAC5E,eAAO,MAAM,SAAS,yKAGrB,CAAC;AAyBF,qBAAqB;AACrB,MAAM,WAAW,iBAAiB;IAChC,uBAAuB;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;CACnC;AAED,+CAA+C;AAC/C,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,CA2B1F"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { findSection, insertSection, lastContentLine } from "./markdown-sections.js";
|
|
2
|
+
import { formatTable, parseTableRow } from "./markdown-table.js";
|
|
3
|
+
import { parseDocMap } from "./parse-doc-map.js";
|
|
4
|
+
import { resolveLink } from "./resolve-link.js";
|
|
5
|
+
/** Claude Code가 AGENTS.md를 읽도록 불러오기만 하는 CLAUDE.md. 규칙이 두 곳으로 갈라지지 않게 한다. */
|
|
6
|
+
export const CLAUDE_MD = `@AGENTS.md
|
|
7
|
+
|
|
8
|
+
<!-- 규칙은 이 파일에 쓰지 않는다. AGENTS.md 와 docs/ 에만 작성한다. -->
|
|
9
|
+
`;
|
|
10
|
+
/** 프리셋이 아무것도 넣지 않은 AGENTS.md. 여기에 프리셋을 합치면 새 지도가 된다. */
|
|
11
|
+
const SKELETON = `# AGENTS.md
|
|
12
|
+
|
|
13
|
+
에이전트 작업 지침의 진입점. 작업 전 이 파일을 읽고, 작업 종류에 맞는 문서를 연다.
|
|
14
|
+
|
|
15
|
+
## 지침 관리
|
|
16
|
+
|
|
17
|
+
- 지침 추가·변경 요청은 메모리에 저장하지 않는다. 이 파일이나 \`docs/\` 에 반영한다.
|
|
18
|
+
- 새 문서를 만들면 위 문서 지도에 한 줄 추가한다.
|
|
19
|
+
- 문서 수정도 코드와 같은 커밋 규칙을 따른다.
|
|
20
|
+
`;
|
|
21
|
+
const DOCS = "문서 지도";
|
|
22
|
+
const RULES = "핵심 규칙";
|
|
23
|
+
const VERIFY = "검증";
|
|
24
|
+
/** 절을 새로 만들 때 이 순서를 지킨다. */
|
|
25
|
+
const SECTION_ORDER = [DOCS, RULES, VERIFY, "지침 관리"];
|
|
26
|
+
const RULES_INTRO = "문서를 다 읽지 못했더라도 아래는 반드시 지킨다.";
|
|
27
|
+
const VERIFY_INTRO = "작업을 마치기 전에 실행하고 결과를 그대로 보고한다. 실패를 숨기지 않는다.";
|
|
28
|
+
const LIST_ITEM = /^(\d+)\.\s+(.*)$|^[-*]\s+(.*)$/;
|
|
29
|
+
const FENCE = /^\s{0,3}(`{3,}|~{3,})/;
|
|
30
|
+
/** 고른 프리셋들의 문서·규칙·검증 명령으로 새 AGENTS.md를 만든다. */
|
|
31
|
+
export function renderAgentsMd(presets) {
|
|
32
|
+
return mergeAgentsMd(SKELETON, presets).content;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 이미 있는 AGENTS.md에 프리셋의 문서·규칙·검증 명령 가운데 빠진 것만 넣는다.
|
|
36
|
+
*
|
|
37
|
+
* 프리셋을 나눠 설치해도 지도에서 문서가 빠지지 않게 하려는 것이다. 설치 순서와 상관없이 같은 항목이 모이고,
|
|
38
|
+
* 같은 프리셋을 다시 합치면 아무것도 바뀌지 않는다. 사람이 고쳐 둔 줄은 지우거나 바꾸지 않는다.
|
|
39
|
+
*
|
|
40
|
+
* - 문서: 이미 링크된 문서는 건너뛰고, `## 문서 지도` 표 끝에 행을 더한다. 표 정렬은 다시 맞춘다.
|
|
41
|
+
* - 규칙: 같은 문장이 없으면 `## 핵심 규칙` 목록 끝에 이어 붙인다.
|
|
42
|
+
* - 검증: 같은 명령 줄이 없으면 `## 검증` 코드 블록에 더한다.
|
|
43
|
+
*
|
|
44
|
+
* 절이나 표, 목록이 없으면 새로 만든다.
|
|
45
|
+
*/
|
|
46
|
+
export function mergeAgentsMd(existing, presets) {
|
|
47
|
+
let lines = existing.split(/\r?\n/);
|
|
48
|
+
const linked = new Set(parseDocMap("AGENTS.md", existing).links.flatMap((link) => resolveLink("AGENTS.md", link.target) ?? []));
|
|
49
|
+
const docs = uniqueByPath(presets.flatMap((preset) => preset.docs ?? [])).filter((doc) => !linked.has(doc.path));
|
|
50
|
+
lines = addDocs(lines, docs);
|
|
51
|
+
const rules = missingItems(listItems(lines), presets.flatMap((preset) => preset.rules ?? []));
|
|
52
|
+
lines = addRules(lines, rules);
|
|
53
|
+
const verify = missingItems(codeBlockLines(lines), presets.flatMap((preset) => (preset.verify === undefined ? [] : [preset.verify])));
|
|
54
|
+
lines = addVerify(lines, verify);
|
|
55
|
+
const content = `${lines.join("\n").replace(/\s+$/, "")}\n`;
|
|
56
|
+
return { content, added: { docs: docs.map((doc) => doc.path), rules, verify } };
|
|
57
|
+
}
|
|
58
|
+
function addDocs(lines, docs) {
|
|
59
|
+
if (docs.length === 0) {
|
|
60
|
+
return lines;
|
|
61
|
+
}
|
|
62
|
+
const newRows = docs.map((doc) => [`[${doc.path}](${doc.path})`, doc.when]);
|
|
63
|
+
const section = findSection(lines, DOCS);
|
|
64
|
+
if (section === undefined) {
|
|
65
|
+
return insertSection(lines, DOCS, docsTable(newRows), later(DOCS));
|
|
66
|
+
}
|
|
67
|
+
const tableStart = findIndexIn(lines, section.start + 1, section.end, isTableLine);
|
|
68
|
+
if (tableStart === undefined) {
|
|
69
|
+
const at = lastContentLine(lines, section) + 1;
|
|
70
|
+
return splice(lines, at, 0, ["", ...docsTable(newRows)]);
|
|
71
|
+
}
|
|
72
|
+
const tableEnd = findIndexIn(lines, tableStart, section.end, (line) => !isTableLine(line)) ?? section.end;
|
|
73
|
+
const [header = [], , ...rows] = lines.slice(tableStart, tableEnd).map(parseTableRow);
|
|
74
|
+
const table = formatTable(header, [...rows, ...newRows]).split("\n");
|
|
75
|
+
return splice(lines, tableStart, tableEnd - tableStart, table);
|
|
76
|
+
}
|
|
77
|
+
function addRules(lines, rules) {
|
|
78
|
+
if (rules.length === 0) {
|
|
79
|
+
return lines;
|
|
80
|
+
}
|
|
81
|
+
const section = findSection(lines, RULES);
|
|
82
|
+
if (section === undefined) {
|
|
83
|
+
return insertSection(lines, RULES, [RULES_INTRO, "", ...numbered(rules, 1)], later(RULES));
|
|
84
|
+
}
|
|
85
|
+
const lastItem = findLastIndexIn(lines, section.start + 1, section.end, (line) => LIST_ITEM.test(line));
|
|
86
|
+
if (lastItem === undefined) {
|
|
87
|
+
const at = lastContentLine(lines, section) + 1;
|
|
88
|
+
return splice(lines, at, 0, ["", ...numbered(rules, 1)]);
|
|
89
|
+
}
|
|
90
|
+
// 목록의 마지막 항목이 여러 줄이면 들여쓴 이어지는 줄 뒤에 넣는다.
|
|
91
|
+
let at = lastItem + 1;
|
|
92
|
+
while (at < section.end && /^\s+\S/.test(lines[at] ?? "")) {
|
|
93
|
+
at++;
|
|
94
|
+
}
|
|
95
|
+
const number = /^(\d+)\./.exec(lines[lastItem] ?? "")?.[1];
|
|
96
|
+
const items = number === undefined ? rules.map((rule) => `- ${rule}`) : numbered(rules, Number(number) + 1);
|
|
97
|
+
return splice(lines, at, 0, items);
|
|
98
|
+
}
|
|
99
|
+
function addVerify(lines, commands) {
|
|
100
|
+
if (commands.length === 0) {
|
|
101
|
+
return lines;
|
|
102
|
+
}
|
|
103
|
+
const block = ["```bash", ...commands, "```"];
|
|
104
|
+
const section = findSection(lines, VERIFY);
|
|
105
|
+
if (section === undefined) {
|
|
106
|
+
return insertSection(lines, VERIFY, [VERIFY_INTRO, "", ...block], later(VERIFY));
|
|
107
|
+
}
|
|
108
|
+
const open = findIndexIn(lines, section.start + 1, section.end, (line) => FENCE.test(line));
|
|
109
|
+
const close = open === undefined
|
|
110
|
+
? undefined
|
|
111
|
+
: findIndexIn(lines, open + 1, section.end, (line) => FENCE.test(line));
|
|
112
|
+
if (close === undefined) {
|
|
113
|
+
const at = lastContentLine(lines, section) + 1;
|
|
114
|
+
return splice(lines, at, 0, ["", ...block]);
|
|
115
|
+
}
|
|
116
|
+
return splice(lines, close, 0, [...commands]);
|
|
117
|
+
}
|
|
118
|
+
function docsTable(rows) {
|
|
119
|
+
return formatTable(["문서", "읽는 시점"], rows).split("\n");
|
|
120
|
+
}
|
|
121
|
+
function numbered(items, from) {
|
|
122
|
+
return items.map((item, index) => `${String(from + index)}. ${item}`);
|
|
123
|
+
}
|
|
124
|
+
/** `## 핵심 규칙` 목록의 항목 문장. 번호·글머리표는 뗀다. */
|
|
125
|
+
function listItems(lines) {
|
|
126
|
+
const section = findSection(lines, RULES);
|
|
127
|
+
if (section === undefined) {
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
return lines.slice(section.start + 1, section.end).flatMap((line) => {
|
|
131
|
+
const match = LIST_ITEM.exec(line);
|
|
132
|
+
const text = match?.[2] ?? match?.[3];
|
|
133
|
+
return text === undefined ? [] : [text.trim()];
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/** `## 검증` 절의 코드 블록 안 줄. */
|
|
137
|
+
function codeBlockLines(lines) {
|
|
138
|
+
const section = findSection(lines, VERIFY);
|
|
139
|
+
if (section === undefined) {
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
let inFence = false;
|
|
143
|
+
return lines.slice(section.start + 1, section.end).flatMap((line) => {
|
|
144
|
+
if (FENCE.test(line)) {
|
|
145
|
+
inFence = !inFence;
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
return inFence ? [line.trim()] : [];
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/** 이미 있는 항목과 같은 것, 앞에서 이미 나온 것을 뺀다. */
|
|
152
|
+
function missingItems(existing, candidates) {
|
|
153
|
+
const seen = new Set(existing);
|
|
154
|
+
return candidates.filter((item) => {
|
|
155
|
+
if (seen.has(item.trim())) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
seen.add(item.trim());
|
|
159
|
+
return true;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
function uniqueByPath(entries) {
|
|
163
|
+
const seen = new Set();
|
|
164
|
+
return entries.filter((entry) => {
|
|
165
|
+
if (seen.has(entry.path)) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
seen.add(entry.path);
|
|
169
|
+
return true;
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
function later(title) {
|
|
173
|
+
return SECTION_ORDER.slice(SECTION_ORDER.indexOf(title) + 1);
|
|
174
|
+
}
|
|
175
|
+
function isTableLine(line) {
|
|
176
|
+
return line.trimStart().startsWith("|");
|
|
177
|
+
}
|
|
178
|
+
function findIndexIn(lines, from, to, test) {
|
|
179
|
+
for (let index = from; index < to; index++) {
|
|
180
|
+
if (test(lines[index] ?? "")) {
|
|
181
|
+
return index;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
function findLastIndexIn(lines, from, to, test) {
|
|
187
|
+
for (let index = to - 1; index >= from; index--) {
|
|
188
|
+
if (test(lines[index] ?? "")) {
|
|
189
|
+
return index;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
function splice(lines, start, deleteCount, items) {
|
|
195
|
+
return [...lines.slice(0, start), ...items, ...lines.slice(start + deleteCount)];
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=agents-md.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents-md.js","sourceRoot":"","sources":["../src/agents-md.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,SAAS,GAAG;;;CAGxB,CAAC;AAEF,wDAAwD;AACxD,MAAM,QAAQ,GAAG;;;;;;;;;CAShB,CAAC;AAEF,MAAM,IAAI,GAAG,OAAO,CAAC;AACrB,MAAM,KAAK,GAAG,OAAO,CAAC;AACtB,MAAM,MAAM,GAAG,IAAI,CAAC;AACpB,4BAA4B;AAC5B,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAErD,MAAM,WAAW,GAAG,6BAA6B,CAAC;AAClD,MAAM,YAAY,GAAG,4CAA4C,CAAC;AAClE,MAAM,SAAS,GAAG,gCAAgC,CAAC;AACnD,MAAM,KAAK,GAAG,uBAAuB,CAAC;AAetC,+CAA+C;AAC/C,MAAM,UAAU,cAAc,CAAC,OAA0B;IACvD,OAAO,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC;AAClD,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,OAA0B;IACxE,IAAI,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEpC,MAAM,MAAM,GAAG,IAAI,GAAG,CACpB,WAAW,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,OAAO,CAC9C,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CACtD,CACF,CAAC;IACF,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAC9E,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAC/B,CAAC;IACF,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAE7B,MAAM,KAAK,GAAG,YAAY,CACxB,SAAS,CAAC,KAAK,CAAC,EAChB,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAChD,CAAC;IACF,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAE/B,MAAM,MAAM,GAAG,YAAY,CACzB,cAAc,CAAC,KAAK,CAAC,EACrB,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAClF,CAAC;IACF,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAEjC,MAAM,OAAO,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC;IAC5D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;AAClF,CAAC;AAED,SAAS,OAAO,CAAC,KAAe,EAAE,IAA4B;IAC5D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5E,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACzC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACnF,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,QAAQ,GACZ,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC;IAC3F,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,AAAD,EAAG,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACtF,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrE,OAAO,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,GAAG,UAAU,EAAE,KAAK,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,QAAQ,CAAC,KAAe,EAAE,KAAwB;IACzD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC1C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAC/E,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CACrB,CAAC;IACF,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAG,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IACD,wCAAwC;IACxC,IAAI,EAAE,GAAG,QAAQ,GAAG,CAAC,CAAC;IACtB,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC1D,EAAE,EAAE,CAAC;IACP,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,KAAK,GACT,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAChG,OAAO,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,SAAS,CAAC,KAAe,EAAE,QAA2B;IAC7D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,SAAS,EAAE,GAAG,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC3C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,YAAY,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5F,MAAM,KAAK,GACT,IAAI,KAAK,SAAS;QAChB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5E,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,SAAS,CAAC,IAAoC;IACrD,OAAO,WAAW,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,QAAQ,CAAC,KAAwB,EAAE,IAAY;IACtD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,yCAAyC;AACzC,SAAS,SAAS,CAAC,KAAwB;IACzC,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC1C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAClE,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QACtC,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,4BAA4B;AAC5B,SAAS,cAAc,CAAC,KAAwB;IAC9C,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC3C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAClE,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,OAAO,GAAG,CAAC,OAAO,CAAC;YACnB,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,uCAAuC;AACvC,SAAS,YAAY,CAAC,QAA2B,EAAE,UAA6B;IAC9E,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC/B,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAChC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC1B,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,OAA+B;IACnD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,KAAK,CAAC,KAAa;IAC1B,OAAO,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,WAAW,CAClB,KAAwB,EACxB,IAAY,EACZ,EAAU,EACV,IAA+B;IAE/B,KAAK,IAAI,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3C,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC7B,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,eAAe,CACtB,KAAwB,EACxB,IAAY,EACZ,EAAU,EACV,IAA+B;IAE/B,KAAK,IAAI,KAAK,GAAG,EAAE,GAAG,CAAC,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAChD,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC7B,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,MAAM,CACb,KAAwB,EACxB,KAAa,EACb,WAAmB,EACnB,KAAwB;IAExB,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC;AACnF,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
export { CLAUDE_MD, mergeAgentsMd, renderAgentsMd } from "./agents-md.js";
|
|
2
|
+
export type { AgentsMdAdditions, MergedAgentsMd } from "./agents-md.js";
|
|
1
3
|
export { checkRepository } from "./check.js";
|
|
2
4
|
export type { CheckOptions } from "./check.js";
|
|
3
5
|
export { DocMapNotFoundError } from "./errors.js";
|
|
6
|
+
export { installEntryFiles } from "./install-entry-files.js";
|
|
7
|
+
export type { EntryFilesResult } from "./install-entry-files.js";
|
|
4
8
|
export { installPreset } from "./install.js";
|
|
5
9
|
export type { InstallOptions, InstallResult } from "./install.js";
|
|
6
|
-
export
|
|
7
|
-
export {
|
|
10
|
+
export { PRE_COMMIT_HOOK } from "./pre-commit-hook.js";
|
|
11
|
+
export type { DocMapEntry, Preset } from "./preset.js";
|
|
8
12
|
export type { DocLink, DocMap, Finding, RuleId } from "./types.js";
|
|
9
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC1E,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACvD,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
export { CLAUDE_MD, mergeAgentsMd, renderAgentsMd } from "./agents-md.js";
|
|
1
2
|
export { checkRepository } from "./check.js";
|
|
2
3
|
export { DocMapNotFoundError } from "./errors.js";
|
|
4
|
+
export { installEntryFiles } from "./install-entry-files.js";
|
|
3
5
|
export { installPreset } from "./install.js";
|
|
4
|
-
export {
|
|
6
|
+
export { PRE_COMMIT_HOOK } from "./pre-commit-hook.js";
|
|
5
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type AgentsMdAdditions } from "./agents-md.js";
|
|
2
|
+
import { type InstallOptions, type InstallResult } from "./install.js";
|
|
3
|
+
import type { Preset } from "./preset.js";
|
|
4
|
+
export interface EntryFilesResult extends InstallResult {
|
|
5
|
+
/** 이미 있던 AGENTS.md에 합쳤으면 새로 넣은 항목. 새로 만들었거나 덮어썼으면 undefined. */
|
|
6
|
+
readonly merged: AgentsMdAdditions | undefined;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* 여러 프리셋이 함께 쓰는 파일을 고른 프리셋에 맞게 만들어 설치한다.
|
|
10
|
+
*
|
|
11
|
+
* - `AGENTS.md`: 고른 프리셋들의 문서 지도를 합친 것
|
|
12
|
+
* - `CLAUDE.md`: `AGENTS.md`를 불러오기만 한다
|
|
13
|
+
* - `<hooksPath>/pre-commit`: 훅이 있는 프리셋을 골랐을 때만. 각 프리셋의 `pre-commit.d/` 검사를 실행한다
|
|
14
|
+
*
|
|
15
|
+
* `AGENTS.md`가 이미 있으면 빠진 문서·규칙·검증 명령만 합친다. 프리셋을 나눠 설치해도 지도에서 빠지지 않게 하려는 것이다.
|
|
16
|
+
* 나머지 파일은 프리셋 파일과 같은 규칙으로, 이미 있으면 건너뛴다. `force`면 모두 새로 쓴다.
|
|
17
|
+
*/
|
|
18
|
+
export declare function installEntryFiles(presets: readonly Preset[], targetDir: string, options?: InstallOptions): Promise<EntryFilesResult>;
|
|
19
|
+
//# sourceMappingURL=install-entry-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-entry-files.d.ts","sourceRoot":"","sources":["../src/install-entry-files.ts"],"names":[],"mappings":"AAGA,OAAO,EAA4C,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAClG,OAAO,EAAc,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAEnF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAU1C,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACrD,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,SAAS,CAAC;CAChD;AAED;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CA0B3B"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { CLAUDE_MD, mergeAgentsMd, renderAgentsMd } from "./agents-md.js";
|
|
5
|
+
import { hasContent } from "./install.js";
|
|
6
|
+
import { PRE_COMMIT_HOOK } from "./pre-commit-hook.js";
|
|
7
|
+
const AGENTS_MD = "AGENTS.md";
|
|
8
|
+
/**
|
|
9
|
+
* 여러 프리셋이 함께 쓰는 파일을 고른 프리셋에 맞게 만들어 설치한다.
|
|
10
|
+
*
|
|
11
|
+
* - `AGENTS.md`: 고른 프리셋들의 문서 지도를 합친 것
|
|
12
|
+
* - `CLAUDE.md`: `AGENTS.md`를 불러오기만 한다
|
|
13
|
+
* - `<hooksPath>/pre-commit`: 훅이 있는 프리셋을 골랐을 때만. 각 프리셋의 `pre-commit.d/` 검사를 실행한다
|
|
14
|
+
*
|
|
15
|
+
* `AGENTS.md`가 이미 있으면 빠진 문서·규칙·검증 명령만 합친다. 프리셋을 나눠 설치해도 지도에서 빠지지 않게 하려는 것이다.
|
|
16
|
+
* 나머지 파일은 프리셋 파일과 같은 규칙으로, 이미 있으면 건너뛴다. `force`면 모두 새로 쓴다.
|
|
17
|
+
*/
|
|
18
|
+
export async function installEntryFiles(presets, targetDir, options = {}) {
|
|
19
|
+
const force = options.force === true;
|
|
20
|
+
const written = [];
|
|
21
|
+
const skipped = [];
|
|
22
|
+
const merged = force ? undefined : await mergeExistingAgentsMd(presets, targetDir);
|
|
23
|
+
for (const file of entryFiles(presets)) {
|
|
24
|
+
const destination = join(targetDir, file.path);
|
|
25
|
+
if (file.path === AGENTS_MD && merged !== undefined) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (!force && existsSync(destination)) {
|
|
29
|
+
if (!(await hasContent(destination, file.content))) {
|
|
30
|
+
skipped.push(file.path);
|
|
31
|
+
}
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
await mkdir(dirname(destination), { recursive: true });
|
|
35
|
+
await writeFile(destination, file.content);
|
|
36
|
+
if (file.executable) {
|
|
37
|
+
await chmod(destination, 0o755);
|
|
38
|
+
}
|
|
39
|
+
written.push(file.path);
|
|
40
|
+
}
|
|
41
|
+
return { written, skipped, merged };
|
|
42
|
+
}
|
|
43
|
+
/** 이미 있는 AGENTS.md에 빠진 항목을 합친다. 파일이 없으면 undefined, 넣을 것이 없으면 파일을 건드리지 않는다. */
|
|
44
|
+
async function mergeExistingAgentsMd(presets, targetDir) {
|
|
45
|
+
const path = join(targetDir, AGENTS_MD);
|
|
46
|
+
if (!existsSync(path)) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
const existing = await readFile(path, "utf8");
|
|
50
|
+
const { content, added } = mergeAgentsMd(existing, presets);
|
|
51
|
+
if (content !== existing) {
|
|
52
|
+
await writeFile(path, content);
|
|
53
|
+
}
|
|
54
|
+
return added;
|
|
55
|
+
}
|
|
56
|
+
function entryFiles(presets) {
|
|
57
|
+
const files = [
|
|
58
|
+
{ path: AGENTS_MD, content: renderAgentsMd(presets), executable: false },
|
|
59
|
+
{ path: "CLAUDE.md", content: CLAUDE_MD, executable: false },
|
|
60
|
+
];
|
|
61
|
+
const hooksPath = presets.find((preset) => preset.hooksPath !== undefined)?.hooksPath;
|
|
62
|
+
if (hooksPath !== undefined) {
|
|
63
|
+
files.push({ path: `${hooksPath}/pre-commit`, content: PRE_COMMIT_HOOK, executable: true });
|
|
64
|
+
}
|
|
65
|
+
return files;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=install-entry-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-entry-files.js","sourceRoot":"","sources":["../src/install-entry-files.ts"],"names":[],"mappings":"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"}
|
package/dist/install.d.ts
CHANGED
|
@@ -6,14 +6,20 @@ export interface InstallOptions {
|
|
|
6
6
|
export interface InstallResult {
|
|
7
7
|
/** 새로 만들었거나 덮어쓴 파일. 대상 디렉터리 기준 posix 경로. */
|
|
8
8
|
readonly written: readonly string[];
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* 이미 있는데 내용이 달라서 건드리지 않은 파일. 대상 디렉터리 기준 posix 경로.
|
|
11
|
+
* 설치할 내용과 똑같은 파일은 할 일이 없으므로 어느 목록에도 넣지 않는다.
|
|
12
|
+
*/
|
|
10
13
|
readonly skipped: readonly string[];
|
|
11
14
|
}
|
|
12
15
|
/**
|
|
13
16
|
* 프리셋 파일을 대상 디렉터리에 복사한다.
|
|
14
17
|
*
|
|
15
18
|
* 기존 저장소에 적용할 때 사람이 다듬어 둔 지침을 지우지 않도록, 기본으로는 이미 있는 파일을 건너뛴다.
|
|
19
|
+
* 내용이 같은 파일은 건너뛴 것으로 알리지 않는다. 같은 프리셋을 다시 설치해도 바뀐 것이 없으면 조용하다.
|
|
16
20
|
* 파일 권한도 함께 복사되므로 Git 훅의 실행 권한이 유지된다.
|
|
17
21
|
*/
|
|
18
22
|
export declare function installPreset(preset: Preset, targetDir: string, options?: InstallOptions): Promise<InstallResult>;
|
|
23
|
+
/** 파일 내용이 주어진 내용과 바이트 단위로 같은지 본다. */
|
|
24
|
+
export declare function hasContent(path: string, content: Uint8Array | string): Promise<boolean>;
|
|
19
25
|
//# sourceMappingURL=install.d.ts.map
|
package/dist/install.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC7B,iCAAiC;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC7B,iCAAiC;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,aAAa,CAAC,CAmBxB;AAED,qCAAqC;AACrC,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG7F"}
|
package/dist/install.js
CHANGED
|
@@ -1,27 +1,36 @@
|
|
|
1
|
-
import { copyFile, mkdir, readdir } from "node:fs/promises";
|
|
1
|
+
import { copyFile, mkdir, readFile, readdir } from "node:fs/promises";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { dirname, join, relative, sep } from "node:path";
|
|
4
4
|
/**
|
|
5
5
|
* 프리셋 파일을 대상 디렉터리에 복사한다.
|
|
6
6
|
*
|
|
7
7
|
* 기존 저장소에 적용할 때 사람이 다듬어 둔 지침을 지우지 않도록, 기본으로는 이미 있는 파일을 건너뛴다.
|
|
8
|
+
* 내용이 같은 파일은 건너뛴 것으로 알리지 않는다. 같은 프리셋을 다시 설치해도 바뀐 것이 없으면 조용하다.
|
|
8
9
|
* 파일 권한도 함께 복사되므로 Git 훅의 실행 권한이 유지된다.
|
|
9
10
|
*/
|
|
10
11
|
export async function installPreset(preset, targetDir, options = {}) {
|
|
11
12
|
const written = [];
|
|
12
13
|
const skipped = [];
|
|
13
14
|
for (const file of await listFiles(preset.filesDir)) {
|
|
15
|
+
const source = join(preset.filesDir, file);
|
|
14
16
|
const destination = join(targetDir, file);
|
|
15
17
|
if (options.force !== true && existsSync(destination)) {
|
|
16
|
-
|
|
18
|
+
if (!(await hasContent(destination, await readFile(source)))) {
|
|
19
|
+
skipped.push(file);
|
|
20
|
+
}
|
|
17
21
|
continue;
|
|
18
22
|
}
|
|
19
23
|
await mkdir(dirname(destination), { recursive: true });
|
|
20
|
-
await copyFile(
|
|
24
|
+
await copyFile(source, destination);
|
|
21
25
|
written.push(file);
|
|
22
26
|
}
|
|
23
27
|
return { written, skipped };
|
|
24
28
|
}
|
|
29
|
+
/** 파일 내용이 주어진 내용과 바이트 단위로 같은지 본다. */
|
|
30
|
+
export async function hasContent(path, content) {
|
|
31
|
+
const existing = await readFile(path);
|
|
32
|
+
return existing.equals(typeof content === "string" ? Buffer.from(content) : content);
|
|
33
|
+
}
|
|
25
34
|
/** 디렉터리 아래 모든 파일을 posix 상대 경로로, 정렬해서 돌려준다. */
|
|
26
35
|
async function listFiles(dir) {
|
|
27
36
|
const entries = await readdir(dir, { recursive: true, withFileTypes: true });
|
package/dist/install.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAkBzD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc,EACd,SAAiB,EACjB,UAA0B,EAAE;IAE5B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,IAAI,IAAI,MAAM,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC1C,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YACtD,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,WAAW,EAAE,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7D,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;YACD,SAAS;QACX,CAAC;QACD,MAAM,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED,qCAAqC;AACrC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,OAA4B;IACzE,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO,QAAQ,CAAC,MAAM,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AACvF,CAAC;AAED,8CAA8C;AAC9C,KAAK,UAAU,SAAS,CAAC,GAAW;IAClC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7E,OAAO,OAAO;SACX,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;SACjC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SACtF,IAAI,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** `## 제목` 절의 줄 범위. `start`는 제목 줄, `end`는 다음 제목 줄(없으면 줄 수)이다. */
|
|
2
|
+
export interface Section {
|
|
3
|
+
readonly start: number;
|
|
4
|
+
readonly end: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* `## 제목` 절을 찾는다. 절은 다음 `#`·`##` 제목 앞에서 끝난다.
|
|
8
|
+
* 코드 블록 안의 `##` 줄은 제목으로 보지 않는다.
|
|
9
|
+
*/
|
|
10
|
+
export declare function findSection(lines: readonly string[], title: string): Section | undefined;
|
|
11
|
+
/** 절 안에서 마지막으로 내용이 있는 줄. 절이 제목뿐이면 제목 줄이다. */
|
|
12
|
+
export declare function lastContentLine(lines: readonly string[], section: Section): number;
|
|
13
|
+
/**
|
|
14
|
+
* 새 `## 제목` 절을 넣는다.
|
|
15
|
+
*
|
|
16
|
+
* `before`에 적힌 절 가운데 문서에 있는 첫 번째 절 앞에 넣고, 하나도 없으면 문서 끝에 붙인다.
|
|
17
|
+
* 절 사이에는 빈 줄 하나를 둔다.
|
|
18
|
+
*/
|
|
19
|
+
export declare function insertSection(lines: readonly string[], title: string, body: readonly string[], before: readonly string[]): string[];
|
|
20
|
+
//# sourceMappingURL=markdown-sections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-sections.d.ts","sourceRoot":"","sources":["../src/markdown-sections.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAKD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAexF;AAED,6CAA6C;AAC7C,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAOlF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB,MAAM,EAAE,CAWV"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const FENCE = /^\s{0,3}(`{3,}|~{3,})/;
|
|
2
|
+
const HEADING = /^#{1,2}\s/;
|
|
3
|
+
/**
|
|
4
|
+
* `## 제목` 절을 찾는다. 절은 다음 `#`·`##` 제목 앞에서 끝난다.
|
|
5
|
+
* 코드 블록 안의 `##` 줄은 제목으로 보지 않는다.
|
|
6
|
+
*/
|
|
7
|
+
export function findSection(lines, title) {
|
|
8
|
+
const start = lines.findIndex((line) => line.trim() === `## ${title}`);
|
|
9
|
+
if (start === -1) {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
let inFence = false;
|
|
13
|
+
for (let index = start + 1; index < lines.length; index++) {
|
|
14
|
+
const line = lines[index] ?? "";
|
|
15
|
+
if (FENCE.test(line)) {
|
|
16
|
+
inFence = !inFence;
|
|
17
|
+
}
|
|
18
|
+
else if (!inFence && HEADING.test(line)) {
|
|
19
|
+
return { start, end: index };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return { start, end: lines.length };
|
|
23
|
+
}
|
|
24
|
+
/** 절 안에서 마지막으로 내용이 있는 줄. 절이 제목뿐이면 제목 줄이다. */
|
|
25
|
+
export function lastContentLine(lines, section) {
|
|
26
|
+
for (let index = section.end - 1; index > section.start; index--) {
|
|
27
|
+
if ((lines[index] ?? "").trim() !== "") {
|
|
28
|
+
return index;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return section.start;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 새 `## 제목` 절을 넣는다.
|
|
35
|
+
*
|
|
36
|
+
* `before`에 적힌 절 가운데 문서에 있는 첫 번째 절 앞에 넣고, 하나도 없으면 문서 끝에 붙인다.
|
|
37
|
+
* 절 사이에는 빈 줄 하나를 둔다.
|
|
38
|
+
*/
|
|
39
|
+
export function insertSection(lines, title, body, before) {
|
|
40
|
+
const block = [`## ${title}`, "", ...body, ""];
|
|
41
|
+
const next = before
|
|
42
|
+
.map((other) => findSection(lines, other)?.start)
|
|
43
|
+
.filter((start) => start !== undefined)
|
|
44
|
+
.sort((a, b) => a - b)[0];
|
|
45
|
+
if (next !== undefined) {
|
|
46
|
+
return [...lines.slice(0, next), ...block, ...lines.slice(next)];
|
|
47
|
+
}
|
|
48
|
+
const trimmed = trimTrailingBlank(lines);
|
|
49
|
+
return [...trimmed, ...(trimmed.length > 0 ? [""] : []), ...block];
|
|
50
|
+
}
|
|
51
|
+
function trimTrailingBlank(lines) {
|
|
52
|
+
let end = lines.length;
|
|
53
|
+
while (end > 0 && (lines[end - 1] ?? "").trim() === "") {
|
|
54
|
+
end--;
|
|
55
|
+
}
|
|
56
|
+
return lines.slice(0, end);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=markdown-sections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-sections.js","sourceRoot":"","sources":["../src/markdown-sections.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 마크다운 표를 Prettier와 같은 모양으로 정렬해 만든다.
|
|
3
|
+
*
|
|
4
|
+
* 설치한 문서가 대상 저장소의 `prettier --check`에 걸리지 않게 하려는 것이다.
|
|
5
|
+
* Prettier는 열 너비를 화면에 보이는 폭으로 맞추므로, 한글처럼 두 칸을 차지하는 글자는 2로 센다.
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatTable(header: readonly string[], rows: readonly (readonly string[])[]): string;
|
|
8
|
+
/** 표의 한 줄을 칸으로 나눈다. `\|`로 이스케이프한 세로선은 칸 구분으로 보지 않는다. */
|
|
9
|
+
export declare function parseTableRow(line: string): string[];
|
|
10
|
+
/** 화면에 보이는 폭. 한글·한자·전각 문자는 2칸, 나머지는 1칸으로 센다. */
|
|
11
|
+
export declare function displayWidth(text: string): number;
|
|
12
|
+
//# sourceMappingURL=markdown-table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-table.d.ts","sourceRoot":"","sources":["../src/markdown-table.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,IAAI,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,GACnC,MAAM,CAYR;AAED,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAMpD;AAMD,gDAAgD;AAChD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjD"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 마크다운 표를 Prettier와 같은 모양으로 정렬해 만든다.
|
|
3
|
+
*
|
|
4
|
+
* 설치한 문서가 대상 저장소의 `prettier --check`에 걸리지 않게 하려는 것이다.
|
|
5
|
+
* Prettier는 열 너비를 화면에 보이는 폭으로 맞추므로, 한글처럼 두 칸을 차지하는 글자는 2로 센다.
|
|
6
|
+
*/
|
|
7
|
+
export function formatTable(header, rows) {
|
|
8
|
+
const widths = header.map((cell, column) => Math.max(3, displayWidth(cell), ...rows.map((row) => displayWidth(row[column] ?? ""))));
|
|
9
|
+
const line = (cells) => `| ${widths.map((width, column) => pad(cells[column] ?? "", width)).join(" | ")} |`;
|
|
10
|
+
return [
|
|
11
|
+
line(header),
|
|
12
|
+
line(widths.map((width) => "-".repeat(width))),
|
|
13
|
+
...rows.map((row) => line(row)),
|
|
14
|
+
].join("\n");
|
|
15
|
+
}
|
|
16
|
+
/** 표의 한 줄을 칸으로 나눈다. `\|`로 이스케이프한 세로선은 칸 구분으로 보지 않는다. */
|
|
17
|
+
export function parseTableRow(line) {
|
|
18
|
+
const inner = line
|
|
19
|
+
.trim()
|
|
20
|
+
.replace(/^\|/, "")
|
|
21
|
+
.replace(/(?<!\\)\|$/, "");
|
|
22
|
+
return inner.split(/(?<!\\)\|/).map((cell) => cell.trim());
|
|
23
|
+
}
|
|
24
|
+
function pad(text, width) {
|
|
25
|
+
return text + " ".repeat(width - displayWidth(text));
|
|
26
|
+
}
|
|
27
|
+
/** 화면에 보이는 폭. 한글·한자·전각 문자는 2칸, 나머지는 1칸으로 센다. */
|
|
28
|
+
export function displayWidth(text) {
|
|
29
|
+
let width = 0;
|
|
30
|
+
for (const char of text) {
|
|
31
|
+
width += isWide(char.codePointAt(0) ?? 0) ? 2 : 1;
|
|
32
|
+
}
|
|
33
|
+
return width;
|
|
34
|
+
}
|
|
35
|
+
function isWide(code) {
|
|
36
|
+
return ((code >= 0x1100 && code <= 0x115f) || // 한글 자모
|
|
37
|
+
(code >= 0x2e80 && code <= 0x303e) || // 한중일 부수·기호
|
|
38
|
+
(code >= 0x3041 && code <= 0x33ff) || // 가나·한글 호환 자모
|
|
39
|
+
(code >= 0x3400 && code <= 0x4dbf) || // 한자 확장 A
|
|
40
|
+
(code >= 0x4e00 && code <= 0x9fff) || // 한자
|
|
41
|
+
(code >= 0xac00 && code <= 0xd7a3) || // 한글 음절
|
|
42
|
+
(code >= 0xf900 && code <= 0xfaff) || // 한자 호환
|
|
43
|
+
(code >= 0xff00 && code <= 0xff60) || // 전각 문자
|
|
44
|
+
(code >= 0xffe0 && code <= 0xffe6));
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=markdown-table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-table.js","sourceRoot":"","sources":["../src/markdown-table.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `.githooks/pre-commit`에 설치할 실행기.
|
|
3
|
+
*
|
|
4
|
+
* 검사 내용은 프리셋마다 `.githooks/pre-commit.d/`에 스크립트로 넣고, 이 실행기는 그것들을 이름 순서로 돌린다.
|
|
5
|
+
* 실행기를 한 프리셋이 가지면 그 프리셋 없이 설치한 다른 프리셋의 검사가 돌지 않으므로, 설치할 때 따로 만든다.
|
|
6
|
+
*/
|
|
7
|
+
export declare const PRE_COMMIT_HOOK = "#!/usr/bin/env bash\n#\n# .githooks/pre-commit.d/ \uC758 \uAC80\uC0AC\uB97C \uC774\uB984 \uC21C\uC11C\uB85C \uC2E4\uD589\uD55C\uB2E4. \uD558\uB098\uB77C\uB3C4 \uC2E4\uD328\uD558\uBA74 \uCEE4\uBC0B\uC744 \uB9C9\uB294\uB2E4.\n# \uC2E4\uD589 \uAD8C\uD55C\uC774 \uC788\uB294 \uD30C\uC77C\uB9CC \uAC80\uC0AC\uB85C \uBCF8\uB2E4. agentsmd init \uC774 \uC124\uCE58\uD55C \uD30C\uC77C\uC774\uB2E4.\n\nset -euo pipefail\n\nchecks_dir=\"$(dirname \"$0\")/pre-commit.d\"\nif [ -d \"$checks_dir\" ]; then\n for check in \"$checks_dir\"/*; do\n if [ -f \"$check\" ] && [ -x \"$check\" ]; then\n \"$check\"\n fi\n done\nfi\n\nexit 0\n";
|
|
8
|
+
//# sourceMappingURL=pre-commit-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-commit-hook.d.ts","sourceRoot":"","sources":["../src/pre-commit-hook.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,eAAe,6nBAiB3B,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `.githooks/pre-commit`에 설치할 실행기.
|
|
3
|
+
*
|
|
4
|
+
* 검사 내용은 프리셋마다 `.githooks/pre-commit.d/`에 스크립트로 넣고, 이 실행기는 그것들을 이름 순서로 돌린다.
|
|
5
|
+
* 실행기를 한 프리셋이 가지면 그 프리셋 없이 설치한 다른 프리셋의 검사가 돌지 않으므로, 설치할 때 따로 만든다.
|
|
6
|
+
*/
|
|
7
|
+
export const PRE_COMMIT_HOOK = `#!/usr/bin/env bash
|
|
8
|
+
#
|
|
9
|
+
# .githooks/pre-commit.d/ 의 검사를 이름 순서로 실행한다. 하나라도 실패하면 커밋을 막는다.
|
|
10
|
+
# 실행 권한이 있는 파일만 검사로 본다. agentsmd init 이 설치한 파일이다.
|
|
11
|
+
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
checks_dir="$(dirname "$0")/pre-commit.d"
|
|
15
|
+
if [ -d "$checks_dir" ]; then
|
|
16
|
+
for check in "$checks_dir"/*; do
|
|
17
|
+
if [ -f "$check" ] && [ -x "$check" ]; then
|
|
18
|
+
"$check"
|
|
19
|
+
fi
|
|
20
|
+
done
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
exit 0
|
|
24
|
+
`;
|
|
25
|
+
//# sourceMappingURL=pre-commit-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-commit-hook.js","sourceRoot":"","sources":["../src/pre-commit-hook.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;CAiB9B,CAAC"}
|
package/dist/preset.d.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* `init`으로 설치할 수 있는 지침 파일 묶음.
|
|
3
3
|
*
|
|
4
4
|
* 프리셋 패키지는 이 형태의 객체 하나를 내보낸다. 파일 내용은 `filesDir` 아래에 설치될 경로 그대로 둔다.
|
|
5
|
+
* 프리셋끼리는 서로 의존하지 않는다. 함께 쓰려면 사용자가 여러 프리셋을 고르고,
|
|
6
|
+
* 여러 프리셋이 함께 쓰는 AGENTS.md·CLAUDE.md·훅 실행기는 `installEntryFiles`가 조합에 맞게 만든다.
|
|
5
7
|
*/
|
|
6
8
|
export interface Preset {
|
|
7
9
|
/** `--preset` 옵션에 쓰는 이름. 예: `java` */
|
|
@@ -12,9 +14,20 @@ export interface Preset {
|
|
|
12
14
|
readonly filesDir: string;
|
|
13
15
|
/** 프리셋에 Git 훅이 있으면 그 디렉터리. 설치 대상 기준 상대 경로. `core.hooksPath`로 연결한다. */
|
|
14
16
|
readonly hooksPath?: string;
|
|
17
|
+
/** 문서 지도(AGENTS.md)에 올릴 이 프리셋의 문서. 여러 프리셋을 고르면 순서대로 합친다. */
|
|
18
|
+
readonly docs?: readonly DocMapEntry[];
|
|
19
|
+
/** 문서를 다 읽지 못해도 지켜야 하는 핵심 규칙. AGENTS.md에 번호를 매겨 싣는다. */
|
|
20
|
+
readonly rules?: readonly string[];
|
|
21
|
+
/** 작업을 마치기 전에 실행할 검증 명령. 예: `pnpm lint && pnpm test` */
|
|
22
|
+
readonly verify?: string;
|
|
15
23
|
/** 파일을 설치한 뒤 사람이 직접 해야 하는 일. 설치 결과 끝에 안내한다. */
|
|
16
24
|
readonly nextSteps?: readonly string[];
|
|
17
|
-
|
|
18
|
-
|
|
25
|
+
}
|
|
26
|
+
/** 문서 지도의 한 줄. 어떤 문서를 언제 읽는지 알려 준다. */
|
|
27
|
+
export interface DocMapEntry {
|
|
28
|
+
/** 저장소 루트 기준 posix 경로. 예: `docs/workflow.md` */
|
|
29
|
+
readonly path: string;
|
|
30
|
+
/** 이 문서를 읽는 시점. */
|
|
31
|
+
readonly when: string;
|
|
19
32
|
}
|
|
20
33
|
//# sourceMappingURL=preset.d.ts.map
|
package/dist/preset.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../src/preset.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../src/preset.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,MAAM;IACrB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wBAAwB;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,+BAA+B;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,wDAAwD;IACxD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,uCAAuC;AACvC,MAAM,WAAW,WAAW;IAC1B,gDAAgD;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mBAAmB;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB"}
|
package/package.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { Preset } from "./preset.js";
|
|
2
|
-
/**
|
|
3
|
-
* 프리셋과 그 프리셋이 요구하는 프리셋을 설치 순서대로 펼친다.
|
|
4
|
-
*
|
|
5
|
-
* 요구되는 프리셋이 먼저 오고, 여러 경로로 요구돼도 한 번만 들어간다 (이름 기준).
|
|
6
|
-
* 순환 요구는 설치 순서를 정할 수 없으므로 오류로 알린다.
|
|
7
|
-
*/
|
|
8
|
-
export declare function resolvePresets(preset: Preset): Preset[];
|
|
9
|
-
//# sourceMappingURL=resolve-presets.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-presets.d.ts","sourceRoot":"","sources":["../src/resolve-presets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAoBvD"}
|
package/dist/resolve-presets.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 프리셋과 그 프리셋이 요구하는 프리셋을 설치 순서대로 펼친다.
|
|
3
|
-
*
|
|
4
|
-
* 요구되는 프리셋이 먼저 오고, 여러 경로로 요구돼도 한 번만 들어간다 (이름 기준).
|
|
5
|
-
* 순환 요구는 설치 순서를 정할 수 없으므로 오류로 알린다.
|
|
6
|
-
*/
|
|
7
|
-
export function resolvePresets(preset) {
|
|
8
|
-
const ordered = [];
|
|
9
|
-
const done = new Set();
|
|
10
|
-
const visit = (current, path) => {
|
|
11
|
-
if (path.includes(current.name)) {
|
|
12
|
-
throw new Error(`프리셋 요구 관계가 순환합니다: ${[...path, current.name].join(" → ")}`);
|
|
13
|
-
}
|
|
14
|
-
if (done.has(current.name)) {
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
for (const required of current.requires ?? []) {
|
|
18
|
-
visit(required, [...path, current.name]);
|
|
19
|
-
}
|
|
20
|
-
done.add(current.name);
|
|
21
|
-
ordered.push(current);
|
|
22
|
-
};
|
|
23
|
-
visit(preset, []);
|
|
24
|
-
return ordered;
|
|
25
|
-
}
|
|
26
|
-
//# sourceMappingURL=resolve-presets.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-presets.js","sourceRoot":"","sources":["../src/resolve-presets.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,MAAM,KAAK,GAAG,CAAC,OAAe,EAAE,IAAuB,EAAQ,EAAE;QAC/D,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9E,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,OAAO;QACT,CAAC;QACD,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;YAC9C,KAAK,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC,CAAC;IAEF,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAClB,OAAO,OAAO,CAAC;AACjB,CAAC"}
|