In #35381, a new Protractor config file was introduced in docs examples, `protractor-puppeteer.conf.js`, that was only supposed to be used on CI and not be shipped with the ZIP archives provided for users to download and experiment with the docs examples locally. The logic to ignore the `protractor-puppeteer.conf.js` file was incorrect, resulting in the file being retained in some examples (e.g. [universal][1]). The problem was not immediately obvious, because most examples explicitly specify all `**/*.js` files as ignored, but for other examples the file was retained in the ZIP archive. This commit fixes the logic to ensure the file is excluded from all docs examples ZIP archives. [1]: https://v9.angular.io/generated/zips/universal/universal.zip PR Close #36018
187 lines
6.3 KiB
JavaScript
187 lines
6.3 KiB
JavaScript
'use strict';
|
|
|
|
// Canonical path provides a consistent path (i.e. always forward slashes) across different OSes
|
|
const path = require('canonical-path');
|
|
const archiver = require('archiver');
|
|
const fs = require('fs-extra');
|
|
const globby = require('globby');
|
|
|
|
const PackageJsonCustomizer = require('./customizer/package-json/packageJsonCustomizer');
|
|
const regionExtractor = require('../transforms/examples-package/services/region-parser');
|
|
|
|
const EXAMPLE_CONFIG_NAME = 'example-config.json';
|
|
|
|
class ExampleZipper {
|
|
constructor(sourceDirName, outputDirName) {
|
|
this.examplesPackageJson = path.join(__dirname, '../examples/shared/package.json');
|
|
this.examplesSystemjsConfig = path.join(__dirname, '../examples/shared/boilerplate/systemjs/src/systemjs.config.js');
|
|
this.examplesSystemjsLoaderConfig = path.join(__dirname, '../examples/shared/boilerplate/systemjs/src/systemjs-angular-loader.js');
|
|
this.exampleTsconfig = path.join(__dirname, '../examples/shared/boilerplate/systemjs/src/tsconfig.json');
|
|
this.customizer = new PackageJsonCustomizer();
|
|
|
|
let gpathStackblitz = path.join(sourceDirName, '**/*stackblitz.json');
|
|
let gpathZipper = path.join(sourceDirName, '**/zipper.json');
|
|
let configFileNames = globby.sync([gpathStackblitz, gpathZipper], { ignore: ['**/node_modules/**'] });
|
|
configFileNames.forEach((configFileName) => {
|
|
this._zipExample(configFileName, sourceDirName, outputDirName);
|
|
});
|
|
}
|
|
|
|
_changeTypeRoots(tsconfig) {
|
|
return tsconfig.replace('../../../', '../');
|
|
}
|
|
|
|
_createZipArchive(zipFileName) {
|
|
let dirName = path.dirname(zipFileName);
|
|
fs.ensureDirSync(dirName);
|
|
let output = fs.createWriteStream(zipFileName);
|
|
let archive = archiver('zip');
|
|
|
|
archive.on('error', function (err) {
|
|
throw err;
|
|
});
|
|
|
|
archive.pipe(output);
|
|
return archive;
|
|
}
|
|
|
|
_getExampleType(sourceFolder) {
|
|
const filePath = path.join(sourceFolder, EXAMPLE_CONFIG_NAME);
|
|
try {
|
|
return require(filePath, 'utf-8').projectType || 'cli';
|
|
} catch (err) { // empty file, so it is cli
|
|
return 'cli';
|
|
}
|
|
}
|
|
|
|
// rename a custom main.ts or index.html file
|
|
_renameFile(file, exampleType) {
|
|
if (/src\/main[-.]\w+\.ts$/.test(file) && exampleType !== 'universal') {
|
|
return 'src/main.ts';
|
|
}
|
|
|
|
if (/src\/index[-.]\w+\.html$/.test(file)) {
|
|
return 'src/index.html';
|
|
}
|
|
|
|
return file;
|
|
}
|
|
|
|
_zipExample(configFileName, sourceDirName, outputDirName) {
|
|
let json = require(configFileName, 'utf-8');
|
|
const basePath = json.basePath || '';
|
|
const jsonFileName = configFileName.replace(/^.*[\\\/]/, '');
|
|
let relativeDirName = path.dirname(path.relative(sourceDirName, configFileName));
|
|
let exampleZipName;
|
|
const exampleType = this._getExampleType(path.join(sourceDirName, relativeDirName));
|
|
if (relativeDirName.indexOf('/') !== -1) { // Special example
|
|
exampleZipName = relativeDirName.split('/').join('-');
|
|
} else {
|
|
exampleZipName = jsonFileName.replace(/(stackblitz|zipper).json/, relativeDirName);
|
|
}
|
|
|
|
const exampleDirName = path.dirname(configFileName);
|
|
const outputFileName = path.join(outputDirName, relativeDirName, exampleZipName + '.zip');
|
|
let defaultIncludes = ['**/*.ts', '**/*.js', '**/*.es6', '**/*.css', '**/*.html', '**/*.md', '**/*.json', '**/*.png', '**/*.svg'];
|
|
let alwaysIncludes = [
|
|
'.editorconfig',
|
|
'.gitignore',
|
|
'angular.json',
|
|
'browserslist',
|
|
'bs-config.json',
|
|
'karma.conf.js',
|
|
'karma-test-shim.js',
|
|
'tsconfig.*',
|
|
'tslint.*',
|
|
'e2e/protractor.conf.js',
|
|
'e2e/tsconfig.json',
|
|
'src/favicon.ico',
|
|
'src/polyfills.ts',
|
|
'src/test.ts',
|
|
'src/typings.d.ts',
|
|
'src/environments/**/*',
|
|
'src/testing/**/*',
|
|
// Only ignore root package.json
|
|
'!package.json'
|
|
];
|
|
var alwaysExcludes = [
|
|
'!**/bs-config.e2e.json',
|
|
'!**/*stackblitz.*',
|
|
'!**/*zipper.*',
|
|
'!**/systemjs.config.js',
|
|
'!**/npm-debug.log',
|
|
'!**/example-config.json',
|
|
'!**/wallaby.js',
|
|
'!**/e2e/protractor-puppeteer.conf.js',
|
|
// AOT related files
|
|
'!**/aot/**/*.*',
|
|
'!**/*-aot.*'
|
|
];
|
|
|
|
if (json.files) {
|
|
if (json.files.length > 0) {
|
|
json.files = json.files.map(file => {
|
|
if (file.startsWith('!')) {
|
|
if (file.startsWith('!**')) {
|
|
return file;
|
|
}
|
|
|
|
return '!' + basePath + file.substr(1);
|
|
}
|
|
|
|
return basePath + file;
|
|
});
|
|
|
|
if (json.files[0][0] === '!') {
|
|
json.files = defaultIncludes.concat(json.files);
|
|
}
|
|
}
|
|
} else {
|
|
json.files = defaultIncludes;
|
|
}
|
|
|
|
json.files = json.files.concat(alwaysIncludes);
|
|
|
|
let gpaths = json.files.map((fileName) => {
|
|
fileName = fileName.trim();
|
|
if (fileName[0] === '!') {
|
|
return '!' + path.join(exampleDirName, fileName.substr(1));
|
|
} else {
|
|
return path.join(exampleDirName, fileName);
|
|
}
|
|
});
|
|
|
|
gpaths.push(...alwaysExcludes);
|
|
|
|
let fileNames = globby.sync(gpaths, { ignore: ['**/node_modules/**'] });
|
|
|
|
let zip = this._createZipArchive(outputFileName);
|
|
fileNames.forEach((fileName) => {
|
|
let relativePath = path.relative(exampleDirName, fileName);
|
|
relativePath = this._renameFile(relativePath, exampleType);
|
|
let content = fs.readFileSync(fileName, 'utf8');
|
|
let extn = path.extname(fileName).substr(1);
|
|
// if we don't need to clean up the file then we can do the following.
|
|
// zip.append(fs.createReadStream(fileName), { name: relativePath });
|
|
let output = regionExtractor()(content, extn).contents;
|
|
|
|
zip.append(output, { name: relativePath } );
|
|
});
|
|
|
|
// we need the package.json from _examples root, not the _boilerplate one
|
|
zip.append(this.customizer.generate(exampleType), { name: 'package.json' });
|
|
// also a systemjs config
|
|
if (exampleType === 'systemjs') {
|
|
zip.append(fs.readFileSync(this.examplesSystemjsConfig, 'utf8'), { name: 'src/systemjs.config.js' });
|
|
zip.append(fs.readFileSync(this.examplesSystemjsLoaderConfig, 'utf8'), { name: 'src/systemjs-angular-loader.js' });
|
|
// a modified tsconfig
|
|
let tsconfig = fs.readFileSync(this.exampleTsconfig, 'utf8');
|
|
zip.append(this._changeTypeRoots(tsconfig), {name: 'src/tsconfig.json'});
|
|
}
|
|
|
|
zip.finalize();
|
|
}
|
|
}
|
|
|
|
module.exports = ExampleZipper;
|