website/generate-plugin-docs.ts (115 lines of code) (raw):

/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format */ import fs from 'fs-extra'; import path from 'path'; const repoRoot = path.resolve(__dirname, '..'); const pluginsDir = path.join( repoRoot, 'desktop', 'plugins', 'public', ); const fbPluginsDir = path.resolve( repoRoot, 'desktop', 'plugins', 'fb' ) const generatedPluginsDocsDir = path.resolve( repoRoot, 'docs', 'features', 'plugins', ); const generatedPluginsSetupDocsDir = path.resolve( repoRoot, 'docs', 'setup', 'plugins' ); const generatedPluginSymlinksDir = path.resolve( __dirname, 'src', 'embedded-pages', 'docs', 'plugins' ); const repoUrl = process.env.FB_INTERNAL ? 'https://www.internalfb.com/code/fbsource/xplat/sonar' : 'https://github.com/facebook/flipper/blob/main'; const relativePluginSymlinksDir = path.relative( generatedPluginsDocsDir, generatedPluginSymlinksDir, ); async function generatePluginDocs() { await Promise.all([fs.emptyDir(generatedPluginsDocsDir), fs.emptyDir(generatedPluginsSetupDocsDir), fs.emptyDir(generatedPluginSymlinksDir)]); const publicDirs = (await fs.readdir(pluginsDir)).map(dir => path.join(pluginsDir, dir)); const fbDirs = process.env.FB_INTERNAL ? (await fs.readdir(fbPluginsDir)).map(dir => path.join(fbPluginsDir, dir)) : []; const allDirs = [...publicDirs, ...fbDirs]; for (const pluginSourceDir of allDirs) { const pluginSourceDocsDir = path.join(pluginSourceDir, 'docs'); const packageJsonPath = path.join(pluginSourceDir, 'package.json'); if ( ( await Promise.all([ fs.pathExists(pluginSourceDocsDir), fs.pathExists(packageJsonPath), ]) ).every(p => p) ) { console.log(`Found docs in ${pluginSourceDir}`); const packageJson = await fs.readJson(packageJsonPath); const name: string = packageJson.name; const title: string = packageJson.title; const id = name.replace('flipper-plugin-', ''); const generatedPluginResourcesPath = path.join(generatedPluginSymlinksDir, id); await fs.symlink(pluginSourceDocsDir, generatedPluginResourcesPath, 'junction'); const setupDocPath = path.join(pluginSourceDocsDir, 'setup.mdx'); const setupDocsExists = await fs.pathExists( setupDocPath, ); const overviewDocPath = path.join(pluginSourceDocsDir, 'overview.mdx'); const overviewDocsExists = await fs.pathExists( overviewDocPath, ); if (setupDocsExists) { const customEditUrl = `${repoUrl}/${path.relative(repoRoot, setupDocPath)}`; await fs.writeFile( path.join(generatedPluginsSetupDocsDir, `${id}.mdx`), `--- id: ${id} title: ${title} Plugin Setup sidebar_label: ${title} custom_edit_url: ${customEditUrl} --- import Article from '${relativePluginSymlinksDir}/${id}/setup.mdx'; <Article /> `, ); } if (overviewDocsExists) { const customEditUrl = `${repoUrl}/${path.relative(repoRoot, overviewDocPath)}`; const linkToSetup = setupDocsExists ? ` → [See setup instructions for the ${title} plugin](../../setup/plugins/${id}.mdx) ` : ''; await fs.writeFile( path.join(generatedPluginsDocsDir, `${id}.mdx`), `--- id: ${id} title: ${title} Plugin sidebar_label: ${title} custom_edit_url: ${customEditUrl} --- import Article from '${relativePluginSymlinksDir}/${id}/overview.mdx'; ${linkToSetup} <Article /> `, ); } } } } generatePluginDocs() .then(() => process.exit(0)) .catch(err => { console.error(err); process.exit(1); });