diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b4458e1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = tab +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false + +[test/fixtures/*] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..2125666 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4e85f0d --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +node_modules/ +temp/ +.idea/ diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..a9ccf70 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,21 @@ +{ + "node": true, + "esnext": true, + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "immed": true, + "indent": 4, + "latedef": true, + "newcap": true, + "noarg": true, + "quotmark": "double", + "regexp": true, + "undef": true, + "unused": true, + "strict": true, + "trailing": true, + "smarttabs": true, + "white": true +} diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..7b5db11 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - '0.8' + - '0.10' +before_install: + - currentfolder=${PWD##*/} + - if [ "$currentfolder" != 'generator-gulp-plugin' ]; then cd .. && eval "mv $currentfolder generator-gulp-plugin" && cd generator-gulp-plugin; fi diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a7cd3be --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright 2014 Mark Lagendijk + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5d70e67 --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +(PLUGIN AUTHOR: Please read [Plugin README conventions](https://github.com/wearefractal/gulp/wiki/Plugin-README-Conventions), then delete this line) + +# gulp-ng-html2js [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][depstat-image]][depstat-url] + +> ng-html2js plugin for [gulp](https://github.com/wearefractal/gulp) + +## Usage + +First, install `gulp-ng-html2js` as a development dependency: + +```shell +npm install --save-dev gulp-ng-html2js +``` + +Then, add it to your `gulpfile.js`: + +```javascript +var ngHtml2Js = require("gulp-ng-html2js"); + +gulp.src("./partials/*.html") + .pipe(ngHtml2Js({ + moduleName: "MyAwesomePartials", + prefix: "/partials" + })) + .pipe(gulp.dest("./dist/partials")); +``` + +## API + +### ngHtml2Js(options) + +#### options.moduleName +Type: `String` + +The name of the generated AngularJS module. Uses the file url if omitted. + +#### options.prefix +Type: `String` + +The prefix which should be prepended to the file path to generate the file url. + +#### options.stripPrefix +Type: `String` + +The prefix which should be subtracted from the file path to generate the file url. + + +## License + +[MIT License](http://en.wikipedia.org/wiki/MIT_License) + +[npm-url]: https://npmjs.org/package/gulp-ng-html2js +[npm-image]: https://badge.fury.io/js/gulp-ng-html2js.png + +[travis-url]: http://travis-ci.org/marklagendijk/gulp-ng-html2js +[travis-image]: https://secure.travis-ci.org/marklagendijk/gulp-ng-html2js.png?branch=master + +[depstat-url]: https://david-dm.org/marklagendijk/gulp-ng-html2js +[depstat-image]: https://david-dm.org/marklagendijk/gulp-ng-html2js.png diff --git a/index.js b/index.js new file mode 100644 index 0000000..217d7f3 --- /dev/null +++ b/index.js @@ -0,0 +1,98 @@ +var util = require("util"); +var es = require("event-stream"); + +var TEMPLATE = 'angular.module(\'%s\', []).run(function($templateCache) {\n' + + ' $templateCache.put(\'%s\',\n \'%s\');\n' + + '});\n'; + +var SINGLE_MODULE_TPL = '(function(module) {\n' + + 'try {\n' + + ' module = angular.module(\'%s\');\n' + + '} catch (e) {\n' + + ' module = angular.module(\'%s\', []);\n' + + '}\n' + + 'module.run(function($templateCache) {\n' + + ' $templateCache.put(\'%s\',\n \'%s\');\n' + + '});\n' + + '})();\n'; + +/** + * @param [options] - The plugin options + * @param [options.moduleName] - The name of the module which will be generated. When omitted the fileUrl will be used. + * @param [options.stripPrefix] - The prefix which should be stripped from the file path + * @param [options.prefix] - The prefix which should be added to the start of the url + * @returns {stream} + */ +module.exports = function(options){ + "use strict"; + + function ngHtml2Js(file, callback){ + if(file.isStream()){ + return callback(new Error("gulp-ng-html2js: Streaming not supported")); + } + + if(file.isBuffer()){ + var filePath = getFileUrl(file, options); + file.contents = new Buffer(generateModuleDeclaration(filePath, String(file.contents), options)); + file.path = file.path.replace(".html", ".js"); + } + + return callback(null, file); + } + + /** + * Generates the Javascript code containing the AngularJS module which puts the HTML file into the $templateCache. + * @param fileUrl - The url with which the HTML will be registered in the $templateCache. + * @param contents - The contents of the HTML file. + * @param [options] - The plugin options + * @param [options.moduleName] - The name of the module which will be generated. When omitted the fileUrl will be used. + * @returns {string} - The generated Javascript code. + */ + function generateModuleDeclaration(fileUrl, contents, options){ + var escapedContent = escapeContent(contents); + if(options && options.moduleName){ + return util.format(SINGLE_MODULE_TPL, options.moduleName, options.moduleName, fileUrl, escapedContent); + } + else{ + return util.format(TEMPLATE, fileUrl, fileUrl, escapedContent); + } + } + + /** + * Generates the url of a file. + * @param file - The file for which a url should be generated + * @param [options] - The plugin options + * @param [options.stripPrefix] - The prefix which should be stripped from the file path + * @param [options.prefix] - The prefix which should be added to the start of the url + * @returns {string} + */ + function getFileUrl(file, options){ + // Start with the relative file path + var url = file.relative; + + // Replace '\' with '/' (Windows) + url = url.replace(/\\/g, '/'); + + // Remove the stripPrefix + if(options && options.stripPrefix && url.indexOf(options.stripPrefix) === 0){ + url = url.replace(options.stripPrefix, ''); + } + // Add the prefix + if(options && options.prefix){ + url = options.prefix + url; + } + + return url; + } + + /** + * Escapes the content of an string so it can be used in a Javascript string declaration + * @param {string} content + * @returns {string} + */ + function escapeContent(content){ + return content.replace(/\\/g, '\\\\').replace(/'/g, '\\\'').replace(/\r?\n/g, '\\n\' +\n \''); + } + + return es.map(ngHtml2Js); +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..13200f4 --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "gulp-ng-html2js", + "version": "0.1.0", + "description": "A Gulp plugin which generates Javascript code which loads the HTML files of your AngularJS app into the $templateCache.", + "keywords": [ + "gulpplugin", + "ng-html2js", + "angular", + "html2js", + "angularjs" + ], + "homepage": "https://github.com/marklagendijk/gulp-ng-html2js", + "bugs": "https://github.com/marklagendijk/gulp-ng-html2js/issues", + "author": { + "name": "Mark Lagendijk", + "url": "https://github.com/marklagendijk" + }, + "main": "./index.js", + "repository": { + "type": "git", + "url": "git://github.com/marklagendijk/gulp-ng-html2js.git" + }, + "scripts": { + "test": "mocha" + }, + "dependencies": { + "event-stream": "*" + }, + "devDependencies": { + "mocha": "~1.14.0", + "should": "~2.1.0", + "gulp-util": "~2.2.0" + }, + "engines": { + "node": ">=0.8.0", + "npm": ">=1.2.10" + }, + "licenses": [ + { + "type": "MIT" + } + ] +} diff --git a/test/expected/example.js b/test/expected/example.js new file mode 100644 index 0000000..8ca8685 --- /dev/null +++ b/test/expected/example.js @@ -0,0 +1,36 @@ +angular.module('fixtures/example.html', []).run(function($templateCache) { + $templateCache.put('fixtures/example.html', + '\n' + + '\n' + + ' \n' + + ' Example\n' + + '\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + '\n' + + ''); +}); diff --git a/test/expected/exampleWithModuleName.js b/test/expected/exampleWithModuleName.js new file mode 100644 index 0000000..d0e84a6 --- /dev/null +++ b/test/expected/exampleWithModuleName.js @@ -0,0 +1,43 @@ +(function(module) { +try { + module = angular.module('myAwesomePartials'); +} catch (e) { + module = angular.module('myAwesomePartials', []); +} +module.run(function($templateCache) { + $templateCache.put('fixtures/example.html', + '\n' + + '\n' + + ' \n' + + ' Example\n' + + '\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + '\n' + + ''); +}); +})(); diff --git a/test/expected/exampleWithPrefix.js b/test/expected/exampleWithPrefix.js new file mode 100644 index 0000000..b0945ac --- /dev/null +++ b/test/expected/exampleWithPrefix.js @@ -0,0 +1,36 @@ +angular.module('/partials/fixtures/example.html', []).run(function($templateCache) { + $templateCache.put('/partials/fixtures/example.html', + '\n' + + '\n' + + ' \n' + + ' Example\n' + + '\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + '\n' + + ''); +}); diff --git a/test/expected/exampleWithStripPrefix.js b/test/expected/exampleWithStripPrefix.js new file mode 100644 index 0000000..38662f9 --- /dev/null +++ b/test/expected/exampleWithStripPrefix.js @@ -0,0 +1,36 @@ +angular.module('example.html', []).run(function($templateCache) { + $templateCache.put('example.html', + '\n' + + '\n' + + ' \n' + + ' Example\n' + + '\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + '\n' + + ''); +}); diff --git a/test/fixtures/example.html b/test/fixtures/example.html new file mode 100644 index 0000000..b392b8e --- /dev/null +++ b/test/fixtures/example.html @@ -0,0 +1,32 @@ + + + + Example + + + + + + + + + + + + diff --git a/test/main.js b/test/main.js new file mode 100644 index 0000000..21db732 --- /dev/null +++ b/test/main.js @@ -0,0 +1,130 @@ +/*global describe, it*/ +"use strict"; + +var fs = require("fs"), + es = require("event-stream"), + should = require("should"); +require("mocha"); + +var gutil = require("gulp-util"), + ngHtml2Js = require("../"); + +describe("gulp-ng-html2js", function () { + + + describe("when file is provided via buffer", function(){ + it("should generate the angular module", function(done){ + var expectedFile = new gutil.File({ + path: "test/expected/example.js", + cwd: "test/", + base: "test/expected", + contents: fs.readFileSync("test/expected/example.js") + }); + + testBufferedFile(null, expectedFile, done); + }); + + it("should use options.moduleName when provided", function(done){ + var expectedFile = new gutil.File({ + path: "test/expected/exampleWithModuleName.js", + cwd: "test/", + base: "test/expected", + contents: fs.readFileSync("test/expected/exampleWithModuleName.js") + }); + + var params = { + moduleName: 'myAwesomePartials' + }; + + testBufferedFile(params, expectedFile, done); + }); + + it("should add options.prefix to the url in the generated file", function(done){ + var expectedFile = new gutil.File({ + path: "test/expected/exampleWithPrefix.js", + cwd: "test/", + base: "test/expected", + contents: fs.readFileSync("test/expected/exampleWithPrefix.js") + }); + + var params = { + prefix: '/partials/' + }; + + testBufferedFile(params, expectedFile, done); + }); + + it("should subtract options.stripPrefix from the url in the generated file", function(done){ + var expectedFile = new gutil.File({ + path: "test/expected/exampleWithStripPrefix.js", + cwd: "test/", + base: "test/expected", + contents: fs.readFileSync("test/expected/exampleWithStripPrefix.js") + }); + + var params = { + stripPrefix: 'fixtures/' + }; + + testBufferedFile(params, expectedFile, done); + }); + + function testBufferedFile(params, expectedFile, done){ + var srcFile = new gutil.File({ + path: "test/fixtures/example.html", + cwd: "test/", + base: "test", + contents: fs.readFileSync("test/fixtures/example.html") + }); + + var stream = ngHtml2Js(params); + + stream.on("error", function(err){ + should.exist(err); + done(err); + }); + + stream.on("data", function(newFile){ + + should.exist(newFile); + should.exist(newFile.contents); + + String(newFile.contents).should.equal(String(expectedFile.contents)); + done(); + }); + + stream.write(srcFile); + stream.end(); + } + }); + + + it("should error on stream", function (done) { + + var srcFile = new gutil.File({ + path: "test/fixtures/example.html", + cwd: "test/", + base: "test/fixtures", + contents: fs.createReadStream("test/fixtures/example.html") + }); + + var stream = ngHtml2Js({ + moduleName: 'myAwesomePartials', + prefix: '/partials/' + }); + + stream.on("error", function(err) { + should.exist(err); + done(); + }); + + stream.on("data", function (newFile) { + newFile.contents.pipe(es.wait(function(err, data) { + done(err); + })); + }); + + stream.write(srcFile); + stream.end(); + }); +});