diff --git a/.yarnrc.yml b/.yarnrc.yml index 3186f3f079..9c99859f73 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -1 +1,8 @@ nodeLinker: node-modules +packageExtensions: + "@patternfly/patternfly-doc-core@*": + peerDependenciesMeta: + astro: + optional: true + "@patternfly/react-icons": + optional: true diff --git a/packages/documentation-framework/scripts/cli/generate.js b/packages/documentation-framework/scripts/cli/generate.js index ed37138d78..bf67c48ecf 100644 --- a/packages/documentation-framework/scripts/cli/generate.js +++ b/packages/documentation-framework/scripts/cli/generate.js @@ -8,7 +8,7 @@ function getSource(options) { async function generate(options) { const start = new Date(); console.log('write source files to patternfly-docs/generated'); - const sourceMDWithOptions = (glob, source, ignore) => sourceMD(glob, source, ignore, options._name); + const sourceMDWithOptions = (glob, source, ignore, mdOptions) => sourceMD(glob, source, ignore, options._name, mdOptions); getSource(options)(sourceMDWithOptions, sourceProps, sourceFunctionDocs); await waitForProps(); processMD(); diff --git a/packages/documentation-framework/scripts/md/parseMD.js b/packages/documentation-framework/scripts/md/parseMD.js index 49967e5460..a5e084b8ec 100644 --- a/packages/documentation-framework/scripts/md/parseMD.js +++ b/packages/documentation-framework/scripts/md/parseMD.js @@ -25,7 +25,7 @@ const globs = { md: [], }; -function toReactComponent(mdFilePath, source, buildMode) { +function toReactComponent(mdFilePath, source, buildMode, { frontmatterDefaults, frontmatterMapping } = {}) { // vfiles allow for nicer error messages and have native `unified` support const vfile = toVfile.readSync(mdFilePath); @@ -47,6 +47,23 @@ function toReactComponent(mdFilePath, source, buildMode) { } frontmatter = yaml.load(yamlNode.value); + // Apply frontmatter mapping (e.g., { title: "id" } maps title -> id) + if (frontmatterMapping) { + Object.entries(frontmatterMapping).forEach(([fromKey, toKey]) => { + if (frontmatter[fromKey] !== undefined && frontmatter[toKey] === undefined) { + frontmatter[toKey] = frontmatter[fromKey]; + } + }); + } + // Apply frontmatter defaults (e.g., { section: "AI" }) + if (frontmatterDefaults) { + Object.entries(frontmatterDefaults).forEach(([key, value]) => { + if (frontmatter[key] === undefined) { + frontmatter[key] = value; + } + }); + } + // Fail early if (!frontmatter.id) { file.fail('id attribute is required in frontmatter for PatternFly docs'); @@ -276,7 +293,7 @@ async function sourcePropsFile(file) { }); } -function sourceMDFile(file, source, buildMode) { +function sourceMDFile(file, source, buildMode, options) { if (path.basename(file).startsWith('_')) { return; } @@ -285,7 +302,7 @@ function sourceMDFile(file, source, buildMode) { if (source === 'design-guidelines' && file.includes('/accessibility/')) { return; } - const { jsx, pageData, outPath } = toReactComponent(file, source, buildMode); + const { jsx, pageData, outPath } = toReactComponent(file, source, buildMode, options); if (jsx) { fs.outputFileSync(outPath, jsx); @@ -352,12 +369,12 @@ module.exports = { async waitForProps() { await Promise.all(pendingProps); }, - sourceMD(glob, source, ignore, buildMode) { - globs.md.push({ glob, source, ignore, buildMode }); + sourceMD(glob, source, ignore, buildMode, options) { + globs.md.push({ glob, source, ignore, buildMode, options }); }, processMD() { - globs.md.forEach(({ glob, source, ignore, buildMode }) => { - globSync(glob, { ignore }).forEach(file => sourceMDFile(file, source, buildMode)); + globs.md.forEach(({ glob, source, ignore, buildMode, options }) => { + globSync(glob, { ignore }).forEach(file => sourceMDFile(file, source, buildMode, options)); }); }, sourceFunctionDocs, @@ -373,10 +390,10 @@ module.exports = { propWatcher.on('add', onPropFile); propWatcher.on('change', onPropFile); }); - globs.md.forEach(({ glob, source, ignore }) => { + globs.md.forEach(({ glob, source, ignore, options }) => { const mdWatcher = chokidar.watch(globSync(glob, { ignored: ignore, ignoreInitial: true })); function onMDFileChange(file) { - sourceMDFile(file, source, 'start'); + sourceMDFile(file, source, 'start', options); writeIndex(); } mdWatcher.on('add', onMDFileChange); diff --git a/packages/documentation-site/patternfly-docs/patternfly-docs.source.js b/packages/documentation-site/patternfly-docs/patternfly-docs.source.js index 3bfd619d90..de2c6f4e08 100644 --- a/packages/documentation-site/patternfly-docs/patternfly-docs.source.js +++ b/packages/documentation-site/patternfly-docs/patternfly-docs.source.js @@ -22,6 +22,15 @@ module.exports = (sourceMD, sourceProps, sourceFunctionDocs) => { sourceMD(path.join(contentBase, 'AI/**/*.md'), 'AI'); + // AI guidelines from @project-felt/ai-guidelines + const aiGuidelinesPath = require + .resolve('@project-felt/ai-guidelines/package.json') + .replace('package.json', 'content'); + sourceMD(path.join(aiGuidelinesPath, '*.md'), 'AI', undefined, { + frontmatterMapping: { title: 'id' }, + frontmatterDefaults: { section: 'AI', subsection: 'Guidelines' } + }); + sourceMD(path.join(contentBase, 'get-help/**/*.md'), 'get-help'); sourceMD(path.join(contentBase, 'get-involved/**/*.md'), 'get-involved'); diff --git a/packages/site/package.json b/packages/site/package.json index df6081b868..d190d0566d 100644 --- a/packages/site/package.json +++ b/packages/site/package.json @@ -19,6 +19,7 @@ "dependencies": { "@patternfly/patternfly-doc-core": "^1.22.0", "@patternfly/react-icons": "^6.5.0-prerelease.29", + "@project-felt/ai-guidelines": "^1.0.0", "astro": "^5.18.0" }, "devDependencies": { diff --git a/packages/site/pf-docs.config.mjs b/packages/site/pf-docs.config.mjs index 8939b08dcb..0029cdfd59 100644 --- a/packages/site/pf-docs.config.mjs +++ b/packages/site/pf-docs.config.mjs @@ -89,6 +89,13 @@ export const config = { base: "../../node_modules/@patternfly/chatbot", pattern: "patternfly-docs/**/*.{md,mdx}", name: "chatbot-docs", + }, + { + base: "../../node_modules/@project-felt/ai-guidelines", + pattern: "content/*.md", + name: "ai-guidelines", + frontmatterDefaults: { section: "AI", subsection: "Guidelines" }, + frontmatterMapping: { title: "id" }, } ], navSectionOrder: [], diff --git a/yarn.lock b/yarn.lock index b43e9cafee..0f8700aa65 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5862,6 +5862,13 @@ __metadata: languageName: node linkType: hard +"@project-felt/ai-guidelines@npm:^1.0.0": + version: 1.0.0 + resolution: "@project-felt/ai-guidelines@npm:1.0.0" + checksum: 10c0/b0338f288ae0c6e27c0bebf5bd6bbafab1e7b9550afb48ee284235e6cc7b4648ea87e630ce26017b972f411693c7da9f0ad1fa468ab5c8d5cce780ecf9e727c0 + languageName: node + linkType: hard + "@puppeteer/browsers@npm:2.13.0": version: 2.13.0 resolution: "@puppeteer/browsers@npm:2.13.0" @@ -21333,6 +21340,7 @@ __metadata: dependencies: "@patternfly/patternfly-doc-core": "npm:^1.22.0" "@patternfly/react-icons": "npm:^6.5.0-prerelease.29" + "@project-felt/ai-guidelines": "npm:^1.0.0" astro: "npm:^5.18.0" tsx: "npm:^4.21.0" wrangler: "npm:^4.69.0"