Add remaining samples, tooling, and local project assets

This commit is contained in:
kmlee1 committed 2026-04-15 18:02:17 +09:00
1 parent 05d43a7999
commit 1ff6c6cbb2
862 files changed
+18979 -21

No files matched your search

+143
View File
@@ -0,0 +1,143 @@
import fs from 'fs';
import path from 'path';
import { getCollection } from 'astro:content';
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkGfm from 'remark-gfm';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import { pageRoutes } from './navigation.js';
/* -------------------------------
* Markdown → 순수 텍스트
* ------------------------------- */
export async function extractPlainText(markdown) {
if (!markdown) return '';
const cleaned = markdown
.replace(/^import\s+.*from\s+['"].*['"];?$/gm, '')
.replace(/<!--[\s\S]*?-->/g, '')
.replace(/<[^>]+>/g, '')
.trim();
const result = await unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeStringify)
.process(cleaned);
return String(result)
.replace(/<[^>]+>/g, ' ')
.replace(/&[a-zA-Z#0-9]+;/g, ' ')
.replace(/\s{2,}/g, ' ')
.trim();
}
/* -------------------------------
* Astro 파일 → 순수 텍스트
* ------------------------------- */
export function extractAstroText(fileContent) {
return fileContent
.replace(/---[\s\S]*?---/g, '')
.replace(/<script[\s\S]*?<\/script>/gi, '')
.replace(/<style[\s\S]*?<\/style>/gi, '')
.replace(/<!--[\s\S]*?-->/g, '')
.replace(/\{[\s\S]*?\}/g, '')
.replace(/<[^>]+>/g, ' ')
.replace(/&nbsp;/gi, ' ')
.replace(/\s{2,}/g, ' ')
.trim();
}
/* -------------------------------
* 폴더 재귀 탐색
* ------------------------------- */
function getAstroFiles(dir) {
if (!fs.existsSync(dir)) return [];
const entries = fs.readdirSync(dir, { withFileTypes: true });
let results = [];
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) results = results.concat(getAstroFiles(fullPath));
else if (entry.isFile() && entry.name.endsWith('.astro')) results.push(fullPath);
}
return results;
}
/* -------------------------------
* 전체 검색 데이터 생성
* ------------------------------- */
export async function generateSearchData() {
// ① Docs 전부
const allDocs = await getCollection('docs');
const mdxSearchData = await Promise.all(
allDocs.map(async (doc) => {
const plain = await extractPlainText(doc.body);
const text = plain.toLowerCase();
const slugPath = (doc.slug || doc.id).replace(/^ko\//, '');
const url = `/${slugPath}${slugPath.endsWith('/') ? '' : '/'}`;
return {
id: slugPath,
title: doc.data.title || slugPath,
titleLower: (doc.data.title || slugPath).toLowerCase(),
content: plain.slice(0, 500),
fullContent: plain,
fullLower: text,
url,
category: 'mdx',
type: 'mdx'
};
})
);
// ② 메뉴
const menuSearchData = pageRoutes
.filter(r => r.path?.startsWith('/'))
.map(route => {
const rawTitle = route.title || path.basename(route.path);
const titleText = rawTitle.startsWith('가이드-') ? rawTitle.substring(4) : rawTitle;
return {
id: route.path,
title: titleText,
titleLower: titleText.toLowerCase(),
content: '',
fullContent: '',
fullLower: '',
url: `/help${route.path}`,
category: 'menu',
type: 'menu'
};
});
// ③ 실제 Astro 파일
const subRoot = path.resolve('./src/content/sub');
const subFiles = getAstroFiles(subRoot);
const subSearchData = subFiles.map(filePath => {
const content = fs.readFileSync(filePath, 'utf-8');
const text = extractAstroText(content);
const fileName = path.basename(filePath, '.astro');
// ✅ navigation/pageRoutes에서 title 가져오기
const route = pageRoutes.find(r => r.path.endsWith(fileName));
let title = route
? route.title.startsWith('가이드-') ? route.title.substring(4) : route.title
: content.match(/<title>(.*?)<\/title>/i)?.[1] ||
content.match(/<h1[^>]*>(.*?)<\/h1>/i)?.[1] ||
fileName;
return {
id: fileName,
title,
titleLower: title.toLowerCase(),
content: text.slice(0, 500),
fullContent: text,
fullLower: text.toLowerCase(),
url: `/help/${fileName}`,
category: 'astro-file',
type: 'astro-file'
};
});
return [...mdxSearchData, ...menuSearchData, ...subSearchData];
}