diff --git a/aio/content/examples/examples.bzl b/aio/content/examples/examples.bzl
index c5f457bf6ef..bfccc58735c 100644
--- a/aio/content/examples/examples.bzl
+++ b/aio/content/examples/examples.bzl
@@ -190,13 +190,15 @@ def docs_example(name, test = True, test_tags = [], test_exec_properties = {}, f
nodejs_test(
name = "e2e",
data = [
- ":%s" % name,
- YARN_LABEL,
"@aio_npm//@angular/build-tooling/bazel/browsers/chromium",
"//aio/tools/examples:run-example-e2e",
"//aio/tools:windows-chromium-path",
# We install the whole node modules for runtime deps of e2e tests
"@{workspace}//:node_modules_files".format(workspace = EXAMPLE_DEPS_WORKSPACE_NAME),
+ ],
+ data_for_expansion = [
+ ":%s" % name,
+ YARN_LABEL,
] + select({
"//aio:aio_local_deps": LOCAL_PACKAGE_DEPS,
"//conditions:default": [],
diff --git a/aio/scripts/BUILD.bazel b/aio/scripts/BUILD.bazel
index a7f08b1f9d5..d7f411322dd 100644
--- a/aio/scripts/BUILD.bazel
+++ b/aio/scripts/BUILD.bazel
@@ -22,7 +22,7 @@ nodejs_binary(
js_library(
name = "fast-serve-and-watch",
srcs = [
- "fast-serve-and-watch.js",
+ "fast-serve-and-watch.mjs",
],
deps = [
"//aio/tools/transforms/authors-package:watchdocs",
@@ -84,9 +84,9 @@ nodejs_test(
testonly = True,
data = [
":audit-web-app",
- ":audit-web-app-script",
"@aio_npm//shelljs",
],
+ data_for_expansion = [":audit-web-app-script"],
entry_point = "test-aio-a11y.mjs",
env = {
"AUDIT_SCRIPT_PATH": "$(rootpath :audit-web-app-script)",
diff --git a/aio/scripts/build-404-page.js b/aio/scripts/build-404-page.mjs
similarity index 63%
rename from aio/scripts/build-404-page.js
rename to aio/scripts/build-404-page.mjs
index 8eaa63daced..1215d5d0321 100644
--- a/aio/scripts/build-404-page.js
+++ b/aio/scripts/build-404-page.mjs
@@ -1,8 +1,8 @@
#!/usr/bin/env node
// Imports
-const {readFileSync, writeFileSync} = require('fs');
-const {join, resolve} = require('path');
+import {readFileSync, writeFileSync} from 'fs';
+import {join, resolve} from 'path';
// Constants
const SOURCE_404_BODY_PATH = resolve(process.argv[2]);
@@ -18,13 +18,16 @@ function _main() {
const srcIndexContent = readFileSync(srcIndexPath, 'utf8');
const src404BodyContent = readFileSync(SOURCE_404_BODY_PATH, 'utf8').trim();
- const dst404PageContent = srcIndexContent
- .replace(/(
)[\s\S]+(<\/body>)/, `$1\n ${src404BodyContent}\n$2`);
+ const dst404PageContent = srcIndexContent.replace(
+ /()[\s\S]+(<\/body>)/,
+ `$1\n ${src404BodyContent}\n$2`
+ );
if (dst404PageContent === srcIndexContent) {
throw new Error(
- 'Failed to generate \'404.html\'. ' +
- 'The content of \'index.html\' does not match the expected pattern.');
+ "Failed to generate '404.html'. " +
+ "The content of 'index.html' does not match the expected pattern."
+ );
}
writeFileSync(DEST_404_PAGE_PATH, dst404PageContent);
diff --git a/aio/scripts/build-ngsw-config.js b/aio/scripts/build-ngsw-config.mjs
similarity index 60%
rename from aio/scripts/build-ngsw-config.js
rename to aio/scripts/build-ngsw-config.mjs
index 08221c0f6fb..f5702c06314 100644
--- a/aio/scripts/build-ngsw-config.js
+++ b/aio/scripts/build-ngsw-config.mjs
@@ -1,13 +1,14 @@
// Imports
-const {basename, dirname, resolve: resolvePath} = require('canonical-path');
-const {mkdirSync, readFileSync, writeFileSync} = require('fs');
-const {parse: parseJson} = require('json5');
-
+import cpath from 'canonical-path';
+import {mkdirSync, readFileSync, writeFileSync} from 'fs';
+import json5 from 'json5';
+import url from 'url';
// Constants
-const FIREBASE_CONFIG_PATH = resolvePath(__dirname, '../firebase.json');
-const NGSW_CONFIG_TEMPLATE_PATH = resolvePath(__dirname, '../ngsw-config.template.json');
-const NGSW_CONFIG_OUTPUT_PATH = resolvePath(__dirname, '../ngsw-config.json');
+const currentDir = cpath.dirname(url.fileURLToPath(import.meta.url));
+const FIREBASE_CONFIG_PATH = cpath.resolve(currentDir, '../firebase.json');
+const NGSW_CONFIG_TEMPLATE_PATH = cpath.resolve(currentDir, '../ngsw-config.template.json');
+const NGSW_CONFIG_OUTPUT_PATH = cpath.resolve(currentDir, '../ngsw-config.json');
// Run
_main();
@@ -15,9 +16,7 @@ _main();
// Helpers
function _main() {
// Allow an alternative output path (used by bazel to output to output dir)
- const ngswConfigOutputPath = process.argv.length > 2
- ? process.argv[2]
- : NGSW_CONFIG_OUTPUT_PATH;
+ const ngswConfigOutputPath = process.argv.length > 2 ? process.argv[2] : NGSW_CONFIG_OUTPUT_PATH;
const firebaseConfig = readJson(FIREBASE_CONFIG_PATH);
const ngswConfig = readJson(NGSW_CONFIG_TEMPLATE_PATH);
@@ -29,18 +28,21 @@ function _main() {
if (regexBasedRedirects.length > 0) {
throw new Error(
'The following redirects use `regex`, which is currently not supported by ' +
- `${basename(__filename)}:` +
- regexBasedRedirects.map(x => `\n - ${JSON.stringify(x)}`).join(''));
+ `${basename(__filename)}:` +
+ regexBasedRedirects.map((x) => `\n - ${JSON.stringify(x)}`).join('')
+ );
}
// Check that there are no unsupported glob characters/patterns.
- const redirectsWithUnsupportedGlobs = firebaseRedirects
- .filter(({source}) => !/^(?:[/\w\-.*]|:\w+|@\([\w\-.|]+\))+$/.test(source));
+ const redirectsWithUnsupportedGlobs = firebaseRedirects.filter(
+ ({source}) => !/^(?:[/\w\-.*]|:\w+|@\([\w\-.|]+\))+$/.test(source)
+ );
if (redirectsWithUnsupportedGlobs.length > 0) {
throw new Error(
'The following redirects use glob characters/patterns that are currently not supported by ' +
- `${basename(__filename)}:` +
- redirectsWithUnsupportedGlobs.map(x => `\n - ${JSON.stringify(x)}`).join(''));
+ `${basename(__filename)}:` +
+ redirectsWithUnsupportedGlobs.map((x) => `\n - ${JSON.stringify(x)}`).join('')
+ );
}
// Compute additional ignore glob patterns to be added to `navigationUrls`.
@@ -48,11 +50,11 @@ function _main() {
// Grab the redirect source glob.
.map(({source}) => source)
// Ignore redirects for files (since these are already ignored by the SW).
- .filter(glob => /\/[^/.]*$/.test(glob))
+ .filter((glob) => /\/[^/.]*$/.test(glob))
// Convert each Firebase-specific glob to a SW-compatible glob.
- .map(glob => `!${glob.replace(/:\w+/g, '*').replace(/@(\([\w\-.|]+\))/g, '$1')}`)
+ .map((glob) => `!${glob.replace(/:\w+/g, '*').replace(/@(\([\w\-.|]+\))/g, '$1')}`)
// Add optional trailing `/` for globs that don't end with `*`.
- .map(glob => /\w$/.test(glob) ? `${glob}\/{0,1}` : glob)
+ .map((glob) => (/\w$/.test(glob) ? `${glob}\/{0,1}` : glob))
// Remove more specific globs that are covered by more generic ones.
.filter((glob, _i, globs) => !isGlobRedundant(glob, globs))
// Sort the generated globs alphabetically.
@@ -61,28 +63,29 @@ function _main() {
// Add the additional `navigationUrls` globs and save the config.
ngswConfig.navigationUrls.push(...additionalNavigationUrls);
- mkdirSync(dirname(ngswConfigOutputPath), {recursive: true});
+ mkdirSync(cpath.dirname(ngswConfigOutputPath), {recursive: true});
writeJson(ngswConfigOutputPath, ngswConfig);
}
function isGlobRedundant(glob, globs) {
// Find all globs that could cover other globs.
// For simplicity, we only consider globs ending with `/**`.
- const genericGlobs = globs.filter(g => g.endsWith('/**'));
+ const genericGlobs = globs.filter((g) => g.endsWith('/**'));
// A glob is redundant if it starts with the path of a potentially generic glob (excluding the
// trailing `**`) followed by a word character or a `*`.
// For example, `/foo/bar/baz` is covered (and thus made redundant) by `/foo/**`, but `/foo/{0,1}`
// is not.
- return genericGlobs.some(g => {
+ return genericGlobs.some((g) => {
const pathPrefix = g.slice(0, -2);
- return (glob !== g) && glob.startsWith(pathPrefix) &&
- /^[\w*]/.test(glob.slice(pathPrefix.length));
+ return (
+ glob !== g && glob.startsWith(pathPrefix) && /^[\w*]/.test(glob.slice(pathPrefix.length))
+ );
});
}
function readJson(filePath) {
- return parseJson(readFileSync(filePath, 'utf8'));
+ return json5.parse(readFileSync(filePath, 'utf8'));
}
function writeJson(filePath, obj) {
diff --git a/aio/scripts/fast-serve-and-watch.js b/aio/scripts/fast-serve-and-watch.js
deleted file mode 100644
index d5649f428d3..00000000000
--- a/aio/scripts/fast-serve-and-watch.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- This script serves the aio app, watches for changes,
- and runs a fast dgeni build on any changed files.
-*/
-
-const spawn = require("cross-spawn");
-const watchr = require("../tools/transforms/authors-package/watchr.js");
-const architectCli = require.resolve("@angular-devkit/architect-cli/bin/architect");
-
-const serve = spawn(process.execPath, ['--preserve-symlinks', architectCli, "site:serve", "--open", "--poll=1000", "--live-reload", "--watch"], {stdio: "inherit"});
-serve.on("error", error => {
- console.error("architect serve script failed");
- console.error(error);
- process.exit(1);
-});
-serve.on("close", code => {
- console.error(`architect serve script exited with code ${code}`);
- process.exit(1);
-})
-
-watchr.watch(true);
\ No newline at end of file
diff --git a/aio/scripts/fast-serve-and-watch.mjs b/aio/scripts/fast-serve-and-watch.mjs
new file mode 100644
index 00000000000..36175a218ca
--- /dev/null
+++ b/aio/scripts/fast-serve-and-watch.mjs
@@ -0,0 +1,33 @@
+/*
+ This script serves the aio app, watches for changes,
+ and runs a fast dgeni build on any changed files.
+*/
+
+import spawn from 'cross-spawn';
+import watchr from '../tools/transforms/authors-package/watchr.js';
+const architectCli = require.resolve('@angular-devkit/architect-cli/bin/architect');
+
+const serve = spawn(
+ process.execPath,
+ [
+ '--preserve-symlinks',
+ architectCli,
+ 'site:serve',
+ '--open',
+ '--poll=1000',
+ '--live-reload',
+ '--watch',
+ ],
+ {stdio: 'inherit'}
+);
+serve.on('error', (error) => {
+ console.error('architect serve script failed');
+ console.error(error);
+ process.exit(1);
+});
+serve.on('close', (code) => {
+ console.error(`architect serve script exited with code ${code}`);
+ process.exit(1);
+});
+
+watchr.watch(true);
diff --git a/aio/scripts/local_server_test.bzl b/aio/scripts/local_server_test.bzl
index a5b102b9d6c..afc044b0429 100644
--- a/aio/scripts/local_server_test.bzl
+++ b/aio/scripts/local_server_test.bzl
@@ -15,17 +15,19 @@ def local_server_test(name, entry_point, serve_target, data = [], args = [], **k
nodejs_test(
name = name,
testonly = True,
+ data_for_expansion = [
+ serve_target,
+ entry_point,
+ "@aio_npm//light-server/bin:light-server",
+ ],
args = [
"$(rootpath @aio_npm//light-server/bin:light-server)",
"$(rootpath %s)" % serve_target,
"$(rootpath %s)" % entry_point,
] + args,
data = [
- entry_point,
- serve_target,
"//aio/scripts:run-with-local-server.mjs",
"@aio_npm//get-port",
- "@aio_npm//light-server/bin:light-server",
"@aio_npm//shelljs",
"@aio_npm//tree-kill",
] + data,
diff --git a/aio/tools/examples/BUILD.bazel b/aio/tools/examples/BUILD.bazel
index 632f03407bf..f7f26830f20 100644
--- a/aio/tools/examples/BUILD.bazel
+++ b/aio/tools/examples/BUILD.bazel
@@ -13,8 +13,9 @@ exports_files([
js_library(
name = "example-boilerplate-lib",
srcs = [
- "constants.js",
- "example-boilerplate.js",
+ "constants.mjs",
+ "example-boilerplate.mjs",
+ "example-boilerplate-cli.mjs",
],
deps = [
"//aio/tools/examples/shared",
@@ -29,20 +30,21 @@ js_library(
nodejs_binary(
name = "example-boilerplate",
data = [":example-boilerplate-lib"],
- entry_point = "example-boilerplate.js",
+ entry_point = "example-boilerplate-cli.js",
)
jasmine_node_test(
name = "example-boilerplate-test",
- srcs = ["example-boilerplate.spec.js"],
+ srcs = ["example-boilerplate.spec.mjs"],
deps = [":example-boilerplate-lib"],
)
js_library(
name = "create-example-lib",
srcs = [
- "create-example.js",
- "constants.js",
+ "create-example.mjs",
+ "create-example-cli.mjs",
+ "constants.mjs",
] + glob(["shared/**"]),
deps = [
"@aio_npm//@bazel/buildozer",
@@ -57,12 +59,12 @@ js_library(
nodejs_binary(
name = "create-example",
data = [":create-example-lib"],
- entry_point = "create-example.js",
+ entry_point = "create-example-cli.mjs",
)
jasmine_node_test(
name = "create-example-test",
- srcs = ["create-example.spec.js"],
+ srcs = ["create-example.spec.mjs"],
deps = [":create-example-lib"],
)
diff --git a/aio/tools/examples/constants.js b/aio/tools/examples/constants.js
deleted file mode 100644
index 8214abaad4a..00000000000
--- a/aio/tools/examples/constants.js
+++ /dev/null
@@ -1,14 +0,0 @@
-const path = require('canonical-path');
-
-exports.RUNFILES_ROOT = path.resolve(process.env.RUNFILES, 'angular');
-
-exports.getExamplesBasePath = function(root) {
- return path.join(root, 'aio', 'content', 'examples');
-}
-
-exports.getSharedPath = function(root) {
- return path.join(root, 'aio', 'tools', 'examples', 'shared');
-}
-
-exports.EXAMPLE_CONFIG_FILENAME = 'example-config.json';
-exports.STACKBLITZ_CONFIG_FILENAME = 'stackblitz.json';
diff --git a/aio/tools/examples/constants.mjs b/aio/tools/examples/constants.mjs
new file mode 100644
index 00000000000..9de5169ab08
--- /dev/null
+++ b/aio/tools/examples/constants.mjs
@@ -0,0 +1,14 @@
+import path from 'canonical-path';
+
+export const RUNFILES_ROOT = path.resolve(process.env.RUNFILES, 'angular');
+
+export function getExamplesBasePath(root) {
+ return path.join(root, 'aio', 'content', 'examples');
+}
+
+export function getSharedPath(root) {
+ return path.join(root, 'aio', 'tools', 'examples', 'shared');
+}
+
+export const EXAMPLE_CONFIG_FILENAME = 'example-config.json';
+export const STACKBLITZ_CONFIG_FILENAME = 'stackblitz.json';
diff --git a/aio/tools/examples/create-example-cli.mjs b/aio/tools/examples/create-example-cli.mjs
new file mode 100644
index 00000000000..d370b97774e
--- /dev/null
+++ b/aio/tools/examples/create-example-cli.mjs
@@ -0,0 +1,3 @@
+import {main} from './create-example.mjs';
+
+main();
diff --git a/aio/tools/examples/create-example.js b/aio/tools/examples/create-example.js
deleted file mode 100644
index 7b34213fe88..00000000000
--- a/aio/tools/examples/create-example.js
+++ /dev/null
@@ -1,156 +0,0 @@
-const fs = require('fs-extra');
-const glob = require('glob');
-const ignore = require('ignore');
-const path = require('canonical-path');
-const shelljs = require('shelljs');
-const yargs = require('yargs');
-const buildozer = require('@bazel/buildozer');
-const {RUNFILES_ROOT, getExamplesBasePath, getSharedPath, EXAMPLE_CONFIG_FILENAME, STACKBLITZ_CONFIG_FILENAME} =
- require('./constants');
-
-// BUILD_WORKSPACE_DIRECTORY is set by Bazel when calling `bazel run` and points to the
-// root of the source tree (e.g., for creating a new example in the source tree). Otherwise,
-// we are in a test so use the runfiles root.
-const PROJECT_ROOT = path.resolve(process.env.BUILD_WORKSPACE_DIRECTORY || RUNFILES_ROOT);
-const EXAMPLES_BASE_PATH = getExamplesBasePath(PROJECT_ROOT);
-const SHARED_PATH = getSharedPath(PROJECT_ROOT);
-
-const BASIC_SOURCE_PATH = path.resolve(SHARED_PATH, 'example-scaffold');
-
-shelljs.set('-e');
-
-if (require.main === module) {
- const options =
- yargs(process.argv.slice(2))
- .command(
- '$0 [source]',
- [
- 'Create a new example.',
- '',
- 'If [source] is provided then the relevant files from the CLI project at that path are copied into the example.',
- ].join('\n'))
- .strict()
- .version(false)
- .argv;
-
- const exampleName = options.name;
- const examplePath = path.resolve(EXAMPLES_BASE_PATH, exampleName);
-
- console.log('Creating new example at', examplePath);
- createEmptyExample(exampleName, examplePath);
-
- const sourcePath =
- options.source !== undefined ? path.resolve(EXAMPLES_BASE_PATH, options.source) : BASIC_SOURCE_PATH;
- console.log('Copying files from', sourcePath);
- copyExampleFiles(sourcePath, examplePath, exampleName);
-
- buildozer.runWithOptions([{commands: [`set name ${exampleName}`], targets: [`//aio/content/examples/${exampleName}:%docs_example`]}], {cwd: PROJECT_ROOT});
-
- console.log(`The new "${exampleName}" example has been created.`);
- console.log(`To include this example, add a "${exampleName}" entry in aio/content/examples/examples.bzl`)
- console.log(
- 'You can find more info on working with docs examples in aio/tools/examples/README.md.')
-}
-
-/**
- * Create the directory and marker files for the new example.
- */
-function createEmptyExample(exampleName, examplePath) {
- validateExampleName(exampleName);
- ensureExamplePath(examplePath);
- writeExampleConfigFile(examplePath);
- writeStackBlitzFile(exampleName, examplePath);
-}
-
-function validateExampleName(exampleName) {
- if (/\s/.test(exampleName)) {
- throw new Error(
- `Unable to create example. The example name contains spaces: '${exampleName}'`
- )
- }
-}
-
-/**
- * Ensure that the new example directory exists.
- */
-function ensureExamplePath(examplePath) {
- if (fs.existsSync(examplePath)) {
- throw new Error(
- `Unable to create example. The path to the new example already exists: ${examplePath}`);
- }
- fs.ensureDirSync(examplePath);
-}
-
-/**
- * Write the `example-config.json` file to the new example.
- */
-function writeExampleConfigFile(examplePath) {
- fs.writeFileSync(path.resolve(examplePath, EXAMPLE_CONFIG_FILENAME), '');
-}
-
-/**
- * Write the `stackblitz.json` file into the new example.
- */
-function writeStackBlitzFile(exampleName, examplePath) {
- const config = {
- description: titleize(exampleName),
- files: ['!**/*.d.ts', '!**/*.js', '!**/*.[1,2].*'],
- tags: [exampleName.split('-')]
- };
- fs.writeFileSync(
- path.resolve(examplePath, STACKBLITZ_CONFIG_FILENAME),
- JSON.stringify(config, null, 2) + '\n');
-}
-
-/**
- * Copy all the files from the `sourcePath` to the `examplePath`, except for files
- * ignored by the source example.
- */
-function copyExampleFiles(sourcePath, examplePath, exampleName) {
- const gitIgnoreSource = getGitIgnore(sourcePath);
-
- // Grab the files in the source folder and filter them based on the gitignore rules.
- const sourceFiles =
- glob.sync('**/*', {
- cwd: sourcePath,
- dot: true,
- ignore: ['**/node_modules/**', '.git/**', '.gitignore'],
- mark: true
- })
- // Filter out the directories, leaving only files
- .filter(filePath => !/\/$/.test(filePath))
- // Filter out files that match the source directory .gitignore rules
- .filter(filePath => !gitIgnoreSource.ignores(filePath))
-
- for (const sourceFile of sourceFiles) {
- console.log(' - ', sourceFile);
- const destPath = path.resolve(examplePath, sourceFile)
- fs.ensureDirSync(path.dirname(destPath));
- fs.copySync(path.resolve(sourcePath, sourceFile), destPath);
- }
-}
-
-function getGitIgnore(directory) {
- const gitIgnoreMatcher = ignore();
- const gitignoreFilePath = path.resolve(directory, '.gitignore');
- if (fs.existsSync(gitignoreFilePath)) {
- const gitignoreFile = fs.readFileSync(gitignoreFilePath, 'utf8');
- gitIgnoreMatcher.add(gitignoreFile);
- }
- return gitIgnoreMatcher;
-}
-
-/**
- * Convert a kebab-case string to space separated Title Case string.
- */
-function titleize(input) {
- return input.replace(
- /(-|^)(.)/g, (_, pre, char) => `${pre === '-' ? ' ' : ''}${char.toUpperCase()}`);
-}
-
-exports.createEmptyExample = createEmptyExample;
-exports.ensureExamplePath = ensureExamplePath;
-exports.writeExampleConfigFile = writeExampleConfigFile;
-exports.writeStackBlitzFile = writeStackBlitzFile;
-exports.copyExampleFiles = copyExampleFiles;
-exports.titleize = titleize;
diff --git a/aio/tools/examples/create-example.mjs b/aio/tools/examples/create-example.mjs
new file mode 100644
index 00000000000..f15c17dcbb4
--- /dev/null
+++ b/aio/tools/examples/create-example.mjs
@@ -0,0 +1,169 @@
+import fs from 'fs-extra';
+import glob from 'glob';
+import ignore from 'ignore';
+import path from 'canonical-path';
+import shelljs from 'shelljs';
+import yargs from 'yargs';
+import buildozer from '@bazel/buildozer';
+
+import {
+ RUNFILES_ROOT,
+ getExamplesBasePath,
+ getSharedPath,
+ EXAMPLE_CONFIG_FILENAME,
+ STACKBLITZ_CONFIG_FILENAME,
+} from './constants.mjs';
+
+// BUILD_WORKSPACE_DIRECTORY is set by Bazel when calling `bazel run` and points to the
+// root of the source tree (e.g., for creating a new example in the source tree). Otherwise,
+// we are in a test so use the runfiles root.
+const PROJECT_ROOT = path.resolve(process.env.BUILD_WORKSPACE_DIRECTORY || RUNFILES_ROOT);
+const EXAMPLES_BASE_PATH = getExamplesBasePath(PROJECT_ROOT);
+const SHARED_PATH = getSharedPath(PROJECT_ROOT);
+
+const BASIC_SOURCE_PATH = path.resolve(SHARED_PATH, 'example-scaffold');
+
+shelljs.set('-e');
+
+export function main() {
+ const options = yargs(process.argv.slice(2))
+ .command(
+ '$0 [source]',
+ [
+ 'Create a new example.',
+ '',
+ 'If [source] is provided then the relevant files from the CLI project at that path are copied into the example.',
+ ].join('\n')
+ )
+ .strict()
+ .version(false).argv;
+
+ const exampleName = options.name;
+ const examplePath = path.resolve(EXAMPLES_BASE_PATH, exampleName);
+
+ console.log('Creating new example at', examplePath);
+ createEmptyExample(exampleName, examplePath);
+
+ const sourcePath =
+ options.source !== undefined
+ ? path.resolve(EXAMPLES_BASE_PATH, options.source)
+ : BASIC_SOURCE_PATH;
+ console.log('Copying files from', sourcePath);
+ copyExampleFiles(sourcePath, examplePath, exampleName);
+
+ buildozer.runWithOptions(
+ [
+ {
+ commands: [`set name ${exampleName}`],
+ targets: [`//aio/content/examples/${exampleName}:%docs_example`],
+ },
+ ],
+ {cwd: PROJECT_ROOT}
+ );
+
+ console.log(`The new "${exampleName}" example has been created.`);
+ console.log(
+ `To include this example, add a "${exampleName}" entry in aio/content/examples/examples.bzl`
+ );
+ console.log(
+ 'You can find more info on working with docs examples in aio/tools/examples/README.md.'
+ );
+}
+
+/**
+ * Create the directory and marker files for the new example.
+ */
+export function createEmptyExample(exampleName, examplePath) {
+ validateExampleName(exampleName);
+ ensureExamplePath(examplePath);
+ writeExampleConfigFile(examplePath);
+ writeStackBlitzFile(exampleName, examplePath);
+}
+
+function validateExampleName(exampleName) {
+ if (/\s/.test(exampleName)) {
+ throw new Error(`Unable to create example. The example name contains spaces: '${exampleName}'`);
+ }
+}
+
+/**
+ * Ensure that the new example directory exists.
+ */
+export function ensureExamplePath(examplePath) {
+ if (fs.existsSync(examplePath)) {
+ throw new Error(
+ `Unable to create example. The path to the new example already exists: ${examplePath}`
+ );
+ }
+ fs.ensureDirSync(examplePath);
+}
+
+/**
+ * Write the `example-config.json` file to the new example.
+ */
+export function writeExampleConfigFile(examplePath) {
+ fs.writeFileSync(path.resolve(examplePath, EXAMPLE_CONFIG_FILENAME), '');
+}
+
+/**
+ * Write the `stackblitz.json` file into the new example.
+ */
+export function writeStackBlitzFile(exampleName, examplePath) {
+ const config = {
+ description: titleize(exampleName),
+ files: ['!**/*.d.ts', '!**/*.js', '!**/*.[1,2].*'],
+ tags: [exampleName.split('-')],
+ };
+ fs.writeFileSync(
+ path.resolve(examplePath, STACKBLITZ_CONFIG_FILENAME),
+ JSON.stringify(config, null, 2) + '\n'
+ );
+}
+
+/**
+ * Copy all the files from the `sourcePath` to the `examplePath`, except for files
+ * ignored by the source example.
+ */
+export function copyExampleFiles(sourcePath, examplePath, exampleName) {
+ const gitIgnoreSource = getGitIgnore(sourcePath);
+
+ // Grab the files in the source folder and filter them based on the gitignore rules.
+ const sourceFiles = glob
+ .sync('**/*', {
+ cwd: sourcePath,
+ dot: true,
+ ignore: ['**/node_modules/**', '.git/**', '.gitignore'],
+ mark: true,
+ })
+ // Filter out the directories, leaving only files
+ .filter((filePath) => !/\/$/.test(filePath))
+ // Filter out files that match the source directory .gitignore rules
+ .filter((filePath) => !gitIgnoreSource.ignores(filePath));
+
+ for (const sourceFile of sourceFiles) {
+ console.log(' - ', sourceFile);
+ const destPath = path.resolve(examplePath, sourceFile);
+ fs.ensureDirSync(path.dirname(destPath));
+ fs.copySync(path.resolve(sourcePath, sourceFile), destPath);
+ }
+}
+
+function getGitIgnore(directory) {
+ const gitIgnoreMatcher = ignore();
+ const gitignoreFilePath = path.resolve(directory, '.gitignore');
+ if (fs.existsSync(gitignoreFilePath)) {
+ const gitignoreFile = fs.readFileSync(gitignoreFilePath, 'utf8');
+ gitIgnoreMatcher.add(gitignoreFile);
+ }
+ return gitIgnoreMatcher;
+}
+
+/**
+ * Convert a kebab-case string to space separated Title Case string.
+ */
+export function titleize(input) {
+ return input.replace(
+ /(-|^)(.)/g,
+ (_, pre, char) => `${pre === '-' ? ' ' : ''}${char.toUpperCase()}`
+ );
+}
diff --git a/aio/tools/examples/create-example.spec.js b/aio/tools/examples/create-example.spec.mjs
similarity index 67%
rename from aio/tools/examples/create-example.spec.js
rename to aio/tools/examples/create-example.spec.mjs
index 4b0bc009f10..ddb9200d8c3 100644
--- a/aio/tools/examples/create-example.spec.js
+++ b/aio/tools/examples/create-example.spec.mjs
@@ -1,18 +1,17 @@
-const path = require('canonical-path');
-const fs = require('fs-extra');
-const {glob} = require('glob');
+import path from 'canonical-path';
+import fs from 'fs-extra';
+import glob from 'glob';
-const {EXAMPLE_CONFIG_FILENAME, STACKBLITZ_CONFIG_FILENAME} =
- require('./constants');
+import {EXAMPLE_CONFIG_FILENAME, STACKBLITZ_CONFIG_FILENAME} from './constants.mjs';
-const {
+import {
copyExampleFiles,
createEmptyExample,
ensureExamplePath,
titleize,
writeExampleConfigFile,
- writeStackBlitzFile
-} = require('./create-example');
+ writeStackBlitzFile,
+} from './create-example.mjs';
describe('create-example tool', () => {
describe('createEmptyExample', () => {
@@ -23,17 +22,19 @@ describe('create-example tool', () => {
createEmptyExample('foo-bar', '/path/to/foo-bar');
expect(writeFileSpy).toHaveBeenCalledTimes(2);
- expect(writeFileSpy)
- .toHaveBeenCalledWith(
- path.resolve(`/path/to/foo-bar/${EXAMPLE_CONFIG_FILENAME}`), jasmine.any(String));
- expect(writeFileSpy)
- .toHaveBeenCalledWith(
- path.resolve(`/path/to/foo-bar/${STACKBLITZ_CONFIG_FILENAME}`), jasmine.any(String));
+ expect(writeFileSpy).toHaveBeenCalledWith(
+ path.resolve(`/path/to/foo-bar/${EXAMPLE_CONFIG_FILENAME}`),
+ jasmine.any(String)
+ );
+ expect(writeFileSpy).toHaveBeenCalledWith(
+ path.resolve(`/path/to/foo-bar/${STACKBLITZ_CONFIG_FILENAME}`),
+ jasmine.any(String)
+ );
});
it('should fail if the example name contains spaces', () => {
- expect(() => createEmptyExample('foo bar', '/path/to/foo-bar')).toThrowError(
- `Unable to create example. The example name contains spaces: 'foo bar'`
+ expect(() => createEmptyExample('foo bar', '/path/to/foo-bar')).toThrowError(
+ `Unable to create example. The example name contains spaces: 'foo bar'`
);
});
});
@@ -41,9 +42,9 @@ describe('create-example tool', () => {
describe('ensureExamplePath', () => {
it('should error if the path already exists', () => {
spyOn(fs, 'existsSync').and.returnValue(true);
- expect(() => ensureExamplePath('foo/bar'))
- .toThrowError(
- `Unable to create example. The path to the new example already exists: foo/bar`);
+ expect(() => ensureExamplePath('foo/bar')).toThrowError(
+ `Unable to create example. The path to the new example already exists: foo/bar`
+ );
});
it('should create the directory on disk', () => {
@@ -66,23 +67,26 @@ describe('create-example tool', () => {
it('should write a JSON file to disk', () => {
const spy = spyOn(fs, 'writeFileSync');
writeStackBlitzFile('bar-bar', '/foo/bar-bar');
- expect(spy).toHaveBeenCalledWith(path.resolve(`/foo/bar-bar/${STACKBLITZ_CONFIG_FILENAME}`), [
- '{',
- ' "description": "Bar Bar",',
- ' "files": [',
- ' "!**/*.d.ts",',
- ' "!**/*.js",',
- ' "!**/*.[1,2].*"',
- ' ],',
- ' "tags": [',
- ' [',
- ' "bar",',
- ' "bar"',
- ' ]',
- ' ]',
- '}',
- '',
- ].join('\n'));
+ expect(spy).toHaveBeenCalledWith(
+ path.resolve(`/foo/bar-bar/${STACKBLITZ_CONFIG_FILENAME}`),
+ [
+ '{',
+ ' "description": "Bar Bar",',
+ ' "files": [',
+ ' "!**/*.d.ts",',
+ ' "!**/*.js",',
+ ' "!**/*.[1,2].*"',
+ ' ],',
+ ' "tags": [',
+ ' [',
+ ' "bar",',
+ ' "bar"',
+ ' ]',
+ ' ]',
+ '}',
+ '',
+ ].join('\n')
+ );
});
});
@@ -92,7 +96,7 @@ describe('create-example tool', () => {
spyOn(console, 'log');
spyOn(fs, 'existsSync').and.returnValue(true);
- const readFileSyncSpy = spyOn(fs, 'readFileSync').and.callFake(p => {
+ const readFileSyncSpy = spyOn(fs, 'readFileSync').and.callFake((p) => {
switch (p) {
case sourceGitIgnorePath:
return '**/*.bad';
@@ -100,9 +104,7 @@ describe('create-example tool', () => {
throw new Error('Unexpected path');
}
});
- spyOn(glob, 'sync').and.returnValue([
- 'a/', 'a/b/', 'a/c', 'x.ts', 'x.bad'
- ]);
+ spyOn(glob, 'sync').and.returnValue(['a/', 'a/b/', 'a/c', 'x.ts', 'x.bad']);
const ensureDirSyncSpy = spyOn(fs, 'ensureDirSync');
const copySyncSpy = spyOn(fs, 'copySync');
diff --git a/aio/tools/examples/example-boilerplate-cli.mjs b/aio/tools/examples/example-boilerplate-cli.mjs
new file mode 100644
index 00000000000..f2347550d69
--- /dev/null
+++ b/aio/tools/examples/example-boilerplate-cli.mjs
@@ -0,0 +1,3 @@
+import boilerplate from './example-boilerplate.mjs';
+
+boilerplate.main();
diff --git a/aio/tools/examples/example-boilerplate.js b/aio/tools/examples/example-boilerplate.mjs
similarity index 65%
rename from aio/tools/examples/example-boilerplate.js
rename to aio/tools/examples/example-boilerplate.mjs
index f2ee0821870..6b3b0f0d185 100644
--- a/aio/tools/examples/example-boilerplate.js
+++ b/aio/tools/examples/example-boilerplate.mjs
@@ -1,10 +1,15 @@
-const fs = require('fs-extra');
-const glob = require('glob');
-const ignore = require('ignore');
-const path = require('canonical-path');
-const shelljs = require('shelljs');
-const yargs = require('yargs');
-const {RUNFILES_ROOT, getExamplesBasePath, getSharedPath, EXAMPLE_CONFIG_FILENAME} = require('./constants');
+import fs from 'fs-extra';
+import glob from 'glob';
+import ignore from 'ignore';
+import path from 'canonical-path';
+import shelljs from 'shelljs';
+import yargs from 'yargs';
+import {
+ RUNFILES_ROOT,
+ getExamplesBasePath,
+ getSharedPath,
+ EXAMPLE_CONFIG_FILENAME,
+} from './constants.mjs';
const PROJECT_ROOT = RUNFILES_ROOT;
const EXAMPLES_BASE_PATH = getExamplesBasePath(PROJECT_ROOT);
@@ -19,19 +24,24 @@ class ExampleBoilerPlate {
* Add boilerplate files to an example
*/
add(exampleFolder, outputDir) {
- const gitignore = ignore().add(fs.readFileSync(path.resolve(BOILERPLATE_BASE_PATH, '.gitignore'), 'utf8'));
+ const gitignore = ignore().add(
+ fs.readFileSync(path.resolve(BOILERPLATE_BASE_PATH, '.gitignore'), 'utf8')
+ );
const exampleConfig = this.loadJsonFile(path.resolve(exampleFolder, EXAMPLE_CONFIG_FILENAME));
// Compute additional boilerplate files that should not be copied over for this specific example
// This allows the example to override boilerplate files locally, perhaps to include doc-regions specific to the example.
const overrideBoilerplate = exampleConfig['overrideBoilerplate'] || [];
- const boilerplateIgnore = ignore().add(gitignore).add(
- // Note that the `*` here is to skip over the boilerplate folder itself.
- // E.g. if the override is `a/b` then we what to match `cli/a/b` and `i18n/a/b` etc.
- overrideBoilerplate.map(p => path.join('*', p))
- );
- const isPathIgnored = absolutePath => boilerplateIgnore.ignores(path.relative(BOILERPLATE_BASE_PATH, absolutePath));
+ const boilerplateIgnore = ignore()
+ .add(gitignore)
+ .add(
+ // Note that the `*` here is to skip over the boilerplate folder itself.
+ // E.g. if the override is `a/b` then we what to match `cli/a/b` and `i18n/a/b` etc.
+ overrideBoilerplate.map((p) => path.join('*', p))
+ );
+ const isPathIgnored = (absolutePath) =>
+ boilerplateIgnore.ignores(path.relative(BOILERPLATE_BASE_PATH, absolutePath));
const boilerPlateType = exampleConfig.projectType || 'cli';
const boilerPlateBasePath = path.resolve(BOILERPLATE_BASE_PATH, boilerPlateType);
@@ -54,16 +64,21 @@ class ExampleBoilerPlate {
}
listOverrides() {
- const exampleFolders =
- this.getFoldersContaining(EXAMPLES_BASE_PATH, EXAMPLE_CONFIG_FILENAME, 'node_modules');
+ const exampleFolders = this.getFoldersContaining(
+ EXAMPLES_BASE_PATH,
+ EXAMPLE_CONFIG_FILENAME,
+ 'node_modules'
+ );
const overriddenFiles = [];
- exampleFolders.forEach(exampleFolder => {
+ exampleFolders.forEach((exampleFolder) => {
const exampleConfig = this.loadJsonFile(path.resolve(exampleFolder, EXAMPLE_CONFIG_FILENAME));
const overrideBoilerplate = exampleConfig['overrideBoilerplate'] || [];
if (overrideBoilerplate.length > 0) {
for (const file of overrideBoilerplate) {
- overriddenFiles.push(path.relative(EXAMPLES_BASE_PATH, path.resolve(exampleFolder, file)));
+ overriddenFiles.push(
+ path.relative(EXAMPLES_BASE_PATH, path.resolve(exampleFolder, file))
+ );
}
}
});
@@ -74,7 +89,9 @@ class ExampleBoilerPlate {
console.log(` - ${file}`);
}
console.log(`(All these paths are relative to ${EXAMPLES_BASE_PATH}.)`);
- console.log('If you are updating the boilerplate files then also consider updating these too.');
+ console.log(
+ 'If you are updating the boilerplate files then also consider updating these too.'
+ );
} else {
console.log('No boilerplate files have been overridden in examples.');
console.log('You are safe to update the boilerplate files.');
@@ -82,23 +99,31 @@ class ExampleBoilerPlate {
}
main() {
- yargs.usage('$0 [args]')
- .command('add ', 'create boilerplate for an example', yrgs => this.add(yrgs.argv._[1], yrgs.argv._[2]))
- .command('list-overrides', 'list all the boilerplate files that have been overridden in examples', () => this.listOverrides())
- .demandCommand(1, 'Please supply a command from the list above')
- .argv;
+ yargs(process.argv.slice(2))
+ .usage('$0 [args]')
+ .command('add ', 'create boilerplate for an example', (yrgs) =>
+ this.add(yrgs.argv._[1], yrgs.argv._[2])
+ )
+ .command(
+ 'list-overrides',
+ 'list all the boilerplate files that have been overridden in examples',
+ () => this.listOverrides()
+ )
+ .demandCommand(1, 'Please supply a command from the list above').argv;
}
getFoldersContaining(basePath, filename, ignore) {
const pattern = path.resolve(basePath, '**', filename);
const ignorePattern = path.resolve(basePath, '**', ignore, '**');
- return glob.sync(pattern, {ignore: [ignorePattern]}).map(file => path.dirname(file));
+ return glob.sync(pattern, {ignore: [ignorePattern]}).map((file) => path.dirname(file));
}
- loadJsonFile(filePath) { return fs.readJsonSync(filePath, {throws: false}) || {}; }
+ loadJsonFile(filePath) {
+ return fs.readJsonSync(filePath, {throws: false}) || {};
+ }
copyDirectoryContents(srcDir, dstDir, isPathIgnored) {
- shelljs.ls('-Al', srcDir).forEach(stat => {
+ shelljs.ls('-Al', srcDir).forEach((stat) => {
const srcPath = path.resolve(srcDir, stat.name);
const dstPath = path.resolve(dstDir, stat.name);
@@ -125,9 +150,4 @@ class ExampleBoilerPlate {
}
}
-module.exports = new ExampleBoilerPlate();
-
-// If this file was run directly then run the main function,
-if (require.main === module) {
- module.exports.main();
-}
+export default new ExampleBoilerPlate();
diff --git a/aio/tools/examples/example-boilerplate.spec.js b/aio/tools/examples/example-boilerplate.spec.mjs
similarity index 75%
rename from aio/tools/examples/example-boilerplate.spec.js
rename to aio/tools/examples/example-boilerplate.spec.mjs
index bb06e4d3d47..6baf24bd5ac 100644
--- a/aio/tools/examples/example-boilerplate.spec.js
+++ b/aio/tools/examples/example-boilerplate.spec.mjs
@@ -1,15 +1,15 @@
-const path = require('canonical-path');
-const fs = require('fs-extra');
-const glob = require('glob');
-const shelljs = require('shelljs');
+import path from 'canonical-path';
+import fs from 'fs-extra';
+import glob from 'glob';
+import shelljs from 'shelljs';
-const {RUNFILES_ROOT, getExamplesBasePath, getSharedPath} = require("./constants");
+import {RUNFILES_ROOT, getExamplesBasePath, getSharedPath} from './constants.mjs';
+import exampleBoilerPlate from './example-boilerplate.mjs';
const PROJECT_ROOT = RUNFILES_ROOT;
const EXAMPLES_BASE_PATH = getExamplesBasePath(PROJECT_ROOT);
const SHARED_PATH = getSharedPath(PROJECT_ROOT);
-const exampleBoilerPlate = require('./example-boilerplate');
const outputDir = process.env.TEST_TMPDIR; // Bazel-provided temp dir
describe('example-boilerplate tool', () => {
@@ -25,7 +25,7 @@ describe('example-boilerplate tool', () => {
it('should copy all the source boilerplate files for systemjs', () => {
const boilerplateDir = path.resolve(sharedDir, 'boilerplate');
- exampleBoilerPlate.loadJsonFile.and.returnValue({ projectType: 'systemjs' });
+ exampleBoilerPlate.loadJsonFile.and.returnValue({projectType: 'systemjs'});
exampleBoilerPlate.add(exampleFolder, outputDir);
@@ -38,7 +38,7 @@ describe('example-boilerplate tool', () => {
it('should copy all the source boilerplate files for cli', () => {
const boilerplateDir = path.resolve(sharedDir, 'boilerplate');
- exampleBoilerPlate.loadJsonFile.and.returnValue({ projectType: 'cli' });
+ exampleBoilerPlate.loadJsonFile.and.returnValue({projectType: 'cli'});
exampleBoilerPlate.add(exampleFolder, outputDir);
@@ -64,7 +64,7 @@ describe('example-boilerplate tool', () => {
it('should copy all the source boilerplate files for i18n (on top of the cli ones)', () => {
const boilerplateDir = path.resolve(sharedDir, 'boilerplate');
- exampleBoilerPlate.loadJsonFile.and.returnValue({ projectType: 'i18n' });
+ exampleBoilerPlate.loadJsonFile.and.returnValue({projectType: 'i18n'});
exampleBoilerPlate.add(exampleFolder, outputDir);
@@ -78,7 +78,7 @@ describe('example-boilerplate tool', () => {
it('should copy all the source boilerplate files for universal (on top of the cli ones)', () => {
const boilerplateDir = path.resolve(sharedDir, 'boilerplate');
- exampleBoilerPlate.loadJsonFile.and.returnValue({ projectType: 'universal' });
+ exampleBoilerPlate.loadJsonFile.and.returnValue({projectType: 'universal'});
exampleBoilerPlate.add(exampleFolder, outputDir);
@@ -93,7 +93,7 @@ describe('example-boilerplate tool', () => {
it('should not copy boilerplate files that match `overrideBoilerplate` in the example-config.json file', () => {
const boilerplateDir = path.resolve(sharedDir, 'boilerplate');
exampleBoilerPlate.loadJsonFile.and.returnValue({
- 'overrideBoilerplate': [ 'c/d' ]
+ 'overrideBoilerplate': ['c/d'],
});
exampleBoilerPlate.add(exampleFolder, outputDir);
@@ -106,12 +106,18 @@ describe('example-boilerplate tool', () => {
it('should try to load the example config file', () => {
exampleBoilerPlate.add(exampleFolder, outputDir);
expect(exampleBoilerPlate.loadJsonFile).toHaveBeenCalledTimes(1);
- expect(exampleBoilerPlate.loadJsonFile).toHaveBeenCalledWith(path.resolve(`${exampleFolder}/example-config.json`));
+ expect(exampleBoilerPlate.loadJsonFile).toHaveBeenCalledWith(
+ path.resolve(`${exampleFolder}/example-config.json`)
+ );
});
});
describe('copyDirectoryContents', () => {
- const spyFnFor = fnName => (...args) => { callLog.push(`${fnName}(${args.join(', ')})`); };
+ const spyFnFor =
+ (fnName) =>
+ (...args) => {
+ callLog.push(`${fnName}(${args.join(', ')})`);
+ };
let isPathIgnoredSpy;
let callLog;
@@ -154,7 +160,7 @@ describe('example-boilerplate tool', () => {
{name: 'file-1.txt', isDirectory: () => false},
{name: 'file-2.txt', isDirectory: () => false},
]);
- isPathIgnoredSpy.and.callFake(path => path.endsWith('file-1.txt'));
+ isPathIgnoredSpy.and.callFake((path) => path.endsWith('file-1.txt'));
exampleBoilerPlate.copyDirectoryContents('source/dir', 'destination/dir', isPathIgnoredSpy);
@@ -186,18 +192,19 @@ describe('example-boilerplate tool', () => {
it('should recursively copy sub-directories', () => {
spyOn(shelljs, 'ls')
- .withArgs('-Al', 'source/dir').and.returnValue([
+ .withArgs('-Al', 'source/dir')
+ .and.returnValue([
{name: 'file-1.txt', isDirectory: () => false},
{name: 'sub-dir-1', isDirectory: () => true},
{name: 'file-2.txt', isDirectory: () => false},
])
- .withArgs('-Al', path.resolve('source/dir/sub-dir-1')).and.returnValue([
+ .withArgs('-Al', path.resolve('source/dir/sub-dir-1'))
+ .and.returnValue([
{name: 'file-3.txt', isDirectory: () => false},
{name: 'sub-dir-2', isDirectory: () => true},
])
- .withArgs('-Al', path.resolve('source/dir/sub-dir-1/sub-dir-2')).and.returnValue([
- {name: 'file-4.txt', isDirectory: () => false},
- ]);
+ .withArgs('-Al', path.resolve('source/dir/sub-dir-1/sub-dir-2'))
+ .and.returnValue([{name: 'file-4.txt', isDirectory: () => false}]);
exampleBoilerPlate.copyDirectoryContents('source/dir', 'destination/dir', isPathIgnoredSpy);
@@ -210,22 +217,22 @@ describe('example-boilerplate tool', () => {
// Create `sub-dir-1` and recursively copy its contents.
`mkdir(-p, ${path.resolve('destination/dir/sub-dir-1')})`,
- // Copy `sub-dir-1/file-3.txt`.
- `test(-f, ${path.resolve('destination/dir/sub-dir-1/file-3.txt')})`,
- 'cp(' +
- `${path.resolve('source/dir/sub-dir-1/file-3.txt')}, ` +
- `${path.resolve('destination/dir/sub-dir-1')})`,
- `chmod(444, ${path.resolve('destination/dir/sub-dir-1/file-3.txt')})`,
+ // Copy `sub-dir-1/file-3.txt`.
+ `test(-f, ${path.resolve('destination/dir/sub-dir-1/file-3.txt')})`,
+ 'cp(' +
+ `${path.resolve('source/dir/sub-dir-1/file-3.txt')}, ` +
+ `${path.resolve('destination/dir/sub-dir-1')})`,
+ `chmod(444, ${path.resolve('destination/dir/sub-dir-1/file-3.txt')})`,
- // Create `sub-dir-1/sub-dir-2` and recursively copy its contents.
- `mkdir(-p, ${path.resolve('destination/dir/sub-dir-1/sub-dir-2')})`,
+ // Create `sub-dir-1/sub-dir-2` and recursively copy its contents.
+ `mkdir(-p, ${path.resolve('destination/dir/sub-dir-1/sub-dir-2')})`,
- // Copy `sub-dir-1/sub-dir-2/file-4.txt`.
- `test(-f, ${path.resolve('destination/dir/sub-dir-1/sub-dir-2/file-4.txt')})`,
- 'cp(' +
- `${path.resolve('source/dir/sub-dir-1/sub-dir-2/file-4.txt')}, ` +
- `${path.resolve('destination/dir/sub-dir-1/sub-dir-2')})`,
- `chmod(444, ${path.resolve('destination/dir/sub-dir-1/sub-dir-2/file-4.txt')})`,
+ // Copy `sub-dir-1/sub-dir-2/file-4.txt`.
+ `test(-f, ${path.resolve('destination/dir/sub-dir-1/sub-dir-2/file-4.txt')})`,
+ 'cp(' +
+ `${path.resolve('source/dir/sub-dir-1/sub-dir-2/file-4.txt')}, ` +
+ `${path.resolve('destination/dir/sub-dir-1/sub-dir-2')})`,
+ `chmod(444, ${path.resolve('destination/dir/sub-dir-1/sub-dir-2/file-4.txt')})`,
// Copy `file-2.txt`.
`test(-f, ${path.resolve('destination/dir/file-2.txt')})`,
@@ -236,18 +243,19 @@ describe('example-boilerplate tool', () => {
it('should skip ignored directories', () => {
spyOn(shelljs, 'ls')
- .withArgs('-Al', 'source/dir').and.returnValue([
+ .withArgs('-Al', 'source/dir')
+ .and.returnValue([
{name: 'file-1.txt', isDirectory: () => false},
{name: 'sub-dir-1', isDirectory: () => true},
])
- .withArgs('-Al', path.resolve('source/dir/sub-dir-1')).and.returnValue([
+ .withArgs('-Al', path.resolve('source/dir/sub-dir-1'))
+ .and.returnValue([
{name: 'file-2.txt', isDirectory: () => false},
{name: 'sub-dir-2', isDirectory: () => true},
])
- .withArgs('-Al', path.resolve('source/dir/sub-dir-1/sub-dir-2')).and.returnValue([
- {name: 'file-3.txt', isDirectory: () => false},
- ]);
- isPathIgnoredSpy.and.callFake(path => path.endsWith('sub-dir-1'));
+ .withArgs('-Al', path.resolve('source/dir/sub-dir-1/sub-dir-2'))
+ .and.returnValue([{name: 'file-3.txt', isDirectory: () => false}]);
+ isPathIgnoredSpy.and.callFake((path) => path.endsWith('sub-dir-1'));
exampleBoilerPlate.copyDirectoryContents('source/dir', 'destination/dir', isPathIgnoredSpy);
@@ -272,30 +280,42 @@ describe('example-boilerplate tool', () => {
it('should list all files that are overridden in examples', () => {
spyOn(exampleBoilerPlate, 'loadJsonFile').and.returnValues(
- {"overrideBoilerplate": ["angular.json", "tsconfig.json"]}, // a/b/example-config.json
- {"overrideBoilerplate": []}, // c/d/example-config.json
- {}, // e/f/example-config.json
+ {'overrideBoilerplate': ['angular.json', 'tsconfig.json']}, // a/b/example-config.json
+ {'overrideBoilerplate': []}, // c/d/example-config.json
+ {} // e/f/example-config.json
);
exampleBoilerPlate.listOverrides();
- expect(exampleBoilerPlate.getFoldersContaining)
- .toHaveBeenCalledWith(examplesDir, 'example-config.json', 'node_modules');
- expect(console.log).toHaveBeenCalledWith('Boilerplate files that have been overridden in examples:');
+ expect(exampleBoilerPlate.getFoldersContaining).toHaveBeenCalledWith(
+ examplesDir,
+ 'example-config.json',
+ 'node_modules'
+ );
+ expect(console.log).toHaveBeenCalledWith(
+ 'Boilerplate files that have been overridden in examples:'
+ );
expect(console.log).toHaveBeenCalledWith(' - a/b/angular.json');
expect(console.log).toHaveBeenCalledWith(' - a/b/tsconfig.json');
expect(console.log).toHaveBeenCalledWith(`(All these paths are relative to ${examplesDir}.)`);
- expect(console.log).toHaveBeenCalledWith('If you are updating the boilerplate files then also consider updating these too.');
+ expect(console.log).toHaveBeenCalledWith(
+ 'If you are updating the boilerplate files then also consider updating these too.'
+ );
});
it('should display a helpful message if there are no overridden files', () => {
spyOn(exampleBoilerPlate, 'loadJsonFile').and.returnValues(
- {"overrideBoilerplate": null}, // a/b/example-config.json
- {"overrideBoilerplate": []}, // c/d/example-config.json
- {}, // e/f/example-config.json
+ {'overrideBoilerplate': null}, // a/b/example-config.json
+ {'overrideBoilerplate': []}, // c/d/example-config.json
+ {} // e/f/example-config.json
);
exampleBoilerPlate.listOverrides();
- expect(exampleBoilerPlate.getFoldersContaining)
- .toHaveBeenCalledWith(examplesDir, 'example-config.json', 'node_modules');
- expect(console.log).toHaveBeenCalledWith('No boilerplate files have been overridden in examples.');
+ expect(exampleBoilerPlate.getFoldersContaining).toHaveBeenCalledWith(
+ examplesDir,
+ 'example-config.json',
+ 'node_modules'
+ );
+ expect(console.log).toHaveBeenCalledWith(
+ 'No boilerplate files have been overridden in examples.'
+ );
expect(console.log).toHaveBeenCalledWith('You are safe to update the boilerplate files.');
});
});
@@ -303,18 +323,24 @@ describe('example-boilerplate tool', () => {
describe('getFoldersContaining', () => {
it('should use glob.sync', () => {
spyOn(glob, 'sync').and.returnValue(['a/b/config.json', 'c/d/config.json']);
- const result = exampleBoilerPlate.getFoldersContaining('base/path', 'config.json', 'node_modules');
- expect(glob.sync).toHaveBeenCalledWith(path.resolve('base/path/**/config.json'), { ignore: [path.resolve('base/path/**/node_modules/**')] });
+ const result = exampleBoilerPlate.getFoldersContaining(
+ 'base/path',
+ 'config.json',
+ 'node_modules'
+ );
+ expect(glob.sync).toHaveBeenCalledWith(path.resolve('base/path/**/config.json'), {
+ ignore: [path.resolve('base/path/**/node_modules/**')],
+ });
expect(result).toEqual(['a/b', 'c/d']);
});
});
describe('loadJsonFile', () => {
it('should use fs.readJsonSync', () => {
- spyOn(fs, 'readJsonSync').and.returnValue({ some: 'value' });
+ spyOn(fs, 'readJsonSync').and.returnValue({some: 'value'});
const result = exampleBoilerPlate.loadJsonFile('some/file');
expect(fs.readJsonSync).toHaveBeenCalledWith('some/file', {throws: false});
- expect(result).toEqual({ some: 'value' });
+ expect(result).toEqual({some: 'value'});
});
it('should return an empty object if readJsonSync fails', () => {
diff --git a/aio/tools/transforms/authors-package/BUILD.bazel b/aio/tools/transforms/authors-package/BUILD.bazel
index ba9b56656ac..7fc8376e58b 100644
--- a/aio/tools/transforms/authors-package/BUILD.bazel
+++ b/aio/tools/transforms/authors-package/BUILD.bazel
@@ -9,7 +9,7 @@ js_library(
["**/*.js"],
exclude = [
"**/*/spec.js",
- "watchr.js",
+ "watchr.mjs",
],
),
deps = [
@@ -25,7 +25,7 @@ js_library(
js_library(
name = "watchdocs",
srcs = [
- "watchr.js",
+ "watchr.mjs",
],
deps = [
":authors-package",
diff --git a/aio/tools/transforms/authors-package/watchr.js b/aio/tools/transforms/authors-package/watchr.js
deleted file mode 100644
index 94b043c88a5..00000000000
--- a/aio/tools/transforms/authors-package/watchr.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/* eslint no-console: "off" */
-const watchr = require('watchr');
-const {relative} = require('canonical-path');
-const {generateDocs} = require('./index.js');
-const { PROJECT_ROOT, CONTENTS_PATH, API_SOURCE_PATH } = require('../config');
-
-function listener(changeType, fullPath) {
- try {
- const relativePath = relative(PROJECT_ROOT, fullPath);
- console.log('The file', relativePath, `was ${changeType}d at`, new Date().toUTCString());
- generateDocs(relativePath);
- } catch(err) {
- console.log('Error generating docs', err);
- }
-}
-
-function next(error) {
- if (error) {
- console.log(error);
- }
-}
-
-function watch() {
- console.log('============================================================================');
- console.log('Started watching files in:');
- console.log(' - ', CONTENTS_PATH);
- console.log(' - ', API_SOURCE_PATH);
- console.log('Doc gen will automatically run on any change to a file in either directory.');
- console.log('============================================================================');
-
- watchr.open(CONTENTS_PATH, listener, next);
- watchr.open(API_SOURCE_PATH, listener, next);
-}
-
-exports.watch = watch;
\ No newline at end of file
diff --git a/aio/tools/transforms/authors-package/watchr.mjs b/aio/tools/transforms/authors-package/watchr.mjs
new file mode 100644
index 00000000000..72ca2878237
--- /dev/null
+++ b/aio/tools/transforms/authors-package/watchr.mjs
@@ -0,0 +1,35 @@
+/* eslint no-console: "off" */
+import watchr from 'watchr';
+import canonicalPath from 'canonical-path';
+import authorsPackage from './index.js';
+import config from '../config.js';
+
+function listener(changeType, fullPath) {
+ try {
+ const relativePath = canonicalPath.relative(config.PROJECT_ROOT, fullPath);
+ console.log('The file', relativePath, `was ${changeType}d at`, new Date().toUTCString());
+ authorsPackage.generateDocs(relativePath);
+ } catch (err) {
+ console.log('Error generating docs', err);
+ }
+}
+
+function next(error) {
+ if (error) {
+ console.log(error);
+ }
+}
+
+function watch() {
+ console.log('============================================================================');
+ console.log('Started watching files in:');
+ console.log(' - ', config.CONTENTS_PATH);
+ console.log(' - ', config.API_SOURCE_PATH);
+ console.log('Doc gen will automatically run on any change to a file in either directory.');
+ console.log('============================================================================');
+
+ watchr.open(config.CONTENTS_PATH, listener, next);
+ watchr.open(config.API_SOURCE_PATH, listener, next);
+}
+
+exports.watch = watch;
diff --git a/packages/compiler-cli/test/compliance/partial/partial_compliance_goldens.bzl b/packages/compiler-cli/test/compliance/partial/partial_compliance_goldens.bzl
index 4df086fec8b..967356fc737 100644
--- a/packages/compiler-cli/test/compliance/partial/partial_compliance_goldens.bzl
+++ b/packages/compiler-cli/test/compliance/partial/partial_compliance_goldens.bzl
@@ -18,7 +18,7 @@ def partial_compliance_golden(filePath):
name = generate_partial_name,
testonly = True,
data = data,
- data_for_args = [filePath],
+ data_for_expansion = [filePath],
visibility = [":__pkg__"],
entry_point = "//packages/compiler-cli/test/compliance/partial:cli.ts",
templated_args = ["$(execpath %s)" % filePath],
diff --git a/tools/circular_dependency_test/index.bzl b/tools/circular_dependency_test/index.bzl
index b3a2eab761f..e2e99b86ee6 100644
--- a/tools/circular_dependency_test/index.bzl
+++ b/tools/circular_dependency_test/index.bzl
@@ -17,7 +17,7 @@ def circular_dependency_test(name, deps, entry_point, **kwargs):
name = name,
data = ["@npm//madge"] + deps,
entry_point = "@npm//:node_modules/madge/bin/cli.js",
- data_for_args = [MADGE_CONFIG_LABEL],
+ data_for_expansion = [MADGE_CONFIG_LABEL],
templated_args = [
"--circular",
"--no-spinner",
diff --git a/tools/esm-interop/nodejs-rules.bzl b/tools/esm-interop/nodejs-rules.bzl
index 120316ffe9a..8b7c010d4e8 100644
--- a/tools/esm-interop/nodejs-rules.bzl
+++ b/tools/esm-interop/nodejs-rules.bzl
@@ -6,7 +6,7 @@ load("//tools/esm-interop:extract-esm-output.bzl", "extract_esm_outputs")
def nodejs_binary(
name,
- data_for_args = [],
+ data_for_expansion = [],
linker_enabled = False,
npm_workspace = "npm",
**kwargs):
@@ -25,12 +25,12 @@ def nodejs_binary(
extract_esm_outputs(
name = "%s_esm_deps" % name,
testonly = testonly,
- deps = data,
+ deps = data + data_for_expansion,
)
_nodejs_binary(
name = name,
- data = [":%s_esm_deps" % name] + data_for_args,
+ data = [":%s_esm_deps" % name] + data_for_expansion,
testonly = testonly,
entry_point = str(entry_point).replace(".js", ".mjs"),
env = env,
@@ -41,7 +41,7 @@ def nodejs_binary(
def nodejs_test(
name,
- data_for_args = [],
+ data_for_expansion = [],
linker_enabled = False,
npm_workspace = "npm",
**kwargs):
@@ -58,12 +58,12 @@ def nodejs_test(
extract_esm_outputs(
name = "%s_esm_deps" % name,
testonly = True,
- deps = data,
+ deps = data + data_for_expansion,
)
_nodejs_test(
name = name,
- data = [":%s_esm_deps" % name] + data_for_args,
+ data = [":%s_esm_deps" % name] + data_for_expansion,
env = env,
templated_args = templated_args,
use_esm = True,
diff --git a/tools/symbol-extractor/index.bzl b/tools/symbol-extractor/index.bzl
index c76739c4b3e..a947335f397 100644
--- a/tools/symbol-extractor/index.bzl
+++ b/tools/symbol-extractor/index.bzl
@@ -23,7 +23,7 @@ def js_expected_symbol_test(name, src, golden, data = [], **kwargs):
data = all_data,
entry_point = entry_point,
tags = kwargs.pop("tags", []) + ["symbol_extractor"],
- data_for_args = [src, golden],
+ data_for_expansion = [src, golden],
templated_args = ["$(rootpath %s)" % src, "$(rootpath %s)" % golden],
**kwargs
)
@@ -33,7 +33,7 @@ def js_expected_symbol_test(name, src, golden, data = [], **kwargs):
testonly = True,
data = all_data,
entry_point = entry_point,
- data_for_args = [src, golden],
+ data_for_expansion = [src, golden],
templated_args = ["$(rootpath %s)" % src, "$(rootpath %s)" % golden, "--accept"],
**kwargs
)