angular-cli/lib/broccoli/angular2-app.js
2016-03-30 04:09:06 +02:00

229 lines
5.5 KiB
JavaScript

var path = require('path');
var configReplace = require('./broccoli-config-replace');
var compileWithTypescript = require('./broccoli-typescript');
var SwManifest = require('./service-worker-manifest').default;
var fs = require('fs');
var Funnel = require('broccoli-funnel');
var mergeTrees = require('broccoli-merge-trees');
var Project = require('ember-cli/lib/models/project');
module.exports = Angular2App;
function Angular2App(defaults, options) {
this._initProject();
this._notifyAddonIncluded();
this.options = options;
}
Angular2App.prototype.toTree = function () {
var sourceDir = 'src';
var sourceTree = new Funnel('src', {
include: ['*.ts', '**/*.ts', '**/*.d.ts'],
destDir: 'src'
});
var typingsTree = new Funnel('typings', {
include: ['browser.d.ts', 'browser/**'],
destDir: 'typings'
});
var vendorNpmFiles = [
'systemjs/dist/system-polyfills.js',
'systemjs/dist/system.src.js',
'es6-shim/es6-shim.js',
'angular2/bundles/angular2-polyfills.js',
'rxjs/bundles/Rx.js',
'angular2/bundles/angular2.dev.js',
'angular2/bundles/http.dev.js',
'angular2/bundles/router.dev.js',
'angular2/bundles/upgrade.dev.js'
];
if (this.options && this.options.vendorNpmFiles) {
vendorNpmFiles = vendorNpmFiles.concat(this.options.vendorNpmFiles);
}
var tsconfig = JSON.parse(fs.readFileSync('src/tsconfig.json', 'utf-8'));
// Add all spec files to files. We need this because spec files are their own entry
// point.
fs.readdirSync(sourceDir).forEach(function addPathRecursive(name) {
const filePath = path.join(sourceDir, name);
if (filePath.match(/\.spec\.[jt]s$/)) {
tsconfig.files.push(name);
} else if (fs.statSync(filePath).isDirectory()) {
// Recursively call this function with the full sub-path.
fs.readdirSync(filePath).forEach(function (n) {
addPathRecursive(path.join(name, n));
});
}
});
// Because the tsconfig does not include the source directory, add this as the first path
// element.
tsconfig.files = tsconfig.files.map(name => path.join(sourceDir, name));
var srcAndTypingsTree = mergeTrees([sourceTree, typingsTree]);
var tsTree = new compileWithTypescript(srcAndTypingsTree, tsconfig);
tsTree = new Funnel(tsTree, {
srcDir: 'src',
exclude: ['*.d.ts', 'tsconfig.json']
});
var jsTree = new Funnel(sourceDir, {
include: ['**/*.js'],
allowEmpty: true
});
var assetTree = new Funnel(sourceDir, {
include: ['**/*.*'],
exclude: ['**/*.ts', '**/*.js'],
allowEmpty: true
});
var vendorNpmTree = new Funnel('node_modules', {
include: vendorNpmFiles,
destDir: 'vendor'
});
var publicDirTree = new Funnel('public', {
allowEmpty: true
});
var merged = mergeTrees([
assetTree,
tsTree,
jsTree,
publicDirTree,
this.index(),
vendorNpmTree
], { overwrite: true });
return mergeTrees([merged, new SwManifest([merged])]);
};
/**
@private
@method _initProject
@param {Object} options
*/
Angular2App.prototype._initProject = function () {
this.project = Project.closestSync(process.cwd());
/*if (options.configPath) {
this.project.configPath = function() { return options.configPath; };
}*/
};
/**
@private
@method _notifyAddonIncluded
*/
Angular2App.prototype._notifyAddonIncluded = function () {
this.initializeAddons();
this.project.addons = this.project.addons.filter(function (addon) {
addon.app = this;
if (!addon.isEnabled || addon.isEnabled()) {
if (addon.included) {
addon.included(this);
}
return addon;
}
}, this);
};
/**
Loads and initializes addons for this project.
Calls initializeAddons on the Project.
@private
@method initializeAddons
*/
Angular2App.prototype.initializeAddons = function () {
this.project.initializeAddons();
};
/**
Returns the content for a specific type (section) for index.html.
Currently supported types:
- 'head'
//- 'config-module'
//- 'app'
//- 'head-footer'
//- 'test-header-footer'
//- 'body-footer'
//- 'test-body-footer'
Addons can also implement this method and could also define additional
types (eg. 'some-addon-section').
@private
@method contentFor
@param {RegExP} match Regular expression to match against
@param {String} type Type of content
@return {String} The content.
*/
Angular2App.prototype.contentFor = function (match, type) {
var content = [];
/*switch (type) {
case 'head': this._contentForHead(content, config); break;
case 'config-module': this._contentForConfigModule(content, config); break;
case 'app-boot': this._contentForAppBoot(content, config); break;
}*/
content = this.project.addons.reduce(function (content, addon) {
var addonContent = addon.contentFor ? addon.contentFor(type) : null;
if (addonContent) {
return content.concat(addonContent);
}
return content;
}, content);
return content.join('\n');
};
/**
@private
@method _configReplacePatterns
@return
*/
Angular2App.prototype._configReplacePatterns = function () {
return [{
match: /\{\{content-for ['"](.+)["']\}\}/g,
replacement: this.contentFor.bind(this)
}];
};
/**
Returns the tree for app/index.html
@private
@method index
@return {Tree} Tree for app/index.html
*/
Angular2App.prototype.index = function () {
var htmlName = 'index.html';
var files = [
'index.html'
];
var index = new Funnel('src', {
files: files,
description: 'Funnel: index.html'
});
return configReplace(index, {
files: [htmlName],
patterns: this._configReplacePatterns()
});
};