diff --git a/docs/content/usage/ejs.md b/docs/content/usage/ejs.md index 1a23388..95c79b9 100644 --- a/docs/content/usage/ejs.md +++ b/docs/content/usage/ejs.md @@ -28,6 +28,4 @@ EJS 模版语言的用法请参考 [EJS 文档](https://www.ejs.co/ "EJS" "_blan 将渲染出来 -``` -PageForge -``` \ No newline at end of file +<%= pageData.title %> \ No newline at end of file diff --git a/lib/file-processor.js b/lib/file-processor.js index 0a6d635..3474202 100644 --- a/lib/file-processor.js +++ b/lib/file-processor.js @@ -7,7 +7,6 @@ const formatTOC = require('./extension/marked/pageforge-toc'); const { getPagePath, appendHtml, - getRelativeBasePath, isFeatureEnabled } = require("./utils"); const TemplateEngine = require("./template-engine"); @@ -19,6 +18,7 @@ const HtmlMinifier = require('./html-minifier'); const GitInfoProvider = require('./git-info-provider'); const I18nProcessor = require('./i18n-processor'); const NavigationProcessor = require('./navigation-processor'); +const PageDataProcessor = require('./page-data-processor'); class FileProcessor { constructor(config, pages, sourcePath, outputPath) { @@ -34,6 +34,7 @@ class FileProcessor { this.gitInfoProvider = new GitInfoProvider(config); this.i18nProcessor = new I18nProcessor(config, pages); this.navigationProcessor = new NavigationProcessor(config, pages); + this.pageDataProcessor = new PageDataProcessor(config, pages); } // 获取缓存的导航数据 @@ -187,27 +188,22 @@ class FileProcessor { const {metadata, content} = this.processMarkdown(sourcePath, locale, relativePath); this.config.languages = this.i18nProcessor.getAvailableLocales() - const forwardPath = this.getPath(relativePath, locale) // 构建基础页面数据 - let pageData = { - pageData: { - config: metadata.config, - toc: metadata.toc, - content: content, - basePath: getRelativeBasePath(baseDir), - layout: metadata.layout || 'layouts/content', - gitInfo, - ...metadata, - ...forwardPath - }, - siteData: { - nav: this.config.nav, - ...this.config - } - }; + let pageData = this.pageDataProcessor.buildBasePageData( + metadata, + content, + relativePath, + locale, + gitInfo + ); // 应用国际化处理 - pageData = this.i18nProcessor.buildI18nPageData(pageData, metadata, locale, this.getCachedNavigation(locale)); + pageData = this.i18nProcessor.buildI18nPageData( + pageData, + metadata, + locale, + this.getCachedNavigation(locale) + ); // 渲染页面 let html = await this.templateEngine.renderWithLayout('layouts/page', pageData); @@ -238,20 +234,9 @@ class FileProcessor { async processLayoutFile(metadata, locale) { metadata.title = this.i18nProcessor.getTranslation(metadata.title, locale); - this.config.languages = this.i18nProcessor.getAvailableLocales(); - const pageData = { - pageData: { - config: metadata.config, - basePath: getRelativeBasePath('/'), - ...metadata - }, - siteData: { - nav: this.config.nav, - ...this.config - } - } + const pageData = this.pageDataProcessor.buildLayoutPageData(metadata, locale); pageData.siteData.nav = this.getCachedNavigation(locale); let html = await this.templateEngine.renderWithLayout('layouts/page', pageData); diff --git a/lib/i18n-processor.js b/lib/i18n-processor.js index 47927b9..6a1f9ca 100644 --- a/lib/i18n-processor.js +++ b/lib/i18n-processor.js @@ -2,7 +2,6 @@ class I18nProcessor { constructor(config, pages) { this.config = config; this.pages = pages; - this.navigationCache = new Map(); } /** diff --git a/lib/navigation-processor.js b/lib/navigation-processor.js index 6da2905..ce5a90b 100644 --- a/lib/navigation-processor.js +++ b/lib/navigation-processor.js @@ -1,5 +1,4 @@ const I18nProcessor = require('./i18n-processor'); -const {transformNavigation} = require("./utils"); class NavigationProcessor { constructor(config, pages) { diff --git a/lib/page-data-processor.js b/lib/page-data-processor.js new file mode 100644 index 0000000..ad2b1ae --- /dev/null +++ b/lib/page-data-processor.js @@ -0,0 +1,78 @@ +const {getPagePath, appendHtml, getRelativeBasePath} = require("./utils"); + +class PageDataProcessor { + constructor(config, pages) { + this.config = config; + this.pages = pages; + } + + /** + * 构建基础页面数据 + * @param {Object} metadata - 页面元数据 + * @param {string} content - 页面内容 + * @param {string} relativePath - 相对路径 + * @param {string} locale - 语言代码 + * @param {Object} gitInfo - Git信息 + * @returns {Object} 处理后的页面数据 + */ + buildBasePageData(metadata, content, relativePath, locale, gitInfo) { + const forwardPath = this.getPath(relativePath, locale); + + return { + pageData: { + config: metadata.config, + toc: metadata.toc, + content: content, + basePath: getRelativeBasePath(relativePath), + layout: metadata.layout || 'layouts/content', + gitInfo, + ...metadata, + ...forwardPath + }, + siteData: { + nav: this.config.nav, + ...this.config + } + }; + } + + /** + * 构建布局页面数据 + * @param {Object} metadata - 页面元数据 + * @param {string} locale - 语言代码 + * @returns {Object} 处理后的布局页面数据 + */ + buildLayoutPageData(metadata, locale) { + return { + pageData: { + config: metadata.config, + basePath: getRelativeBasePath('/'), + ...metadata + }, + siteData: { + nav: this.config.nav, + ...this.config + } + }; + } + + /** + * 获取页面路径信息 + * @private + */ + getPath(relativePath, locale) { + const pagePath = getPagePath(relativePath); + const localPath = appendHtml(pagePath, this.config, locale); + const noLocalePath = this.config.feature?.i18n?.enable + ? localPath.replace(`/${locale}`, '') + : localPath; + + return { + localPath, + noLocalePath, + relativePath: relativePath.replace(locale, '') + }; + } +} + +module.exports = PageDataProcessor; \ No newline at end of file diff --git a/lib/utils.js b/lib/utils.js index a47f763..b2a9659 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -20,23 +20,6 @@ function isFeatureEnabled(config, featureName) { return config.feature?.[featureName]?.enable === true; } -// 获取翻译的方法 -function getTranslation(config, key, locale) { - if (!isFeatureEnabled(config, 'i18n')) { - return key; - } - - const i18n = config.i18n || {}; - // 如果没有指定语言,使用默认语言 - const currentLocale = locale || i18n.default; - - // 直接从配置中获取对应语言的翻译 - const translations = i18n[currentLocale]?.translations; - - // 返回翻译,如果没有找到则返回原key - return translations?.[key] || key; -} - function appendHtml(path, config, locale) { // 如果是字符串,替换 .md 为 .html if (typeof path === 'string') { @@ -82,65 +65,9 @@ function getRelativeBasePath(baseDir) { return Array(depth).fill('..').join('/') || '.'; } -// 递归转换导航 -function transformNavigation(navigation, pages, config, language) { - const getPageData = (path) => { - // 如果开启了国际化且不是默认语言,先尝试获取带语言后缀的页面数据 - if (isFeatureEnabled(config, 'i18n') && language !== config.i18n?.default) { - const langPath = `${path}.${language}`; - const langPageData = pages.get(langPath); - if (langPageData) { - return langPageData; - } - } - // 如果没有找到带语言后缀的数据,返回默认路径的数据 - return pages.get(path); - }; - - const processItem = (item) => { - // 如果是字符串类型的链接(如 "/docs/get-started") - if (typeof item === 'string') { - const pageData = getPageData(item); - if (pageData) { - const title = pageData.title - ? getTranslation(config, pageData.title, language) - : pageData.title; - - return { - ...pageData, - title, - href: appendHtml(item, config, language) - }; - } - // 如果在 pages 中找不到,使用路径最后一段作为标题 - return { - title: item.split('/').pop(), - href: appendHtml(item.replace(/\.(md|html)$/, ''), config, language) - }; - } - - // 如果是对象(有子项的导航) - if (typeof item === 'object') { - const [[title, items]] = Object.entries(item); - const translatedTitle = title ? getTranslation(config, title, language) : title; - - return { - title: translatedTitle, - href: appendHtml(items[0], config, language), - items: Array.isArray(items) ? items.map(processItem) : [] - }; - } - - return item; - }; - - return navigation.map(processItem); -} - module.exports = { getPagePath, isFeatureEnabled, appendHtml, - getRelativeBasePath, - transformNavigation + getRelativeBasePath } \ No newline at end of file