|
1 | 1 | #! /usr/bin/env node |
2 | 2 |
|
3 | | -/* eslint-disable */ |
4 | | -var { program } = require('commander'); |
5 | | -var path = require('path'); |
6 | | -var shell = require('shelljs'); |
7 | | -var fs = require('fs'); |
8 | | -var examples = {}; |
9 | | -var basePath = path.resolve('./Documentation'); |
10 | | -var webpackConfigPath = path.join(__dirname, 'webpack.config.js'); |
11 | | -var distDir = path.join(__dirname, 'dist'); |
12 | | -var buildConfig = require('./template-config.js'); |
13 | | -const rootPath = path.resolve(path.join(__dirname, '../..')); |
14 | | -var webpackSettings = require(path.join(rootPath, 'webpack.settings.js')); |
| 3 | +/* eslint-disable no-console */ |
| 4 | +const { program } = require('commander'); |
| 5 | +const path = require('path'); |
| 6 | +const fs = require('fs'); |
| 7 | + |
| 8 | +const REPO_ROOT = path.resolve(__dirname, '../..'); |
| 9 | +const SOURCES_ROOT = path.join(REPO_ROOT, 'Sources'); |
| 10 | +const EXAMPLES_ROOT = path.join(REPO_ROOT, 'Examples'); |
| 11 | +const VITE_CONFIG_PATH = path.join( |
| 12 | + REPO_ROOT, |
| 13 | + 'Utilities', |
| 14 | + 'ExampleRunner', |
| 15 | + 'vite.example.config.mjs' |
| 16 | +); |
| 17 | +const DEFAULT_HOST = '0.0.0.0'; |
| 18 | +const DEFAULT_PORT = '3000'; |
15 | 19 |
|
16 | 20 | program |
17 | 21 | .option('--no-browser', 'Do not open the browser') |
18 | | - .option('--server-type <type>', 'Specify http (default) or self-signed https for serving examples', 'http') |
| 22 | + .option( |
| 23 | + '--server-type <type>', |
| 24 | + 'Specify http (default) or self-signed https for serving examples', |
| 25 | + 'http' |
| 26 | + ) |
19 | 27 | .parse(process.argv); |
20 | 28 |
|
21 | 29 | const options = program.opts(); |
22 | 30 |
|
23 | | -function getSplitedPath(filePath) { |
24 | | - var a = filePath.split('/'); |
25 | | - var b = filePath.split('\\'); |
26 | | - return a.length > b.length ? a : b; |
| 31 | +function normalizePath(filePath) { |
| 32 | + return filePath.replace(/\\/g, '/'); |
| 33 | +} |
| 34 | + |
| 35 | +function isClassExample(relPath) { |
| 36 | + return /\/example\/index\.js$/.test(relPath); |
27 | 37 | } |
28 | 38 |
|
29 | | -function validPath(str) { |
30 | | - return str.replace(/\//g, path.sep); |
| 39 | +function isStandaloneExample(relPath) { |
| 40 | + const parts = relPath.split('/'); |
| 41 | + return parts.length === 3 && parts[2] === 'index.js'; |
31 | 42 | } |
32 | 43 |
|
33 | | -// ---------------------------------------------------------------------------- |
34 | | -// Find examples |
35 | | -// ---------------------------------------------------------------------------- |
36 | | - |
37 | | -if (webpackSettings.examples) { |
38 | | - var filterExamples = [].concat(program.args).filter(i => !!i); |
39 | | - var buildExample = filterExamples.length === 1; |
40 | | - var exampleCount = 0; |
41 | | - |
42 | | - console.log('\n=> Extract examples\n'); |
43 | | - webpackSettings.examples.forEach(function (entry) { |
44 | | - const regexp = entry.regexp ? new RegExp(entry.regexp) : /example\/index.js$/; |
45 | | - var fullPath = path.join(basePath, entry.path ? entry.path : entry); |
46 | | - |
47 | | - // Single example use case |
48 | | - examples[fullPath] = {}; |
49 | | - var currentExamples = examples[fullPath]; |
50 | | - shell.cd(fullPath); |
51 | | - shell.find('.') |
52 | | - .filter( function(file) { |
53 | | - return file.match(regexp); |
54 | | - }) |
55 | | - .forEach( function(file) { |
56 | | - var fullPath = getSplitedPath(file), |
57 | | - exampleName = fullPath.pop(); |
58 | | - |
59 | | - while (['index.js', 'example'].indexOf(exampleName) !== -1) { |
60 | | - exampleName = fullPath.pop(); |
61 | | - } |
62 | | - |
63 | | - if (!buildExample || filterExamples.indexOf(exampleName) !== -1) { |
64 | | - currentExamples[exampleName] = './' + file; |
65 | | - console.log(' -', exampleName, ':', file); |
66 | | - exampleCount++; |
67 | | - } else { |
68 | | - console.log(' -', exampleName, ': SKIPPED'); |
69 | | - } |
70 | | - }); |
| 44 | +function walkFiles(dirPath, onFile) { |
| 45 | + if (!fs.existsSync(dirPath)) { |
| 46 | + return; |
| 47 | + } |
| 48 | + const entries = fs.readdirSync(dirPath, { withFileTypes: true }); |
| 49 | + entries.forEach((entry) => { |
| 50 | + const fullPath = path.join(dirPath, entry.name); |
| 51 | + if (entry.isDirectory()) { |
| 52 | + walkFiles(fullPath, onFile); |
| 53 | + return; |
| 54 | + } |
| 55 | + onFile(fullPath); |
71 | 56 | }); |
72 | | - console.log(); |
| 57 | +} |
73 | 58 |
|
74 | | - if (exampleCount === 0) { |
75 | | - examples = null; |
76 | | - if (buildExample) { |
77 | | - console.error(`=> Error: Did not find any examples matching ${filterExamples[0]}`); |
78 | | - process.exit(1); |
| 59 | +function collectExamples() { |
| 60 | + const examples = {}; |
| 61 | + |
| 62 | + walkFiles(SOURCES_ROOT, (fullPath) => { |
| 63 | + if (!fullPath.endsWith('index.js')) { |
| 64 | + return; |
79 | 65 | } |
80 | | - } |
| 66 | + const relPath = normalizePath(path.relative(SOURCES_ROOT, fullPath)); |
| 67 | + if ( |
| 68 | + relPath.startsWith('Testing/') || |
| 69 | + relPath === 'Testing' || |
| 70 | + !isClassExample(relPath) |
| 71 | + ) { |
| 72 | + return; |
| 73 | + } |
| 74 | + const exampleName = path.basename(path.dirname(path.dirname(fullPath))); |
| 75 | + examples[exampleName] = fullPath; |
| 76 | + }); |
| 77 | + |
| 78 | + walkFiles(EXAMPLES_ROOT, (fullPath) => { |
| 79 | + if (!fullPath.endsWith('index.js')) { |
| 80 | + return; |
| 81 | + } |
| 82 | + const relPath = normalizePath(path.relative(EXAMPLES_ROOT, fullPath)); |
| 83 | + if (!isStandaloneExample(relPath)) { |
| 84 | + return; |
| 85 | + } |
| 86 | + const exampleName = path.basename(path.dirname(fullPath)); |
| 87 | + examples[exampleName] = fullPath; |
| 88 | + }); |
| 89 | + |
| 90 | + return examples; |
| 91 | +} |
81 | 92 |
|
82 | | - if (buildExample) { |
83 | | - var exBasePath = null; |
84 | | - const exampleName = filterExamples[0]; |
85 | | - Object.keys(examples).forEach((exampleBasePath) => { |
86 | | - if (examples[exampleBasePath][exampleName]) { |
87 | | - exBasePath = exampleBasePath; |
88 | | - } |
89 | | - }); |
90 | | - |
91 | | - // console.log(exampleName, ' => ', exBasePath, examples[exBasePath][exampleName]); |
92 | | - const conf = buildConfig(exampleName, validPath(examples[exBasePath][exampleName]), distDir, validPath(rootPath), validPath(exBasePath)); |
93 | | - shell.ShellString(conf).to(webpackConfigPath); |
94 | | - shell.cd(exBasePath); |
95 | | - shell.exec(`webpack serve --server-type ${options.serverType} --progress --config ${webpackConfigPath}`) |
96 | | - } else { |
97 | | - console.log('=> To run an example:') |
98 | | - console.log(' $ npm run example -- PUT_YOUR_EXAMPLE_NAME_HERE\n'); |
| 93 | +function printExamples(examples) { |
| 94 | + const names = Object.keys(examples).sort((a, b) => a.localeCompare(b)); |
| 95 | + if (!names.length) { |
| 96 | + console.log('=> No examples found'); |
| 97 | + return; |
99 | 98 | } |
100 | 99 |
|
| 100 | + console.log('\n=> Available examples\n'); |
| 101 | + names.forEach((name) => { |
| 102 | + const relPath = normalizePath(path.relative(REPO_ROOT, examples[name])); |
| 103 | + console.log(` - ${name}: ${relPath}`); |
| 104 | + }); |
| 105 | + console.log('\n=> To run an example:'); |
| 106 | + console.log(' $ npm run example -- PUT_YOUR_EXAMPLE_NAME_HERE\n'); |
101 | 107 | } |
| 108 | + |
| 109 | +async function runExample(exampleName, entryPath) { |
| 110 | + const env = { ...process.env }; |
| 111 | + env.EXAMPLE_ENTRY = entryPath; |
| 112 | + env.EXAMPLE_NAME = exampleName; |
| 113 | + env.EXAMPLE_REPO_ROOT = REPO_ROOT; |
| 114 | + env.EXAMPLE_HOST = env.EXAMPLE_HOST || DEFAULT_HOST; |
| 115 | + env.EXAMPLE_PORT = env.EXAMPLE_PORT || DEFAULT_PORT; |
| 116 | + env.EXAMPLE_OPEN = options.browser ? '1' : '0'; |
| 117 | + env.EXAMPLE_HTTPS = options.serverType === 'https' ? '1' : '0'; |
| 118 | + |
| 119 | + console.log(`\n=> Running example "${exampleName}"`); |
| 120 | + console.log( |
| 121 | + `=> Entry: ${normalizePath(path.relative(REPO_ROOT, entryPath))}\n` |
| 122 | + ); |
| 123 | + |
| 124 | + Object.assign(process.env, env); |
| 125 | + |
| 126 | + const { createServer } = await import('vite'); |
| 127 | + const server = await createServer({ |
| 128 | + configFile: VITE_CONFIG_PATH, |
| 129 | + }); |
| 130 | + await server.listen(); |
| 131 | + server.printUrls(); |
| 132 | + |
| 133 | + const closeServer = async () => { |
| 134 | + await server.close(); |
| 135 | + process.exit(0); |
| 136 | + }; |
| 137 | + |
| 138 | + process.on('SIGINT', closeServer); |
| 139 | + process.on('SIGTERM', closeServer); |
| 140 | +} |
| 141 | + |
| 142 | +const examples = collectExamples(); |
| 143 | +const requestedExample = (program.args || []).find((arg) => !!arg); |
| 144 | + |
| 145 | +if (!requestedExample) { |
| 146 | + printExamples(examples); |
| 147 | + process.exit(0); |
| 148 | +} |
| 149 | + |
| 150 | +const entryPath = examples[requestedExample]; |
| 151 | +if (!entryPath) { |
| 152 | + console.error( |
| 153 | + `=> Error: Did not find any examples matching ${requestedExample}` |
| 154 | + ); |
| 155 | + process.exit(1); |
| 156 | +} |
| 157 | + |
| 158 | +runExample(requestedExample, entryPath).catch((err) => { |
| 159 | + console.error(err); |
| 160 | + process.exit(1); |
| 161 | +}); |
0 commit comments