@handsupmin/gc-tree 0.7.0 → 0.7.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/dist/src/markdown.js +52 -0
- package/dist/src/onboard.js +3 -3
- package/dist/src/store.js +13 -8
- package/package.json +1 -1
package/dist/src/markdown.js
CHANGED
|
@@ -7,6 +7,29 @@ export function slugify(value) {
|
|
|
7
7
|
.replace(/^-|-$/g, '');
|
|
8
8
|
return normalized || 'doc';
|
|
9
9
|
}
|
|
10
|
+
function parseDocReference(value) {
|
|
11
|
+
const trimmed = String(value || '').trim().replace(/^\.?\//, '');
|
|
12
|
+
if (!trimmed)
|
|
13
|
+
return null;
|
|
14
|
+
const normalized = trimmed.replace(/\\/g, '/');
|
|
15
|
+
const docsMatch = normalized.match(/^docs\/([^/]+)\/([^/]+?)(?:\.md)?$/i);
|
|
16
|
+
if (docsMatch) {
|
|
17
|
+
const category = normalizeCategory(docsMatch[1]);
|
|
18
|
+
const slug = slugify(docsMatch[2]);
|
|
19
|
+
if (slug === 'index')
|
|
20
|
+
return null;
|
|
21
|
+
return { category, slug, label: docsMatch[2].replace(/\.md$/i, '').trim() };
|
|
22
|
+
}
|
|
23
|
+
const directMatch = normalized.match(/^(role|repos|domain|workflows|conventions|infra|verification)\/([^/]+?)(?:\.md)?$/i);
|
|
24
|
+
if (directMatch) {
|
|
25
|
+
const category = normalizeCategory(directMatch[1]);
|
|
26
|
+
const slug = slugify(directMatch[2]);
|
|
27
|
+
if (slug === 'index')
|
|
28
|
+
return null;
|
|
29
|
+
return { category, slug, label: directMatch[2].replace(/\.md$/i, '').trim() };
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
10
33
|
export function ensureSummary(summary) {
|
|
11
34
|
const trimmed = String(summary || '').trim();
|
|
12
35
|
if (!trimmed) {
|
|
@@ -158,6 +181,35 @@ export function extractIndexEntries(markdown) {
|
|
|
158
181
|
.map((line) => line.slice(2).trim())
|
|
159
182
|
.filter(Boolean);
|
|
160
183
|
}
|
|
184
|
+
export function normalizeIndexEntry(value, fallback) {
|
|
185
|
+
const reference = parseDocReference(value);
|
|
186
|
+
if (reference) {
|
|
187
|
+
return {
|
|
188
|
+
category: reference.category,
|
|
189
|
+
label: reference.label,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
const trimmed = String(value || '').trim();
|
|
193
|
+
if (!trimmed)
|
|
194
|
+
return null;
|
|
195
|
+
if (/^docs\/index\.md$/i.test(trimmed) || /^index\.md$/i.test(trimmed))
|
|
196
|
+
return null;
|
|
197
|
+
return {
|
|
198
|
+
category: fallback.category,
|
|
199
|
+
label: trimmed,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
export function inferDocPlacement(input) {
|
|
203
|
+
for (const candidate of [input.slug, input.indexLabel]) {
|
|
204
|
+
const reference = parseDocReference(candidate || '');
|
|
205
|
+
if (reference) {
|
|
206
|
+
return { category: reference.category, slug: reference.slug };
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const explicitCategory = input.category ? slugify(input.category) : null;
|
|
210
|
+
const slug = slugify(input.slug || input.indexLabel || input.title);
|
|
211
|
+
return { category: explicitCategory, slug };
|
|
212
|
+
}
|
|
161
213
|
export function extractSummary(markdown) {
|
|
162
214
|
const match = String(markdown || '').match(/## Summary\s+([\s\S]*?)(?:\n## |$)/);
|
|
163
215
|
return match?.[1]?.trim() || '';
|
package/dist/src/onboard.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { mkdir, rm, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { inferDocPlacement, renderDocMarkdown } from './markdown.js';
|
|
4
4
|
import { branchDocsDir, DEFAULT_BRANCH } from './paths.js';
|
|
5
5
|
import { ensureBranchExists, updateBranchMeta, writeIndexFromDocs } from './store.js';
|
|
6
6
|
function docRelativePath(doc) {
|
|
7
7
|
if (doc.slug?.includes('/'))
|
|
8
8
|
return `${doc.slug.replace(/\.md$/i, '')}.md`;
|
|
9
|
-
const
|
|
10
|
-
const
|
|
9
|
+
const { category, slug } = inferDocPlacement(doc);
|
|
10
|
+
const fileBase = slug;
|
|
11
11
|
return category ? `${category}/${fileBase}.md` : `${fileBase}.md`;
|
|
12
12
|
}
|
|
13
13
|
export async function onboardBranch({ home, input, branch, }) {
|
package/dist/src/store.js
CHANGED
|
@@ -2,7 +2,7 @@ import { cp, mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises';
|
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { branchDir, branchDocsDir, branchIndexPath, branchMetaPath, branchesRoot, DEFAULT_BRANCH, headPath, } from './paths.js';
|
|
5
|
-
import { extractIndexEntries, renderIndexMarkdown } from './markdown.js';
|
|
5
|
+
import { extractIndexEntries, inferDocPlacement, normalizeIndexEntry, renderIndexMarkdown } from './markdown.js';
|
|
6
6
|
async function listDocRelativePaths(dir, prefix = '') {
|
|
7
7
|
const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
8
8
|
const files = [];
|
|
@@ -113,14 +113,19 @@ export async function writeIndexFromDocs(home, branch) {
|
|
|
113
113
|
const raw = await readFile(join(docsDir, file), 'utf8');
|
|
114
114
|
const title = raw.match(/^#\s+(.+)$/m)?.[1]?.trim() || file.replace(/\.md$/i, '').replace(/-/g, ' ');
|
|
115
115
|
const parts = file.replace(/\.md$/i, '').split('/').filter(Boolean);
|
|
116
|
-
const
|
|
117
|
-
const
|
|
118
|
-
const
|
|
119
|
-
const
|
|
120
|
-
|
|
116
|
+
const fallbackCategory = parts.length > 1 ? parts[0] : 'general';
|
|
117
|
+
const fallbackLabel = parts.length > 1 ? parts[parts.length - 1] : title;
|
|
118
|
+
const inferred = inferDocPlacement({ title, indexLabel: title });
|
|
119
|
+
const docCategory = inferred.category || fallbackCategory;
|
|
120
|
+
const indexEntries = extractIndexEntries(raw)
|
|
121
|
+
.map((entry) => normalizeIndexEntry(entry, { category: docCategory, label: fallbackLabel }))
|
|
122
|
+
.filter((entry) => Boolean(entry));
|
|
123
|
+
const entryLabels = indexEntries.length > 0 ? indexEntries : [{ category: docCategory, label: fallbackLabel }];
|
|
124
|
+
const uniqueEntries = [...new Map(entryLabels.map((entry) => [`${entry.category}::${entry.label}`, entry])).values()];
|
|
125
|
+
return uniqueEntries.map((entry) => ({
|
|
121
126
|
title,
|
|
122
|
-
label:
|
|
123
|
-
category,
|
|
127
|
+
label: entry.label,
|
|
128
|
+
category: entry.category,
|
|
124
129
|
path: `docs/${file}`,
|
|
125
130
|
}));
|
|
126
131
|
}));
|