├── .eslintrc ├── .gitattributes ├── .gitignore ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── gruntfile.js ├── lib ├── html2js.js └── index.js ├── package.json └── test ├── helpers └── template_cache.coffee └── html2js.spec.coffee /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "standard" 3 | } 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/dealing-with-line-endings 2 | 3 | # By default, normalize all files to unix line endings when commiting. 4 | * text 5 | 6 | # Denote all files that are truly binary and should not be modified. 7 | *.png binary 8 | *.jpg binary 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .* 2 | test 3 | 4 | Gruntfile.coffee 5 | CONTRIBUTING.md 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.8" 4 | - "0.10" 5 | 6 | before_install: 7 | - '[ "${TRAVIS_NODE_VERSION}" != "0.8" ] || npm install -g npm@1.4.28' 8 | 9 | before_script: 10 | - npm install -g grunt-cli 11 | 12 | script: 13 | - grunt 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # [1.0.0](https://github.com/karma-runner/karma-ng-html2js-preprocessor/compare/v0.2.2...v1.0.0) (2016-05-04) 3 | 4 | 5 | 6 | 7 | 8 | ## [0.2.2](https://github.com/karma-runner/karma-ng-html2js-preprocessor/compare/v0.2.1...v0.2.2) (2016-04-07) 9 | 10 | 11 | ### Features 12 | 13 | * Add support for Angular 2 template cache ([09609a0](https://github.com/karma-runner/karma-ng-html2js-preprocessor/commit/09609a0)) 14 | 15 | 16 | 17 | 18 | ## [0.2.1](https://github.com/karma-runner/karma-ng-html2js-preprocessor/compare/v0.2.0...v0.2.1) (2016-02-12) 19 | 20 | 21 | ### Features 22 | 23 | * Support loading Angular with RequireJS ([08748a2](https://github.com/karma-runner/karma-ng-html2js-preprocessor/commit/08748a2)) 24 | 25 | 26 | 27 | 28 | # [0.2.0](https://github.com/karma-runner/karma-ng-html2js-preprocessor/compare/v0.1.2...v0.2.0) (2015-10-08) 29 | 30 | 31 | ### Bug Fixes 32 | 33 | * explicit annotations for $templateCache dependency ([d8f2ec5](https://github.com/karma-runner/karma-ng-html2js-preprocessor/commit/d8f2ec5)) 34 | * explicit annotations for $templateCache dependency ([c7666b9](https://github.com/karma-runner/karma-ng-html2js-preprocessor/commit/c7666b9)) 35 | * Suffix is misspelled ([e7e20dd](https://github.com/karma-runner/karma-ng-html2js-preprocessor/commit/e7e20dd)), closes [#56](https://github.com/karma-runner/karma-ng-html2js-preprocessor/issues/56) 36 | * **runner:** removing the html2js name overwrite ([50e4f9e](https://github.com/karma-runner/karma-ng-html2js-preprocessor/commit/50e4f9e)), closes [#43](https://github.com/karma-runner/karma-ng-html2js-preprocessor/issues/43) 37 | 38 | ### Features 39 | 40 | * Multiple module names ([e0d3620](https://github.com/karma-runner/karma-ng-html2js-preprocessor/commit/e0d3620)) 41 | 42 | 43 | 44 | 45 | 46 | ## [0.1.2](https://github.com/karma-runner/karma-ng-html2js-preprocessor/compare/v0.1.1...v0.1.2) (2014-10-24) 47 | 48 | 49 | ### Bug Fixes 50 | 51 | * only append .js to file.path when not already present ([dfa8661](https://github.com/karma-runner/karma-ng-html2js-preprocessor/commit/dfa8661)), closes [#36](https://github.com/karma-runner/karma-ng-html2js-preprocessor/issues/36) 52 | 53 | 54 | 55 | 56 | ## [0.1.1](https://github.com/karma-runner/karma-ng-html2js-preprocessor/compare/v0.1.0...v0.1.1) (2014-10-15) 57 | 58 | 59 | ### Features 60 | 61 | * Add stripSufix config option ([e0e6126](https://github.com/karma-runner/karma-ng-html2js-preprocessor/commit/e0e6126)), closes [#37](https://github.com/karma-runner/karma-ng-html2js-preprocessor/issues/37) [#38](https://github.com/karma-runner/karma-ng-html2js-preprocessor/issues/38) 62 | 63 | 64 | 65 | 66 | # [0.1.0](https://github.com/karma-runner/karma-ng-html2js-preprocessor/compare/v0.0.4...v0.1.0) (2013-08-06) 67 | 68 | 69 | 70 | 71 | 72 | ## [0.0.4](https://github.com/karma-runner/karma-ng-html2js-preprocessor/compare/v0.0.3...v0.0.4) (2013-08-05) 73 | 74 | 75 | ### Features 76 | 77 | * add moduleName option to generate only one module ([0a05ee5](https://github.com/karma-runner/karma-ng-html2js-preprocessor/commit/0a05ee5)) 78 | 79 | 80 | 81 | 82 | ## [0.0.3](https://github.com/karma-runner/karma-ng-html2js-preprocessor/compare/v0.0.2...v0.0.3) (2013-07-29) 83 | 84 | 85 | ### Features 86 | 87 | * register the preprocessor as ng-html2js too ([1d3cb4d](https://github.com/karma-runner/karma-ng-html2js-preprocessor/commit/1d3cb4d)) 88 | 89 | 90 | 91 | 92 | ## [0.0.2](https://github.com/karma-runner/karma-ng-html2js-preprocessor/compare/v0.0.1...v0.0.2) (2013-07-04) 93 | 94 | 95 | ### Bug Fixes 96 | 97 | * handling of the backslash character ([a3e4b06](https://github.com/karma-runner/karma-ng-html2js-preprocessor/commit/a3e4b06)) 98 | 99 | 100 | 101 | 102 | ## [0.0.1](https://github.com/karma-runner/karma-ng-html2js-preprocessor/compare/5b59ac6...v0.0.1) (2013-06-27) 103 | 104 | 105 | ### Features 106 | 107 | * configurable $templateCache key ([5b59ac6](https://github.com/karma-runner/karma-ng-html2js-preprocessor/commit/5b59ac6)), closes [#7](https://github.com/karma-runner/karma-ng-html2js-preprocessor/issues/7) 108 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Please see the [Contributing to Karma] guide for information on contributing to this project. 2 | 3 | [Contributing to Karma]: https://github.com/karma-runner/karma/blob/master/CONTRIBUTING.md 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (C) 2011-2013 Google, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # karma-ng-html2js-preprocessor 2 | 3 | [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/karma-runner/karma-ng-html2js-preprocessor) 4 | [![npm version](https://img.shields.io/npm/v/karma-ng-html2js-preprocessor.svg?style=flat-square)](https://www.npmjs.com/package/karma-ng-html2js-preprocessor) [![npm downloads](https://img.shields.io/npm/dm/karma-ng-html2js-preprocessor.svg?style=flat-square)](https://www.npmjs.com/package/karma-ng-html2js-preprocessor) 5 | 6 | [![Build Status](https://img.shields.io/travis/karma-runner/karma-ng-html2js-preprocessor/master.svg?style=flat-square)](https://travis-ci.org/karma-runner/karma-ng-html2js-preprocessor) [![Dependency Status](https://img.shields.io/david/karma-runner/karma-ng-html2js-preprocessor.svg?style=flat-square)](https://david-dm.org/karma-runner/karma-ng-html2js-preprocessor) [![devDependency Status](https://img.shields.io/david/dev/karma-runner/karma-ng-html2js-preprocessor.svg?style=flat-square)](https://david-dm.org/karma-runner/karma-ng-html2js-preprocessor#info=devDependencies) 7 | 8 | > Preprocessor for converting HTML files to [AngularJS 1.x](http://angularjs.org/) and [Angular 2](http://angular.io/) templates. 9 | 10 | *Note:* If you are looking for a general preprocessor that is not tied to Angular, check out [karma-html2js-preprocessor](https://github.com/karma-runner/karma-html2js-preprocessor). 11 | 12 | ## Installation 13 | 14 | The easiest way is to keep `karma-ng-html2js-preprocessor` as a devDependency in your `package.json`. Just run 15 | 16 | ```bash 17 | $ npm install karma-ng-html2js-preprocessor --save-dev 18 | ``` 19 | 20 | ## Configuration 21 | ```js 22 | // karma.conf.js 23 | module.exports = function(config) { 24 | config.set({ 25 | preprocessors: { 26 | '**/*.html': ['ng-html2js'] 27 | }, 28 | 29 | files: [ 30 | '*.js', 31 | '*.html', 32 | '*.html.ext', 33 | // if you wanna load template files in nested directories, you must use this 34 | '**/*.html' 35 | ], 36 | 37 | // if you have defined plugins explicitly, add karma-ng-html2js-preprocessor 38 | // plugins: [ 39 | // 40 | // 'karma-ng-html2js-preprocessor', 41 | // ] 42 | 43 | ngHtml2JsPreprocessor: { 44 | // strip this from the file path 45 | stripPrefix: 'public/', 46 | stripSuffix: '.ext', 47 | // prepend this to the 48 | prependPrefix: 'served/', 49 | 50 | // or define a custom transform function 51 | // - cacheId returned is used to load template 52 | // module(cacheId) will return template at filepath 53 | cacheIdFromPath: function(filepath) { 54 | // example strips 'public/' from anywhere in the path 55 | // module(app/templates/template.html) => app/public/templates/template.html 56 | var cacheId = filepath.strip('public/', ''); 57 | return cacheId; 58 | }, 59 | 60 | // - setting this option will create only a single module that contains templates 61 | // from all the files, so you can load them all with module('foo') 62 | // - you may provide a function(htmlPath, originalPath) instead of a string 63 | // if you'd like to generate modules dynamically 64 | // htmlPath is a originalPath stripped and/or prepended 65 | // with all provided suffixes and prefixes 66 | moduleName: 'foo' 67 | } 68 | }) 69 | } 70 | ``` 71 | 72 | ### Multiple module names 73 | 74 | Use *function* if more than one module that contains templates is required. 75 | 76 | ```js 77 | // karma.conf.js 78 | module.exports = function(config) { 79 | config.set({ 80 | // ... 81 | 82 | ngHtml2JsPreprocessor: { 83 | // ... 84 | 85 | moduleName: function (htmlPath, originalPath) { 86 | return htmlPath.split('/')[0]; 87 | } 88 | } 89 | }) 90 | } 91 | ``` 92 | 93 | If only some of the templates should be placed in the modules, 94 | return `''`, `null` or `undefined` for those which should not. 95 | 96 | ```js 97 | // karma.conf.js 98 | module.exports = function(config) { 99 | config.set({ 100 | // ... 101 | 102 | ngHtml2JsPreprocessor: { 103 | // ... 104 | 105 | moduleName: function (htmlPath, originalPath) { 106 | var module = htmlPath.split('/')[0]; 107 | return module !== 'tpl' ? module : null; 108 | } 109 | } 110 | }) 111 | } 112 | ``` 113 | 114 | 115 | ## How does it work ? 116 | 117 | This preprocessor converts HTML files into JS strings and generates Angular modules. These modules, when loaded, puts these HTML files into the `$templateCache` and therefore Angular won't try to fetch them from the server. 118 | 119 | For instance this `template.html`... 120 | ```html 121 |
something
122 | ``` 123 | ... will be served as `template.html.js`: 124 | ```js 125 | angular.module('template.html', []).run(function($templateCache) { 126 | $templateCache.put('template.html', '
something
') 127 | }) 128 | ``` 129 | 130 | See the [ng-directive-testing](https://github.com/vojtajina/ng-directive-testing) for a complete example. 131 | 132 | ---- 133 | 134 | ## Angular2 template caching 135 | 136 | For using this preprocessor with Angular 2 templates use `angular: 2` option in the config file. 137 | 138 | ```js 139 | // karma.conf.js 140 | module.exports = function(config) { 141 | config.set({ 142 | // ... 143 | 144 | ngHtml2JsPreprocessor: { 145 | // ... 146 | 147 | angular: 2 148 | } 149 | }) 150 | } 151 | ``` 152 | 153 | The template `template.html`... 154 | ```html 155 |
something
156 | ``` 157 | ... will be served as `template.html.js` that sets the template content in the global $templateCache variable: 158 | ```js 159 | window.$templateCache = window.$templateCache || {} 160 | window.$templateCache['template.html'] = '
something
'; 161 | ``` 162 | 163 | To use the cached templates in your Angular 2 tests use the provider for the Cached XHR implementation - `CACHED_TEMPLATE_PROVIDER` from `angular2/platform/testing/browser`. The following shows the change in `karma-test-shim.js` to use the cached XHR and template cache in all your tests. 164 | ```js 165 | // karma-test-shim.js 166 | ... 167 | System.import('angular2/testing').then(function(testing) { 168 | return System.import('angular2/platform/testing/browser').then(function(providers) { 169 | testing.setBaseTestProviders( 170 | providers.TEST_BROWSER_PLATFORM_PROVIDERS, 171 | [providers.TEST_BROWSER_APPLICATION_PROVIDERS, providers.CACHED_TEMPLATE_PROVIDER]); 172 | }); 173 | }).then(function() { 174 | ... 175 | ``` 176 | 177 | Now when your component under test uses `template.html` in its `templateUrl` the contents of the template will be used from the template cache instead of making a XHR to fetch the contents of the template. This can be useful while writing fakeAsync tests where the component can be loaded synchronously without the need to make a XHR to get the templates. 178 | 179 | --- 180 | 181 | For more information on Karma see the [homepage]. 182 | 183 | 184 | [homepage]: http://karma-runner.github.com 185 | -------------------------------------------------------------------------------- /gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | grunt.initConfig({ 3 | pkgFile: 'package.json', 4 | simplemocha: { 5 | options: { 6 | ui: 'bdd', 7 | reporter: 'dot' 8 | }, 9 | unit: { 10 | src: [ 11 | 'test/**/*.spec.coffee' 12 | ] 13 | } 14 | }, 15 | 'npm-contributors': { 16 | options: { 17 | commitMessage: 'chore: update contributors' 18 | } 19 | }, 20 | conventionalChangelog: { 21 | release: { 22 | options: { 23 | changelogOpts: { 24 | preset: 'angular' 25 | } 26 | }, 27 | src: 'CHANGELOG.md' 28 | } 29 | }, 30 | conventionalGithubReleaser: { 31 | release: { 32 | options: { 33 | auth: { 34 | type: 'oauth', 35 | token: process.env.GH_TOKEN 36 | }, 37 | changelogOpts: { 38 | preset: 'angular' 39 | } 40 | } 41 | } 42 | }, 43 | bump: { 44 | options: { 45 | commitMessage: 'chore: release v%VERSION%', 46 | pushTo: 'upstream', 47 | commitFiles: [ 48 | 'package.json', 49 | 'CHANGELOG.md' 50 | ] 51 | } 52 | }, 53 | eslint: { 54 | target: [ 55 | 'lib/**/*.js', 56 | 'gruntfile.js' 57 | ] 58 | } 59 | }) 60 | 61 | require('load-grunt-tasks')(grunt) 62 | 63 | grunt.registerTask('test', ['simplemocha']) 64 | grunt.registerTask('default', ['eslint', 'test']) 65 | 66 | grunt.registerTask('release', 'Bump the version and publish to NPM.', function (type) { 67 | grunt.task.run([ 68 | 'npm-contributors', 69 | 'bump:' + (type || 'patch') + ':bump-only', 70 | 'conventionalChangelog', 71 | 'bump-commit', 72 | 'conventionalGithubReleaser', 73 | 'npm-publish' 74 | ]) 75 | }) 76 | } 77 | -------------------------------------------------------------------------------- /lib/html2js.js: -------------------------------------------------------------------------------- 1 | var util = require('util') 2 | 3 | var TEMPLATE = "angular.module('%s', []).run(['$templateCache', function($templateCache) {\n" + 4 | " $templateCache.put('%s',\n '%s');\n" + 5 | '}]);\n' 6 | 7 | var SINGLE_MODULE_TPL = '(function(module) {\n' + 8 | 'try {\n' + 9 | " module = angular.module('%s');\n" + 10 | '} catch (e) {\n' + 11 | " module = angular.module('%s', []);\n" + 12 | '}\n' + 13 | "module.run(['$templateCache', function($templateCache) {\n" + 14 | " $templateCache.put('%s',\n '%s');\n" + 15 | '}]);\n' + 16 | '})();\n' 17 | 18 | var REQUIRE_MODULE_TPL = 'require([\'%s\'], function(angular) {%s});\n' 19 | 20 | var ANGULAR2_TPL = 'window.$templateCache = window.$templateCache || {};\n' + 21 | "window.$templateCache['%s'] = '%s';\n" 22 | 23 | var escapeContent = function (content) { 24 | return content.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/\r?\n/g, "\\n' +\n '") 25 | } 26 | 27 | var createHtml2JsPreprocessor = function (logger, basePath, config) { 28 | config = typeof config === 'object' ? config : {} 29 | 30 | var log = logger.create('preprocessor.html2js') 31 | var getModuleName = typeof config.moduleName === 'function' ? config.moduleName : function () { 32 | return config.moduleName 33 | } 34 | var stripPrefix = new RegExp('^' + (config.stripPrefix || '')) 35 | var prependPrefix = config.prependPrefix || '' 36 | var stripSufix = new RegExp((config.stripSuffix || config.stripSufix || '') + '$') 37 | var cacheIdFromPath = config && config.cacheIdFromPath || function (filepath) { 38 | return prependPrefix + filepath.replace(stripPrefix, '').replace(stripSufix, '') 39 | } 40 | var enableRequireJs = config.enableRequireJs 41 | var requireJsAngularId = config.requireJsAngularId || 'angular' 42 | var angular = config.angular || 1 43 | 44 | return function (content, file, done) { 45 | log.debug('Processing "%s".', file.originalPath) 46 | 47 | var originalPath = file.originalPath.replace(basePath + '/', '') 48 | var htmlPath = cacheIdFromPath(originalPath) 49 | var moduleName = getModuleName(htmlPath, originalPath) 50 | 51 | if (!/\.js$/.test(file.path)) { 52 | file.path = file.path + '.js' 53 | } 54 | 55 | var tpl 56 | if (angular === 2 || angular === '2') { 57 | tpl = util.format(ANGULAR2_TPL, htmlPath, escapeContent(content)) 58 | } else { 59 | if (moduleName) { 60 | tpl = util.format(SINGLE_MODULE_TPL, moduleName, moduleName, htmlPath, escapeContent(content)) 61 | } else { 62 | tpl = util.format(TEMPLATE, htmlPath, htmlPath, escapeContent(content)) 63 | } 64 | 65 | if (enableRequireJs) { 66 | tpl = util.format(REQUIRE_MODULE_TPL, requireJsAngularId, tpl) 67 | } 68 | } 69 | 70 | done(tpl) 71 | } 72 | } 73 | 74 | createHtml2JsPreprocessor.$inject = ['logger', 'config.basePath', 'config.ngHtml2JsPreprocessor'] 75 | 76 | module.exports = createHtml2JsPreprocessor 77 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | // PUBLISH DI MODULE 2 | 3 | module.exports = { 4 | 'preprocessor:ng-html2js': ['factory', require('./html2js')] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "karma-ng-html2js-preprocessor", 3 | "version": "1.0.0", 4 | "description": "A Karma plugin. Compile AngularJS templates to JavaScript on the fly.", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "test": "grunt test" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/karma-runner/karma-ng-html2js-preprocessor.git" 12 | }, 13 | "keywords": [ 14 | "karma-plugin", 15 | "karma-preprocessor", 16 | "angularjs", 17 | "angular", 18 | "html2js" 19 | ], 20 | "author": "Vojta Jina ", 21 | "dependencies": {}, 22 | "devDependencies": { 23 | "chai": "^3.3.0", 24 | "eslint": "^1.6.0", 25 | "eslint-config-standard": "^4.4.0", 26 | "eslint-plugin-standard": "^1.3.1", 27 | "grunt": "^0.4.1", 28 | "grunt-auto-release": "^0.0.2", 29 | "grunt-bump": "^0.6.0", 30 | "grunt-conventional-changelog": "^5.0.0", 31 | "grunt-conventional-github-releaser": "^0.5.0", 32 | "grunt-eslint": "^17.2.0", 33 | "grunt-npm": "^0.0.2", 34 | "grunt-simple-mocha": "^0.4", 35 | "load-grunt-tasks": "^3.3.0", 36 | "mocha": "^2.3.3", 37 | "sinon": "^1.17.1" 38 | }, 39 | "peerDependencies": { 40 | "karma": ">=0.9" 41 | }, 42 | "license": "MIT", 43 | "contributors": [ 44 | "Friedel Ziegelmayer ", 45 | "dignifiedquire ", 46 | "Friedel Ziegelmayer ", 47 | "Scott O'Hara ", 48 | "Mark Ethan Trostler ", 49 | "tawez ", 50 | "Levi Thomason ", 51 | "Lukasz Bandzarewicz ", 52 | "BrianLenzo ", 53 | "Alex O'Rielly ", 54 | "Maksim Ryzhikov ", 55 | "Christopher Lowenthal ", 56 | "Mark Trostler ", 57 | "Mike Fisher ", 58 | "Mike Frawley ", 59 | "Murphy McMahon ", 60 | "Pawel Kozlowski ", 61 | "Robin Roestenburg ", 62 | "Sahat Yalkabov ", 63 | "Chirayu Krishnappa ", 64 | "Vikram Subramanian ", 65 | "Charles Hsieh ", 66 | "Jan Dudulski ", 67 | "Lucas Galfasó " 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /test/helpers/template_cache.coffee: -------------------------------------------------------------------------------- 1 | vm = require('vm') 2 | sinon = require('sinon'); 3 | 4 | module.exports = (chai, utils) -> 5 | 6 | class AngularModule 7 | constructor: (@name, @deps) -> 8 | templates = @templates = {} 9 | 10 | run: (block) -> 11 | # Block is an annotation array ["$templateCache", function($templateCache) {..}] 12 | block[1] 13 | put: (id, content) => 14 | @templates[id] = content 15 | 16 | 17 | # Evaluates generated js code fot the template cache 18 | # processedContent - The String to be evaluated 19 | # Returns an object with the following fields 20 | # moduleName - generated module name `angular.module('myApp')...` 21 | # templateId - generated template id `$templateCache.put('id', ...)` 22 | # templateContent - template content `$templateCache.put(...,
cache me!
')` 23 | evaluateTemplate = (processedContent, require=null) -> 24 | modules = {} 25 | 26 | context = 27 | # Mock for AngularJS $templateCache 28 | angular: 29 | module: (name, deps) -> 30 | if deps? then return modules[name] = new AngularModule name, deps 31 | if modules[name] then return modules[name] 32 | throw new Error "Module #{name} does not exists!" 33 | 34 | context.require = (require || sinon.stub()).callsArgWith(1, context.angular) 35 | 36 | vm.runInNewContext processedContent, context 37 | modules 38 | 39 | evaluateAngular2Template = (processedContent) -> 40 | mockWindow = {} 41 | context = 42 | window: mockWindow 43 | 44 | vm.runInNewContext processedContent, context 45 | mockWindow 46 | 47 | # Assert that require is used 48 | chai.Assertion.addMethod 'requireModule', (expectedModuleName) -> 49 | require = sinon.stub() 50 | 51 | code = utils.flag @, 'object' 52 | evaluateTemplate code, require 53 | 54 | sinon.assert.calledWith(require, [expectedModuleName]) 55 | @ 56 | 57 | # Assert that a module with the given name is defined 58 | chai.Assertion.addMethod 'defineModule', (expectedModuleName) -> 59 | code = utils.flag @, 'object' 60 | modules = evaluateTemplate code 61 | module = modules[expectedModuleName] 62 | definedModuleNames = (Object.keys modules).join ', ' 63 | 64 | @assert module?, 65 | "expected to define module '#{expectedModuleName}' but only defined #{definedModuleNames}" 66 | 67 | utils.flag @, 'lastAssertedModule', module 68 | @ 69 | 70 | # Assert that a template with the given id is defined 71 | chai.Assertion.addMethod 'defineTemplateId', (expectedTemplateId) -> 72 | # code = utils.flag @, 'object' 73 | # modules = evaluateTemplate code 74 | module = utils.flag @, 'lastAssertedModule' 75 | 76 | @assert module?, 77 | "you have to assert to.defineModule before asserting to.defineTemplateId" 78 | 79 | templateContent = module.templates[expectedTemplateId] 80 | definedTemplateIds = (Object.keys module.templates).join ', ' 81 | 82 | @assert templateContent?, 83 | "expected to define template '#{expectedTemplateId}' but only defined #{definedTemplateIds}" 84 | 85 | utils.flag @, 'lastAssertedTemplateContent', templateContent 86 | @ 87 | 88 | # Assert that a template with given id was defined in a Angular 2 template 89 | chai.Assertion.addMethod 'defineAngular2TemplateId', (expectedTemplateId) -> 90 | code = utils.flag @, 'object' 91 | mockWindow = evaluateAngular2Template code 92 | 93 | templateCache = mockWindow.$templateCache 94 | @assert templateCache?, 95 | "expected window.$templateCache to be defined but was not defined" 96 | 97 | templateContent = templateCache[expectedTemplateId] 98 | definedTemplateIds = (Object.keys templateCache).join ', ' 99 | @assert templateContent?, 100 | "expected to define template '#{expectedTemplateId}' but only defined #{definedTemplateIds}" 101 | 102 | utils.flag @, 'lastAssertedTemplateContent', templateContent 103 | @ 104 | 105 | # Assert that the cache has a valid content 106 | chai.Assertion.addMethod 'haveContent', (expectedContent) -> 107 | templateContent = utils.flag @, 'lastAssertedTemplateContent' 108 | 109 | @assert templateContent?, 110 | "you have to assert to.defineTemplateId or to.defineAngular2TemplateId " + 111 | "before asserting to.haveContent" 112 | 113 | @assert templateContent is expectedContent, 114 | "expected template content '#{templateContent}' to be '#{expectedContent}'" 115 | -------------------------------------------------------------------------------- /test/html2js.spec.coffee: -------------------------------------------------------------------------------- 1 | describe 'preprocessors html2js', -> 2 | chai = require('chai') 3 | 4 | templateHelpers = require('./helpers/template_cache') 5 | chai.use(templateHelpers) 6 | 7 | expect = chai.expect 8 | 9 | html2js = require '../lib/html2js' 10 | logger = create: -> {debug: ->} 11 | process = null 12 | 13 | # TODO(vojta): refactor this somehow ;-) it's copy pasted from lib/file-list.js 14 | File = (path, mtime) -> 15 | @path = path 16 | @originalPath = path 17 | @contentPath = path 18 | @mtime = mtime 19 | @isUrl = false 20 | 21 | createPreprocessor = (config = {}) -> 22 | html2js logger, '/base', config 23 | 24 | beforeEach -> 25 | process = createPreprocessor() 26 | 27 | it 'should convert html to js code', (done) -> 28 | file = new File '/base/path/file.html' 29 | HTML = 'test me!' 30 | 31 | process HTML, file, (processedContent) -> 32 | expect(processedContent) 33 | .to.defineModule('path/file.html').and 34 | .to.defineTemplateId('path/file.html').and 35 | .to.haveContent HTML 36 | done() 37 | 38 | 39 | it 'should change path to *.js', (done) -> 40 | file = new File '/base/path/file.html' 41 | 42 | process '', file, (processedContent) -> 43 | expect(file.path).to.equal '/base/path/file.html.js' 44 | done() 45 | 46 | it 'should not append *.js to a processed file\'s path more than once', (done) -> 47 | file = new File '/base/path/file.html' 48 | 49 | process '', file, (processedContent) -> 50 | process '', file, (processedContent) -> 51 | expect(file.path).to.equal '/base/path/file.html.js' 52 | done() 53 | 54 | it 'should preserve new lines', (done) -> 55 | file = new File '/base/path/file.html' 56 | 57 | process 'first\nsecond', file, (processedContent) -> 58 | expect(processedContent) 59 | .to.defineModule('path/file.html').and 60 | .to.defineTemplateId('path/file.html').and 61 | .to.haveContent 'first\nsecond' 62 | done() 63 | 64 | 65 | it 'should preserve Windows new lines', (done) -> 66 | file = new File '/base/path/file.html' 67 | 68 | process 'first\r\nsecond', file, (processedContent) -> 69 | expect(processedContent).to.not.contain '\r' 70 | done() 71 | 72 | 73 | it 'should preserve the backslash character', (done) -> 74 | file = new File '/base/path/file.html' 75 | 76 | process 'first\\second', file, (processedContent) -> 77 | expect(processedContent) 78 | .to.defineModule('path/file.html').and 79 | .to.defineTemplateId('path/file.html').and 80 | .to.haveContent 'first\\second' 81 | done() 82 | 83 | 84 | describe 'options', -> 85 | describe 'stripPrefix', -> 86 | beforeEach -> 87 | process = createPreprocessor stripPrefix: 'path/' 88 | 89 | 90 | it 'strips the given prefix from the file path', (done) -> 91 | file = new File '/base/path/file.html' 92 | HTML = '' 93 | 94 | process HTML, file, (processedContent) -> 95 | expect(processedContent) 96 | .to.defineModule('file.html').and 97 | .to.defineTemplateId('file.html').and 98 | .to.haveContent HTML 99 | done() 100 | 101 | 102 | describe 'prependPrefix', -> 103 | beforeEach -> 104 | process = createPreprocessor prependPrefix: 'served/' 105 | 106 | 107 | it 'prepends the given prefix from the file path', (done) -> 108 | file = new File '/base/path/file.html' 109 | HTML = '' 110 | 111 | process HTML, file, (processedContent) -> 112 | expect(processedContent) 113 | .to.defineModule('served/path/file.html').and 114 | .to.defineTemplateId('served/path/file.html').and 115 | .to.haveContent HTML 116 | done() 117 | 118 | 119 | describe 'stripSuffix', -> 120 | beforeEach -> 121 | process = createPreprocessor stripSuffix: '.ext' 122 | 123 | it 'strips the given suffix from the file path', (done) -> 124 | file = new File 'file.html.ext' 125 | HTML = '' 126 | 127 | process HTML, file, (processedContent) -> 128 | expect(processedContent) 129 | .to.defineModule('file.html').and 130 | .to.defineTemplateId('file.html').and 131 | .to.haveContent HTML 132 | done() 133 | 134 | 135 | describe 'stripSufix', -> 136 | beforeEach -> 137 | process = createPreprocessor stripSufix: '.ext' 138 | 139 | 140 | it 'strips the given sufix from the file path', (done) -> 141 | file = new File 'file.html.ext' 142 | HTML = '' 143 | 144 | process HTML, file, (processedContent) -> 145 | expect(processedContent) 146 | .to.defineModule('file.html').and 147 | .to.defineTemplateId('file.html').and 148 | .to.haveContent HTML 149 | done() 150 | 151 | 152 | describe 'cacheIdFromPath', -> 153 | beforeEach -> 154 | process = createPreprocessor 155 | cacheIdFromPath: (filePath) -> "generated_id_for/#{filePath}" 156 | 157 | 158 | it 'invokes custom transform function', (done) -> 159 | file = new File '/base/path/file.html' 160 | HTML = '' 161 | 162 | process HTML, file, (processedContent) -> 163 | expect(processedContent) 164 | .to.defineModule('generated_id_for/path/file.html').and 165 | .to.defineTemplateId('generated_id_for/path/file.html').and 166 | .to.haveContent HTML 167 | done() 168 | 169 | describe 'moduleName', -> 170 | it 'should generate code with a given module name', -> 171 | process = createPreprocessor 172 | moduleName: 'foo' 173 | file1 = new File '/base/tpl/one.html' 174 | HTML1 = 'one' 175 | file2 = new File '/base/tpl/two.html' 176 | HTML2 = 'two' 177 | bothFilesContent = '' 178 | 179 | process HTML1, file1, (processedContent) -> 180 | bothFilesContent += processedContent 181 | 182 | process HTML2, file2, (processedContent) -> 183 | bothFilesContent += processedContent 184 | 185 | # evaluate both files (to simulate multiple files in the browser) 186 | expect(bothFilesContent) 187 | .to.defineModule('foo').and 188 | .to.defineTemplateId('tpl/one.html').and 189 | .to.haveContent(HTML1).and 190 | .to.defineTemplateId('tpl/two.html').and 191 | .to.haveContent(HTML2) 192 | 193 | 194 | it 'should generate code with multiple module names', -> 195 | process = createPreprocessor 196 | moduleName: (htmlPath) -> 197 | module = htmlPath.split('/')[0] 198 | if module != 'tpl' 199 | module 200 | 201 | file1 = new File '/base/app/one.html' 202 | HTML1 = 'one' 203 | file2 = new File '/base/common/two.html' 204 | HTML2 = 'two' 205 | file3 = new File '/base/tpl/three.html' 206 | HTML3 = 'three' 207 | threeFilesContent = '' 208 | 209 | process HTML1, file1, (processedContent) -> 210 | threeFilesContent += processedContent 211 | 212 | process HTML2, file2, (processedContent) -> 213 | threeFilesContent += processedContent 214 | 215 | process HTML3, file3, (processedContent) -> 216 | threeFilesContent += processedContent 217 | 218 | # evaluate three files (to simulate multiple module names) 219 | expect(threeFilesContent) 220 | .to.defineModule('app').and 221 | .to.defineTemplateId('app/one.html').and 222 | .to.haveContent(HTML1).and 223 | .to.defineModule('common').and 224 | .to.defineTemplateId('common/two.html').and 225 | .to.haveContent(HTML2) 226 | .to.defineModule('tpl/three.html').and 227 | .to.defineTemplateId('tpl/three.html').and 228 | .to.haveContent(HTML3) 229 | 230 | describe 'RequireJS', -> 231 | it 'should wrap module with require', (done) -> 232 | process = createPreprocessor 233 | enableRequireJs: true 234 | 235 | file = new File '/base/path/file.html' 236 | HTML = 'test me!' 237 | 238 | process HTML, file, (processedContent) -> 239 | expect(processedContent) 240 | .to.requireModule('angular') 241 | .to.defineModule('path/file.html') 242 | .to.defineTemplateId('path/file.html').and 243 | .to.haveContent HTML 244 | done() 245 | 246 | it 'should use custom angular module ID', (done) -> 247 | process = createPreprocessor 248 | enableRequireJs: true 249 | requireJsAngularId: 'foo' 250 | 251 | file = new File '/base/path/file.html' 252 | HTML = 'test me!' 253 | 254 | process HTML, file, (processedContent) -> 255 | expect(processedContent) 256 | .to.requireModule('foo') 257 | .to.defineModule('path/file.html') 258 | .to.defineTemplateId('path/file.html').and 259 | .to.haveContent HTML 260 | done() 261 | 262 | describe 'angular version 2', -> 263 | it 'should store the template in window.$templateCache', (done) -> 264 | process = createPreprocessor 265 | angular: 2 266 | 267 | file = new File '/base/path/file.html' 268 | HTML = 'test' 269 | 270 | process HTML, file, (processedContent) -> 271 | expect(processedContent) 272 | .to.defineAngular2TemplateId('path/file.html').and 273 | .to.haveContent HTML 274 | done() 275 | --------------------------------------------------------------------------------