// Copyright 2021 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. const fs = require('fs'); const http = require('http'); const path = require('path'); const parseURL = require('url').parse; const {argv} = require('yargs'); const {getTestRunnerConfigSetting} = require('../test/test_config_helpers.js'); const serverPort = parseInt(process.env.PORT, 10) || 8090; const target = argv.target || process.env.TARGET || 'Default'; /** * This configures the base of the URLs that are injected into each component * doc example to load. By default it's /, so that we load /front_end/..., but * this can be configured if you have a different file structure. */ const sharedResourcesBase = argv.sharedResourcesBase || getTestRunnerConfigSetting('component-server-shared-resources-path', '/'); /** * The server assumes that examples live in * devtoolsRoot/out/Target/gen/front_end/ui/components/docs, but if you need to add a * prefix you can pass this argument. Passing `foo` will redirect the server to * look in devtoolsRoot/out/Target/gen/foo/front_end/ui/components/docs. */ const componentDocsBaseArg = argv.componentDocsBase || process.env.COMPONENT_DOCS_BASE || getTestRunnerConfigSetting('component-server-base-path', ''); /** * When you run npm run components-server we run the script as is from scripts/, * but when this server is run as part of a test suite it's run from * out/Default/gen/scripts, so we have to do a bit of path mangling to figure * out where we are. */ const isRunningInGen = __dirname.includes(path.join('out', path.sep, target)); let pathToOutTargetDir = __dirname; /** * If we are in the gen directory, we need to find the out/Default folder to use * as our base to find files from. We could do this with path.join(x, '..', * '..') until we get the right folder, but that's brittle. It's better to * search up for out/Default to be robust to any folder structures. */ while (isRunningInGen && !pathToOutTargetDir.endsWith(`out${path.sep}${target}`)) { pathToOutTargetDir = path.resolve(pathToOutTargetDir, '..'); } /* If we are not running in out/Default, we'll assume the script is running from the repo root, and navigate to {CWD}/out/Target */ const pathToBuiltOutTargetDirectory = isRunningInGen ? pathToOutTargetDir : path.resolve(path.join(process.cwd(), 'out', target)); const devtoolsRootFolder = path.resolve(path.join(pathToBuiltOutTargetDirectory, 'gen')); const componentDocsBaseFolder = path.join(devtoolsRootFolder, componentDocsBaseArg); if (!fs.existsSync(devtoolsRootFolder)) { console.error(`ERROR: Generated front_end folder (${devtoolsRootFolder}) does not exist.`); console.log( 'The components server works from the built Ninja output; you may need to run Ninja to update your built DevTools.'); console.log('If you build to a target other than default, you need to pass --target=X as an argument'); process.exit(1); } const server = http.createServer(requestHandler); server.listen(serverPort); server.once('listening', () => { if (process.send) { process.send(serverPort); } console.log(`Started components server at http://localhost:${serverPort}\n`); console.log(`ui/components/docs location: ${ path.relative(process.cwd(), path.join(componentDocsBaseFolder, 'front_end', 'ui', 'components', 'docs'))}`); }); server.once('error', error => { if (process.send) { process.send('ERROR'); } throw error; }); function createComponentIndexFile(componentPath, componentExamples) { const componentName = componentPath.replace('/front_end/ui/components/docs/', '').replace(/_/g, ' ').replace('/', ''); // clang-format off return `