Added angular-librarian for manage library
This commit is contained in:
parent
9d174550f5
commit
e625f9fd30
44 changed files with 1867 additions and 228 deletions
69
tasks/build.js
Normal file
69
tasks/build.js
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const ngc = require('@angular/compiler-cli/src/main').main;
|
||||
const librarianUtils = require('angular-librarian/commands/utilities');
|
||||
const path = require('path');
|
||||
|
||||
const copyGlobs = require('./copy-globs');
|
||||
const copyToBuild = require('./copy-build');
|
||||
const inlineResources = require('./inline-resources');
|
||||
const rollup = require('./rollup');
|
||||
|
||||
const colorize = librarianUtils.colorize;
|
||||
const rootDir = path.resolve(__dirname, '..');
|
||||
const buildDir = path.resolve(rootDir, 'build');
|
||||
const distDir = path.resolve(rootDir, 'dist');
|
||||
const libName = require(path.resolve(rootDir, 'package.json')).name;
|
||||
const srcDir = path.resolve(rootDir, 'src');
|
||||
const tscDir = path.resolve(rootDir, 'out-tsc');
|
||||
const es5Dir = path.resolve(tscDir, 'lib-es5');
|
||||
const es2015Dir = path.resolve(tscDir, 'lib-es2015');
|
||||
|
||||
const runPromise = (message, fn) => {
|
||||
return function() {
|
||||
console.info(colorize.colorize(message, 'cyan'));
|
||||
return fn().then(complete);
|
||||
};
|
||||
};
|
||||
|
||||
const complete = (depth = 0) => {
|
||||
const spaces = ' '.repeat(depth);
|
||||
console.info(colorize.colorize(`${ spaces }> Complete`, 'green'));
|
||||
};
|
||||
const compileCode = () => Promise.all([2015, 5].map((type) =>
|
||||
ngc({ project: path.resolve(rootDir, `tsconfig.es${ type }.json`)})
|
||||
.then((exitCode) =>
|
||||
exitCode === 0 ? Promise.resolve() : Promise.reject()
|
||||
)
|
||||
));
|
||||
const copyMetadata = () =>
|
||||
copyGlobs(['**/*.d.ts', '**/*.metadata.json'], es2015Dir, distDir);
|
||||
const copyPackageFiles = () =>
|
||||
copyGlobs(['.npmignore', 'package.json', 'README.md'], rootDir, distDir)
|
||||
.then(() => {
|
||||
const contents = fs.readFileSync(path.resolve(distDir, 'package.json'), 'utf8');
|
||||
|
||||
return fs.writeFileSync(path.resolve(distDir, 'package.json'), contents.replace('"dependencies":', '"peerDependencies":'));
|
||||
});
|
||||
const copySource = () => copyGlobs('**/*', srcDir, buildDir);
|
||||
const doInlining = () => inlineResources(buildDir, 'src');
|
||||
const rollupBundles = () => rollup(libName, {
|
||||
dist: distDir,
|
||||
es2015: es2015Dir,
|
||||
es5: es5Dir,
|
||||
root: rootDir
|
||||
});
|
||||
|
||||
return Promise.resolve()
|
||||
.then(runPromise('Copying `src` files into `build`', copySource))
|
||||
.then(runPromise('Inlining resources', doInlining))
|
||||
.then(runPromise('Compiling code', compileCode))
|
||||
.then(runPromise('Copying typings + metadata to `dist`', copyMetadata))
|
||||
.then(runPromise('Generating bundles via rollup', rollupBundles))
|
||||
.then(runPromise('Copying package files to `dist`', copyPackageFiles))
|
||||
.catch((error) => {
|
||||
console.error('\x1b[31m%s\x1b[0m', '> Build failed\n');
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
16
tasks/copy-build.js
Normal file
16
tasks/copy-build.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs-extra');
|
||||
|
||||
// copy all src files -> build
|
||||
const copyToBuild = (buildDir, sourceDir) => {
|
||||
fs.ensureDirSync(buildDir);
|
||||
fs.emptyDirSync(buildDir);
|
||||
fs.copySync(sourceDir, buildDir);
|
||||
};
|
||||
|
||||
module.exports = copyToBuild;
|
||||
|
||||
if (!module.parent) {
|
||||
copyToBuild('./build', './src');
|
||||
}
|
||||
35
tasks/copy-globs.js
Normal file
35
tasks/copy-globs.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const glob = require('glob');
|
||||
const path = require('path');
|
||||
|
||||
const copy = (globs, from, to) => {
|
||||
if (typeof globs === 'string') {
|
||||
globs = [globs];
|
||||
}
|
||||
|
||||
fs.ensureDir(to);
|
||||
return Promise.all(
|
||||
globs.map((fileGlob) => copyGlob(fileGlob, from, to))
|
||||
);
|
||||
};
|
||||
|
||||
const copyGlob = (fileGlob, from, to) => new Promise((resolve, reject) => {
|
||||
glob(fileGlob, { cwd: from, nodir: true }, (error, files) => {
|
||||
if (error) reject(error);
|
||||
|
||||
files.forEach((file) => {
|
||||
const origin = path.resolve(from, file);
|
||||
const destination = path.resolve(to, file);
|
||||
const contents = fs.readFileSync(origin, 'utf8');
|
||||
|
||||
fs.ensureDirSync(path.dirname(destination));
|
||||
fs.writeFileSync(destination, contents);
|
||||
});
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = copy;
|
||||
186
tasks/inline-resources.js
Normal file
186
tasks/inline-resources.js
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
'use strict';
|
||||
// original code by the Angular Material 2 team
|
||||
|
||||
const fs = require('fs');
|
||||
const glob = require('glob');
|
||||
const path = require('path');
|
||||
const sass = require('node-sass');
|
||||
|
||||
const inlineResources = (globs, sourcePrefix) => {
|
||||
if (typeof globs === 'string') {
|
||||
globs = [globs];
|
||||
}
|
||||
|
||||
return Promise.all(
|
||||
globs.map((pattern) => replaceSource(pattern, sourcePrefix))
|
||||
);
|
||||
};
|
||||
|
||||
const replaceSource = (pattern, sourcePrefix) => {
|
||||
// pattern is a directory
|
||||
if (pattern.indexOf('*') === -1) {
|
||||
pattern = path.join(pattern, '**', '*');
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
glob(pattern, {}, (error, files) => {
|
||||
if (error) reject(Error);
|
||||
|
||||
files.filter((name) => /\.ts$/.test(name)).forEach((filePath) => {
|
||||
try {
|
||||
inlineFileResources(filePath, sourcePrefix);
|
||||
} catch (readError) {
|
||||
reject(readError);
|
||||
}
|
||||
});
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const inlineFileResources = (filePath, sourcePrefix) => {
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
const inlineContents = inlineResourcesFromString(content, sourcePrefix, (url) =>
|
||||
path.join(path.dirname(filePath), url)
|
||||
);
|
||||
|
||||
fs.writeFileSync(filePath, inlineContents);
|
||||
};
|
||||
|
||||
const inlineResourcesFromString = (content, sourcePrefix, callback) => [
|
||||
inlineTemplate, inlineStyle, removeModuleId
|
||||
].reduce((final, method) => method(final, sourcePrefix, callback), content);
|
||||
|
||||
const inlineTemplate = (content, sourcePrefix, callback) =>
|
||||
content.replace(/templateUrl:\s*'([^']+?\.html)'/g, (match, url) => {
|
||||
const mini = getMiniContents(url, sourcePrefix, callback);
|
||||
|
||||
return `template: "${mini}"`;
|
||||
});
|
||||
|
||||
const inlineStyle = (content, sourcePrefix, callback) =>
|
||||
content.replace(/styleUrls:\s*(\[[\s\S]*?\])/gm, (match, styleUrls) => {
|
||||
const urls = eval(styleUrls); // string -> array
|
||||
return 'styles: [' + urls.map((url) => {
|
||||
const mini = getMiniContents(url, sourcePrefix, callback);
|
||||
|
||||
return `"${mini}"`;
|
||||
}).join(',\n') + ']';
|
||||
});
|
||||
|
||||
const getMiniContents = (url, sourcePrefix, callback) => {
|
||||
const srcFile = callback(url);
|
||||
const file = srcFile.replace(/^dist/, sourcePrefix)
|
||||
const srcDir = file.slice(0, file.lastIndexOf(path.sep));
|
||||
let template = '';
|
||||
|
||||
if (file.match(/\.s(a|c)ss$/)) {
|
||||
// convert SASS -> CSS
|
||||
template = sass.renderSync({
|
||||
file,
|
||||
importer: (url) => handleSassImport(url, srcDir)
|
||||
});
|
||||
template = template.css.toString();
|
||||
} else {
|
||||
template = fs.readFileSync(file, 'utf8');
|
||||
}
|
||||
|
||||
return minifyText(template);
|
||||
};
|
||||
|
||||
const handleSassImport = (url, srcDir) => {
|
||||
const fullUrl = getFullSassUrl(url, srcDir);
|
||||
let isPartial = false;
|
||||
let validUrls = getSassUrls(fullUrl);
|
||||
|
||||
// if we can't find the file, try to
|
||||
// see find it as a partial (underscore-prefixed)
|
||||
if (validUrls.length === 0) {
|
||||
validUrls = getSassUrls(fullUrl, true);
|
||||
isPartial = true;
|
||||
}
|
||||
|
||||
const file = getSassImportUrl(validUrls);
|
||||
|
||||
// CSS files don't get compiled in
|
||||
return /\.css$/.test(file) ?
|
||||
{ contents: fs.readFileSync(file, 'utf8') } :
|
||||
{ file };
|
||||
};
|
||||
|
||||
const getSassUrls = (url, partial) => {
|
||||
let extensions = ['sass', 'scss'];
|
||||
|
||||
if (!partial) {
|
||||
extensions = extensions.concat('', 'css');
|
||||
} else {
|
||||
const lastSlash = url.lastIndexOf(path.sep);
|
||||
const urlDir = url.slice(0, lastSlash);
|
||||
const fileName = url.slice(lastSlash + 1);
|
||||
|
||||
if (fileName[0] !== '_') {
|
||||
url = urlDir + path.sep + '_' + fileName;
|
||||
}
|
||||
}
|
||||
|
||||
return extensions.reduce((valid, extension) => {
|
||||
const extensionUrl = verifyUrl(url, extension);
|
||||
|
||||
if (extensionUrl) {
|
||||
valid = valid.concat(extensionUrl);
|
||||
}
|
||||
|
||||
return valid;
|
||||
}, []);
|
||||
};
|
||||
|
||||
const verifyUrl = (url, extension) => {
|
||||
if (extension) {
|
||||
url = url + `.${ extension }`;
|
||||
}
|
||||
|
||||
if (!fs.existsSync(url)) {
|
||||
url = null;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
// convert ~-prefixed filenames to node_modules-prefixed
|
||||
// make all others relative to srcDir
|
||||
const getFullSassUrl = (url, srcDir) =>
|
||||
/^~/.test(url) ?
|
||||
path.resolve('node_modules', url.slice(1)) :
|
||||
path.resolve(srcDir, url);
|
||||
|
||||
const getSassImportUrl = (validUrls) => {
|
||||
if (validUrls.length !== 1) {
|
||||
let error = 'Cannot determine Sass/CSS file to process. ';
|
||||
|
||||
if (validUrls.length === 0) {
|
||||
error = error + `\n There are no files matching ${ url }`;
|
||||
} else {
|
||||
error = error + 'Candidates:\n ' + validUrls.join('\n ')
|
||||
+ '\nPlease delete or rename all but one of these files or specify the extension to use.';
|
||||
}
|
||||
|
||||
throw new Error(error);
|
||||
}
|
||||
|
||||
return validUrls[0];
|
||||
};
|
||||
|
||||
|
||||
const minifyText = (text) => text
|
||||
.replace(/([\n\r]\s*)+/gm, ' ')
|
||||
.replace(/"/g, '\\"');
|
||||
|
||||
const removeModuleId = (content) =>
|
||||
content.replace(/\s*moduleId:\s*module\.id\s*,?\s*/gm, '');
|
||||
|
||||
module.exports = inlineResources;
|
||||
|
||||
if (!module.parent) {
|
||||
inlineResources('./build', 'src');
|
||||
}
|
||||
134
tasks/rollup.js
Normal file
134
tasks/rollup.js
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
'use strict';
|
||||
|
||||
const erectorUtils = require('erector-set/src/utils');
|
||||
const fs = require('fs-extra');
|
||||
const librarianUtils = require('angular-librarian/commands/utilities');
|
||||
const path = require('path');
|
||||
const rollup = require('rollup');
|
||||
const rollupCommon = require('rollup-plugin-commonjs');
|
||||
const rollupNodeResolve = require('rollup-plugin-node-resolve');
|
||||
const rollupSourcemaps = require('rollup-plugin-sourcemaps');
|
||||
const rollupUglify = require('rollup-plugin-uglify');
|
||||
|
||||
const doRollup = (libName, dirs) => {
|
||||
const nameParts = extractName(libName);
|
||||
const es5Entry = path.resolve(dirs.es5, `${ nameParts.package }.js`);
|
||||
const es2015Entry = path.resolve(dirs.es2015, `${ nameParts.package }.js`);
|
||||
const destinations = generateDestinations(dirs.dist, nameParts);
|
||||
const baseConfig = generateConfig({
|
||||
entry: es5Entry,
|
||||
external: [
|
||||
'@angular/common',
|
||||
'@angular/core'
|
||||
],
|
||||
globals: {
|
||||
'@angular/common': 'ng.common',
|
||||
'@angular/core': 'ng.core'
|
||||
},
|
||||
moduleName: librarianUtils.caseConvert.dashToCamel(nameParts.package),
|
||||
onwarn: function rollupOnWarn(warning) {
|
||||
// keeps TypeScript this errors down
|
||||
if (warning.code !== 'THIS_IS_UNDEFINED') {
|
||||
console.warn(warning.message);
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
rollupNodeResolve({
|
||||
jsnext: true,
|
||||
module: true
|
||||
}),
|
||||
rollupSourcemaps()
|
||||
],
|
||||
sourceMap: true
|
||||
}, dirs.root);
|
||||
const fesm2015Config = Object.assign({}, baseConfig, {
|
||||
entry: es2015Entry,
|
||||
dest: destinations.fesm2015,
|
||||
format: 'es'
|
||||
});
|
||||
const fesm5Config = Object.assign({}, baseConfig, {
|
||||
dest: destinations.fesm5,
|
||||
format: 'es'
|
||||
});
|
||||
const minUmdConfig = Object.assign({}, baseConfig, {
|
||||
dest: destinations.minUmd,
|
||||
format: 'umd',
|
||||
plugins: baseConfig.plugins.concat([rollupUglify({})])
|
||||
});
|
||||
const umdConfig = Object.assign({}, baseConfig, {
|
||||
dest: destinations.umd,
|
||||
format: 'umd'
|
||||
});
|
||||
|
||||
const bundles = [
|
||||
fesm2015Config,
|
||||
fesm5Config,
|
||||
minUmdConfig,
|
||||
umdConfig
|
||||
].map((config) =>
|
||||
rollup.rollup(config).then((bundle) =>
|
||||
bundle.write(config)
|
||||
)
|
||||
);
|
||||
|
||||
return Promise.all(bundles);
|
||||
};
|
||||
|
||||
const extractName = (libName) => {
|
||||
const isScoped = librarianUtils.checkIsScopedName(libName);
|
||||
const nameParts = {
|
||||
package: libName,
|
||||
scope: undefined
|
||||
};
|
||||
|
||||
if (isScoped) {
|
||||
const parts = libName.split('/', 2);
|
||||
|
||||
nameParts.package = parts[1];
|
||||
nameParts.scope = parts[0];
|
||||
}
|
||||
|
||||
return nameParts;
|
||||
};
|
||||
|
||||
const generateDestinations = (dist, nameParts) => {
|
||||
const bundleDest = path.resolve(dist, 'bundles');
|
||||
let fesmDest = path.resolve(dist);
|
||||
|
||||
if (nameParts.scope) {
|
||||
fesmDest = path.resolve(fesmDest, nameParts.scope);
|
||||
fs.ensureDirSync(fesmDest);
|
||||
}
|
||||
|
||||
return Object.freeze({
|
||||
fesm2015: path.resolve(fesmDest,`${ nameParts.package }.js`),
|
||||
fesm5: path.resolve(fesmDest,`${ nameParts.package }.es5.js`),
|
||||
minUmd: path.resolve(bundleDest, `${ nameParts.package }.umd.min.js`),
|
||||
umd: path.resolve(bundleDest, `${ nameParts.package }.umd.js`)
|
||||
});
|
||||
};
|
||||
|
||||
const generateConfig = (base, rootDir) => {
|
||||
let commonjsIncludes = ['node_modules/rxjs/**'];
|
||||
const customLocation = path.resolve(rootDir, 'configs', 'rollup.config.js');
|
||||
|
||||
if (fs.existsSync(customLocation)) {
|
||||
const custom = require(customLocation);
|
||||
const external = (custom.external || []).filter((external) => base.external.indexOf(external) === -1);
|
||||
const includes = (custom.commonjs || []).filter((include) => commonjsIncludes.indexOf(include) === -1);
|
||||
|
||||
base.external = base.external.concat(external);
|
||||
base.globals = erectorUtils.mergeDeep(custom.globals, base.globals);
|
||||
commonjsIncludes = commonjsIncludes.concat(includes);
|
||||
}
|
||||
|
||||
base.plugins.unshift(
|
||||
rollupCommon({
|
||||
include: commonjsIncludes
|
||||
})
|
||||
);
|
||||
|
||||
return base;
|
||||
};
|
||||
|
||||
module.exports = doRollup;
|
||||
66
tasks/test.js
Normal file
66
tasks/test.js
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const Server = require('karma').Server;
|
||||
|
||||
function run(type) {
|
||||
const config = getConfig(type);
|
||||
const server = new Server(config, function(exitCode) {
|
||||
process.exit(exitCode);
|
||||
});
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
||||
function getConfig(type) {
|
||||
switch (type) {
|
||||
case 'headless':
|
||||
case 'hl':
|
||||
case 'h':
|
||||
return getHeadlessConfig();
|
||||
case 'all':
|
||||
case 'a':
|
||||
return getAllConfig();
|
||||
case 'watch':
|
||||
case 'w':
|
||||
return getWatchConfig();
|
||||
default:
|
||||
return getSingleConfig();
|
||||
}
|
||||
}
|
||||
|
||||
function getSingleConfig() {
|
||||
let config = getHeadlessConfig();
|
||||
|
||||
config.singleRun = true;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
function getHeadlessConfig() {
|
||||
let config = getAllConfig();
|
||||
|
||||
config.browsers = ['PhantomJS'];
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
function getWatchConfig() {
|
||||
let config = getAllConfig(true);
|
||||
|
||||
config.browsers = ['Chrome'];
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
const getAllConfig = (watch) => ({
|
||||
configFile: path.resolve(__dirname, '..', 'karma.conf.js'),
|
||||
webpack: require(path.resolve(__dirname, '..', 'webpack', 'webpack.test.js'))(watch),
|
||||
});
|
||||
|
||||
module.exports = run;
|
||||
|
||||
if (!module.parent) {
|
||||
run(process.argv[2]);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue