| // Copyright 2025 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| import fs from 'node:fs'; | |
| import path from 'node:path'; | |
| import yargs from 'yargs'; | |
| import {hideBin} from 'yargs/helpers'; | |
| const argv = yargs(hideBin(process.argv)) | |
| .option('html-output-file', { | |
| type: 'string', | |
| demandOption: true, | |
| }) | |
| .option('js-output-file', { | |
| type: 'string', | |
| demandOption: true, | |
| }) | |
| .option('sources-file', { | |
| type: 'string', | |
| demandOption: true, | |
| }) | |
| .option('environment-setup-file', { | |
| type: 'string', | |
| demandOption: true, | |
| }) | |
| .parseSync(); | |
| const HTML_OUTPUT_FILE = argv.htmlOutputFile; | |
| const JS_OUTPUT_FILE = argv.jsOutputFile; | |
| const SOURCES_FILE = argv.sourcesFile; | |
| const ENVIRONMENT_FILE = argv.environmentSetupFile; | |
| if (!HTML_OUTPUT_FILE || !JS_OUTPUT_FILE || !SOURCES_FILE || !ENVIRONMENT_FILE) { | |
| console.error( | |
| 'Usage: node generate_docs.js --devtools-frontend-path <path> --html-output-file <path> --js-output-file <path> --sources-file <path> --environment-setup-file <path>'); | |
| process.exit(1); | |
| } | |
| async function main() { | |
| const componentDocs = JSON.parse(fs.readFileSync(SOURCES_FILE, 'utf-8')); | |
| const componentLinks = componentDocs | |
| .map(p => path.basename(p, '.docs.js')) | |
| .sort() | |
| .map(componentName => `<li><a href="#${componentName}">${componentName}</a></li>`) | |
| .join('\n'); | |
| const docImports = componentDocs | |
| .map(p => { | |
| const componentName = path.basename(p, '.docs.js'); | |
| return `'${componentName}': () => import('${p}'),`; | |
| }) | |
| .join('\n'); | |
| let environmentSetupPath = path.relative(path.dirname(JS_OUTPUT_FILE), ENVIRONMENT_FILE); | |
| if (!environmentSetupPath.startsWith('.')) { | |
| environmentSetupPath = `./${environmentSetupPath}`; | |
| } | |
| const docLoader = ` | |
| import {setup, cleanup} from '${environmentSetupPath}'; | |
| const components = { | |
| ${docImports} | |
| }; | |
| const mainContent = document.querySelector('.main-content'); | |
| async function loadComponent(name) { | |
| if (!components[name] || !mainContent) { | |
| return; | |
| } | |
| let container = document.getElementById('container'); | |
| // Replace the container to start off with a clean one. | |
| if (container) { | |
| container.remove(); | |
| await cleanup(); | |
| } | |
| container = document.createElement('div'); | |
| container.id = 'container'; | |
| mainContent.appendChild(container); | |
| await setup(); | |
| const {render} = await components[name](); | |
| render(container); | |
| } | |
| window.addEventListener('hashchange', () => { | |
| const componentName = window.location.hash.substr(1); | |
| loadComponent(componentName); | |
| }); | |
| if (window.location.hash) { | |
| loadComponent(window.location.hash.substr(1)); | |
| } | |
| `; | |
| const styleSheets = [ | |
| 'front_end/design_system_tokens.css', | |
| 'front_end/application_tokens.css', | |
| 'front_end/ui/legacy/inspectorCommon.css', | |
| 'front_end/ui/components/buttons/textButton.css', | |
| 'scripts/component_docs/component_docs.css', | |
| ]; | |
| const linksToStyleSheets = styleSheets | |
| .map( | |
| link => `<link rel="stylesheet" href="./${link}" type="text/css" />`, | |
| ) | |
| .join('\n'); | |
| // The path to the loader script is now relative from the root of gen/. | |
| const loaderScriptPath = path.relative(path.dirname(HTML_OUTPUT_FILE), JS_OUTPUT_FILE); | |
| const indexHtml = ` | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width" /> | |
| <title>DevTools components</title> | |
| <script type="importmap"> | |
| { | |
| "imports": { | |
| "chai": "data:text/javascript,export const assert = new Proxy({}, {get: () => () => {}});", | |
| "sinon": "data:text/javascript,export default new Proxy({}, {get: () => () => new Proxy({}, {get: () => () => {}})});" | |
| } | |
| } | |
| </script> | |
| ${linksToStyleSheets} | |
| </head> | |
| <body> | |
| <nav class="sidebar"> | |
| <h1>DevTools components</h1> | |
| <ul class="components-list"> | |
| ${componentLinks} | |
| </ul> | |
| </nav> | |
| <div class="divider"></div> | |
| <main class="main-content"> | |
| <div id="container"></div> | |
| </main> | |
| <script type="module" src="${loaderScriptPath}"></script> | |
| </body> | |
| </html> | |
| `; | |
| fs.writeFileSync(HTML_OUTPUT_FILE, indexHtml); | |
| fs.writeFileSync(JS_OUTPUT_FILE, docLoader); | |
| } | |
| main(); |