diff --git a/README.md b/README.md index a91d41328aec..4eae9e984ea4 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ The generated project has dependencies that require * [Linting and formatting code](#linting-and-formatting-code) * [Support for offline applications](#support-for-offline-applications) * [Commands autocompletion](#commands-autocompletion) +* [HTML template engine integration](#html-template-engine-integration) * [CSS preprocessor integration](#css-preprocessor-integration) * [3rd Party Library Installation](#3rd-party-library-installation) * [Updating angular-cli](#updating-angular-cli) @@ -222,6 +223,12 @@ ng completion >> ~/.bash_profile source ~/.bash_profile ``` +### HTML Template Engine integration + +We currently support `Pug` (ex `Jade`) HTML template engine. +To use `Pug` install `npm install pug --save` in your project and rename `.html` template extensions to `.pug`. Templates will be compiled automatically. + +If you already have `pug` installed globally the plugin will be instatinated automatically and the templates will be compiled to HTML. ### CSS Preprocessor integration diff --git a/lib/broccoli/angular-broccoli-pug.js b/lib/broccoli/angular-broccoli-pug.js new file mode 100644 index 000000000000..13d72a5f48e8 --- /dev/null +++ b/lib/broccoli/angular-broccoli-pug.js @@ -0,0 +1,54 @@ +/* jshint node: true, esversion: 6 */ +'use strict'; + +const requireOrNull = require('./require-or-null'); +const Plugin = require('broccoli-caching-writer'); +const fse = require('fs-extra'); +const path = require('path'); +const Funnel = require('broccoli-funnel'); + +let pug = requireOrNull('pug'); +if (!pug) { + pug = requireOrNull(`${process.env.PROJECT_ROOT}/node_modules/pug`); +} + +class PugPlugin extends Plugin { + constructor(inputNodes, options) { + super(inputNodes, {}); + + options = options || {}; + Plugin.call(this, inputNodes, { + cacheInclude: [/\.pug$|\.jade$/] + }); + this.options = options; + } + + build() { + return Promise.all(this.listEntries().map(e => { + let fileName = path.resolve(e.basePath, e.relativePath); + return this.compile(fileName, this.inputPaths[0], this.outputPath); + })); + } + + compile(fileName, inputPath, outputPath) { + return new Promise(resolve => { + let filePath = fileName.replace(inputPath, outputPath).replace(/\.pug$|\.jade$/, '.html'); + let html = pug.renderFile(fileName, { + pretty: true + }); + fse.outputFileSync(filePath, html, 'utf8'); + resolve(); + }); + } +} + +exports.makeBroccoliTree = (sourceDir, options) => { + if (pug) { + let pugSrcTree = new Funnel(sourceDir, { + include: ['**/*.pug', '**/*.jade'], + allowEmpty: true + }); + + return new PugPlugin([pugSrcTree], options); + } +}; diff --git a/lib/broccoli/angular2-app.js b/lib/broccoli/angular2-app.js index 487b9bbe4771..bf8e567ac605 100644 --- a/lib/broccoli/angular2-app.js +++ b/lib/broccoli/angular2-app.js @@ -127,8 +127,8 @@ class Angular2App extends BroccoliPlugin { var buildTrees = [assetTree, tsTree, indexTree, vendorNpmTree]; - // Add available and supported CSS plugins. - for (const suffix of ['sass', 'less', 'stylus', 'compass']) { + // Add available CSS and HTML template plugins. + for (const suffix of ['sass', 'less', 'stylus', 'compass', 'pug']) { const plugin = require(`./angular-broccoli-${suffix}`); const tree = plugin.makeBroccoliTree(this._inputNode, this._options[`${suffix}Compiler`]); @@ -145,7 +145,7 @@ class Angular2App extends BroccoliPlugin { return n; } })); - } + } var merged = new BroccoliMergeTrees(buildTrees, { overwrite: true });