chore(lint): lint ts as well as js (#1823)

This commit is contained in:
Filipe Silva 2016-08-25 18:06:54 +01:00 committed by Hans
parent b5e86c9fa9
commit d17bc71a0b
40 changed files with 376 additions and 251 deletions

View File

@ -17,7 +17,12 @@ module.exports = Command.extend({
aliases: ['b'],
availableOptions: [
{ name: 'target', type: String, default: 'development', aliases: ['t', { 'dev': 'development' }, { 'prod': 'production' }] },
{
name: 'target',
type: String,
default: 'development',
aliases: ['t', { 'dev': 'development' }, { 'prod': 'production' }]
},
{ name: 'environment', type: String, default: '', aliases: ['e'] },
{ name: 'output-path', type: 'Path', default: 'dist/', aliases: ['o'] },
{ name: 'watch', type: Boolean, default: false, aliases: ['w'] },
@ -26,18 +31,18 @@ module.exports = Command.extend({
],
run: function (commandOptions: BuildOptions) {
if (commandOptions.environment === ''){
if (commandOptions.environment === '') {
if (commandOptions.target === 'development') {
commandOptions.environment = 'dev';
}
if (commandOptions.target === 'production') {
commandOptions.environment = 'prod';
}
}
}
var project = this.project;
var ui = this.ui;
var buildTask = commandOptions.watch ?
const project = this.project;
const ui = this.ui;
const buildTask = commandOptions.watch ?
new WebpackBuildWatch({
cliProject: project,
ui: ui,

View File

@ -10,10 +10,10 @@ const DocCommand = Command.extend({
'<keyword>'
],
run: function(commandOptions, rawArgs:Array<string>) {
var keyword = rawArgs[0];
var docTask = new DocTask({
run: function(commandOptions, rawArgs: Array<string>) {
const keyword = rawArgs[0];
const docTask = new DocTask({
ui: this.ui,
analytics: this.analytics,
project: this.project
@ -23,4 +23,4 @@ const DocCommand = Command.extend({
}
});
module.exports = DocCommand;
module.exports = DocCommand;

View File

@ -9,7 +9,7 @@ module.exports = Command.extend({
run: function () {
this.project.ngConfig = this.project.ngConfig || CliConfig.fromProject();
var e2eTask = new E2ETask({
const e2eTask = new E2ETask({
ui: this.ui,
analytics: this.analytics,
project: this.project

View File

@ -2,9 +2,9 @@ import * as EmberGenerateCommand from 'ember-cli/lib/commands/generate';
import * as fs from 'fs';
import * as path from 'path';
import * as SilentError from 'silent-error';
var chalk = require('chalk');
import * as Blueprint from 'ember-cli/lib/models/blueprint';
var EOL = require('os').EOL;
const chalk = require('chalk');
const EOL = require('os').EOL;
const GenerateCommand = EmberGenerateCommand.extend({
name: 'generate',
@ -21,16 +21,16 @@ const GenerateCommand = EmberGenerateCommand.extend({
!fs.existsSync(path.join(__dirname, '..', 'blueprints', rawArgs[0]))) {
SilentError.debugOrThrow('angular-cli/commands/generate', `Invalid blueprint: ${rawArgs[0]}`);
}
// Override default help to hide ember blueprints
EmberGenerateCommand.prototype.printDetailedHelp = function (options) {
var blueprintList = fs.readdirSync(path.join(__dirname, '..', 'blueprints'));
var blueprints = blueprintList
const blueprintList = fs.readdirSync(path.join(__dirname, '..', 'blueprints'));
const blueprints = blueprintList
.filter(bp => bp.indexOf('-test') === -1)
.filter(bp => bp !== 'ng2')
.map(bp => Blueprint.load(path.join(__dirname, '..', 'blueprints', bp)));
var output = '';
let output = '';
blueprints
.forEach(function (bp) {
output += bp.printBasicHelp(false) + EOL;
@ -38,7 +38,7 @@ const GenerateCommand = EmberGenerateCommand.extend({
this.ui.writeLine(chalk.cyan(' Available blueprints'));
this.ui.writeLine(output);
};
return EmberGenerateCommand.prototype.beforeRun.apply(this, arguments);
}
});

View File

@ -9,6 +9,7 @@ import * as path from 'path';
import * as WebpackBuild from '../tasks/build-webpack';
import * as CreateGithubRepo from '../tasks/create-github-repo';
import { CliConfig } from '../models/config';
import { oneLine } from 'common-tags';
const fsReadFile = Promise.denodeify(fs.readFile);
const fsWriteFile = Promise.denodeify(fs.writeFile);
@ -18,7 +19,10 @@ const fsCopy = Promise.denodeify(fse.copy);
module.exports = Command.extend({
name: 'github-pages:deploy',
aliases: ['gh-pages:deploy'],
description: 'Build the test app for production, commit it into a git branch, setup GitHub repo and push to it',
description: oneLine`
Build the test app for production, commit it into a git branch,
setup GitHub repo and push to it
`,
works: 'insideProject',
availableOptions: [
@ -60,13 +64,13 @@ module.exports = Command.extend({
}],
run: function(options, rawArgs) {
var ui = this.ui;
var root = this.project.root;
var execOptions = {
const ui = this.ui;
const root = this.project.root;
const execOptions = {
cwd: root
};
if (options.environment === ''){
if (options.environment === '') {
if (options.target === 'development') {
options.environment = 'dev';
}
@ -75,7 +79,7 @@ module.exports = Command.extend({
}
}
var projectName = this.project.pkg.name;
const projectName = this.project.pkg.name;
const outDir = CliConfig.fromProject().config.apps[0].outDir;
@ -86,7 +90,7 @@ module.exports = Command.extend({
// declared here so that tests can stub exec
const execPromise = Promise.denodeify(exec);
var buildTask = new WebpackBuild({
const buildTask = new WebpackBuild({
ui: this.ui,
analytics: this.analytics,
cliProject: this.project,
@ -95,19 +99,19 @@ module.exports = Command.extend({
outputPath: outDir
});
var buildOptions = {
const buildOptions = {
target: options.target,
environment: options.environment,
outputPath: outDir
};
var createGithubRepoTask = new CreateGithubRepo({
const createGithubRepoTask = new CreateGithubRepo({
ui: this.ui,
analytics: this.analytics,
project: this.project
});
var createGithubRepoOptions = {
const createGithubRepoOptions = {
projectName,
ghUsername: options.ghUsername,
ghToken: options.ghToken
@ -137,7 +141,7 @@ module.exports = Command.extend({
}
function build() {
if (options.skipBuild) return Promise.resolve();
if (options.skipBuild) { return Promise.resolve(); }
return buildTask.run(buildOptions);
}
@ -165,7 +169,7 @@ module.exports = Command.extend({
function checkoutGhPages() {
return execPromise(`git checkout ${ghPagesBranch}`)
.catch(createGhPagesBranch)
.catch(createGhPagesBranch);
}
function createGhPagesBranch() {
@ -179,16 +183,16 @@ module.exports = Command.extend({
function copyFiles() {
return fsReadDir(outDir)
.then((files) => Promise.all(files.map((file) => {
if (file === '.gitignore'){
if (file === '.gitignore') {
// don't overwrite the .gitignore file
return Promise.resolve();
}
return fsCopy(path.join(outDir, file), path.join('.', file))
return fsCopy(path.join(outDir, file), path.join('.', file));
})));
}
function updateBaseHref() {
if (options.userPage) return Promise.resolve();
if (options.userPage) { return Promise.resolve(); }
let indexHtml = path.join(root, 'index.html');
return fsReadFile(indexHtml, 'utf8')
.then((data) => data.replace(/<base href="\/">/g, `<base href="/${projectName}/">`))
@ -215,7 +219,8 @@ module.exports = Command.extend({
function printProjectUrl() {
return execPromise('git remote -v')
.then((stdout) => {
let userName = stdout.match(/origin\s+(?:https:\/\/|git@)github\.com(?:\:|\/)([^\/]+)/m)[1].toLowerCase();
let match = stdout.match(/origin\s+(?:https:\/\/|git@)github\.com(?:\:|\/)([^\/]+)/m);
let userName = match[1].toLowerCase();
let url = `https://${userName}.github.io/${options.userPage ? '' : (projectName + '/')}`;
ui.writeLine(chalk.green(`Deployed! Visit ${url}`));
ui.writeLine('Github pages might take a few minutes to show the deployed site.');
@ -225,7 +230,8 @@ module.exports = Command.extend({
function failGracefully(error) {
if (error && (/git clean/.test(error.message) || /Permission denied/.test(error.message))) {
ui.writeLine(error.message);
let msg = 'There was a permissions error during git file operations, please close any open project files/folders and try again.';
let msg = 'There was a permissions error during git file operations, ' +
'please close any open project files/folders and try again.';
msg += `\nYou might also need to return to the ${initialBranch} branch manually.`;
return Promise.reject(new SilentError(msg));
} else {

View File

@ -6,7 +6,7 @@ module.exports = Command.extend({
description: 'Lints code in existing project',
works: 'insideProject',
run: function () {
var lintTask = new LintTask({
const lintTask = new LintTask({
ui: this.ui,
analytics: this.analytics,
project: this.project

View File

@ -3,7 +3,6 @@ import * as Command from 'ember-cli/lib/models/command';
import * as Promise from 'ember-cli/lib/ext/promise';
import * as SilentError from 'silent-error';
import * as PortFinder from 'portfinder';
import * as EOL from 'os';
import * as ServeWebpackTask from '../tasks/serve-webpack.ts';
PortFinder.basePort = 49152;
@ -36,15 +35,46 @@ module.exports = Command.extend({
availableOptions: [
{ name: 'port', type: Number, default: defaultPort, aliases: ['p'] },
{ name: 'host', type: String, default: 'localhost', aliases: ['H'], description: 'Listens on all interfaces by default' },
{
name: 'host',
type: String,
default: 'localhost',
aliases: ['H'],
description: 'Listens on all interfaces by default'
},
{ name: 'proxy-config', type: 'Path', aliases: ['pc'] },
{ name: 'watcher', type: String, default: 'events', aliases: ['w'] },
{ name: 'live-reload', type: Boolean, default: true, aliases: ['lr'] },
{ name: 'live-reload-host', type: String, aliases: ['lrh'], description: 'Defaults to host' },
{ name: 'live-reload-base-url', type: String, aliases: ['lrbu'], description: 'Defaults to baseURL' },
{ name: 'live-reload-port', type: Number, aliases: ['lrp'], description: '(Defaults to port number within [49152...65535])' },
{ name: 'live-reload-live-css', type: Boolean, default: true, description: 'Whether to live reload CSS (default true)' },
{ name: 'target', type: String, default: 'development', aliases: ['t', { 'dev': 'development' }, { 'prod': 'production' }] },
{
name: 'live-reload-host',
type: String,
aliases: ['lrh'],
description: 'Defaults to host'
},
{
name: 'live-reload-base-url',
type: String,
aliases: ['lrbu'],
description: 'Defaults to baseURL'
},
{
name: 'live-reload-port',
type: Number,
aliases: ['lrp'],
description: '(Defaults to port number within [49152...65535])'
},
{
name: 'live-reload-live-css',
type: Boolean,
default: true,
description: 'Whether to live reload CSS (default true)'
},
{
name: 'target',
type: String,
default: 'development',
aliases: ['t', { 'dev': 'development' }, { 'prod': 'production' }]
},
{ name: 'environment', type: String, default: '', aliases: ['e'] },
{ name: 'ssl', type: Boolean, default: false },
{ name: 'ssl-key', type: String, default: 'ssl/server.key' },
@ -52,7 +82,7 @@ module.exports = Command.extend({
],
run: function(commandOptions: ServeTaskOptions) {
if (commandOptions.environment === ''){
if (commandOptions.environment === '') {
if (commandOptions.target === 'development') {
commandOptions.environment = 'dev';
}
@ -65,20 +95,12 @@ module.exports = Command.extend({
return this._checkExpressPort(commandOptions)
.then(this._autoFindLiveReloadPort.bind(this))
.then((commandOptions: ServeTaskOptions) => {
commandOptions = assign({}, commandOptions, {
.then((opts: ServeTaskOptions) => {
commandOptions = assign({}, opts, {
baseURL: this.project.config(commandOptions.target).baseURL || '/'
});
if (commandOptions.proxy) {
if (!commandOptions.proxy.match(/^(http:|https:)/)) {
var message = 'You need to include a protocol with the proxy URL.' + EOL + 'Try --proxy http://' + commandOptions.proxy;
return Promise.reject(new SilentError(message));
}
}
var serve = new ServeWebpackTask({
const serve = new ServeWebpackTask({
ui: this.ui,
analytics: this.analytics,
project: this.project,
@ -93,7 +115,7 @@ module.exports = Command.extend({
.then((foundPort: number) => {
if (commandOptions.port !== foundPort && commandOptions.port !== 0) {
var message = 'Port ' + commandOptions.port + ' is already in use.';
const message = 'Port ' + commandOptions.port + ' is already in use.';
return Promise.reject(new SilentError(message));
}

View File

@ -16,7 +16,7 @@ module.exports = TestCommand.extend({
run: function (commandOptions) {
this.project.ngConfig = this.project.ngConfig || CliConfig.fromProject();
var testTask = new TestTask({
const testTask = new TestTask({
ui: this.ui,
analytics: this.analytics,
project: this.project

View File

@ -14,18 +14,18 @@ const VersionCommand = Command.extend({
}],
run: function (options) {
var versions = process.versions;
var pkg = require(path.resolve(__dirname, '..', '..', '..', 'package.json'));
const versions = process.versions;
const pkg = require(path.resolve(__dirname, '..', '..', '..', 'package.json'));
versions['os'] = process.platform + ' ' + process.arch;
var alwaysPrint = ['node', 'os'];
const alwaysPrint = ['node', 'os'];
var ngCliVersion = pkg.version;
let ngCliVersion = pkg.version;
if (!__dirname.match(/node_modules/)) {
var gitBranch = '??';
let gitBranch = '??';
try {
var gitRefName = '' + child_process.execSync('git symbolic-ref HEAD', {cwd: __dirname});
const gitRefName = '' + child_process.execSync('git symbolic-ref HEAD', {cwd: __dirname});
gitBranch = path.basename(gitRefName.replace('\n', ''));
} catch (e) {
}
@ -35,7 +35,7 @@ const VersionCommand = Command.extend({
this.printVersion('angular-cli', ngCliVersion);
for (var module in versions) {
for (const module in versions) {
if (options.verbose || alwaysPrint.indexOf(module) > -1) {
this.printVersion(module, versions[module]);
}

View File

@ -3,7 +3,7 @@ interface IWebpackDevServerConfigurationOptions {
hot?: boolean;
historyApiFallback?: boolean;
compress?: boolean;
proxy?: {[key: string] : string};
proxy?: {[key: string]: string};
staticOptions?: any;
quiet?: boolean;
noInfo?: boolean;
@ -14,8 +14,8 @@ interface IWebpackDevServerConfigurationOptions {
poll?: number;
};
publicPath?: string;
headers?: { [key:string]: string };
stats?: { [key:string]: boolean };
headers?: { [key: string]: string };
stats?: { [key: string]: boolean };
inline: boolean;
}

View File

@ -1,12 +1,10 @@
import {CliConfig as CliConfigBase} from './config/config';
import {CliConfig as ConfigInterface} from '../../../lib/config/schema';
import { oneLine } from 'common-tags';
import * as chalk from 'chalk';
import * as fs from 'fs';
import * as path from 'path';
const schemaPath = path.resolve(process.env.CLI_ROOT, 'lib/config/schema.json');
const schema = require(schemaPath);
export const CLI_CONFIG_FILE_NAME = 'angular-cli.json';
@ -51,11 +49,11 @@ export class CliConfig extends CliConfigBase<ConfigInterface> {
const cliConfig = CliConfigBase.fromConfigPath(CliConfig._configFilePath(), [globalConfigPath]);
if (cliConfig.alias('apps.0.root', 'defaults.sourceDir')
+ cliConfig.alias('apps.0.prefix', 'defaults.prefix')) {
console.error(chalk.yellow(
'The "defaults.prefix" and "defaults.sourceDir" properties of angular-cli.json\n'
+ 'are deprecated in favor of "apps[0].root" and "apps[0].prefix".\n'
+ 'Please update in order to avoid errors in future versions of angular-cli.'
));
console.error(chalk.yellow(oneLine`
The "defaults.prefix" and "defaults.sourceDir" properties of angular-cli.json
are deprecated in favor of "apps[0].root" and "apps[0].prefix".\n
Please update in order to avoid errors in future versions of angular-cli.
`));
}
return cliConfig as CliConfig;

View File

@ -17,7 +17,7 @@ export class InvalidConfigError extends Error {
export class CliConfig<Config> {
private _config: SchemaClass<Config>;
private constructor(private _configPath: string,
constructor(private _configPath: string,
schema: Object,
configJson: Config,
fallbacks: Config[] = []) {
@ -29,7 +29,7 @@ export class CliConfig<Config> {
save(path: string = this._configPath) {
return fs.writeFileSync(path, this.serialize(), 'utf-8');
}
serialize(mimetype: string = 'application/json'): string {
serialize(mimetype = 'application/json'): string {
return this._config.$$serialize(mimetype);
}
@ -73,7 +73,7 @@ export class CliConfig<Config> {
try {
content = JSON.parse(configContent);
schema = JSON.parse(schemaContent);
others = otherContents.map(content => JSON.parse(content));
others = otherContents.map(content => JSON.parse(otherContent));
} catch (err) {
throw new InvalidConfigError(err);
}

View File

@ -3,13 +3,9 @@ import * as glob from 'glob';
import * as path from 'path';
import * as ts from 'typescript';
import {Observable} from 'rxjs/Observable';
import {getSource, findNodes, getContentOfKeyLiteral} from '../utilities/ast-utils';
const loadChildrenRegex = /(\{[^{}]+?(loadChildren|['"]loadChildren['"])\s*:\s*)('[^']+'|"[^"]+")/gm;
interface Array<T> {
flatMap: <R>(mapFn: (item: T) => Array<R>) => Array<R>;
}
@ -37,15 +33,15 @@ export function findLoadChildren(tsFilePath: string): string[] {
// key is an expression, can't do anything.
return false;
}
return key == 'loadChildren'
return key == 'loadChildren';
})
// Remove initializers that are not files.
.filter((node: ts.PropertyAssignment) => {
return node.initializer.kind === ts.SyntaxKind.StringLiteral;
})
// Get the full text of the initiliazer.
// Get the full text of the initializer.
.map((node: ts.PropertyAssignment) => {
return eval(node.initializer.getText(source));
return eval(node.initializer.getText(source)); // tslint:disable-line
})
.flatMap((value: string) => unique[value] ? undefined : unique[value] = value)
.map((moduleName: string) => moduleName.split('#')[0]);

View File

@ -108,7 +108,7 @@ class SchemaClassBase<T> implements SchemaClass<T> {
$$set(path: string, value: any) {
const node = _getSchemaNodeForPath(this[kSchemaNode], path);
if (node) {
node.set(value)
node.set(value);
} else {
// This might be inside an object that can have additionalProperties, so
// a TreeNode would not exist.
@ -137,7 +137,7 @@ class SchemaClassBase<T> implements SchemaClass<T> {
return node ? node.defined : false;
}
$$delete(path: string){
$$delete(path: string) {
const node = _getSchemaNodeForPath(this[kSchemaNode], path);
if (node) {
node.destroy();
@ -145,7 +145,7 @@ class SchemaClassBase<T> implements SchemaClass<T> {
}
/** Serialize into a string. */
$$serialize(mimetype: string = 'application/json', ...options: any[]): string {
$$serialize(mimetype = 'application/json', ...options: any[]): string {
let str = '';
const serializer = Serializer.fromMimetype(mimetype, (s) => str += s, ...options);

View File

@ -75,7 +75,7 @@ export abstract class SchemaTreeNode<T> {
get parent<ParentType>(): SchemaTreeNode<ParentType> { return this._parent; }
get children<ChildType>(): { [key: string]: SchemaTreeNode<ChildType>} { return null; }
abstract get() : T;
abstract get(): T;
set(v: T) {
if (!this.readOnly) {
throw new MissingImplementationError();
@ -105,7 +105,7 @@ export abstract class SchemaTreeNode<T> {
/** Base Class used for Non-Leaves TreeNode. Meaning they can have children. */
abstract class NonLeafSchemaTreeNode<T> extends SchemaTreeNode<T> {
dispose() {
for (const key of Object.keys(this.children) {
for (const key of Object.keys(this.children)) {
this.children[key].dispose();
}
super.dispose();
@ -132,7 +132,7 @@ abstract class NonLeafSchemaTreeNode<T> extends SchemaTreeNode<T> {
const type = schema['type'];
let Klass: TreeNodeConstructor = null;
switch(type) {
switch (type) {
case 'object': Klass = ObjectSchemaTreeNode; break;
case 'array': Klass = ArraySchemaTreeNode; break;
case 'string': Klass = StringSchemaTreeNode; break;

View File

@ -60,9 +60,6 @@ class JsonSerializer implements Serializer {
private _top() {
return this._state[this._state.length - 1] || {};
}
private _topIsArray() {
return this._top().type == 'array';
}
private _indent(): string {
if (this._indentDelta == 0) {

View File

@ -4,7 +4,7 @@ import * as HtmlWebpackPlugin from 'html-webpack-plugin';
import * as webpack from 'webpack';
import * as atl from 'awesome-typescript-loader';
import {findLazyModules} from './find-lazy-modules';
import { findLazyModules } from './find-lazy-modules';
export function getWebpackCommonConfig(projectRoot: string, environment: string, appConfig: any) {
@ -14,13 +14,13 @@ export function getWebpackCommonConfig(projectRoot: string, environment: string,
const scripts = appConfig.scripts.map(script => path.resolve(appRoot, script));
const lazyModules = findLazyModules(appRoot);
let entry = {
let entry = {
main: [appMain]
};
// Only add styles/scripts if there's actually entries there
if (appConfig.styles.length > 0) entry.styles = styles;
if (appConfig.scripts.length > 0) entry.scripts = scripts;
if (appConfig.styles.length > 0) { entry['styles'] = styles; }
if (appConfig.scripts.length > 0) { entry['scripts'] = scripts; }
return {
devtool: 'source-map',
@ -62,16 +62,42 @@ export function getWebpackCommonConfig(projectRoot: string, environment: string,
},
// in main, load css as raw text
       { exclude: styles, test: /\.css$/, loaders: ['raw-loader', 'postcss-loader'] },
       { exclude: styles, test: /\.styl$/, loaders: ['raw-loader', 'postcss-loader', 'stylus-loader'] },
       { exclude: styles, test: /\.less$/, loaders: ['raw-loader', 'postcss-loader', 'less-loader'] },
       { exclude: styles, test: /\.scss$|\.sass$/, loaders: ['raw-loader', 'postcss-loader', 'sass-loader'] },
       {
exclude: styles,
test: /\.css/,
loaders: ['raw-loader', 'postcss-loader']
}, {
exclude: styles,
test: /\.styl$/,
loaders: ['raw-loader', 'postcss-loader', 'stylus-loader'] },
       {
exclude: styles,
test: /\.less$/,
loaders: ['raw-loader', 'postcss-loader', 'less-loader']
}, {
exclude: styles,
test: /\.scss$|\.sass$/,
loaders: ['raw-loader', 'postcss-loader', 'sass-loader']
},
// outside of main, load it via style-loader
       { include: styles, test: /\.css$/, loaders: ['style-loader', 'css-loader', 'postcss-loader'] },
       { include: styles, test: /\.styl$/, loaders: ['style-loader', 'css-loader', 'postcss-loader', 'stylus-loader'] },
       { include: styles, test: /\.less$/, loaders: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'] },
       { include: styles, test: /\.scss$|\.sass$/, loaders: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] },
       {
include: styles,
test: /\.css$/,
loaders: ['style-loader', 'css-loader', 'postcss-loader']
}, {
include: styles,
test: /\.styl$/,
loaders: ['style-loader', 'css-loader', 'postcss-loader', 'stylus-loader']
}, {
include: styles,
test: /\.less$/,
loaders: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
}, {
include: styles,
test: /\.scss$|\.sass$/,
loaders: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader']
},
// load global scripts using script-loader
{ include: scripts, test: /\.js$/, loader: 'script-loader' },
@ -97,7 +123,7 @@ export function getWebpackCommonConfig(projectRoot: string, environment: string,
// Since it takes a RegExp as first parameter, we need to escape the path.
// See https://webpack.github.io/docs/list-of-plugins.html#normalmodulereplacementplugin
new RegExp(path.resolve(appRoot, appConfig.environments['source'])
.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")),
.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&')),
path.resolve(appRoot, appConfig.environments[environment])
),
new webpack.optimize.CommonsChunkPlugin({
@ -124,5 +150,5 @@ export function getWebpackCommonConfig(projectRoot: string, environment: string,
clearImmediate: false,
setImmediate: false
}
}
};
}

View File

@ -1,4 +1,4 @@
const path = require('path')
const path = require('path');
export const getWebpackDevConfigPartial = function(projectRoot: string, appConfig: any) {
return {
@ -24,4 +24,4 @@ export const getWebpackDevConfigPartial = function(projectRoot: string, appConfi
setImmediate: false
}
};
}
};

View File

@ -1,4 +1,3 @@
import * as webpack from 'webpack';
import * as path from 'path';
import * as OfflinePlugin from 'offline-plugin';
import * as CopyWebpackPlugin from 'copy-webpack-plugin';
@ -10,8 +9,13 @@ export const getWebpackMobileConfigPartial = function (projectRoot: string, appC
return {
plugins: [
new CopyWebpackPlugin([
{from: path.resolve(projectRoot, appConfig.root, 'icons'), to: path.resolve(projectRoot, appConfig.outDir, 'icons')},
{from: path.resolve(projectRoot, appConfig.root, 'manifest.webapp'), to: path.resolve(projectRoot, appConfig.outDir)}
{
from: path.resolve(projectRoot, appConfig.root, 'icons'),
to: path.resolve(projectRoot, appConfig.outDir, 'icons')
}, {
from: path.resolve(projectRoot, appConfig.root, 'manifest.webapp'),
to: path.resolve(projectRoot, appConfig.outDir)
}
]),
new PrerenderWebpackPlugin({
templatePath: 'index.html',
@ -19,7 +23,7 @@ export const getWebpackMobileConfigPartial = function (projectRoot: string, appC
appPath: path.resolve(projectRoot, appConfig.root)
})
]
}
};
};
export const getWebpackMobileProdConfigPartial = function (projectRoot: string, appConfig: any) {
@ -30,5 +34,5 @@ export const getWebpackMobileProdConfigPartial = function (projectRoot: string,
plugins: [
new OfflinePlugin()
]
}
};
};

View File

@ -1,5 +1,4 @@
import * as path from 'path';
import * as webpackMerge from 'webpack-merge'; // used to merge webpack configs
import * as WebpackMd5Hash from 'webpack-md5-hash';
import * as CompressionPlugin from 'compression-webpack-plugin';
import * as webpack from 'webpack';
@ -17,12 +16,11 @@ export const getWebpackProdConfigPartial = function(projectRoot: string, appConf
plugins: [
new WebpackMd5Hash(),
new webpack.optimize.DedupePlugin(),
// ~107kb
new webpack.optimize.UglifyJsPlugin({
beautify: false, //prod
mangle: { screw_ie8 : true, keep_fnames: true }, //prod
compress: { screw_ie8: true }, //prod
comments: false //prod
beautify: false,
mangle: { screw_ie8 : true, keep_fnames: true },
compress: { screw_ie8: true },
comments: false
}),
new CompressionPlugin({
asset: '[path].gz[query]',
@ -57,5 +55,5 @@ export const getWebpackProdConfigPartial = function(projectRoot: string, appConf
clearImmediate: false,
setImmediate: false
}
}
};
};

View File

@ -2,15 +2,15 @@ import * as path from 'path';
export const ngAppResolve = (resolvePath: string): string => {
return path.resolve(process.cwd(), resolvePath);
}
};
export const webpackOutputOptions: WebpackProgressPluginOutputOptions = {
export const webpackOutputOptions = {
colors: true,
chunks: true,
modules: false,
reasons: false,
chunkModules: false
}
};
export const webpackDevServerOutputOptions = {
assets: true,
@ -20,4 +20,4 @@ export const webpackDevServerOutputOptions = {
timings: true,
chunks: false,
chunkModules: false
}
};

View File

@ -12,27 +12,31 @@ export class NgCliWebpackConfig {
// TODO: When webpack2 types are finished lets replace all these any types
// so this is more maintainable in the future for devs
public config: any;
private webpackDevConfigPartial: any;
private webpackProdConfigPartial: any;
private webpackBaseConfig: any;
private webpackMobileConfigPartial: any;
private webpackMobileProdConfigPartial: any;
private devConfigPartial: any;
private prodConfigPartial: any;
private baseConfig: any;
constructor(public ngCliProject: any, public target: string, public environment: string, outputDir?: string) {
constructor(
public ngCliProject: any,
public target: string,
public environment: string,
outputDir?: string
) {
const config: CliConfig = CliConfig.fromProject();
const appConfig = config.config.apps[0];
appConfig.outDir = outputDir || appConfig.outDir;
this.webpackBaseConfig = getWebpackCommonConfig(this.ngCliProject.root, environment, appConfig);
this.webpackDevConfigPartial = getWebpackDevConfigPartial(this.ngCliProject.root, appConfig);
this.webpackProdConfigPartial = getWebpackProdConfigPartial(this.ngCliProject.root, appConfig);
this.baseConfig = getWebpackCommonConfig(this.ngCliProject.root, environment, appConfig);
this.devConfigPartial = getWebpackDevConfigPartial(this.ngCliProject.root, appConfig);
this.prodConfigPartial = getWebpackProdConfigPartial(this.ngCliProject.root, appConfig);
if (appConfig.mobile){
this.webpackMobileConfigPartial = getWebpackMobileConfigPartial(this.ngCliProject.root, appConfig);
this.webpackMobileProdConfigPartial = getWebpackMobileProdConfigPartial(this.ngCliProject.root, appConfig);
this.webpackBaseConfig = webpackMerge(this.webpackBaseConfig, this.webpackMobileConfigPartial);
this.webpackProdConfigPartial = webpackMerge(this.webpackProdConfigPartial, this.webpackMobileProdConfigPartial);
if (appConfig.mobile) {
let mobileConfigPartial = getWebpackMobileConfigPartial(this.ngCliProject.root, appConfig);
let mobileProdConfigPartial = getWebpackMobileProdConfigPartial(this.ngCliProject.root,
appConfig);
this.baseConfig = webpackMerge(this.baseConfig, mobileConfigPartial);
this.prodConfigPartial = webpackMerge(this.prodConfigPartial, mobileProdConfigPartial);
}
this.generateConfig();
@ -40,15 +44,14 @@ export class NgCliWebpackConfig {
generateConfig(): void {
switch (this.target) {
case "development":
this.config = webpackMerge(this.webpackBaseConfig, this.webpackDevConfigPartial);
case 'development':
this.config = webpackMerge(this.baseConfig, this.devConfigPartial);
break;
case "production":
this.config = webpackMerge(this.webpackBaseConfig, this.webpackProdConfigPartial);
case 'production':
this.config = webpackMerge(this.baseConfig, this.prodConfigPartial);
break;
default:
throw new Error("Invalid build target. Only 'development' and 'production' are available.");
break;
}
}
}

View File

@ -16,7 +16,12 @@ module.exports = Task.extend({
rimraf.sync(path.resolve(project.root, runTaskOptions.outputPath));
const config = new NgCliWebpackConfig(project, runTaskOptions.target, runTaskOptions.environment, runTaskOptions.outputPath).config;
const config = new NgCliWebpackConfig(
project,
runTaskOptions.target,
runTaskOptions.environment,
runTaskOptions.outputPath
).config;
const webpackCompiler = webpack(config);
webpackCompiler.apply(new ProgressPlugin({
@ -28,15 +33,15 @@ module.exports = Task.extend({
if (err) {
lastHash = null;
console.error(err.stack || err);
if(err.details) console.error(err.details);
if (err.details) { console.error(err.details); }
reject(err.details);
}
if(stats.hash !== lastHash) {
if (stats.hash !== lastHash) {
lastHash = stats.hash;
process.stdout.write(stats.toString(webpackOutputOptions) + "\n");
process.stdout.write(stats.toString(webpackOutputOptions) + '\n');
}
})
})
});
});
}
});

View File

@ -13,11 +13,16 @@ module.exports = Task.extend({
// Options: String outputPath
run: function(runTaskOptions: ServeTaskOptions) {
var project = this.cliProject;
const project = this.cliProject;
rimraf.sync(path.resolve(project.root, runTaskOptions.outputPath));
var config = new NgCliWebpackConfig(project, runTaskOptions.target, runTaskOptions.environment, runTaskOptions.outputPath).config;
const config = new NgCliWebpackConfig(
project,
runTaskOptions.target,
runTaskOptions.environment,
runTaskOptions.outputPath
).config;
const webpackCompiler = webpack(config);
const ProgressPlugin = require('webpack/lib/ProgressPlugin');
@ -32,16 +37,16 @@ module.exports = Task.extend({
// TODO: Make conditional if using --watch
webpackCompiler.purgeInputFileSystem();
if(err) {
if (err) {
lastHash = null;
console.error(err.stack || err);
if(err.details) console.error(err.details);
if (err.details) { console.error(err.details); }
reject(err.details);
}
if(stats.hash !== lastHash) {
if (stats.hash !== lastHash) {
lastHash = stats.hash;
process.stdout.write(stats.toString(webpackOutputOptions) + "\n");
process.stdout.write(stats.toString(webpackOutputOptions) + '\n');
}
resolve();
});

View File

@ -3,10 +3,11 @@ import * as Task from 'ember-cli/lib/models/task';
import * as SilentError from 'silent-error';
import { exec } from 'child_process';
import * as https from 'https';
import { oneLine } from 'common-tags';
module.exports = Task.extend({
run: function(commandOptions) {
var ui = this.ui;
const ui = this.ui;
let promise;
// declared here so that tests can stub exec
@ -18,16 +19,24 @@ module.exports = Task.extend({
ghUsername: commandOptions.ghUsername
});
} else {
ui.writeLine("\nIn order to deploy this project via GitHub Pages, we must first create a repository for it.");
ui.writeLine("It's safer to use a token than to use a password, so you will need to create one.\n");
ui.writeLine("Go to the following page and click 'Generate new token'.");
ui.writeLine("https://github.com/settings/tokens\n");
ui.writeLine("Choose 'public_repo' as scope and then click 'Generate token'.\n");
ui.writeLine();
ui.writeLine(oneLine`
In order to deploy this project via GitHub Pages, we must first create a repository for it.
`);
ui.writeLine(oneLine`
It\'s safer to use a token than to use a password so you will need to create one
`);
ui.writeLine('Go to the following page and click "Generate new token".');
ui.writeLine('https://github.com/settings/tokens\n');
ui.writeLine('Choose "public_repo" as scope and then click "Generate token".\n');
promise = ui.prompt([
{
name: 'ghToken',
type: 'input',
message: 'Please enter GitHub token you just created (used only once to create the repo):',
message: oneLine`
Please enter GitHub token you just created
(used only once to create the repo):
`,
validate: function(token) {
return /.+/.test(token);
}
@ -44,11 +53,11 @@ module.exports = Task.extend({
return promise
.then((answers) => {
return new Promise(function(resolve, reject) {
var postData = JSON.stringify({
const postData = JSON.stringify({
'name': commandOptions.projectName
});
var req = https.request({
const req = https.request({
hostname: 'api.github.com',
port: 443,
path: '/user/repos',
@ -63,9 +72,14 @@ module.exports = Task.extend({
req.on('response', function(response) {
if (response.statusCode === 201) {
resolve(execPromise(`git remote add origin git@github.com:${answers.ghUsername}/${commandOptions.projectName}.git`))
resolve(execPromise(oneLine`
git remote add origin
git@github.com:${answers.ghUsername}/${commandOptions.projectName}.git
`));
} else {
reject(new SilentError(`Failed to create GitHub repo. Error: ${response.statusCode} ${response.statusMessage}`));
reject(new SilentError(oneLine`
Failed to create GitHub repo. Error: ${response.statusCode} ${response.statusMessage}
`));
}
});

View File

@ -3,9 +3,9 @@ import * as opn from 'opn';
const DocTask = Task.extend({
run: function(keyword: string) {
var searchUrl = `https://angular.io/docs/ts/latest/api/#!?apiFilter=${keyword}`;
const searchUrl = `https://angular.io/docs/ts/latest/api/#!?apiFilter=${keyword}`;
return opn(searchUrl, { wait: false });
}
});
module.exports = DocTask;
module.exports = DocTask;

View File

@ -5,21 +5,22 @@ import {exec} from 'child_process';
module.exports = Task.extend({
run: function () {
var ui = this.ui;
var exitCode = 0;
const ui = this.ui;
let exitCode = 0;
return new Promise((resolve) => {
exec(`npm run e2e -- ${this.project.ngConfig.config.e2e.protractor.config}`, (err, stdout, stderr) => {
ui.writeLine(stdout);
if (err) {
ui.writeLine(stderr);
ui.writeLine(chalk.red('Some end-to-end tests failed, see above.'));
exitCode = err.code;
} else {
ui.writeLine(chalk.green('All end-to-end tests pass.'));
}
resolve(exitCode);
});
exec(`npm run e2e -- ${this.project.ngConfig.config.e2e.protractor.config}`,
(err, stdout, stderr) => {
ui.writeLine(stdout);
if (err) {
ui.writeLine(stderr);
ui.writeLine(chalk.red('Some end-to-end tests failed, see above.'));
exitCode = err.code;
} else {
ui.writeLine(chalk.green('All end-to-end tests pass.'));
}
resolve(exitCode);
});
});
}
});

View File

@ -5,7 +5,7 @@ import {exec} from 'child_process';
module.exports = Task.extend({
run: function() {
var ui = this.ui;
const ui = this.ui;
return new Promise(function(resolve, reject) {
exec('npm link angular-cli', (err) => {

View File

@ -5,7 +5,7 @@ import {exec} from 'child_process';
module.exports = Task.extend({
run: function () {
var ui = this.ui;
const ui = this.ui;
return new Promise(function(resolve, reject) {
exec('npm run lint', (err, stdout) => {

View File

@ -10,18 +10,24 @@ import { webpackDevServerOutputOptions } from '../models/';
import { NgCliWebpackConfig } from '../models/webpack-config';
import { ServeTaskOptions } from '../commands/serve';
import { CliConfig } from '../models/config';
import { oneLine } from 'common-tags';
module.exports = Task.extend({
run: function(commandOptions: ServeTaskOptions) {
const ui = this.ui;
let lastHash = null;
let webpackCompiler: any;
var config = new NgCliWebpackConfig(this.project, commandOptions.target, commandOptions.environment).config;
let config = new NgCliWebpackConfig(
this.project, commandOptions.target,
commandOptions.environment
).config;
// This allows for live reload of page when changes are made to repo.
// https://webpack.github.io/docs/webpack-dev-server.html#inline-mode
config.entry.main.unshift(`webpack-dev-server/client?http://${commandOptions.host}:${commandOptions.port}/`);
config.entry.main.unshift(
`webpack-dev-server/client?http://${commandOptions.host}:${commandOptions.port}/`
);
webpackCompiler = webpack(config);
webpackCompiler.apply(new ProgressPlugin({
@ -35,39 +41,39 @@ module.exports = Task.extend({
if (fs.existsSync(proxyPath)) {
proxyConfig = require(proxyPath);
} else {
var message = 'Proxy config file ' + proxyPath + ' does not exist.';
return Promise.reject(new SilentError(message));
const message = 'Proxy config file ' + proxyPath + ' does not exist.';
return Promise.reject(new SilentError(message));
}
}
const webpackDevServerConfiguration: IWebpackDevServerConfigurationOptions = {
contentBase: path.resolve(this.project.root, `./${CliConfig.fromProject().config.apps[0].root}`),
contentBase: path.resolve(
this.project.root,
`./${CliConfig.fromProject().config.apps[0].root}`
),
historyApiFallback: true,
stats: webpackDevServerOutputOptions,
inline: true,
proxy: proxyConfig
};
const serveMessage:string = chalk.green(`\n*\n*\n NG Live Development Server is running on http://${commandOptions.host}:${commandOptions.port}.\n*\n*`);
const server = new WebpackDevServer(webpackCompiler, webpackDevServerConfiguration);
ui.writeLine(chalk.green(oneLine`
**
NG Live Development Server is running on
http://${commandOptions.host}:${commandOptions.port}.
**
`));
const server = new WebpackDevServer(webpackCompiler, webpackDevServerConfiguration);
return new Promise((resolve, reject) => {
server.listen(commandOptions.port, `${commandOptions.host}`, function(err, stats) {
if(err) {
lastHash = null;
if (err) {
console.error(err.stack || err);
if(err.details) console.error(err.details);
reject(err.details);
if (err.details) { console.error(err.details); }
reject(err.details);
}
if(stats && stats.hash && stats.hash !== lastHash) {
lastHash = stats.hash;
process.stdout.write(stats.toString(webpackOutputOptions) + '\n' + serveMessage + '\n');
}
process.stdout.write(serveMessage);
});
})
});
}
});

View File

@ -1,7 +1,6 @@
import * as Promise from 'ember-cli/lib/ext/promise';
import * as Task from 'ember-cli/lib/models/task';
import * as path from 'path';
import { getWebpackTestConfig } from '../models/webpack-build-test';
// require dependencies within the target project
function requireDependency(root, moduleName) {
@ -10,7 +9,7 @@ function requireDependency(root, moduleName) {
return require(path.join(root, 'node_modules', moduleName, main));
}
module.exports = Task.extend({
module.exports = Task.extend({
run: function (options) {
const projectRoot = this.project.root;
return new Promise((resolve) => {

View File

@ -14,6 +14,9 @@
"sourceRoot": "/",
"target": "es5",
"lib": ["es6"],
"typeRoots": [
"../../node_modules/@types"
],
"paths": {
"@angular-cli/ast-tools": [ "../../packages/ast-tools/src" ]
}

View File

@ -10,7 +10,7 @@ interface IWebpackPrerender {
export class PrerenderWebpackPlugin {
private bootloader: any;
private cachedTemplate: string
private cachedTemplate: string;
constructor(private options: IWebpackPrerender) {
// maintain your platform instance
@ -53,4 +53,4 @@ export class PrerenderWebpackPlugin {
delete require.cache[key];
});
}
}
};

View File

@ -15,8 +15,10 @@
"test:cli": "node tests/runner",
"test:inspect": "node --inspect --debug-brk tests/runner",
"test:packages": "node scripts/run-packages-spec.js",
"lint": "eslint .",
"build-config-interface": "dtsgen lib/config/schema.json --out lib/config/schema.d.ts"
"build-config-interface": "dtsgen lib/config/schema.json --out lib/config/schema.d.ts",
"eslint": "eslint .",
"tslint": "tslint \"**/*.ts\" -c tslint.json -e \"**/blueprints/*/files/**/*.ts\" -e \"node_modules/**\" -e \"tmp/**\"",
"lint": "npm-run-all -c eslint tslint"
},
"repository": {
"type": "git",
@ -41,6 +43,7 @@
"angular2-template-loader": "^0.5.0",
"awesome-typescript-loader": "^2.2.1",
"chalk": "^1.1.3",
"common-tags": "^1.3.1",
"compression-webpack-plugin": "^0.3.1",
"copy-webpack-plugin": "^3.0.1",
"core-js": "^2.4.0",
@ -66,6 +69,7 @@
"lodash": "^4.11.1",
"node-sass": "^3.7.0",
"npm": "3.10.2",
"npm-run-all": "^3.0.0",
"offline-plugin": "^3.4.1",
"opn": "4.0.1",
"parse5": "^2.1.5",

View File

@ -42,7 +42,7 @@ export function getSourceNodes(sourceFile: ts.SourceFile): Observable<ts.Node> {
const subject = new ReplaySubject<ts.Node>();
let nodes: ts.Node[] = [sourceFile];
while(nodes.length > 0) {
while (nodes.length > 0) {
const node = nodes.shift();
if (node) {
@ -82,7 +82,7 @@ function nodesByPosition(first: ts.Node, second: ts.Node): number {
*/
export function insertAfterLastOccurrence(nodes: ts.Node[], toInsert: string,
file: string, fallbackPos?: number, syntaxKind?: ts.SyntaxKind): Change {
var lastItem = nodes.sort(nodesByPosition).pop();
let lastItem = nodes.sort(nodesByPosition).pop();
if (syntaxKind) {
lastItem = findNodes(lastItem, syntaxKind).sort(nodesByPosition).pop();
}
@ -99,7 +99,7 @@ export function getContentOfKeyLiteral(source: ts.SourceFile, node: ts.Node): st
return (<ts.Identifier>node).text;
} else if (node.kind == ts.SyntaxKind.StringLiteral) {
try {
return JSON.parse(node.getFullText(source))
return JSON.parse(node.getFullText(source));
} catch (e) {
return null;
}

View File

@ -65,7 +65,7 @@ export class MultiChange implements Change {
return this._changes
.sort((a: Change, b: Change) => b.order - a.order)
.reduce((promise, change) => {
return promise.then(() => change.apply())
return promise.then(() => change.apply());
}, Promise.resolve());
}
}

View File

@ -168,7 +168,9 @@ describe('route utils', () => {
});
});
it('does not add provideRouter to bootstrap if present', () => {
let editedFile = new InsertChange(mainFile, 124, ', [ HTTP_PROVIDERS, provideRouter(routes) ]');
let editedFile = new InsertChange(mainFile,
124,
', [ HTTP_PROVIDERS, provideRouter(routes) ]');
return editedFile.apply()
.then(() => nru.applyChanges(nru.bootstrapItem(mainFile, routes, toBootstrap)))
.then(() => readFile(mainFile, 'utf8'))
@ -203,14 +205,14 @@ describe('route utils', () => {
.then(() => readFile(mainFile, 'utf8'))
.then(content => {
expect(content).toEqual(prefix + routerImport +
'bootstrap(AppComponent, [ provideRouter(routes) ]);\n if(e){bootstrap, provideRouter});');
'bootstrap(AppComponent, [ provideRouter(routes) ]);\n if(e){bootstrap, provideRouter});'); // tslint:disable-line
});
});
});
describe('addPathToRoutes', () => {
const routesFile = 'src/routes.ts';
var options = {dir: 'src/app', appRoot: 'src/app', routesFile: routesFile,
let options = {dir: 'src/app', appRoot: 'src/app', routesFile: routesFile,
component: 'NewRouteComponent', dasherizedName: 'new-route'};
const nestedRoutes = `\n { path: 'home', component: HomeComponent,
children: [
@ -235,7 +237,8 @@ describe('route utils', () => {
});
it('adds import to new route component if absent', () => {
return nru.applyChanges(nru.addPathToRoutes(routesFile, _.merge({route: 'new-route'}, options)))
return nru.applyChanges(nru.addPathToRoutes(routesFile,
_.merge({route: 'new-route'}, options)))
.then(() => readFile(routesFile, 'utf8'))
.then(content => {
expect(content).toEqual(
@ -289,6 +292,7 @@ export default [\n { path: 'new-route', component: NewRouteComponent }\n];`);
nru.addPathToRoutes(routesFile, _.merge({route: 'home/about/details'}, options))); })
.then(() => readFile(routesFile, 'utf8'))
.then(content => {
// tslint:disable-next-line
let expected = `import { DetailsComponent } from './app/home/about/details/details.component';
export default [
{ path: 'home', component: HomeComponent,
@ -310,9 +314,11 @@ export default [
options.dasherizedName = 'sections';
options.component = 'SectionsComponent';
return nru.applyChanges(
nru.addPathToRoutes(routesFile, _.merge({route: 'home/about/more/sections'}, options))); })
nru.addPathToRoutes(routesFile,
_.merge({route: 'home/about/more/sections'}, options))); })
.then(() => readFile(routesFile, 'utf8'))
.then(content => {
// tslint:disable-next-line
let expected = `import { SectionsComponent } from './app/home/about/more/sections/sections.component';
export default [
{ path: 'home', component: HomeComponent,
@ -347,6 +353,7 @@ export default [
nru.addPathToRoutes(routesFile, _.merge({route: 'home/about/:id'}, options))); })
.then(() => readFile(routesFile, 'utf8'))
.then(content => {
// tslint:disable-next-line
expect(content).toEqual(`import { AboutComponent_1 } from './app/home/about/about.component';
export default [
{ path: 'main', component: MainComponent }
@ -435,6 +442,7 @@ export default [
})
.then(() => readFile(routesFile, 'utf8'))
.then(content => {
// tslint:disable-next-line
let expected = `import { TrapQueenComponent } from './app/home/trap-queen/trap-queen.component';
export default [
{ path: 'home', component: HomeComponent,
@ -489,7 +497,7 @@ export default [
let editedFile = new InsertChange(routesFile, 0,
`import { AboutComponent } from './app/about/about.component';
import { DetailsComponent } from './app/about/details/details.component';
import { DetailsComponent as DetailsComponent_1 } from './app/about/description/details.component;\n`);
import { DetailsComponent as DetailsComponent_1 } from './app/about/description/details.component;\n`); // tslint:disable-line
return editedFile.apply();
}).then(() => {
options.dasherizedName = 'details';

View File

@ -12,9 +12,13 @@ import {insertAfterLastOccurrence} from './ast-utils';
* @param imports Object { importedClass: ['path/to/import/from', defaultStyleImport?] }
* @param toBootstrap
*/
export function bootstrapItem(mainFile: string, imports: {[key: string]: (string | boolean)[]}, toBootstrap: string ) {
export function bootstrapItem(
mainFile: string,
imports: {[key: string]: (string | boolean)[]},
toBootstrap: string
) {
let changes = Object.keys(imports).map(importedClass => {
var defaultStyleImport = imports[importedClass].length === 2 && !!imports[importedClass][1];
let defaultStyleImport = imports[importedClass].length === 2 && !!imports[importedClass][1];
return insertImport(
mainFile,
importedClass,
@ -43,8 +47,8 @@ export function bootstrapItem(mainFile: string, imports: {[key: string]: (string
}
// if bracket exitst already, add configuration template,
// otherwise, insert into bootstrap parens
var fallBackPos: number, configurePathsTemplate: string, separator: string;
var syntaxListNodes: any;
let fallBackPos: number, configurePathsTemplate: string, separator: string;
let syntaxListNodes: any;
let bootstrapProviders = bootstrapNode.getChildAt(2).getChildAt(2); // array of providers
if ( bootstrapProviders ) {
@ -88,7 +92,7 @@ export function insertImport(fileToEdit: string, symbolName: string,
if (relevantImports.length > 0) {
var importsAsterisk = false;
let importsAsterisk = false;
// imports from import file
let imports: ts.Node[] = [];
relevantImports.forEach(n => {
@ -128,7 +132,13 @@ export function insertImport(fileToEdit: string, symbolName: string,
let separator = insertAtBeginning ? '' : ';\n';
let toInsert = `${separator}import ${open}${symbolName}${close}` +
` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`;
return insertAfterLastOccurrence(allImports, toInsert, fileToEdit, fallbackPos, ts.SyntaxKind.StringLiteral);
return insertAfterLastOccurrence(
allImports,
toInsert,
fileToEdit,
fallbackPos,
ts.SyntaxKind.StringLiteral
);
};
/**
@ -149,9 +159,13 @@ export function addPathToRoutes(routesFile: string, pathOptions: any): Change[]
let routePath = route.replace(positionalRoutes, '');
routePath = `./app/${routePath}/${pathOptions.dasherizedName}.component`;
let originalComponent = pathOptions.component;
pathOptions.component = resolveImportName(pathOptions.component, routePath, pathOptions.routesFile);
pathOptions.component = resolveImportName(
pathOptions.component,
routePath,
pathOptions.routesFile
);
var content = `{ path: '${route}', component: ${pathOptions.component}${isDefault}${outlet} }`;
let content = `{ path: '${route}', component: ${pathOptions.component}${isDefault}${outlet} }`;
let rootNode = getRootNode(routesFile);
let routesNode = rootNode.getChildAt(0).getChildren().filter(n => {
// get export statement
@ -162,7 +176,7 @@ export function addPathToRoutes(routesFile: string, pathOptions: any): Change[]
throw new Error('Did not insert path in routes.ts because ' +
`there were multiple or no 'export default' statements`);
}
var pos = routesNode[0].getChildAt(2).getChildAt(0).end; // openBracketLiteral
let pos = routesNode[0].getChildAt(2).getChildAt(0).end; // openBracketLiteral
// all routes in export route array
let routesArray = routesNode[0].getChildAt(2).getChildAt(1)
.getChildren()
@ -172,14 +186,16 @@ export function addPathToRoutes(routesFile: string, pathOptions: any): Change[]
// don't duplicate routes
throw new Error('Route was not added since it is a duplicate');
}
var isChild = false;
let isChild = false;
// get parent to insert under
let parent: ts.Node;
if (pathOptions.parent) {
// append '_' to route to find the actual parent (not parent of the parent)
parent = getParent(routesArray, `${pathOptions.parent}/_`);
if (!parent) {
throw new Error(`You specified parent '${pathOptions.parent}'' which was not found in routes.ts`);
throw new Error(
`You specified parent '${pathOptions.parent}'' which was not found in routes.ts`
);
}
if (route.indexOf(pathOptions.parent) === 0) {
route = route.substring(pathOptions.parent.length);
@ -296,8 +312,8 @@ function resolveImportName (importName: string, importPath: string, fileName: st
return importName;
}
const baseName = importNames[index].split('_')[0];
var newName = baseName;
var resolutionNumber = 1;
let newName = baseName;
let resolutionNumber = 1;
while (importNames.indexOf(newName) !== -1) {
newName = `${baseName}_${resolutionNumber}`;
resolutionNumber++;
@ -328,8 +344,9 @@ export function resolveComponentPath(projectRoot: string, currentDir: string, fi
// only component file name is given
filePath = componentName;
}
var directory = filePath[0] === path.sep ?
path.resolve(path.join(projectRoot, 'src', 'app', filePath)) : path.resolve(currentDir, filePath);
let directory = filePath[0] === path.sep ?
path.resolve(path.join(projectRoot, 'src', 'app', filePath)) :
path.resolve(currentDir, filePath);
if (!fs.existsSync(directory)) {
throw new Error(`path '${filePath}' must be relative to current directory` +
@ -364,13 +381,14 @@ function addChildPath (parentObject: ts.Node, pathOptions: any, route: string) {
if (!parentObject) {
return;
}
var pos: number;
var newContent: string;
let pos: number;
let newContent: string;
// get object with 'children' property
let childrenNode = parentObject.getChildAt(1).getChildren()
.filter(n => n.kind === ts.SyntaxKind.PropertyAssignment
&& ((n as ts.PropertyAssignment).name as ts.Identifier).text === 'children');
.filter(n =>
n.kind === ts.SyntaxKind.PropertyAssignment
&& ((n as ts.PropertyAssignment).name as ts.Identifier).text === 'children');
// find number of spaces to pad nested paths
let nestingLevel = 1; // for indenting route object in the `children` array
let n = parentObject;
@ -417,7 +435,7 @@ function getParent(routesArray: ts.Node[], route: string, parent?: ts.Node): ts.
if (route.length === 0) {
return; // route has been completely matched
}
var splitRoute = route.split('/');
let splitRoute = route.split('/');
// don't treat positional parameters separately
if (splitRoute.length > 1 && splitRoute[1].indexOf(':') !== -1) {
let actualRoute = splitRoute.shift();
@ -442,13 +460,18 @@ function getParent(routesArray: ts.Node[], route: string, parent?: ts.Node): ts.
* Helper for addPathToRoutes.
* @return whether path with same route and component exists
*/
function pathExists(routesArray: ts.Node[], route: string, component: string, fullRoute?: string): boolean {
function pathExists(
routesArray: ts.Node[],
route: string,
component: string,
fullRoute?: string
): boolean {
if (routesArray.length === 0) {
return false;
}
fullRoute = fullRoute ? fullRoute : route;
var sameRoute = false;
var splitRoute = route.split('/');
let sameRoute = false;
let splitRoute = route.split('/');
// don't treat positional parameters separately
if (splitRoute.length > 1 && splitRoute[1].indexOf(':') !== -1) {
let actualRoute = splitRoute.shift();
@ -461,7 +484,7 @@ function pathExists(routesArray: ts.Node[], route: string, component: string, fu
sameRoute = currentRoute === splitRoute[0];
// Confirm that it's parents are the same
if (sameRoute && sameComponent) {
var path = currentRoute;
let path = currentRoute;
let objExp = n.parent;
while (objExp) {
if (objExp.kind === ts.SyntaxKind.ObjectLiteralExpression) {

View File

@ -130,7 +130,8 @@ describe('ModuleResolver', () => {
.then((tsFile: ts.SourceFile) => {
let contentsBaz = dependentFilesUtils.getImportClauses(tsFile);
let barExpectedContent = path.normalize('../bar/bar.component');
let fooBarExpectedContent = `.${path.sep}qux${path.sep}quux${path.sep}foobar${path.sep}foobar.component`;
let fooBarExpectedContent =
`.${path.sep}qux${path.sep}quux${path.sep}foobar${path.sep}foobar.component`;
expect(contentsBaz[0].specifierText).to.equal(barExpectedContent);
expect(contentsBaz[1].specifierText).to.equal(fooBarExpectedContent);
});

View File

@ -18,9 +18,9 @@
"no-internal-module": true,
"no-trailing-whitespace": true,
"no-bitwise": true,
"no-shadowed-variable": true,
"no-unused-expression": true,
"no-unused-variable": true,
"no-var-keyword": true,
"one-line": [
true,
"check-catch",
@ -49,7 +49,8 @@
true,
"ban-keywords",
"check-format",
"allow-trailing-underscore"
"allow-leading-underscore",
"allow-pascal-case"
],
"whitespace": [
true,