Repository: VFK/gulp-html-replace Branch: master Commit: 4b99045040b3 Files: 15 Total size: 37.9 KB Directory structure: gitextract_3frrgmvh/ ├── .gitignore ├── .travis.yml ├── LICENSE ├── appveyor.yml ├── lib/ │ ├── block.js │ ├── common.js │ ├── index.js │ └── parser.js ├── package.json ├── readme.md └── test/ ├── buffer.js ├── expected.html ├── fixture.html ├── null.js └── stream.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ .idea Thumbs.db .DS_Store node_modules coverage ================================================ FILE: .travis.yml ================================================ language: node_js node_js: - "0.10" - "0.11" - "0.12" - "iojs" after_script: - npm run coveralls ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2014 Vladimir Kucherenko 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. ================================================ FILE: appveyor.yml ================================================ environment: matrix: # node.js - nodejs_version: "0.10" - nodejs_version: "0.11" - nodejs_version: "0.12" # io.js - nodejs_version: "1.0" install: - ps: Install-Product node $env:nodejs_version - npm install test_script: - node --version - npm --version - npm test build: off ================================================ FILE: lib/block.js ================================================ 'use strict'; var util = require('util'); var path = require('path'); var slash = require('slash'); var Block = function (config, file, match) { this.replacement = match[0]; this.linefeed = match[1]; this.indent = match[2]; this.beginTag = match[3]; this.taskName = match[4]; this.originalContent = match[5]; this.endTag = match[6]; this.replacements = []; this.config = config; this.template = null; this.file = file; }; Block.prototype.build = function () { if (!this.replacements.length) { return this.config.keepUnassigned ? [this.indent + this.originalContent.trim()] : []; } // get the replacement strings and do replacements for extensions if (this.uniqueExts) { var extname = path.extname(this.file.path); var basename = path.basename(this.file.path, extname); if (this.uniqueExts['%f']) { this.uniqueExts['%f'].value = basename; } if (this.uniqueExts['%e']) { this.uniqueExts['%e'].value = extname; } Object.keys(this.uniqueExts).forEach(function (key) { var unique = this.uniqueExts[key]; this.template = this.template.replace(unique.regex, unique.value); }.bind(this)); } if (this.srcIsNull) { return [this.indent + this.template]; } return this.replacements.map(function (replacement) { if (this.template) { if (Array.isArray(replacement)) { replacement.unshift(this.template); return this.indent + util.format.apply(util, replacement); } else { return this.indent + util.format(this.template, replacement); } } if (this.config.resolvePaths) { var replacementPath = path.resolve(this.file.cwd, replacement); replacement = path.relative(path.dirname(this.file.path), replacementPath); replacement = slash(replacement); } var ext = replacement.split('?')[0].toLowerCase().split('.').pop(); if (ext === 'js') { return util.format('%s', this.indent, replacement); } else if (ext === 'css') { return util.format('%s', this.indent, replacement); } return this.indent + replacement; }.bind(this)); }; Block.prototype.compile = function (tasks) { var task = tasks[this.taskName]; if (task) { this.replacements = task.src; this.template = task.tpl; this.uniqueExts = task.uni; this.srcIsNull = task.srcIsNull; } var buildResult = this.build(); if (this.config.keepBlockTags) { buildResult.unshift(this.indent + this.beginTag); buildResult.push(this.indent + this.endTag); } buildResult.unshift(null); buildResult.push(null); return buildResult.join(this.linefeed); }; module.exports = Block; ================================================ FILE: lib/common.js ================================================ 'use strict'; var Promise = require('bluebird'); var buffer = require('vinyl-buffer'); function isStream(obj) { return obj && typeof obj.pipe === 'function' && typeof obj.on === 'function'; } /** * Takes the src property of the task configuration and deeply "resolves" any vinyl file stream in it by turning * it into a string. * * This function doesn't change the "arborescence" of the given value: all the forms with strings accepted * work with vinyl file streams. * * @returns {Promise} */ function resolveSrcString(srcProperty) { if (Array.isArray(srcProperty)) { // handle multiple tag replacement return Promise.all(srcProperty.map(function (item) { return resolveSrcString(item); })); } else if (isStream(srcProperty)) { return new Promise(function (resolve, reject) { var strings = []; srcProperty.pipe(buffer()) .on('data', function (file) { strings.push(file.contents.toString()); }) .on('error', function(error) { reject(error); this.end(); }) .once('end', function () { resolve(strings); }); }); } else { return Promise.resolve(srcProperty); } } module.exports = { /** * tasks = { * 'task-name': { * 'src': [file1, file2], * 'tpl': '' * }, * .... * } **/ parseTasks: function (options) { options = options || {}; var utilExtensions = /%f|%e/g; var tasksByNames = {}; var tasksPromises = Object.keys(options).map(function (name) { var task = { src: [], tpl: null, uni: {}, srcIsNull: false }; return Promise .resolve() .then(function () { var item = options[name]; var src = typeof item.src !== 'undefined' ? item.src : item; return resolveSrcString(src) .then(function(srcStrings) { task.srcIsNull = srcStrings === null; task.src = task.src.concat(srcStrings); task.tpl = item.tpl; }); }) .then(function () { var result; while (result = utilExtensions.exec(task.tpl)) { var type = result[0]; var unique = {}; if (task.uni[type]) { continue; } unique.regex = new RegExp(result[0], "g"); unique.value = null; task.uni[type] = unique; } }) .then(function () { tasksByNames[name] = task; }); }); return Promise.all(tasksPromises) .then(function() { return tasksByNames; }); }, regexMatchAll: function (string, regexp) { var matches = []; string.replace(regexp, function () { var arr = Array.prototype.slice.call(arguments); matches.push(arr); }); return matches; } }; ================================================ FILE: lib/index.js ================================================ 'use strict'; var clone = require('clone'); var objectAssign = require('object-assign'); var Transform = require('readable-stream/transform'); var common = require('./common'); var Parser = require('./parser'); module.exports = function (options, userConfig) { var tasksPromise = common.parseTasks(options); var config = { keepUnassigned: false, keepBlockTags: false, resolvePaths: false }; if (typeof userConfig === 'boolean') { config.keepUnassigned = userConfig; } else if (typeof userConfig === 'object') { objectAssign(config, userConfig); } return new Transform({ objectMode: true, transform: function (file, enc, callback) { tasksPromise .then(function (tasks) { var parser = new Parser(clone(tasks), config, file); if (file.isBuffer()) { parser.write(file.contents); parser.end(); var contents = new Buffer(0); parser.on('data', function (data) { contents = Buffer.concat([contents, data]); }); parser.once('end', function () { file.contents = contents; callback(null, file); }); return; } if (file.isStream()) { file.contents = file.contents.pipe(parser); } callback(null, file); }) .catch(callback); } }); }; ================================================ FILE: lib/parser.js ================================================ 'use strict'; var util = require('util'); var Transform = require('readable-stream/transform'); var Block = require('./block'); var common = require('./common'); /** * 1 - newline * 2 - indentation * 3 - begin tag * 4 - task name * 5 - original content * 6 - end tag * * @type {RegExp} */ var regex = /(\n?)([ \t]*)()\n?([\s\S]*?)\n?()\n?/ig; function Parser(tasks, config, file) { Transform.call(this); this.tasks = tasks; this.config = config; this.file = file; } util.inherits(Parser, Transform); Parser.prototype._transform = function (chunk, enc, done) { var content = chunk.toString('utf8'); var matches = common.regexMatchAll(content, regex); matches.forEach(function (match) { var block = new Block(this.config, this.file, match); content = content.replace(block.replacement, function () { return block.compile(this.tasks) }.bind(this)); }.bind(this)); done(null, content); }; module.exports = Parser; ================================================ FILE: package.json ================================================ { "name": "gulp-html-replace", "version": "1.6.2", "description": "Replace build blocks in HTML. Like useref but done right.", "keywords": [ "gulpplugin", "html", "replace" ], "files": [ "lib" ], "repository": { "type": "git", "url": "https://github.com/VFK/gulp-html-replace.git" }, "author": { "name": "Vladimir Kucherenko", "email": "kvsoftware@gmail.com" }, "contributors": [ { "name": "Bruce MacNaughton", "email": "bmacnaughton@gmail.com" } ], "main": "./lib/index.js", "scripts": { "test": "mocha", "coverage": "istanbul cover _mocha -- -R dot", "coveralls": "istanbul cover _mocha && istanbul-coveralls" }, "engines": { "node": ">= 0.9" }, "dependencies": { "bluebird": "^3.1.1", "clone": "^1.0.2", "object-assign": "^4.0.1", "readable-stream": "^2.0.4", "slash": "^1.0.0", "vinyl-buffer": "^1.0.0" }, "devDependencies": { "concat-stream": "^1.5.1", "from2-string": "^1.1.0", "gulp-util": "^3.0.7", "istanbul": "^0.4.0", "istanbul-coveralls": "^1.0.3", "mocha": "^2.3.4", "vinyl": "^1.1.0", "vinyl-source-stream": "^1.1.0" }, "license": "MIT" } ================================================ FILE: readme.md ================================================ # gulp-html-replace [![NPM version][npm-image]][npm-url] [![Travis][travis-image]][travis-url] [![AppVeyor][appveyor-image]][appveyor-url] [![Coverage Status][coveralls-image]][coveralls-url] > Replace build blocks in HTML. Like useref but done right.   ### Table of Contents - [Usage](#usage) - [API](#api) - [Example](#example) - [Upgrade](#upgrade) ## Usage Install: ```shell npm install --save-dev gulp-html-replace ``` Put some blocks in your HTML file: ```html Everything here will be replaced ``` `name` is the name of the block. Could consist of letters, digits, underscore ( **_** ) and hyphen ( **-** ) symbols. ## API ### htmlreplace(tasks, options) #### tasks Type: `Object` `{task-name: replacement}` * **task-name** - The name of the block in your HTML. * **replacement** - `String|Array|stream.Readable|Object` The replacement. See examples below. ###### Simple example: ```javascript // Options is a single string htmlreplace({js: 'js/main.js'}) // Options is an array of strings htmlreplace({js: ['js/monster.js', 'js/hero.js']}) ``` >If your options strings ends with `.js` or `.css` they will be replaced by correct script/style tags, so you don't need to specify a template like in the example below. ###### Advanced example: ```javascript // Options is an object htmlreplace({ js: { src: 'img/avatar.png', tpl: '' } }) // Multiple tag replacement htmlreplace({ js: { src: [['data-main.js', 'require-src.js']], tpl: '' } }) ``` * **src** - `String|Array|stream.Readable` Same thing as in simple example. * **tpl** - `String` Template string. Uses [util.format()](http://nodejs.org/api/util.html#util_util_format_format) internally. > In the first example `%s` will be replaced with `img/avatar.png` producing `` as the result. > In the second example `data-main="%s"` and `src="%s"` will be replaced with `data-main.js` and `require-src.js` accordingly, producing `` as the result ###### Extended replacements: ```javascript // Replacement based on the file being processed htmlreplace({ js: { src: null, tpl: '' } }) // Extended replacement combined with standard replacement htmlreplace({ js: { src: 'dir', tpl: '' } }) ``` * **src** - `null|String|Array|stream.Readable` Same as examples above but null if there are no standard replacements in the template. * **tpl** - `String` Template string. Extended replacements do not use `util.format()` and are performed before standard replacements. > In the first example `src` is null because there are no standard replacements. `%f` is replaced with the name (without extension) of the file currently being processed. If the file being processed is `xyzzy.html` the result is ``. > In the second example `src` has been set to the string `'dir'`. Extended replacements are processed first, replacing `%f` with `xyzzy`, then `%s` will be replaced with `dir` resulting in ``. Valid extended replacements are: * **%f** - this will be replaced with the filename, without an extension. * **%e** - this will be replaced with the extension including the `.` character. ###### Stream replacements: Everywhere a string replacement can be given, a stream of vinyl is also accepted. The content of each file will be treated as UTF-8 text and used for replacement. If the stream produces more than a file the behavior is the same as when an array is given. ```javascript // Replacement is a stream htmlreplace({ cssInline: { src: gulp.src('style/main.scss').pipe(sass()), tpl: '' } }) ``` #### options Type: `object` All `false` by default. - {Boolean} **keepUnassigned** - Whether to keep blocks with unused names or remove them. - {Boolean} **keepBlockTags** - Whether to keep `` and `` comments or remove them. - {Boolean} **resolvePaths** - Try to resolve *relative* paths. For example if your `cwd` is ``/``, your html file is `/page/index.html` and you set replacement as `lib/file.js` the result path in that html will be `../lib/file.js` ###### Options example: ```javascript htmlreplace({ js: { src: null, tpl: '' } }, { keepUnassigned: false, keepBlockTags: false, resolvePaths: false }) ``` ## Example index.html: ```html ``` gulpfile.js: ```javascript var gulp = require('gulp'); var htmlreplace = require('gulp-html-replace'); gulp.task('default', function() { gulp.src('index.html') .pipe(htmlreplace({ 'css': 'styles.min.css', 'js': 'js/bundle.min.js' })) .pipe(gulp.dest('build/')); }); ``` Result: ```html ``` ## Upgrade ### From 0.x to 1.x >This version introduces streaming support, less confusing API, new option *keepUnused* and full code overhaul. * If you used single task like this: `htmlreplace('js', 'script.js')` just change it to `htmlreplace({js: 'script.js'})` * If you used single task with template: `htmlreplace('js', 'script.js', '')` change it to `htmlreplace({js: {src: 'script.js', tpl: ''})` * `files` renamed to `src`, see previous example. Rename if needed. ### From 1.1.x to 1.2.x >This version switches to the new way of specifying options which is more future-proof. Before it was `htmlreplace(tasks, keepUnassigned = false)`, now it's `htmlreplace(tasks, {keepUnassigned: false})`. No action required, old syntax will still work, but it is advisable to switch to the new syntax. [npm-url]: https://npmjs.org/package/gulp-html-replace [npm-image]: http://img.shields.io/npm/v/gulp-html-replace.svg [travis-url]: https://travis-ci.org/VFK/gulp-html-replace [travis-image]: https://travis-ci.org/VFK/gulp-html-replace.svg [appveyor-url]: https://ci.appveyor.com/project/VFK/gulp-html-replace [appveyor-image]: https://ci.appveyor.com/api/projects/status/66kwbnis5a1gwp6d?svg=true [coveralls-url]: https://coveralls.io/github/VFK/gulp-html-replace?branch=master [coveralls-image]: https://coveralls.io/repos/VFK/gulp-html-replace/badge.svg?branch=master&service=github ================================================ FILE: test/buffer.js ================================================ 'use strict'; var plugin = require('..'); var fs = require('fs'); var path = require('path'); var File = require('vinyl'); var assert = require('assert'); var stringToStream = require('from2-string'); var source = require('vinyl-source-stream'); function compare(fixture, expected, stream, done) { stream .once('data', function (file) { assert(file.isBuffer()); assert.strictEqual(String(file.contents), expected); done(); }) .end(new File({ base: path.resolve('www'), path: path.resolve('www', 'pages', 'index.html'), contents: fixture })); } describe('Buffer mode', function () { it('should replace blocks', function (done) { var fixture = fs.readFileSync(path.join('test', 'fixture.html')); var expected = fs.readFileSync(path.join('test', 'expected.html'), 'utf8'); var stream = plugin({ css: 'css/combined.css', js_files: ['js/one.js', 'js/two.js?ts=123', 'js/three.js?v=v1.5.3-1-g91cd575'], js_files_tpl: { src: 'js/with_tpl.js', tpl: '' }, js_files_tpl_multiple: { src: ['js/with_tpl.js', 'js/with_tpl_2.js'], tpl: '' }, js_files_tpl_2vars: { src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js']], tpl: '' }, js_files_tpl_2vars_multiple: { src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js'], ['js/with_tpl_2vars1_2.js', 'js/with_tpl_2vars2_2.js']], tpl: '' }, js_files_x_tpl: { src: null, tpl: '' }, js_files_x_tpl_src: { src: 'js', tpl: '' }, js_files_x_tpl_multiple: { src: ['js/with_tpl.js', 'js/with_tpl_2.js'], tpl: '' }, js_files_x_tpl_2vars: { src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js']], tpl: '' }, js_files_x_tpl_2vars_multiple: { src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js'], ['js/with_tpl_2vars1_2.js', 'js/with_tpl_2vars2_2.js']], tpl: '' }, 'lorem-ipsum': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 'stream-simple': stringToStream('Stream simple replacement').pipe(source('fake-vinyl.txt')), 'stream-advanced': { src: stringToStream('Stream advanced replacement').pipe(source('fake-vinyl.txt')) }, 'stream-special': { src: stringToStream('Stream $$ special replacement pattern').pipe(source('fake-vinyl.txt')) } }); compare(fixture, expected, stream, done); }); it('should work with inline html', function (done) { var fixture = ''; var expected = ''; var stream = plugin({css: 'css/combined.css'}); compare(new Buffer(fixture), expected, stream, done); }); it('should not fail if there are no build tags at all', function (done) { var fixture = ''; var stream = plugin({css: 'css/combined.css'}); compare(new Buffer(fixture), fixture, stream, done); }); describe('Options', function () { describe('keepUnassigned', function () { it('Should keep empty blocks', function (done) { var fixture = '\n\nSome text\n\n'; var expected = '\nSome text\n'; var stream = plugin({}, {keepUnassigned: true}); compare(new Buffer(fixture), expected, stream, done); }); it('Should remove empty blocks', function (done) { var fixture = '\n\nSome text\n\n'; var expected = '\n'; var stream = plugin(); compare(new Buffer(fixture), expected, stream, done); }); }); describe('keepBlockTags', function () { it('Should keep placeholder tags without arguments', function (done) { var fixture = '\n\nSome text\n\n'; var expected = '\n\n\n'; var stream = plugin({}, {keepBlockTags: true}); compare(new Buffer(fixture), expected, stream, done); }); it('Should keep placeholder tags with arguments', function (done) { var fixture = '\n\nSome text\n\n'; var expected = '\n\nipsum\n\n'; var stream = plugin({lorem: 'ipsum'}, {keepBlockTags: true}); compare(new Buffer(fixture), expected, stream, done); }); it('Should remove placeholder tags without arguments', function (done) { var fixture = '\n\nSome text\n\n'; var expected = '\n'; var stream = plugin(); compare(new Buffer(fixture), expected, stream, done); }); it('Should remove placeholder tags with arguments', function (done) { var fixture = '\n\nSome text\n\n'; var expected = '\nipsum\n'; var stream = plugin({lorem: 'ipsum'}); compare(new Buffer(fixture), expected, stream, done); }); it('Should keep indentation', function (done) { var fixture = '\n \n Some text\n \n'; var expected = '\n \n \n'; var stream = plugin({}, {keepBlockTags: true}); compare(new Buffer(fixture), expected, stream, done); }); }); describe('resolvePaths', function () { it('Should resolve relative paths', function (done) { var fixture = '\n\n\n\n'; var expected = '\n\n'; var stream = plugin({js: 'lib/script.js'}, {resolvePaths: true}); compare(new Buffer(fixture), expected, stream, done); }); }); }); describe('Legacy versions', function () { it('[version <1.2] should keep empty blocks (keepUnassigned = true)', function (done) { var fixture = '\n\nThis should be removed if "keepUnassigned" is false\n\n'; var expected = '\nThis should be removed if "keepUnassigned" is false\n'; var stream = plugin({}, true); compare(new Buffer(fixture), expected, stream, done); }); it('[version <1.2] should remove empty blocks (keepUnassigned = false)', function (done) { var fixture = '\n\nThis should be removed if "keepUnassigned" is false\n\n'; var expected = '\n'; var stream = plugin(); compare(new Buffer(fixture), expected, stream, done); }); }); }); ================================================ FILE: test/expected.html ================================================ Test file Lorem ipsum dolor sit amet, consectetur adipiscing elit. Stream simple replacement Stream advanced replacement Stream $$ special replacement pattern ================================================ FILE: test/fixture.html ================================================ Test file ================================================ FILE: test/null.js ================================================ 'use strict'; var plugin = require('..'); var File = require('vinyl'); var assert = require('assert'); describe('null files', function () { it('should be passed through', function (done) { plugin() .once('data', function (file) { assert(file.isNull()); done(); }) .end(new File({contents: null})); }); }); ================================================ FILE: test/stream.js ================================================ 'use strict'; var plugin = require('..'); var fs = require('fs'); var path = require('path'); var File = require('vinyl'); var assert = require('assert'); var concatStream = require('concat-stream'); var stringToStream = require('from2-string'); var source = require('vinyl-source-stream'); function compare(fixture, expected, stream, done) { var fakeFile = new File({ base: path.resolve('www'), path: path.resolve('www', 'pages', 'index.html'), contents: fixture }); stream.write(fakeFile); stream.once('data', function (file) { assert(file.isStream()); file.contents.pipe(concatStream({encoding: 'string'}, function (data) { assert.equal(data, expected); done(); })); }); } describe('Stream mode', function () { it('should replace blocks', function (done) { var fixture = fs.createReadStream(path.join('test', 'fixture.html')); var expected = fs.readFileSync(path.join('test', 'expected.html'), 'utf8'); var stream = plugin({ css: 'css/combined.css', js_files: ['js/one.js', 'js/two.js?ts=123', 'js/three.js?v=v1.5.3-1-g91cd575'], js_files_tpl: { src: 'js/with_tpl.js', tpl: '' }, js_files_tpl_multiple: { src: ['js/with_tpl.js', 'js/with_tpl_2.js'], tpl: '' }, js_files_tpl_2vars: { src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js']], tpl: '' }, js_files_tpl_2vars_multiple: { src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js'], ['js/with_tpl_2vars1_2.js', 'js/with_tpl_2vars2_2.js']], tpl: '' }, js_files_x_tpl: { src: null, tpl: '' }, js_files_x_tpl_src: { src: 'js', tpl: '' }, js_files_x_tpl_multiple: { src: ['js/with_tpl.js', 'js/with_tpl_2.js'], tpl: '' }, js_files_x_tpl_2vars: { src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js']], tpl: '' }, js_files_x_tpl_2vars_multiple: { src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js'], ['js/with_tpl_2vars1_2.js', 'js/with_tpl_2vars2_2.js']], tpl: '' }, 'lorem-ipsum': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 'stream-simple': stringToStream('Stream simple replacement').pipe(source('fake-vinyl.txt')), 'stream-advanced': { src: stringToStream('Stream advanced replacement').pipe(source('fake-vinyl.txt')) }, 'stream-special': { src: stringToStream('Stream $$ special replacement pattern').pipe(source('fake-vinyl.txt')) } }); compare(fixture, expected, stream, done); }); it('should work with inline html', function (done) { var fixture = ''; var expected = ''; var stream = plugin({css: 'css/combined.css'}); compare(stringToStream(fixture), expected, stream, done); }); it('should not fail if there are no build tags at all', function (done) { var fixture = ''; var stream = plugin({css: 'css/combined.css'}); compare(stringToStream(fixture), fixture, stream, done); }); describe('Options', function () { describe('keepUnassigned', function () { it('Should keep empty blocks', function (done) { var fixture = '\n\nSome text\n\n'; var expected = '\nSome text\n'; var stream = plugin({}, {keepUnassigned: true}); compare(stringToStream(fixture), expected, stream, done); }); it('Should remove empty blocks', function (done) { var fixture = '\n\nSome text\n\n'; var expected = '\n'; var stream = plugin(); compare(stringToStream(fixture), expected, stream, done); }); }); describe('keepBlockTags', function () { it('Should keep placeholder tags without arguments', function (done) { var fixture = '\n\nSome text\n\n'; var expected = '\n\n\n'; var stream = plugin({}, {keepBlockTags: true}); compare(stringToStream(fixture), expected, stream, done); }); it('Should keep placeholder tags with arguments', function (done) { var fixture = '\n\nSome text\n\n'; var expected = '\n\nipsum\n\n'; var stream = plugin({lorem: 'ipsum'}, {keepBlockTags: true}); compare(stringToStream(fixture), expected, stream, done); }); it('Should remove placeholder tags without arguments', function (done) { var fixture = '\n\nSome text\n\n'; var expected = '\n'; var stream = plugin(); compare(stringToStream(fixture), expected, stream, done); }); it('Should remove placeholder tags with arguments', function (done) { var fixture = '\n\nSome text\n\n'; var expected = '\nipsum\n'; var stream = plugin({lorem: 'ipsum'}); compare(stringToStream(fixture), expected, stream, done); }); it('Should keep indentation', function (done) { var fixture = '\n \n Some text\n \n'; var expected = '\n \n \n'; var stream = plugin({}, {keepBlockTags: true}); compare(stringToStream(fixture), expected, stream, done); }); }); describe('resolvePaths', function () { it('Should resolve relative paths', function (done) { var fixture = '\n\n\n\n'; var expected = '\n\n'; var stream = plugin({js: 'lib/script.js'}, {resolvePaths: true}); compare(stringToStream(fixture), expected, stream, done); }); }); }); describe('Legacy versions', function () { it('[version <1.2] should keep empty blocks (keepUnused = true)', function (done) { var fixture = '\n\nThis should not be removed\n\n'; var expected = '\nThis should not be removed\n'; var stream = plugin({}, true); compare(stringToStream(fixture), expected, stream, done); }); it('[version <1.2] should remove empty blocks (keepUnused = false)', function (done) { var fixture = '\n\nThis should be removed\n\n'; var expected = '\n'; var stream = plugin(); compare(stringToStream(fixture), expected, stream, done); }); }); });