| const fs = require('node:fs'); | |
| const path = require('node:path'); | |
| const matter = require('gray-matter'); | |
| const getSlug = require('@docusaurus/plugin-content-docs/lib/slug.js').default; | |
| const {DefaultNumberPrefixParser, stripPathNumberPrefixes} = require('@docusaurus/plugin-content-docs/lib/numberPrefix.js'); | |
| const normalizeVersion = version => version === 'current' ? 'dev' : version; | |
| function availableVersions(root) { | |
| const versions = [root, path.join(root, 'archived_docs')].flatMap(sourceRoot => { | |
| const directory = path.join(sourceRoot, 'versioned_docs'); | |
| return fs.existsSync(directory) ? fs.readdirSync(directory, {withFileTypes: true}) | |
| .filter(entry => entry.isDirectory() && entry.name.startsWith('version-')).map(entry => entry.name.slice(8)) : []; | |
| }); | |
| return [...(fs.existsSync(path.join(root, 'docs')) ? ['dev'] : []), ...[...new Set(versions)].sort((a, b) => b.localeCompare(a, 'en', {numeric: true}))]; | |
| } | |
| function versionRoot(root, version) { | |
| const archived = path.join(root, 'archived_docs'); | |
| return fs.existsSync(path.join(archived, `versioned_docs/version-${version}`)) ? archived : root; | |
| } | |
| function contentDirectory(root, version, locale) { | |
| const current = normalizeVersion(version) === 'dev'; | |
| return path.join(current ? root : versionRoot(root, version), locale === 'en' ? (current ? 'docs' : `versioned_docs/version-${version}`) | |
| : `i18n/${locale}/docusaurus-plugin-content-docs/${current ? 'current' : `version-${version}`}`); | |
| } | |
| function inventory(root, inputVersion, locale) { | |
| const version = normalizeVersion(inputVersion); | |
| if (!availableVersions(root).includes(version)) throw new Error(`Unknown documentation version: ${inputVersion}`); | |
| if (!['en', 'zh-CN'].includes(locale)) throw new Error(`Unsupported documentation locale: ${locale}`); | |
| const directory = contentDirectory(root, version, locale); | |
| if (!fs.existsSync(directory)) throw new Error(`Missing documentation source directory: ${directory}`); | |
| const docs = []; | |
| function walk(dir) { | |
| for (const entry of fs.readdirSync(dir, {withFileTypes: true}).sort((a, b) => a.name.localeCompare(b.name, 'en'))) { | |
| const file = path.join(dir, entry.name); | |
| if (entry.isDirectory()) walk(file); | |
| else if (/\.mdx?$/.test(entry.name)) { | |
| const source = path.relative(directory, file).split(path.sep).join('/'); | |
| const {data, content} = matter(fs.readFileSync(file, 'utf8')); | |
| const basename = path.basename(source).replace(/\.mdx?$/, ''); | |
| const baseID = data.id ?? (data.parse_number_prefixes === false ? basename : DefaultNumberPrefixParser(basename).filename); | |
| const sourceDirName = path.posix.dirname(source); | |
| const dirname = data.parse_number_prefixes === false ? sourceDirName : stripPathNumberPrefixes(sourceDirName, DefaultNumberPrefixParser); | |
| const id = [sourceDirName === '.' ? '' : dirname, baseID].filter(Boolean).join('/'); | |
| const slug = getSlug({baseID, frontMatterSlug: data.slug, source, sourceDirName, | |
| stripDirNumberPrefixes: data.parse_number_prefixes !== false}); | |
| const prefix = locale === 'en' ? '' : `/${locale}`; | |
| docs.push({source, file, id, title: String(data.title ?? content.match(/^#\s+(.+)$/m)?.[1] ?? baseID), | |
| content, route: `${prefix}/docs/${version}${slug}`.replace(/\/$/, ''), position: data.sidebar_position}); | |
| } | |
| } | |
| } | |
| walk(directory); | |
| const sidebarFile = path.join(version === 'dev' ? root : versionRoot(root, version), | |
| version === 'dev' ? 'sidebars.ts' : `versioned_sidebars/version-${version}-sidebars.json`); | |
| if (!fs.existsSync(sidebarFile)) throw new Error(`Missing documentation sidebar: ${sidebarFile}`); | |
| const sidebar = version === 'dev' ? require('jiti')(__filename, {interopDefault: true})(sidebarFile) | |
| : JSON.parse(fs.readFileSync(sidebarFile, 'utf8')); | |
| const order = new Map(); | |
| function visit(value) { | |
| if (typeof value === 'string' && !order.has(value)) order.set(value, order.size); | |
| else if (Array.isArray(value)) value.forEach(visit); | |
| else if (value && typeof value === 'object') { | |
| if (value.type === 'doc') visit(value.id); | |
| if (value.link?.type === 'doc') visit(value.link.id); | |
| if (value.type === 'autogenerated') { | |
| const prefix = value.dirName === '.' ? '' : value.dirName.replace(/\/$/, '') + '/'; | |
| docs.filter(doc => doc.id.startsWith(prefix)).sort((a, b) => | |
| (a.position ?? Infinity) - (b.position ?? Infinity) || a.source.localeCompare(b.source, 'en')).forEach(doc => visit(doc.id)); | |
| } | |
| if (value.items) visit(value.items); | |
| else if (!value.type) Object.values(value).forEach(visit); | |
| } | |
| } | |
| visit(sidebar); | |
| return docs.sort((a, b) => (order.get(a.id) ?? Infinity) - (order.get(b.id) ?? Infinity) || a.source.localeCompare(b.source, 'en')); | |
| } | |
| const filename = (version, locale) => `apache-doris-${normalizeVersion(version)}-${locale}.pdf`; | |
| module.exports = {availableVersions, contentDirectory, inventory, filename, normalizeVersion}; |