[
  {
    "path": ".gitignore",
    "content": ".idea\nThumbs.db\n.DS_Store\nnode_modules\ncoverage\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"0.10\"\n  - \"0.11\"\n  - \"0.12\"\n  - \"iojs\"\nafter_script:\n  - npm run coveralls\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2014 Vladimir Kucherenko <kvsoftware@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "appveyor.yml",
    "content": "environment:\n  matrix:\n  # node.js\n  - nodejs_version: \"0.10\"\n  - nodejs_version: \"0.11\"\n  - nodejs_version: \"0.12\"\n  # io.js\n  - nodejs_version: \"1.0\"\n\ninstall:\n  - ps: Install-Product node $env:nodejs_version\n  - npm install\n\ntest_script:\n  - node --version\n  - npm --version\n  - npm test\n\nbuild: off\n"
  },
  {
    "path": "lib/block.js",
    "content": "'use strict';\n\nvar util = require('util');\nvar path = require('path');\nvar slash = require('slash');\n\nvar Block = function (config, file, match) {\n    this.replacement = match[0];\n    this.linefeed = match[1];\n    this.indent = match[2];\n    this.beginTag = match[3];\n    this.taskName = match[4];\n    this.originalContent = match[5];\n    this.endTag = match[6];\n\n    this.replacements = [];\n    this.config = config;\n    this.template = null;\n    this.file = file;\n};\n\nBlock.prototype.build = function () {\n    if (!this.replacements.length) {\n        return this.config.keepUnassigned ? [this.indent + this.originalContent.trim()] : [];\n    }\n\n    // get the replacement strings and do replacements for extensions\n    if (this.uniqueExts) {\n        var extname = path.extname(this.file.path);\n        var basename = path.basename(this.file.path, extname);\n\n        if (this.uniqueExts['%f']) {\n            this.uniqueExts['%f'].value = basename;\n        }\n        if (this.uniqueExts['%e']) {\n            this.uniqueExts['%e'].value = extname;\n        }\n\n        Object.keys(this.uniqueExts).forEach(function (key) {\n            var unique = this.uniqueExts[key];\n            this.template = this.template.replace(unique.regex, unique.value);\n        }.bind(this));\n    }\n\n    if (this.srcIsNull) {\n        return [this.indent + this.template];\n    }\n\n    return this.replacements.map(function (replacement) {\n        if (this.template) {\n            if (Array.isArray(replacement)) {\n                replacement.unshift(this.template);\n                return this.indent + util.format.apply(util, replacement);\n            } else {\n                return this.indent + util.format(this.template, replacement);\n            }\n        }\n\n        if (this.config.resolvePaths) {\n            var replacementPath = path.resolve(this.file.cwd, replacement);\n            replacement = path.relative(path.dirname(this.file.path), replacementPath);\n            replacement = slash(replacement);\n        }\n\n        var ext = replacement.split('?')[0].toLowerCase().split('.').pop();\n\n        if (ext === 'js') {\n            return util.format('%s<script src=\"%s\"></script>', this.indent, replacement);\n        } else if (ext === 'css') {\n            return util.format('%s<link rel=\"stylesheet\" href=\"%s\">', this.indent, replacement);\n        }\n        return this.indent + replacement;\n    }.bind(this));\n};\n\nBlock.prototype.compile = function (tasks) {\n    var task = tasks[this.taskName];\n    \n    if (task) {\n        this.replacements = task.src;\n        this.template = task.tpl;\n        this.uniqueExts = task.uni;\n        this.srcIsNull = task.srcIsNull;\n    }\n\n    var buildResult = this.build();\n\n    if (this.config.keepBlockTags) {\n        buildResult.unshift(this.indent + this.beginTag);\n        buildResult.push(this.indent + this.endTag);\n    }\n\n    buildResult.unshift(null);\n    buildResult.push(null);\n\n    return buildResult.join(this.linefeed);\n};\n\nmodule.exports = Block;\n"
  },
  {
    "path": "lib/common.js",
    "content": "'use strict';\n\nvar Promise = require('bluebird');\nvar buffer = require('vinyl-buffer');\n\nfunction isStream(obj) {\n    return obj && typeof obj.pipe === 'function' && typeof obj.on === 'function';\n}\n\n/**\n * Takes the src property of the task configuration and deeply \"resolves\" any vinyl file stream in it by turning\n * it into a string.\n *\n * This function doesn't change the \"arborescence\" of the given value: all the forms with strings accepted\n * work with vinyl file streams.\n *\n * @returns {Promise}\n */\nfunction resolveSrcString(srcProperty) {\n    if (Array.isArray(srcProperty)) {\n        // handle multiple tag replacement\n        return Promise.all(srcProperty.map(function (item) {\n            return resolveSrcString(item);\n        }));\n    } else if (isStream(srcProperty)) {\n        return new Promise(function (resolve, reject) {\n            var strings = [];\n\n            srcProperty.pipe(buffer())\n                .on('data', function (file) {\n                    strings.push(file.contents.toString());\n                })\n                .on('error', function(error) {\n                    reject(error);\n                    this.end();\n                })\n                .once('end', function () {\n                    resolve(strings);\n                });\n        });\n    } else {\n        return Promise.resolve(srcProperty);\n    }\n}\n\nmodule.exports = {\n    /**\n     * tasks = {\n     *     'task-name': {\n     *         'src': [file1, file2],\n     *         'tpl': '<script src=\"%s\"></script>'\n     *     },\n     *     ....\n     * }\n     **/\n    parseTasks: function (options) {\n        options = options || {};\n\n        var utilExtensions = /%f|%e/g;\n        var tasksByNames = {};\n\n        var tasksPromises = Object.keys(options).map(function (name) {\n\n            var task = {\n                src: [],\n                tpl: null,\n                uni: {},\n                srcIsNull: false\n            };\n\n            return Promise\n                .resolve()\n                .then(function () {\n                    var item = options[name];\n                    var src = typeof item.src !== 'undefined' ? item.src : item;\n\n                    return resolveSrcString(src)\n                      .then(function(srcStrings) {\n                          task.srcIsNull = srcStrings === null;\n                          task.src = task.src.concat(srcStrings);\n                          task.tpl = item.tpl;\n                      });\n                })\n                .then(function () {\n                    var result;\n\n                    while (result = utilExtensions.exec(task.tpl)) {\n                        var type = result[0];\n                        var unique = {};\n\n                        if (task.uni[type]) {\n                            continue;\n                        }\n\n                        unique.regex = new RegExp(result[0], \"g\");\n                        unique.value = null;\n                        task.uni[type] = unique;\n                    }\n                })\n                .then(function () {\n                    tasksByNames[name] = task;\n                });\n        });\n\n        return Promise.all(tasksPromises)\n            .then(function() {\n               return tasksByNames;\n        });\n    },\n\n    regexMatchAll: function (string, regexp) {\n        var matches = [];\n        string.replace(regexp, function () {\n            var arr = Array.prototype.slice.call(arguments);\n            matches.push(arr);\n        });\n        return matches;\n    }\n};\n"
  },
  {
    "path": "lib/index.js",
    "content": "'use strict';\n\nvar clone = require('clone');\nvar objectAssign = require('object-assign');\nvar Transform = require('readable-stream/transform');\nvar common = require('./common');\nvar Parser = require('./parser');\n\nmodule.exports = function (options, userConfig) {\n    var tasksPromise = common.parseTasks(options);\n\n    var config = {\n        keepUnassigned: false,\n        keepBlockTags: false,\n        resolvePaths: false\n    };\n\n    if (typeof userConfig === 'boolean') {\n        config.keepUnassigned = userConfig;\n    } else if (typeof userConfig === 'object') {\n        objectAssign(config, userConfig);\n    }\n\n    return new Transform({\n        objectMode: true,\n        transform: function (file, enc, callback) {\n            tasksPromise\n                .then(function (tasks) {\n\n                    var parser = new Parser(clone(tasks), config, file);\n\n                    if (file.isBuffer()) {\n                        parser.write(file.contents);\n                        parser.end();\n\n                        var contents = new Buffer(0);\n                        parser.on('data', function (data) {\n                            contents = Buffer.concat([contents, data]);\n                        });\n                        parser.once('end', function () {\n                            file.contents = contents;\n                            callback(null, file);\n                        });\n                        return;\n                    }\n\n                    if (file.isStream()) {\n                        file.contents = file.contents.pipe(parser);\n                    }\n\n                    callback(null, file);\n                })\n            .catch(callback);\n        }\n    });\n};\n"
  },
  {
    "path": "lib/parser.js",
    "content": "'use strict';\n\nvar util = require('util');\nvar Transform = require('readable-stream/transform');\nvar Block = require('./block');\nvar common = require('./common');\n\n/**\n * 1 - newline\n * 2 - indentation\n * 3 - begin tag\n * 4 - task name\n * 5 - original content\n * 6 - end tag\n *\n * @type {RegExp}\n */\nvar regex = /(\\n?)([ \\t]*)(<!--\\s*build:(\\w+(?:-\\w+)*)\\s*-->)\\n?([\\s\\S]*?)\\n?(<!--\\s*endbuild\\s*-->)\\n?/ig;\n\nfunction Parser(tasks, config, file) {\n    Transform.call(this);\n\n    this.tasks = tasks;\n    this.config = config;\n    this.file = file;\n}\nutil.inherits(Parser, Transform);\n\nParser.prototype._transform = function (chunk, enc, done) {\n    var content = chunk.toString('utf8');\n\n    var matches = common.regexMatchAll(content, regex);\n    matches.forEach(function (match) {\n        var block = new Block(this.config, this.file, match);\n        content = content.replace(block.replacement, function () {\n            return block.compile(this.tasks)\n        }.bind(this));\n    }.bind(this));\n\n    done(null, content);\n};\n\nmodule.exports = Parser;\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"gulp-html-replace\",\n  \"version\": \"1.6.2\",\n  \"description\": \"Replace build blocks in HTML. Like useref but done right.\",\n  \"keywords\": [\n    \"gulpplugin\",\n    \"html\",\n    \"replace\"\n  ],\n  \"files\": [\n    \"lib\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/VFK/gulp-html-replace.git\"\n  },\n  \"author\": {\n    \"name\": \"Vladimir Kucherenko\",\n    \"email\": \"kvsoftware@gmail.com\"\n  },\n  \"contributors\": [\n    {\n      \"name\": \"Bruce MacNaughton\",\n      \"email\": \"bmacnaughton@gmail.com\"\n    }\n  ],\n  \"main\": \"./lib/index.js\",\n  \"scripts\": {\n    \"test\": \"mocha\",\n    \"coverage\": \"istanbul cover _mocha -- -R dot\",\n    \"coveralls\": \"istanbul cover _mocha && istanbul-coveralls\"\n  },\n  \"engines\": {\n    \"node\": \">= 0.9\"\n  },\n  \"dependencies\": {\n    \"bluebird\": \"^3.1.1\",\n    \"clone\": \"^1.0.2\",\n    \"object-assign\": \"^4.0.1\",\n    \"readable-stream\": \"^2.0.4\",\n    \"slash\": \"^1.0.0\",\n    \"vinyl-buffer\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"concat-stream\": \"^1.5.1\",\n    \"from2-string\": \"^1.1.0\",\n    \"gulp-util\": \"^3.0.7\",\n    \"istanbul\": \"^0.4.0\",\n    \"istanbul-coveralls\": \"^1.0.3\",\n    \"mocha\": \"^2.3.4\",\n    \"vinyl\": \"^1.1.0\",\n    \"vinyl-source-stream\": \"^1.1.0\"\n  },\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "readme.md",
    "content": "# 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]\n\n> Replace build blocks in HTML. Like useref but done right.\n \n\n### Table of Contents\n\n- [Usage](#usage)\n- [API](#api)\n- [Example](#example)\n- [Upgrade](#upgrade)\n\n\n## Usage\nInstall:\n```shell\nnpm install --save-dev gulp-html-replace\n```\n\nPut some blocks in your HTML file:\n```html\n<!-- build:<name> -->\nEverything here will be replaced\n<!-- endbuild -->\n```\n`name` is the name of the block. Could consist of letters, digits, underscore ( **_** ) and hyphen ( **-** ) symbols.\n\n## API\n### htmlreplace(tasks, options)\n\n#### tasks\nType: `Object` `{task-name: replacement}`\n\n* **task-name** - The name of the block in your HTML.\n* **replacement** - `String|Array|stream.Readable|Object` The replacement. See examples below.\n\n###### Simple example:\n```javascript\n// Options is a single string\nhtmlreplace({js: 'js/main.js'})\n\n// Options is an array of strings\nhtmlreplace({js: ['js/monster.js', 'js/hero.js']})\n```\n>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.\n\n###### Advanced example:\n```javascript\n// Options is an object\nhtmlreplace({\n  js: {\n    src: 'img/avatar.png',\n    tpl: '<img src=\"%s\" align=\"left\" />'\n  }\n})\n\n// Multiple tag replacement\nhtmlreplace({\n  js: {\n    src: [['data-main.js', 'require-src.js']],\n    tpl: '<script data-main=\"%s\" src=\"%s\"></script>'\n  }\n})\n```\n* **src** - `String|Array|stream.Readable` Same thing as in simple example.\n* **tpl** - `String` Template string. Uses [util.format()](http://nodejs.org/api/util.html#util_util_format_format) internally.\n\n> In the first example `%s` will be replaced with `img/avatar.png` producing `<img src=\"img/avatar.png\" align=\"left\">` as the result.\n\n> In the second example `data-main=\"%s\"` and `src=\"%s\"` will be replaced with `data-main.js` and `require-src.js` accordingly, producing `<script data-main=\"data-main.js\" src=\"require-src.js\"></script>` as the result\n\n###### Extended replacements:\n```javascript\n// Replacement based on the file being processed\nhtmlreplace({\n  js: {\n    src: null,\n    tpl: '<script src=\"%f\".js></script>'\n  }\n})\n// Extended replacement combined with standard replacement\nhtmlreplace({\n  js: {\n    src: 'dir',\n    tpl: '<script src=\"%s/%f\".js\"></script>'\n  }\n})\n\n```\n* **src** - `null|String|Array|stream.Readable` Same as examples above but null if there are no standard replacements in the template.\n* **tpl** - `String` Template string. Extended replacements do not use `util.format()` and are performed before standard replacements.\n\n> 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 `<script src=\"xyzzy.js\"></script>`.\n\n> 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 `<script src=\"dir/xyzzy.js\"></script>`.\n\nValid extended replacements are:\n\n* **%f** - this will be replaced with the filename, without an extension.\n* **%e** - this will be replaced with the extension including the `.` character.\n\n###### Stream replacements:\nEverywhere 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.\n```javascript\n// Replacement is a stream\nhtmlreplace({\n  cssInline: {\n    src: gulp.src('style/main.scss').pipe(sass()),\n    tpl: '<style>%s</style>'\n  }\n})\n\n```\n\n#### options\nType: `object`\n\nAll `false` by default.\n\n- {Boolean} **keepUnassigned** - Whether to keep blocks with unused names or remove them.\n- {Boolean} **keepBlockTags** - Whether to keep `<!-- build -->` and `<!-- endbuild -->` comments or remove them.\n- {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`\n\n###### Options example:\n```javascript\nhtmlreplace({\n  js: {\n    src: null,\n    tpl: '<script src=\"%f\".js></script>'\n  }\n}, {\n  keepUnassigned: false,\n  keepBlockTags: false,\n  resolvePaths: false\n})\n```\n\n## Example\nindex.html:\n\n```html\n<!DOCTYPE html>\n<html>\n    <head>\n\n    <!-- build:css -->\n    <link rel=\"stylesheet\" href=\"css/normalize.css\">\n    <link rel=\"stylesheet\" href=\"css/main.css\">\n    <!-- endbuild -->\n\n    </head>\n    <body>\n\n    <!-- build:js -->\n    <script src=\"js/player.js\"></script>\n    <script src=\"js/monster.js\"></script>\n    <script src=\"js/world.js\"></script>\n    <!-- endbuild -->\n```\n\ngulpfile.js:\n\n```javascript\nvar gulp = require('gulp');\nvar htmlreplace = require('gulp-html-replace');\n\ngulp.task('default', function() {\n  gulp.src('index.html')\n    .pipe(htmlreplace({\n        'css': 'styles.min.css',\n        'js': 'js/bundle.min.js'\n    }))\n    .pipe(gulp.dest('build/'));\n});\n```\n\nResult:\n\n```html\n<!DOCTYPE html>\n<html>\n    <head>\n\n    <link rel=\"stylesheet\" href=\"styles.min.css\">\n\n    </head>\n    <body>\n\n    <script src=\"js/bundle.min.js\"></script>\n```\n\n## Upgrade\n\n### From 0.x to 1.x\n>This version introduces streaming support, less confusing API, new option *keepUnused* and full code overhaul.\n* If you used single task like this: `htmlreplace('js', 'script.js')` just change it to `htmlreplace({js: 'script.js'})`\n* If you used single task with template: `htmlreplace('js', 'script.js', '<script=\"%s\">')` change it to `htmlreplace({js: {src: 'script.js', tpl: '<script=\"%s\">'})`\n* `files` renamed to `src`, see previous example. Rename if needed.\n\n### From 1.1.x to 1.2.x\n>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})`.\nNo action required, old syntax will still work, but it is advisable to switch to the new syntax.\n\n[npm-url]: https://npmjs.org/package/gulp-html-replace\n[npm-image]: http://img.shields.io/npm/v/gulp-html-replace.svg\n[travis-url]: https://travis-ci.org/VFK/gulp-html-replace\n[travis-image]: https://travis-ci.org/VFK/gulp-html-replace.svg\n[appveyor-url]: https://ci.appveyor.com/project/VFK/gulp-html-replace\n[appveyor-image]: https://ci.appveyor.com/api/projects/status/66kwbnis5a1gwp6d?svg=true\n[coveralls-url]: https://coveralls.io/github/VFK/gulp-html-replace?branch=master\n[coveralls-image]: https://coveralls.io/repos/VFK/gulp-html-replace/badge.svg?branch=master&service=github\n"
  },
  {
    "path": "test/buffer.js",
    "content": "'use strict';\n\nvar plugin = require('..');\nvar fs = require('fs');\nvar path = require('path');\nvar File = require('vinyl');\nvar assert = require('assert');\nvar stringToStream = require('from2-string');\nvar source = require('vinyl-source-stream');\n\nfunction compare(fixture, expected, stream, done) {\n    stream\n    .once('data', function (file) {\n        assert(file.isBuffer());\n        assert.strictEqual(String(file.contents), expected);\n        done();\n    })\n    .end(new File({\n        base: path.resolve('www'),\n        path: path.resolve('www', 'pages', 'index.html'),\n        contents: fixture\n    }));\n}\n\ndescribe('Buffer mode', function () {\n    it('should replace blocks', function (done) {\n        var fixture = fs.readFileSync(path.join('test', 'fixture.html'));\n        var expected = fs.readFileSync(path.join('test', 'expected.html'), 'utf8');\n\n        var stream = plugin({\n            css: 'css/combined.css',\n            js_files: ['js/one.js', 'js/two.js?ts=123', 'js/three.js?v=v1.5.3-1-g91cd575'],\n            js_files_tpl: {\n                src: 'js/with_tpl.js',\n                tpl: '<script src=\"%s\"></script>'\n            },\n            js_files_tpl_multiple: {\n                src: ['js/with_tpl.js', 'js/with_tpl_2.js'],\n                tpl: '<script src=\"%s\"></script>'\n            },\n            js_files_tpl_2vars: {\n                src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js']],\n                tpl: '<script data-main=\"%s\" src=\"%s\"></script>'\n            },\n            js_files_tpl_2vars_multiple: {\n                src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js'], ['js/with_tpl_2vars1_2.js', 'js/with_tpl_2vars2_2.js']],\n                tpl: '<script data-main=\"%s\" src=\"%s\"></script>'\n            },\n            js_files_x_tpl: {\n                src: null,\n                tpl: '<script src=\"js/%f.min.js\"></script>'\n            },\n            js_files_x_tpl_src: {\n                src: 'js',\n                tpl: '<script src=\"%s/%f.min.js\"></script>'\n            },\n            js_files_x_tpl_multiple: {\n                src: ['js/with_tpl.js', 'js/with_tpl_2.js'],\n                tpl: '<script data-src=\"%f.data\" src=\"%s\"></script>'\n            },\n            js_files_x_tpl_2vars: {\n                src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js']],\n                tpl: '<script data-src=\"%f%e\" data-main=\"%s\" src=\"%s\"></script>'\n            },\n            js_files_x_tpl_2vars_multiple: {\n                src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js'], ['js/with_tpl_2vars1_2.js', 'js/with_tpl_2vars2_2.js']],\n                tpl: '<script data-src=\"%f.data\" data-main=\"%s\" src=\"%s\"></script>'\n            },\n            'lorem-ipsum': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',\n            'stream-simple': stringToStream('Stream simple replacement').pipe(source('fake-vinyl.txt')),\n            'stream-advanced': {\n                src:  stringToStream('Stream advanced replacement').pipe(source('fake-vinyl.txt'))\n            },\n            'stream-special': {\n                src: stringToStream('Stream $$ special replacement pattern').pipe(source('fake-vinyl.txt'))\n            }\n        });\n\n        compare(fixture, expected, stream, done);\n    });\n\n    it('should work with inline html', function (done) {\n        var fixture = '<!DOCTYPE html><head><!-- build:css --><link rel=\"stylesheet\" href=\"_index.prefix.css\"><!-- endbuild --></head>';\n        var expected = '<!DOCTYPE html><head><link rel=\"stylesheet\" href=\"css/combined.css\"></head>';\n\n        var stream = plugin({css: 'css/combined.css'});\n        compare(new Buffer(fixture), expected, stream, done);\n    });\n\n    it('should not fail if there are no build tags at all', function (done) {\n        var fixture = '<!DOCTYPE html><head><link rel=\"stylesheet\" href=\"_index.prefix.css\"></head>';\n\n        var stream = plugin({css: 'css/combined.css'});\n        compare(new Buffer(fixture), fixture, stream, done);\n    });\n\n    describe('Options', function () {\n\n        describe('keepUnassigned', function () {\n            it('Should keep empty blocks', function (done) {\n                var fixture = '<html>\\n<!-- build:js -->\\nSome text\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\nSome text\\n</html>';\n\n                var stream = plugin({}, {keepUnassigned: true});\n                compare(new Buffer(fixture), expected, stream, done);\n            });\n\n            it('Should remove empty blocks', function (done) {\n                var fixture = '<html>\\n<!-- build:js -->\\nSome text\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\n</html>';\n\n                var stream = plugin();\n                compare(new Buffer(fixture), expected, stream, done);\n            });\n        });\n\n        describe('keepBlockTags', function () {\n            it('Should keep placeholder tags without arguments', function (done) {\n                var fixture = '<html>\\n<!-- build:js -->\\nSome text\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\n<!-- build:js -->\\n<!-- endbuild -->\\n</html>';\n\n                var stream = plugin({}, {keepBlockTags: true});\n                compare(new Buffer(fixture), expected, stream, done);\n            });\n\n            it('Should keep placeholder tags with arguments', function (done) {\n                var fixture = '<html>\\n<!-- build:lorem -->\\nSome text\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\n<!-- build:lorem -->\\nipsum\\n<!-- endbuild -->\\n</html>';\n\n                var stream = plugin({lorem: 'ipsum'}, {keepBlockTags: true});\n                compare(new Buffer(fixture), expected, stream, done);\n            });\n\n            it('Should remove placeholder tags without arguments', function (done) {\n                var fixture = '<html>\\n<!-- build:js -->\\nSome text\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\n</html>';\n\n                var stream = plugin();\n                compare(new Buffer(fixture), expected, stream, done);\n            });\n\n            it('Should remove placeholder tags with arguments', function (done) {\n                var fixture = '<html>\\n<!-- build:lorem -->\\nSome text\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\nipsum\\n</html>';\n\n                var stream = plugin({lorem: 'ipsum'});\n                compare(new Buffer(fixture), expected, stream, done);\n            });\n\n            it('Should keep indentation', function (done) {\n                var fixture = '<html>\\n  <!-- build:js -->\\n  Some text\\n  <!-- endbuild -->\\n</html>';\n                var expected = '<html>\\n  <!-- build:js -->\\n  <!-- endbuild -->\\n</html>';\n\n                var stream = plugin({}, {keepBlockTags: true});\n                compare(new Buffer(fixture), expected, stream, done);\n            });\n        });\n\n        describe('resolvePaths', function () {\n            it('Should resolve relative paths', function (done) {\n                var fixture = '<html>\\n<!-- build:js -->\\n<script src=\"file.js\"></script>\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\n<script src=\"../../lib/script.js\"></script>\\n</html>';\n\n                var stream = plugin({js: 'lib/script.js'}, {resolvePaths: true});\n                compare(new Buffer(fixture), expected, stream, done);\n            });\n        });\n    });\n\n    describe('Legacy versions', function () {\n        it('[version <1.2] should keep empty blocks (keepUnassigned = true)', function (done) {\n            var fixture = '<html>\\n<!-- build:js -->\\nThis should be removed if \"keepUnassigned\" is false\\n<!-- endbuild -->\\n</html>';\n            var expected = '<html>\\nThis should be removed if \"keepUnassigned\" is false\\n</html>';\n\n            var stream = plugin({}, true);\n            compare(new Buffer(fixture), expected, stream, done);\n        });\n\n        it('[version <1.2] should remove empty blocks (keepUnassigned = false)', function (done) {\n            var fixture = '<html>\\n<!-- build:js -->\\nThis should be removed if \"keepUnassigned\" is false\\n<!-- endbuild -->\\n</html>';\n            var expected = '<html>\\n</html>';\n\n            var stream = plugin();\n            compare(new Buffer(fixture), expected, stream, done);\n        });\n    });\n\n});\n"
  },
  {
    "path": "test/expected.html",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta charset=\"UTF-8\">\n    <title>Test file</title>\n\n    <link rel=\"stylesheet\" href=\"css/combined.css\">\n</head>\n<body>\n    <script src=\"js/one.js\"></script>\n    <script src=\"js/two.js?ts=123\"></script>\n    <script src=\"js/three.js?v=v1.5.3-1-g91cd575\"></script>\n\n<script src=\"js/with_tpl.js\"></script>\n\n<script src=\"js/with_tpl.js\"></script>\n<script src=\"js/with_tpl_2.js\"></script>\n\n<script data-main=\"js/with_tpl_2vars1.js\" src=\"js/with_tpl_2vars2.js\"></script>\n\n<script data-main=\"js/with_tpl_2vars1.js\" src=\"js/with_tpl_2vars2.js\"></script>\n<script data-main=\"js/with_tpl_2vars1_2.js\" src=\"js/with_tpl_2vars2_2.js\"></script>\n\n<script src=\"js/index.min.js\"></script>\n\n<script src=\"js/index.min.js\"></script>\n\n<script data-src=\"index.data\" src=\"js/with_tpl.js\"></script>\n<script data-src=\"index.data\" src=\"js/with_tpl_2.js\"></script>\n\n<script data-src=\"index.html\" data-main=\"js/with_tpl_2vars1.js\" src=\"js/with_tpl_2vars2.js\"></script>\n\n<script data-src=\"index.data\" data-main=\"js/with_tpl_2vars1.js\" src=\"js/with_tpl_2vars2.js\"></script>\n<script data-src=\"index.data\" data-main=\"js/with_tpl_2vars1_2.js\" src=\"js/with_tpl_2vars2_2.js\"></script>\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit.\n\nStream simple replacement\n\nStream advanced replacement\n\nStream $$ special replacement pattern\n</body>\n</html>\n"
  },
  {
    "path": "test/fixture.html",
    "content": "<!DOCTYPE html>\n<html>\n<head lang=\"en\">\n    <meta charset=\"UTF-8\">\n    <title>Test file</title>\n\n    <!-- build:css -->\n    <link rel=\"stylesheet\" href=\"one.css\">\n    <link rel=\"stylesheet\" href=\"two.css\">\n    <!-- endbuild -->\n</head>\n<body>\n    <!-- build:js_files -->\n    <script src=\"uncompressed.js\"></script>\n    <!-- endbuild -->\n\n<!-- build:js_files_tpl -->\n<script src=\"uncompressed.js\"></script>\n<!-- endbuild -->\n\n<!-- build:js_files_tpl_multiple -->\n<script src=\"uncompressed.js\"></script>\n<!-- endbuild -->\n\n<!-- build:js_files_tpl_2vars -->\n<script data-main=\"main.js\" src=\"uncompressed.js\"></script>\n<!-- endbuild -->\n\n<!-- build:js_files_tpl_2vars_multiple -->\n<script data-main=\"main.js\" src=\"uncompressed.js\"></script>\n<!-- endbuild -->\n\n<!-- build:js_files_x_tpl -->\n<script src=\"uncompressed.js\"></script>\n<!-- endbuild -->\n\n<!-- build:js_files_x_tpl_src -->\n<script src=\"uncompressed.js\"></script>\n<!-- endbuild -->\n\n<!-- build:js_files_x_tpl_multiple -->\n<script src=\"uncompressed.js\"></script>\n<!-- endbuild -->\n\n<!-- build:js_files_x_tpl_2vars -->\n<script src=\"uncompressed.js\"></script>\n<!-- endbuild -->\n\n<!-- build:js_files_x_tpl_2vars_multiple -->\n<script src=\"uncompressed.js\"></script>\n<!-- endbuild -->\n\n<!-- build:lorem-ipsum -->\n<!-- endbuild -->\n\n<!-- build:stream-simple -->\n<!-- endbuild -->\n\n<!-- build:stream-advanced -->\n<!-- endbuild -->\n\n<!-- build:stream-special -->\n<!-- endbuild -->\n</body>\n</html>\n"
  },
  {
    "path": "test/null.js",
    "content": "'use strict';\n\nvar plugin = require('..');\nvar File = require('vinyl');\nvar assert = require('assert');\n\ndescribe('null files', function () {\n    it('should be passed through', function (done) {\n        plugin()\n        .once('data', function (file) {\n            assert(file.isNull());\n            done();\n        })\n        .end(new File({contents: null}));\n    });\n});\n"
  },
  {
    "path": "test/stream.js",
    "content": "'use strict';\n\nvar plugin = require('..');\nvar fs = require('fs');\nvar path = require('path');\nvar File = require('vinyl');\nvar assert = require('assert');\nvar concatStream = require('concat-stream');\nvar stringToStream = require('from2-string');\nvar source = require('vinyl-source-stream');\n\nfunction compare(fixture, expected, stream, done) {\n    var fakeFile = new File({\n        base: path.resolve('www'),\n        path: path.resolve('www', 'pages', 'index.html'),\n        contents: fixture\n    });\n\n    stream.write(fakeFile);\n\n    stream.once('data', function (file) {\n        assert(file.isStream());\n\n        file.contents.pipe(concatStream({encoding: 'string'}, function (data) {\n            assert.equal(data, expected);\n            done();\n        }));\n    });\n}\n\ndescribe('Stream mode', function () {\n    it('should replace blocks', function (done) {\n        var fixture = fs.createReadStream(path.join('test', 'fixture.html'));\n        var expected = fs.readFileSync(path.join('test', 'expected.html'), 'utf8');\n\n        var stream = plugin({\n            css: 'css/combined.css',\n            js_files: ['js/one.js', 'js/two.js?ts=123', 'js/three.js?v=v1.5.3-1-g91cd575'],\n            js_files_tpl: {\n                src: 'js/with_tpl.js',\n                tpl: '<script src=\"%s\"></script>'\n            },\n            js_files_tpl_multiple: {\n                src: ['js/with_tpl.js', 'js/with_tpl_2.js'],\n                tpl: '<script src=\"%s\"></script>'\n            },\n            js_files_tpl_2vars: {\n                src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js']],\n                tpl: '<script data-main=\"%s\" src=\"%s\"></script>'\n            },\n            js_files_tpl_2vars_multiple: {\n                src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js'], ['js/with_tpl_2vars1_2.js', 'js/with_tpl_2vars2_2.js']],\n                tpl: '<script data-main=\"%s\" src=\"%s\"></script>'\n            },\n            js_files_x_tpl: {\n                src: null,\n                tpl: '<script src=\"js/%f.min.js\"></script>'\n            },\n            js_files_x_tpl_src: {\n                src: 'js',\n                tpl: '<script src=\"%s/%f.min.js\"></script>'\n            },\n            js_files_x_tpl_multiple: {\n                src: ['js/with_tpl.js', 'js/with_tpl_2.js'],\n                tpl: '<script data-src=\"%f.data\" src=\"%s\"></script>'\n            },\n            js_files_x_tpl_2vars: {\n                src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js']],\n                tpl: '<script data-src=\"%f%e\" data-main=\"%s\" src=\"%s\"></script>'\n            },\n            js_files_x_tpl_2vars_multiple: {\n                src: [['js/with_tpl_2vars1.js', 'js/with_tpl_2vars2.js'], ['js/with_tpl_2vars1_2.js', 'js/with_tpl_2vars2_2.js']],\n                tpl: '<script data-src=\"%f.data\" data-main=\"%s\" src=\"%s\"></script>'\n            },\n            'lorem-ipsum': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',\n            'stream-simple': stringToStream('Stream simple replacement').pipe(source('fake-vinyl.txt')),\n            'stream-advanced': {\n                src:  stringToStream('Stream advanced replacement').pipe(source('fake-vinyl.txt'))\n            },\n            'stream-special': {\n                src: stringToStream('Stream $$ special replacement pattern').pipe(source('fake-vinyl.txt'))\n            }\n        });\n\n        compare(fixture, expected, stream, done);\n    });\n\n    it('should work with inline html', function (done) {\n        var fixture = '<!DOCTYPE html><head><!-- build:css --><link rel=\"stylesheet\" href=\"_index.prefix.css\"><!-- endbuild --></head>';\n        var expected = '<!DOCTYPE html><head><link rel=\"stylesheet\" href=\"css/combined.css\"></head>';\n\n        var stream = plugin({css: 'css/combined.css'});\n        compare(stringToStream(fixture), expected, stream, done);\n    });\n\n    it('should not fail if there are no build tags at all', function (done) {\n        var fixture = '<!DOCTYPE html><head><link rel=\"stylesheet\" href=\"_index.prefix.css\"></head>';\n\n        var stream = plugin({css: 'css/combined.css'});\n        compare(stringToStream(fixture), fixture, stream, done);\n    });\n\n    describe('Options', function () {\n\n        describe('keepUnassigned', function () {\n            it('Should keep empty blocks', function (done) {\n                var fixture = '<html>\\n<!-- build:js -->\\nSome text\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\nSome text\\n</html>';\n\n                var stream = plugin({}, {keepUnassigned: true});\n                compare(stringToStream(fixture), expected, stream, done);\n            });\n\n            it('Should remove empty blocks', function (done) {\n                var fixture = '<html>\\n<!-- build:js -->\\nSome text\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\n</html>';\n\n                var stream = plugin();\n                compare(stringToStream(fixture), expected, stream, done);\n            });\n        });\n\n        describe('keepBlockTags', function () {\n            it('Should keep placeholder tags without arguments', function (done) {\n                var fixture = '<html>\\n<!-- build:js -->\\nSome text\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\n<!-- build:js -->\\n<!-- endbuild -->\\n</html>';\n\n                var stream = plugin({}, {keepBlockTags: true});\n                compare(stringToStream(fixture), expected, stream, done);\n            });\n\n            it('Should keep placeholder tags with arguments', function (done) {\n                var fixture = '<html>\\n<!-- build:lorem -->\\nSome text\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\n<!-- build:lorem -->\\nipsum\\n<!-- endbuild -->\\n</html>';\n\n                var stream = plugin({lorem: 'ipsum'}, {keepBlockTags: true});\n                compare(stringToStream(fixture), expected, stream, done);\n            });\n\n            it('Should remove placeholder tags without arguments', function (done) {\n                var fixture = '<html>\\n<!-- build:js -->\\nSome text\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\n</html>';\n\n                var stream = plugin();\n                compare(stringToStream(fixture), expected, stream, done);\n            });\n\n            it('Should remove placeholder tags with arguments', function (done) {\n                var fixture = '<html>\\n<!-- build:lorem -->\\nSome text\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\nipsum\\n</html>';\n\n                var stream = plugin({lorem: 'ipsum'});\n                compare(stringToStream(fixture), expected, stream, done);\n            });\n\n            it('Should keep indentation', function (done) {\n                var fixture = '<html>\\n  <!-- build:js -->\\n  Some text\\n  <!-- endbuild -->\\n</html>';\n                var expected = '<html>\\n  <!-- build:js -->\\n  <!-- endbuild -->\\n</html>';\n\n                var stream = plugin({}, {keepBlockTags: true});\n                compare(stringToStream(fixture), expected, stream, done);\n            });\n        });\n\n        describe('resolvePaths', function () {\n            it('Should resolve relative paths', function (done) {\n                var fixture = '<html>\\n<!-- build:js -->\\n<script src=\"file.js\"></script>\\n<!-- endbuild -->\\n</html>';\n                var expected = '<html>\\n<script src=\"../../lib/script.js\"></script>\\n</html>';\n\n                var stream = plugin({js: 'lib/script.js'}, {resolvePaths: true});\n                compare(stringToStream(fixture), expected, stream, done);\n            });\n        });\n    });\n\n    describe('Legacy versions', function () {\n        it('[version <1.2] should keep empty blocks (keepUnused = true)', function (done) {\n            var fixture = '<html>\\n<!-- build:js -->\\nThis should not be removed\\n<!-- endbuild -->\\n</html>';\n            var expected = '<html>\\nThis should not be removed\\n</html>';\n\n            var stream = plugin({}, true);\n            compare(stringToStream(fixture), expected, stream, done);\n        });\n\n        it('[version <1.2] should remove empty blocks (keepUnused = false)', function (done) {\n            var fixture = '<html>\\n<!-- build:js -->\\nThis should be removed\\n<!-- endbuild -->\\n</html>';\n            var expected = '<html>\\n</html>';\n\n            var stream = plugin();\n            compare(stringToStream(fixture), expected, stream, done);\n        });\n    });\n\n});\n"
  }
]