import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; import { parse } from 'yaml'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); /** * 读取Markdown文件的frontmatter部分 * @param {string} filePath - Markdown文件路径 * @returns {Object} - frontmatter数据对象 */ function readMarkdownFrontmatter(filePath) { try { const content = fs.readFileSync(filePath, 'utf-8'); const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/m); if (frontmatterMatch && frontmatterMatch[1]) { try { const yamlContent = frontmatterMatch[1].trim(); console.log(`解析文件: ${filePath}`); console.log(`YAML内容:\n${yamlContent}`); const metadata = parse(yamlContent); console.log(`解析结果:`, metadata); // 确保所有字段都有默认值 return { title: metadata.title || '', name: metadata.name || metadata.title || '', description: metadata.description || '', summary: metadata.summary || '', usage: Array.isArray(metadata.usage) ? metadata.usage : [], categoryId: metadata.categoryId || '', category: metadata.category || '', image: metadata.image || '', series: Array.isArray(metadata.series) ? metadata.series : [], gallery: Array.isArray(metadata.gallery) ? metadata.gallery : [], capacities: Array.isArray(metadata.capacities) ? metadata.capacities : [], products: Array.isArray(metadata.products) ? metadata.products : [], audiences: metadata.audiences, id: metadata.id || '', recommend: metadata.recommend || false, recommendIndex: metadata.recommendIndex || -1 }; } catch (err) { console.error(`解析frontmatter失败: ${filePath}`, err); return {}; } } return {}; } catch (err) { console.error(`读取文件失败: ${filePath}`, err); return {}; } } /** * 获取所有产品ID和详细信息的函数 * @param {string} locale - 语言代码 * @returns {Object[]} - 产品信息数组 */ function getProducts(locale) { try { const productsDir = path.resolve(__dirname, '../content/products', locale); if (!fs.existsSync(productsDir)) { console.log(`找不到产品目录: ${productsDir}`); return []; } // 读取所有.md文件 const productFiles = fs.readdirSync(productsDir) .filter(file => file.endsWith('.md')); console.log(`找到 ${locale} 语言的产品文件: ${productFiles.length}个`); // 读取每个产品文件的frontmatter return productFiles.map(file => { const filePath = path.join(productsDir, file); const metadata = readMarkdownFrontmatter(filePath); console.log(`metadata: ${JSON.stringify(metadata)} ${metadata}`); const id = path.basename(file, '.md'); // 使用原始图片路径,如果没有则使用默认路径 const imagePath = metadata.image; return { id, title: metadata.title || id, name: metadata.name || metadata.title || id, usage: metadata.usage || [], category: metadata.categoryId || '', image: imagePath, description: metadata.description || '', summary: metadata.summary || '', series: metadata.series || [], gallery: metadata.gallery || [], capacities: metadata.capacities || [], recommend: metadata.recommend || false, recommendIndex: metadata.recommendIndex || -1 }; }); } catch (err) { console.error(`获取产品信息时出错 (${locale}):`, err); return []; } } /** * 获取所有用途类别 * @param {string} locale - 语言代码 * @returns {Object[]} - 用途类别数组 */ function getUsages(locale) { try { const usagesDir = path.resolve(__dirname, '../content/usages', locale); if (!fs.existsSync(usagesDir)) { console.log(`找不到用途目录: ${usagesDir}`); return []; } // 读取所有.md文件 const usageFiles = fs.readdirSync(usagesDir) .filter(file => file.endsWith('.md')); // 读取每个用途文件的frontmatter return usageFiles.map(file => { const filePath = path.join(usagesDir, file); const content = fs.readFileSync(filePath, 'utf-8'); const frontmatterMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/m); if (frontmatterMatch && frontmatterMatch[1]) { try { const yamlContent = frontmatterMatch[1].trim(); const metadata = parse(yamlContent); const id = path.basename(file, '.md'); return { id: metadata.id || id, title: metadata.title || id }; } catch (err) { console.error(`解析frontmatter失败: ${filePath}`, err); return {}; } } return { id: path.basename(file, '.md'), title: path.basename(file, '.md'), }; }); } catch (err) { console.error(`获取用途信息时出错 (${locale}):`, err); return []; } } /** * 获取所有分类 * @param {string} locale - 语言代码 * @returns {Object[]} - 分类数组 */ function getCategories(locale) { try { const categoriesDir = path.resolve(__dirname, '../content/categories', locale); if (!fs.existsSync(categoriesDir)) { console.log(`找不到分类目录: ${categoriesDir}`); return []; } // 读取所有.md文件 const categoryFiles = fs.readdirSync(categoriesDir) .filter(file => file.endsWith('.md')); console.log(`找到 ${locale} 语言的分类文件: ${categoryFiles.length}个`); // 读取每个分类文件的frontmatter return categoryFiles.map(file => { const filePath = path.join(categoriesDir, file); const metadata = readMarkdownFrontmatter(filePath); const id = path.basename(file, '.md'); return { id, title: metadata.title, description: metadata.description, image: metadata.image, summary: metadata.summary, capacities: metadata.capacities, sort: metadata.sort, audiences: metadata.audiences, }; }); } catch (err) { console.error(`获取分类信息时出错 (${locale}):`, err); return []; } } // 定义基础路由和支持的语言 const baseRoutes = [ '/', '/products', '/faq', '/contact', '/about', ]; const locales = ['ja', 'en', 'zh']; // 生成所有路由 function generateAllRoutes() { let routes = [...baseRoutes]; // 添加语言前缀路由 zh 是默认语言 locales.forEach(locale => { if (locale !== 'zh') { routes.push(`/${locale}`); baseRoutes.forEach(route => { if (route !== '/') { routes.push(`/${locale}${route}`); } }); } }); // 为每个语言添加产品详情页路由 locales.forEach(locale => { const products = getProducts(locale); const prefixPath = locale === 'zh' ? '' : `/${locale}`; products.forEach(product => { routes.push(`${prefixPath}/products/${product.id}`); }); // 添加按用途筛选的产品列表页 const usages = getUsages(locale); usages.forEach(usage => { routes.push(`${prefixPath}/products?usage=${encodeURIComponent(usage.title)}`); }); // 添加按分类筛选的产品列表页 const categories = getCategories(locale); categories.forEach(category => { routes.push(`${prefixPath}/products?category=${category.id}`); }); }); // 移除重复项 routes = [...new Set(routes)]; console.log(`总共生成了 ${routes.length} 条路由`); return routes; } // 生成路由并保存到文件 const routes = generateAllRoutes(); fs.writeFileSync(path.resolve(__dirname, '../prerenderRoutes.json'), JSON.stringify(routes, null, 2)); console.log('路由生成完成,已保存到 prerenderRoutes.json'); // 输出数据文件,供前端使用 function generateDataFiles() { const dataDir = path.resolve(__dirname, '../public/data'); // 确保目录存在 if (!fs.existsSync(dataDir)) { fs.mkdirSync(dataDir, { recursive: true }); } // 为每种语言生成产品数据 locales.forEach(locale => { const products = getProducts(locale); const usages = getUsages(locale); const categories = getCategories(locale); // 保存产品数据 fs.writeFileSync( path.resolve(dataDir, `products-${locale}.json`), JSON.stringify(products, null, 2) ); // 保存用途数据 fs.writeFileSync( path.resolve(dataDir, `usages-${locale}.json`), JSON.stringify(usages, null, 2) ); // 保存分类数据 fs.writeFileSync( path.resolve(dataDir, `categories-${locale}.json`), JSON.stringify(categories, null, 2) ); }); console.log('数据文件生成完成,已保存到 public/data 目录'); } // 生成数据文件 generateDataFiles();