├── .editorconfig ├── .eslintrc.json ├── .github └── workflows │ └── main.yml ├── .gitignore ├── .npmignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── gulpfile.js ├── index.js ├── lib ├── addFilesFromExtStreams.js ├── addHtmlToStream.js ├── end.js ├── getGlobs.js ├── getPattern.js ├── reorderTheStream.js └── unprocessedCounter.js ├── package-lock.json ├── package.json └── test ├── .tmp ├── css │ ├── one.css │ └── two.css └── scripts │ ├── anotherone.js │ ├── module1.js │ ├── module2.js │ ├── that.js │ ├── this.js │ └── yetonemore.js ├── expected ├── 01.html ├── 02.html ├── 03.html ├── 04.html ├── css │ └── ordered.css ├── custom-blocks.html ├── noconcat-css.html └── noconcat-js.html ├── fixtures ├── 01.html ├── 02.html ├── 03.html ├── 04.html ├── 05.html ├── 06.html ├── 07.html ├── 08.html ├── 09.html ├── 10.html ├── 11.html ├── 12.html ├── absolute-search-path.html ├── alternate-search-paths.html ├── bad-path.html ├── bulk │ ├── useref.01.css │ ├── useref.01.html │ ├── useref.02.css │ ├── useref.02.html │ ├── useref.03.css │ ├── useref.03.html │ ├── useref.04.css │ ├── useref.04.html │ ├── useref.05.css │ ├── useref.05.html │ ├── useref.06.css │ ├── useref.06.html │ ├── useref.07.css │ ├── useref.07.html │ ├── useref.08.css │ ├── useref.08.html │ ├── useref.09.css │ ├── useref.09.html │ ├── useref.10.css │ ├── useref.10.html │ ├── useref.11.css │ ├── useref.11.html │ ├── useref.12.css │ ├── useref.12.html │ ├── useref.13.css │ ├── useref.13.html │ ├── useref.14.css │ ├── useref.14.html │ ├── useref.15.css │ ├── useref.15.html │ ├── useref.16.css │ ├── useref.16.html │ ├── useref.17.css │ ├── useref.17.html │ ├── useref.18.css │ ├── useref.18.html │ ├── useref.19.css │ ├── useref.19.html │ ├── useref.20.css │ ├── useref.20.html │ ├── useref.21.css │ ├── useref.21.html │ ├── useref.22.css │ ├── useref.22.html │ ├── useref.23.css │ ├── useref.23.html │ ├── useref.24.css │ ├── useref.24.html │ ├── useref.25.css │ ├── useref.25.html │ ├── useref.26.css │ ├── useref.26.html │ ├── useref.27.css │ ├── useref.27.html │ ├── useref.28.css │ ├── useref.28.html │ ├── useref.29.css │ ├── useref.29.html │ ├── useref.30.css │ ├── useref.30.html │ ├── useref.31.css │ ├── useref.31.html │ ├── useref.32.css │ ├── useref.32.html │ ├── useref.33.css │ ├── useref.33.html │ ├── useref.34.css │ ├── useref.34.html │ ├── useref.35.css │ ├── useref.35.html │ ├── useref.36.css │ ├── useref.36.html │ ├── useref.37.css │ ├── useref.37.html │ ├── useref.38.css │ ├── useref.38.html │ ├── useref.39.css │ ├── useref.39.html │ ├── useref.40.css │ ├── useref.40.html │ ├── useref.41.css │ ├── useref.41.html │ ├── useref.42.css │ ├── useref.42.html │ ├── useref.43.css │ ├── useref.43.html │ ├── useref.44.css │ ├── useref.44.html │ ├── useref.45.css │ ├── useref.45.html │ ├── useref.46.css │ ├── useref.46.html │ ├── useref.47.css │ ├── useref.47.html │ ├── useref.48.css │ ├── useref.48.html │ ├── useref.49.css │ ├── useref.49.html │ ├── useref.50.css │ ├── useref.50.html │ ├── useref.51.css │ ├── useref.51.html │ ├── useref.52.css │ ├── useref.52.html │ ├── useref.53.css │ ├── useref.53.html │ ├── useref.54.css │ ├── useref.54.html │ ├── useref.55.css │ ├── useref.55.html │ ├── useref.56.css │ └── useref.56.html ├── css │ ├── a.css │ ├── four.css │ ├── one.css │ ├── three.css │ ├── two.css │ └── z.css ├── custom-blocks.html ├── nonexistent.html ├── order.html ├── relative │ ├── child │ │ └── index.html │ ├── index.html │ └── styles │ │ └── main.css ├── remote-path.html ├── scripts │ ├── anotherone.js │ ├── that.js │ ├── this.js │ └── yetonemore.js ├── templates1 │ └── component.html └── templates2 │ └── component.html ├── mock-all.js ├── mock-relative.js └── test.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 4 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | 23 | [{package.json,*.yml}] 24 | indent_style = space 25 | indent_size = 2 26 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true, 4 | "node": true 5 | }, 6 | "globals": {}, 7 | "extends": "eslint:recommended", 8 | 9 | // Stop ESLint from looking for a configuration file in parent folders 10 | "root": true, 11 | 12 | "parser": "babel-eslint", 13 | "parserOptions": { 14 | "ecmaVersion": 8, 15 | "sourceType": "script", 16 | "ecmaFeatures": { 17 | "experimentalObjectRestSpread": true 18 | } 19 | }, 20 | "rules": { 21 | "block-scoped-var": 2, 22 | "complexity": [ 23 | 0, 24 | 5 25 | ], 26 | "consistent-return": 1, 27 | "curly": [ 28 | 2, 29 | "all" 30 | ], 31 | "dot-notation": 2, 32 | "eqeqeq": 2, 33 | "no-caller": 2, 34 | "no-else-return": 2, 35 | "no-eq-null": 2, 36 | "no-extend-native": 2, 37 | "no-implicit-coercion": 2, 38 | "no-loop-func": 2, 39 | "no-multi-spaces": 2, 40 | "no-multi-str": 2, 41 | "no-new-func": 2, 42 | "no-new-wrappers": 2, 43 | "no-new": 2, 44 | "no-param-reassign": 2, 45 | "no-unused-expressions": 2, 46 | "no-useless-call": 2, 47 | "no-useless-concat": 2, 48 | "no-with": 2, 49 | "vars-on-top": 2, 50 | "wrap-iife": [2, "any"], 51 | "yoda": [ 52 | 2, 53 | "never" 54 | ], 55 | 56 | "no-shadow": 2, 57 | "no-use-before-define": 2, 58 | 59 | "callback-return": 2, 60 | "handle-callback-err": 2, 61 | "no-path-concat": 2, 62 | 63 | "array-bracket-spacing": [ 64 | 1, 65 | "always", { 66 | "objectsInArrays": false 67 | } 68 | ], 69 | "block-spacing": 1, 70 | "brace-style": 1, 71 | "camelcase": [ 72 | 1, { 73 | "properties": "never" 74 | } 75 | ], 76 | "comma-spacing": [ 77 | 1, { 78 | "before": false, 79 | "after": true 80 | } 81 | ], 82 | "comma-style": [ 83 | 1, 84 | "last" 85 | ], 86 | "computed-property-spacing": [ 87 | 1, 88 | "never" 89 | ], 90 | "consistent-this": [ 91 | 1, 92 | "self" 93 | ], 94 | "eol-last": 1, 95 | "indent": [ 96 | 2, 97 | 4, { 98 | "SwitchCase": 1 99 | } 100 | ], 101 | "key-spacing": [ 102 | 1, { 103 | "beforeColon": false, 104 | "afterColon": true 105 | } 106 | ], 107 | "keyword-spacing": 1, 108 | "linebreak-style": [ 109 | 1, 110 | "unix" 111 | ], 112 | "lines-around-comment": [ 113 | 1, { 114 | "allowBlockStart": true, 115 | "beforeBlockComment": true, 116 | "beforeLineComment": true 117 | } 118 | ], 119 | "max-depth": [ 120 | 1, 121 | 4 122 | ], 123 | "max-params": [ 124 | 1, 125 | 3 126 | ], 127 | "max-statements": [ 128 | 0, 129 | 10 130 | ], 131 | "new-cap": 2, 132 | "new-parens": 2, 133 | "padding-line-between-statements": [ 134 | "error", 135 | { "blankLine": "always", "prev": ["const", "let", "var"], "next": "*"}, 136 | { "blankLine": "any", "prev": ["const", "let", "var"], "next": ["const", "let", "var"]} 137 | ], 138 | "no-array-constructor": 2, 139 | "no-bitwise": 1, 140 | "no-lonely-if": 1, 141 | "no-multiple-empty-lines": 1, 142 | "no-new-object": 2, 143 | "no-spaced-func": 1, 144 | "no-trailing-spaces": 1, 145 | "no-unneeded-ternary": 1, 146 | "object-curly-spacing": [ 147 | 1, 148 | "always" 149 | ], 150 | "operator-assignment": [ 151 | 1, 152 | "always" 153 | ], 154 | "operator-linebreak": [ 155 | 1, 156 | "after" 157 | ], 158 | "quote-props": [ 159 | 1, 160 | "as-needed" 161 | ], 162 | "quotes": [ 163 | 1, 164 | "single" 165 | ], 166 | "semi": [ 167 | 2, 168 | "always" 169 | ], 170 | "semi-spacing": [ 171 | 1, { 172 | "before": false, 173 | "after": true 174 | } 175 | ], 176 | "space-before-blocks": [ 177 | 1, 178 | "always" 179 | ], 180 | "space-before-function-paren": [1, { "anonymous": "always", "named": "never" }], 181 | "space-in-parens": [1, "never"], 182 | "space-infix-ops": 1, 183 | "space-unary-ops": 0, 184 | "spaced-comment": [1, "always", { "line": { "exceptions": ["-"] } }] 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | test: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | node-version: [12.x, 14.x, 16.x] 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | - name: Node.js ${{ matrix.node-version }} 24 | uses: actions/setup-node@v2 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | - run: npm install 28 | - run: gulp lint 29 | - run: npm test 30 | - run: npm run coveralls 31 | 32 | - name: Coveralls 33 | uses: coverallsapp/github-action@master 34 | with: 35 | github-token: ${{ secrets.GITHUB_TOKEN }} 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .editorconfig 2 | .travis.yml 3 | .jscsrc 4 | .jshintrc 5 | .gitattributes 6 | CONTRIBUTING.md 7 | gulpfile.js 8 | test 9 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to gulp-useref 2 | 3 | First, thanks for your initiative to help out! One of the reasons that open 4 | source is so great is because of the eagerness of others to help. 5 | 6 | Please take a moment to review this document in order to make the contribution 7 | process easy and effective for everyone involved. 8 | 9 | Following these guidelines helps to communicate that you respect the time of 10 | the developers managing and developing this open source project. In return, 11 | they should reciprocate that respect in addressing your issue or assessing 12 | patches and features. 13 | 14 | 15 | ## Asking a Question 16 | 17 | Before you ask, do some searching and reading. Check the docs, Google, GitHub, 18 | and StackOverflow. If your question is something that has been answered many 19 | times before, the project maintainers might be tired of repeating themselves. 20 | 21 | Whenever possible, ask your question on a public forum. This allows anyone to 22 | answer and makes the answer available for the next person with the same question. 23 | If all else fails, you might tweet at or email the maintainer(s). 24 | 25 | 26 | ## Using the issue tracker 27 | 28 | The issue tracker is the preferred channel for [bug reports](#bug-reports), 29 | [features requests](#feature-requests) and [submitting pull 30 | requests](#pull-requests), but please respect the following restrictions: 31 | 32 | * Please **do not** use the issue tracker for personal support requests (use 33 | [Stack Overflow](http://stackoverflow.com) or IRC). 34 | 35 | * Please **do not** derail or troll issues. Keep the discussion on topic and 36 | respect the opinions of others. 37 | 38 | 39 | ## Bug reports 40 | 41 | A bug is a _demonstrable problem_ that is caused by the code in the repository. 42 | Good bug reports are extremely helpful - thank you! 43 | 44 | ### Has This Been Asked Before? 45 | 46 | Before you submit a bug report, you should search existing issues. Be sure to 47 | check both currently open issues, as well as issues that are already closed. If 48 | you find an issue that seems to be similar to yours, read through it. 49 | 50 | If this issue is the same as yours, you can comment with additional information 51 | to help the maintainer debug it. Adding a comment will subscribe you to email 52 | notifications, which can be helpful in getting important updates regarding the 53 | issue. If you don't have anything to add but still want to receive email 54 | updates, you can click the "watch" button at the bottom of the comments. 55 | 56 | ### Nope, Hasn't Been Asked Before 57 | 58 | If you can't find anything in the existing issues, don't be shy about filing a 59 | new one. 60 | 61 | You should be sure to include the version the project, as well as versions of 62 | related software. For example, be sure to include the version numbers output by 63 | the commands `node --version` and `npm list`. If you notice that your installed 64 | version is not the latest, use `npm update` and confirm that the issue is still 65 | there. 66 | 67 | Please be as thorough as possible. It helps us address the problem more quickly, 68 | so everyone wins! 69 | 70 | Guidelines for bug reports: 71 | 72 | 1. **Use the GitHub issue search** — check if the issue has already been 73 | reported. 74 | 75 | 2. **Check if the issue has been fixed** — try to reproduce it using the 76 | latest `master` or development branch in the repository. 77 | 78 | 3. **Isolate the problem** — create a [reduced test 79 | case](https://css-tricks.com/reduced-test-cases/) and a live example. 80 | 81 | A good bug report shouldn't leave others needing to chase you up for more 82 | information. Please try to be as detailed as possible in your report. What is 83 | your environment? What steps will reproduce the issue? What browser(s) and OS 84 | experience the problem? What would you expect to be the outcome? All these 85 | details will help people to fix any potential bugs. 86 | 87 | Example: 88 | 89 | > Short and descriptive example bug report title 90 | > 91 | > A summary of the issue and the browser/OS environment in which it occurs. If 92 | > suitable, include the steps required to reproduce the bug. 93 | > 94 | > 1. This is the first step 95 | > 2. This is the second step 96 | > 3. Further steps, etc. 97 | > 98 | > `` - a link to the reduced test case 99 | > 100 | > Any other information you want to share that is relevant to the issue being 101 | > reported. This might include the lines of code that you have identified as 102 | > causing the bug, and potential solutions (and your opinions on their 103 | > merits). 104 | 105 | 106 | ## Feature requests 107 | 108 | Feature requests are welcome. But take a moment to find out whether your idea 109 | fits with the scope and aims of the project. It's up to *you* to make a strong 110 | case to convince the project's developers of the merits of this feature. Please 111 | provide as much detail and context as possible. 112 | 113 | 114 | ## Pull requests 115 | 116 | Good pull requests - patches, improvements, new features - are a fantastic 117 | help. They should remain focused in scope and avoid containing unrelated 118 | commits. 119 | 120 | **Please ask first** before embarking on any significant pull request (e.g. 121 | implementing features, refactoring code, porting to a different language), 122 | otherwise you risk spending a lot of time working on something that the 123 | project's developers might not want to merge into the project. 124 | 125 | Before you set out to improve the code, you should have a focused idea in mind 126 | of what you want to do. 127 | 128 | Each commit should do one thing, and each PR should be one specific improvement. 129 | 130 | Please adhere to the coding conventions used throughout a project (indentation, 131 | accurate comments, etc.) and any other requirements (such as test coverage). 132 | 133 | Follow this process if you'd like your work considered for inclusion in the 134 | project: 135 | 136 | 1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork, 137 | and configure the remotes: 138 | 139 | ```bash 140 | # Clone your fork of the repo into the current directory 141 | $ git clone https://github.com//gulp-useref 142 | # Navigate to the newly cloned directory 143 | $ cd gulp-useref 144 | # Assign the original repo to a remote called "upstream" 145 | $ git remote add upstream https://github.com/jonkemp/gulp-useref 146 | ``` 147 | 148 | 2. If you cloned a while ago, get the latest changes from upstream: 149 | 150 | ```bash 151 | $ git checkout 152 | $ git pull upstream 153 | ``` 154 | 155 | 3. Create a new topic branch (off the main project development branch) to 156 | contain your feature, change, or fix: 157 | 158 | ```bash 159 | $ git checkout -b 160 | ``` 161 | 162 | 4. Add relevant tests to cover the change. 163 | 164 | 5. Make sure test-suite passes: `npm test` 165 | 166 | 6. Commit your changes in logical chunks. Please adhere to these [git commit 167 | message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) 168 | or your code is unlikely be merged into the main project. Use Git's 169 | [interactive rebase](https://help.github.com/articles/interactive-rebase) 170 | feature to tidy up your commits before making them public. 171 | 172 | 7. Locally merge (or rebase) the upstream development branch into your topic branch: 173 | 174 | ```bash 175 | $ git pull [--rebase] upstream 176 | ``` 177 | 178 | 8. Push your topic branch up to your fork: 179 | 180 | ```bash 181 | $ git push origin 182 | ``` 183 | 184 | 9. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) 185 | with a clear title and description. 186 | 187 | ## Conventions of commit messages 188 | 189 | Addding files on repo 190 | 191 | ```bash 192 | $ git commit -m "Add filename" 193 | ``` 194 | 195 | Updating files on repo 196 | 197 | ```bash 198 | $ git commit -m "Update filename, filename2, filename3" 199 | ``` 200 | 201 | Removing files on repo 202 | 203 | ```bash 204 | $ git commit -m "Remove filename" 205 | ``` 206 | 207 | Renaming files on repo 208 | 209 | ```bash 210 | $ git commit -m "Rename filename" 211 | ``` 212 | 213 | Fixing errors and issues on repo 214 | 215 | ```bash 216 | $ git commit -m "Fixed #issuenumber Message about this fix" 217 | ``` 218 | 219 | Adding features on repo 220 | 221 | ```bash 222 | $ git commit -m "Add Feature: nameoffeature Message about this feature" 223 | ``` 224 | 225 | Updating features on repo 226 | 227 | ```bash 228 | $ git commit -m "Update Feature: nameoffeature Message about this update" 229 | ``` 230 | 231 | Removing features on repo 232 | 233 | ```bash 234 | $ git commit -m "Remove Feature: nameoffeature Message about this" 235 | ``` 236 | 237 | Ignoring Travis CI build on repo 238 | 239 | ```bash 240 | $ git commit -m "Commit message here [ci-skip]" 241 | ``` 242 | 243 | **IMPORTANT**: By submitting a patch, you agree to allow the project owner to 244 | license your work under the same license as that used by the project. 245 | 246 | 247 | ## Etiquette 248 | 249 | ### Assume Everyone is Doing Their Best 250 | 251 | Project maintainers are busy, so give them some time. Developers involved in 252 | open source often contribute to many projects. It's not uncommon for a developer 253 | to receive dozens of issues notifications a day, so be patient. Maybe the 254 | maintainer has other important things in their life that they need to address. 255 | Prioritizing those things over something on GitHub doesn't make someone lazy. 256 | The health, happiness, and wellbeing of the real person on the other end of the 257 | internet is much more important than any bug. 258 | 259 | One of the strengths of open source is that you can always fork and fix problems 260 | yourself. 261 | 262 | 263 | ## Conclusion 264 | 265 | Thanks for taking the time to read this! Contributions are welcome. Hopefully, 266 | this guide will help make good contributions easier and ultimately, everyone 267 | benefits. 268 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Jonathan Kemp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [gulp](https://github.com/gulpjs/gulp)-useref ![Build Status](https://github.com/jonkemp/gulp-useref/actions/workflows/main.yml/badge.svg?branch=master) [![Coverage Status](https://coveralls.io/repos/jonkemp/gulp-useref/badge.svg?branch=master&service=github)](https://coveralls.io/github/jonkemp/gulp-useref?branch=master) 2 | 3 | [![NPM](https://nodei.co/npm/gulp-useref.png?downloads=true)](https://nodei.co/npm/gulp-useref/) 4 | 5 | > Parse build blocks in HTML files to replace references to non-optimized scripts or stylesheets with [useref](https://github.com/jonkemp/useref) 6 | 7 | Inspired by the grunt plugin [grunt-useref](https://github.com/pajtai/grunt-useref). It can handle file concatenation but not minification. Files are then passed down the stream. For minification of assets or other modifications, use [gulp-if](https://github.com/robrich/gulp-if) to conditionally handle specific types of assets. 8 | 9 | 10 | ## What's new in 3.0? 11 | 12 | Changes under the hood have made the code more efficient and simplified the API. Since the API has changed, please observe the usage examples below. 13 | 14 | If you get errors like 15 | 16 | TypeError: useref.assets is not a function 17 | 18 | or 19 | 20 | TypeError: $.useref.assets is not a function 21 | 22 | please read the Migration Notes below. 23 | 24 | ## Install 25 | 26 | Install with [npm](https://npmjs.org/package/gulp-useref) 27 | 28 | ``` 29 | npm install --save-dev gulp-useref 30 | ``` 31 | 32 | 33 | ## Usage 34 | 35 | The following example will parse the build blocks in the HTML, replace them and pass those files through. Assets inside the build blocks will be concatenated and passed through in a stream as well. 36 | 37 | ```js 38 | var gulp = require('gulp'), 39 | useref = require('gulp-useref'); 40 | 41 | gulp.task('default', function () { 42 | return gulp.src('app/*.html') 43 | .pipe(useref()) 44 | .pipe(gulp.dest('dist')); 45 | }); 46 | ``` 47 | 48 | With options: 49 | 50 | ```js 51 | var gulp = require('gulp'), 52 | useref = require('gulp-useref'); 53 | 54 | gulp.task('default', function () { 55 | return gulp.src('app/*.html') 56 | .pipe(useref({ searchPath: '.tmp' })) 57 | .pipe(gulp.dest('dist')); 58 | }); 59 | ``` 60 | 61 | If you want to minify your assets or perform some other modification, you can use [gulp-if](https://github.com/robrich/gulp-if) to conditionally handle specific types of assets. 62 | 63 | ```js 64 | var gulp = require('gulp'), 65 | useref = require('gulp-useref'), 66 | gulpif = require('gulp-if'), 67 | uglify = require('gulp-uglify'), 68 | minifyCss = require('gulp-clean-css'); 69 | 70 | gulp.task('html', function () { 71 | return gulp.src('app/*.html') 72 | .pipe(useref()) 73 | .pipe(gulpif('*.js', uglify())) 74 | .pipe(gulpif('*.css', minifyCss())) 75 | .pipe(gulp.dest('dist')); 76 | }); 77 | ``` 78 | 79 | Blocks are expressed as: 80 | 81 | ```html 82 | 83 | ... HTML Markup, list of script / link tags. 84 | 85 | ``` 86 | 87 | - **type**: either `js`, `css` or `remove`; `remove` will remove the build block entirely without generating a file 88 | - **alternate search path**: (optional) By default the input files are relative to the treated file. Alternate search path allows one to change that. The path can also contain a sequence of paths processed from right to left, using JSON brace array notation e.g ``. 89 | - **path**: the file path of the optimized file, the target output 90 | - **parameters**: extra parameters that should be added to the tag 91 | 92 | An example of this in completed form can be seen below: 93 | 94 | ```html 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | ``` 110 | 111 | The resulting HTML would be: 112 | 113 | ```html 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | ``` 123 | 124 | See [useref](https://github.com/jonkemp/useref) for more information. 125 | 126 | ## API 127 | 128 | ### useref(options [, transformStream1 [, transformStream2 [, ... ]]]) 129 | 130 | Returns a stream with the asset replaced resulting HTML files as well as the concatenated asset files from the build blocks inside the HTML. Supports all options from [useref](https://github.com/jonkemp/useref). 131 | 132 | ### Transform Streams 133 | 134 | Type: `Stream` 135 | Default: `none` 136 | 137 | Transform assets before concat. For example, to integrate source maps: 138 | 139 | ```js 140 | var gulp = require('gulp'), 141 | sourcemaps = require('gulp-sourcemaps'), 142 | useref = require('gulp-useref'), 143 | lazypipe = require('lazypipe'); 144 | 145 | gulp.task('default', function () { 146 | return gulp.src('index.html') 147 | .pipe(useref({}, lazypipe().pipe(sourcemaps.init, { loadMaps: true }))) 148 | .pipe(sourcemaps.write('maps')) 149 | .pipe(gulp.dest('dist')); 150 | }); 151 | ``` 152 | 153 | ### Options 154 | 155 | #### options.searchPath 156 | 157 | Type: `String` or `Array` 158 | Default: `none` 159 | 160 | Specify the location to search for asset files, relative to the current working directory. Can be a string or array of strings. 161 | 162 | #### options.base 163 | 164 | Type: `String` 165 | Default: `process.cwd()` 166 | 167 | Specify the output folder relative to the cwd. 168 | 169 | #### options.noAssets 170 | 171 | Type: `Boolean` 172 | Default: `false` 173 | 174 | Skip assets and only process the HTML files. 175 | 176 | #### options.noconcat 177 | 178 | Type: `Boolean` 179 | Default: `false` 180 | 181 | Skip concatenation and add all assets to the stream instead. 182 | 183 | #### options.newLine 184 | 185 | Type: `String` 186 | Default: `none` 187 | 188 | Add a string that should separate the concatenated files. 189 | 190 | #### options.additionalStreams 191 | 192 | Type: `Array` 193 | Default: `none` 194 | 195 | Use additional streams as sources of assets. Useful for combining gulp-useref with preprocessing tools. For example, to use with TypeScript: 196 | 197 | ```javascript 198 | var ts = require('gulp-typescript'); 199 | 200 | // create stream of virtual files 201 | var tsStream = gulp.src('src/**/*.ts') 202 | .pipe(ts()); 203 | 204 | gulp.task('default', function () { 205 | // use gulp-useref normally 206 | return gulp.src('src/index.html') 207 | .pipe(useref({ additionalStreams: [tsStream] })) 208 | .pipe(gulp.dest('dist')); 209 | }); 210 | ``` 211 | 212 | #### options.transformPath 213 | 214 | Type: `Function` 215 | Default: `none` 216 | 217 | Add a transformPath function in case the path needs to be modified before search happens. 218 | 219 | ```js 220 | var gulp = require('gulp'), 221 | useref = require('gulp-useref'); 222 | 223 | gulp.task('default', function () { 224 | return gulp.src('app/*.html') 225 | .pipe(useref({ 226 | transformPath: function(filePath) { 227 | return filePath.replace('/rootpath','') 228 | } 229 | })) 230 | .pipe(gulp.dest('dist')); 231 | }); 232 | ``` 233 | 234 | ## Migration from v2 API 235 | 236 | If you upgrade gulp-useref from v2 without changing your gulpfile, 237 | you will get errors like this: 238 | 239 | TypeError: $.useref.assets is not a function 240 | 241 | or 242 | 243 | TypeError: useref.assets is not a function 244 | 245 | For a simple configuration, you can replace this V2 code: 246 | 247 | ```js 248 | var gulp = require('gulp'), 249 | useref = require('gulp-useref'); 250 | 251 | gulp.task('default', function () { 252 | var assets = useref.assets(); 253 | 254 | return gulp.src('app/*.html') 255 | .pipe(assets) 256 | .pipe(assets.restore()) 257 | .pipe(useref()) 258 | .pipe(gulp.dest('dist')); 259 | }); 260 | ``` 261 | 262 | with this V3 code: 263 | 264 | ```js 265 | var gulp = require('gulp'), 266 | useref = require('gulp-useref'); 267 | 268 | gulp.task('default', function () { 269 | return gulp.src('app/*.html') 270 | .pipe(useref()) 271 | .pipe(gulp.dest('dist')); 272 | }); 273 | ``` 274 | 275 | If you were previously using useref in a multi-stage pipe, 276 | you may need to rewrite the pipe, since the simplified V3 API 277 | may not allow for its previous usage. 278 | 279 | If the gulpfile you are using came from a generator, (for example, 280 | in JohnPapa's excellent "opinionated" HotTowel generator), it may 281 | be more practical to go back to that generator project to see 282 | whether they have upgraded to the V3 gulp-useref API, rather than 283 | trying to understand their pipe. 284 | 285 | 286 | ## Notes 287 | 288 | * [ClosureCompiler.js](https://github.com/dcodeIO/ClosureCompiler.js) doesn't support Buffers, which means if you want to use [gulp-closure-compiler](https://github.com/sindresorhus/gulp-closure-compiler) you'll have to first write out the `combined.js` to disk. See [this](https://github.com/dcodeIO/ClosureCompiler.js/issues/11) for more information. 289 | 290 | 291 | ## Contributing 292 | 293 | See the [CONTRIBUTING Guidelines](https://github.com/jonkemp/gulp-useref/blob/master/CONTRIBUTING.md) 294 | 295 | 296 | ## License 297 | 298 | MIT © [Jonathan Kemp](http://jonkemp.com) 299 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | const gulp = require('gulp'); 3 | const mocha = require('gulp-mocha'); 4 | const eslint = require('gulp-eslint'); 5 | 6 | const paths = { 7 | scripts: ['./*.js', './lib/*.js', '!./gulpfile.js'] 8 | }; 9 | 10 | gulp.task('lint', () => gulp.src(paths.scripts) 11 | .pipe(eslint({fix: true})) 12 | .pipe(eslint.format()) 13 | .pipe(eslint.failAfterError())); 14 | 15 | gulp.task('test', () => gulp.src('./test/*.js') 16 | .pipe(mocha({ reporter: 'spec' }))); 17 | 18 | gulp.task('watch', () => { 19 | gulp.watch(paths.scripts, gulp.parallel('lint', 'test')); 20 | }); 21 | 22 | gulp.task('default', gulp.parallel('lint', 'test', 'watch')); 23 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const PluginError = require('plugin-error'); 3 | const es = require('event-stream'); 4 | const through = require('through2'); 5 | const useref = require('useref'); 6 | const getGlobs = require('./lib/getGlobs'); 7 | const addFilesFromExtStreams = require('./lib/addFilesFromExtStreams'); 8 | const addHtmlToStream = require('./lib/addHtmlToStream'); 9 | const unprocessedCounter = require('./lib/unprocessedCounter')(); 10 | const end = require('./lib/end')(); 11 | const additionalFiles = []; 12 | let transforms; 13 | let pluginOptions; 14 | 15 | function handleAdditionalStreams(additionalStreams) { 16 | let _additionalStreams = additionalStreams; 17 | 18 | if (!Array.isArray(additionalStreams)) { 19 | _additionalStreams = [ additionalStreams ]; 20 | } 21 | 22 | // filters stream to select needed files 23 | return _additionalStreams.map(stream => stream.pipe(es.through(file => { 24 | additionalFiles.push(file); 25 | }))); 26 | } 27 | 28 | function addAssetsToStream(paths, files) { 29 | const self = this; 30 | const gulpif = require('gulp-if'); 31 | const concat = require('gulp-concat'); 32 | const vfs = require('vinyl-fs'); 33 | const extend = require('extend'); 34 | let src; 35 | let globs; 36 | const name = paths.name; 37 | const basePath = paths.basePath; 38 | const filepaths = files[name].assets; 39 | const type = paths.type; 40 | const options = extend({}, pluginOptions); 41 | const gulpConcatOptions = {}; 42 | 43 | if (!filepaths.length) { 44 | return; 45 | } 46 | 47 | unprocessedCounter.increment(); 48 | 49 | // Get relative file paths and join with search paths to send to vinyl-fs 50 | globs = filepaths 51 | .filter(url => !/^(?:\w+:)?\/\//.test(url)) // test if url is relative 52 | .map(filepath => { 53 | paths.filepath = filepath; 54 | 55 | return getGlobs(paths, files); 56 | }); 57 | 58 | src = vfs.src(globs, { 59 | base: basePath, 60 | nosort: true 61 | }) 62 | .on('error', err => { 63 | self.emit('error', new Error(err)); 64 | }); 65 | 66 | // add files from external streams 67 | src = addFilesFromExtStreams.call(self, additionalFiles, globs, src); 68 | 69 | // If any external transforms were included, pipe all files to them first 70 | transforms.forEach(fn => { 71 | src = src.pipe(fn(name)); 72 | }); 73 | 74 | // option for newLine in gulp-concat 75 | if (Object.prototype.hasOwnProperty.call(options, 'newLine')) { 76 | if (options.newLine === ';' && type === 'css') { 77 | options.newLine = null; 78 | } 79 | gulpConcatOptions.newLine = options.newLine; 80 | } 81 | 82 | // Add assets to the stream 83 | // If noconcat option is false, concat the files first. 84 | src 85 | .pipe(gulpif(!options.noconcat, concat(name, gulpConcatOptions))) 86 | .pipe(through.obj((newFile, encoding, callback) => { 87 | // specify an output path relative to the cwd 88 | if (options.base) { 89 | newFile.path = path.join(options.base, name); 90 | newFile.base = options.base; 91 | } 92 | 93 | // add file to the asset stream 94 | self.push(newFile); 95 | callback(); 96 | })) 97 | .on('finish', () => { 98 | const unprocessed = unprocessedCounter.decrement(); 99 | 100 | if (unprocessed === 0 && end.get()) { 101 | // end the asset stream 102 | end.fn(); 103 | } 104 | }); 105 | } 106 | 107 | function processAssets({ cwd }, basePath, data) { 108 | const self = this; 109 | const types = pluginOptions.types || [ 'css', 'js' ]; 110 | 111 | types.forEach(type => { 112 | const files = data[type]; 113 | let name; 114 | 115 | if (!files) { 116 | return; 117 | } 118 | 119 | for (name in files) { 120 | addAssetsToStream.call(self, { 121 | name, 122 | basePath, 123 | searchPath: pluginOptions.searchPath, 124 | cwd, 125 | transformPath: pluginOptions.transformPath, 126 | type 127 | }, files); 128 | } 129 | }); 130 | } 131 | 132 | module.exports = function (options) { 133 | const opts = options || {}; 134 | let waitForAssets; 135 | let additionalStreams; 136 | 137 | pluginOptions = opts; 138 | transforms = Array.prototype.slice.call(arguments, 1); 139 | 140 | // If any external streams were included, add matched files to src 141 | if (opts.additionalStreams) { 142 | additionalStreams = handleAdditionalStreams(opts.additionalStreams); 143 | 144 | // If we have additional streams, wait for them to run before continuing 145 | waitForAssets = es.merge(additionalStreams).pipe(through.obj()); 146 | } else { 147 | // Else, create a fake stream 148 | waitForAssets = through.obj(); 149 | } 150 | 151 | return through.obj(function (file, enc, cb) { 152 | const self = this; 153 | 154 | waitForAssets.pipe(es.wait(() => { 155 | let output; 156 | 157 | // Cache the file base path relative to the cwd 158 | // Use later when it could be dropped 159 | const _basePath = path.dirname(file.path); 160 | 161 | if (file.isNull()) { 162 | return cb(null, file); 163 | } 164 | 165 | if (file.isStream()) { 166 | return cb(new PluginError('gulp-useref', 'Streaming not supported')); 167 | } 168 | 169 | output = useref(file.contents.toString(), opts); 170 | 171 | addHtmlToStream.call(self, file, output[0]); 172 | 173 | if (!opts.noAssets) { 174 | processAssets.call(self, file, _basePath, output[1]); 175 | } 176 | 177 | return cb(); 178 | })); 179 | 180 | // If no external streams were included, 181 | // emit 'end' on the empty stream 182 | if (!additionalStreams) { 183 | waitForAssets.emit('end'); 184 | } 185 | }, cb => { 186 | const unprocessed = unprocessedCounter.get(); 187 | let fn = () => {}; 188 | 189 | end.set(cb); 190 | 191 | if (unprocessed === 0) { 192 | fn = cb; 193 | } 194 | 195 | return fn(); 196 | }); 197 | }; 198 | -------------------------------------------------------------------------------- /lib/addFilesFromExtStreams.js: -------------------------------------------------------------------------------- 1 | const reorderTheStream = require('./reorderTheStream'); 2 | 3 | module.exports = function (additionalFiles, globs, src) { 4 | const self = this; 5 | let source; 6 | 7 | additionalFiles.forEach(addFile => { 8 | src.push(addFile); 9 | }); 10 | 11 | // if we added additional files, reorder the stream 12 | if (additionalFiles.length > 0) { 13 | source = reorderTheStream.call(self, globs, src); 14 | } 15 | 16 | return source || src; 17 | }; 18 | -------------------------------------------------------------------------------- /lib/addHtmlToStream.js: -------------------------------------------------------------------------------- 1 | const PluginError = require('plugin-error'); 2 | 3 | module.exports = function (file, data) { 4 | const self = this; 5 | 6 | try { 7 | file.contents = Buffer.from(data); 8 | self.push(file); 9 | } catch (err) { 10 | self.emit('error', new PluginError('gulp-useref', err)); 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /lib/end.js: -------------------------------------------------------------------------------- 1 | module.exports = () => { 2 | let _end; 3 | 4 | function get() { 5 | return _end; 6 | } 7 | 8 | function set(cb) { 9 | _end = cb; 10 | 11 | return _end; 12 | } 13 | 14 | function fn() { 15 | return _end(); 16 | } 17 | 18 | return { 19 | get, 20 | set, 21 | fn 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /lib/getGlobs.js: -------------------------------------------------------------------------------- 1 | const getPattern = require('./getPattern'); 2 | 3 | module.exports = (paths, files) => { 4 | let pattern; 5 | let matches; 6 | const glob = require('glob'); 7 | let searchPath = paths.searchPath; 8 | const name = paths.name; 9 | const cwd = paths.cwd; 10 | const basePath = paths.basePath; 11 | const filepath = paths.filepath; 12 | const transformPath = paths.transformPath; 13 | 14 | if (searchPath && Array.isArray(searchPath)) { 15 | searchPath = searchPath.length === 1 ? searchPath[0] : `{${searchPath.join(',')}}`; 16 | } 17 | 18 | pattern = getPattern(files, { 19 | destPath: name, 20 | searchPath, 21 | cwd, 22 | basePath, 23 | srcPath: filepath 24 | }); 25 | 26 | matches = glob.sync(pattern, { nosort: true }); 27 | 28 | if (!matches.length) { 29 | matches.push(pattern); 30 | } 31 | 32 | if (transformPath) { 33 | matches[0] = transformPath(matches[0]); 34 | } 35 | 36 | return matches[0]; 37 | }; 38 | -------------------------------------------------------------------------------- /lib/getPattern.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = (files, paths) => { 4 | let searchPaths; 5 | const destPath = paths.destPath; 6 | const searchPath = paths.searchPath; 7 | const cwd = paths.cwd; 8 | const basePath = paths.basePath; 9 | const srcPath = paths.srcPath; 10 | 11 | if (files[destPath].searchPaths || searchPath) { 12 | searchPaths = path.resolve(cwd, files[destPath].searchPaths || searchPath); 13 | } 14 | return (searchPaths || basePath) + path.sep + srcPath; 15 | }; 16 | -------------------------------------------------------------------------------- /lib/reorderTheStream.js: -------------------------------------------------------------------------------- 1 | const through = require('through2'); 2 | 3 | module.exports = function (globs, src) { 4 | const self = this; 5 | const sortIndex = {}; 6 | let i = 0; 7 | const sortedFiles = []; 8 | const unsortedFiles = []; 9 | 10 | // Create a sort index so we don't iterate over the globs for every file 11 | globs.forEach(filename => { 12 | sortIndex[filename] = i++; 13 | }); 14 | 15 | return src.pipe(through.obj((srcFile, encoding, callback) => { 16 | const index = sortIndex[srcFile.path]; 17 | 18 | if (index === undefined) { 19 | unsortedFiles.push(srcFile); 20 | } else { 21 | sortedFiles[index] = srcFile; 22 | } 23 | callback(); 24 | }, callback => { 25 | sortedFiles.forEach(function (sorted) { 26 | if (sorted !== undefined) { 27 | this.push(sorted); 28 | } 29 | }, self); 30 | 31 | unsortedFiles.forEach(function (unsorted) { 32 | this.push(unsorted); 33 | }, self); 34 | callback(); 35 | })); 36 | }; 37 | -------------------------------------------------------------------------------- /lib/unprocessedCounter.js: -------------------------------------------------------------------------------- 1 | module.exports = () => { 2 | let unprocessed = 0; 3 | 4 | return { 5 | get() { 6 | return unprocessed; 7 | }, 8 | 9 | increment() { 10 | return unprocessed++; 11 | }, 12 | 13 | decrement() { 14 | return --unprocessed; 15 | } 16 | }; 17 | }; 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-useref", 3 | "version": "5.0.0", 4 | "description": "Parse build blocks in HTML files to replace references to non-optimized scripts or stylesheets.", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "dependencies": { 10 | "event-stream": "^4.0.1", 11 | "extend": "^3.0.2", 12 | "glob": "^7.2.0", 13 | "gulp-concat": "^2.6.1", 14 | "gulp-if": "^3.0.0", 15 | "plugin-error": "^1.0.1", 16 | "through2": "^4.0.2", 17 | "useref": "^1.4.4", 18 | "vinyl-fs": "^3.0.3" 19 | }, 20 | "devDependencies": { 21 | "async-once": "^1.0.1", 22 | "babel-eslint": "^10.1.0", 23 | "coveralls": "^3.1.1", 24 | "gulp": "^4.0.2", 25 | "gulp-eslint": "^6.0.0", 26 | "gulp-mocha": "^8.0.0", 27 | "gulp-rename": "^2.0.0", 28 | "mocha": "^9.2.2", 29 | "mock-gulp-dest": "^0.1.1", 30 | "nyc": "^15.1.0", 31 | "should": "*", 32 | "vinyl": "^2.2.1" 33 | }, 34 | "engines": { 35 | "node": ">=0.10.0" 36 | }, 37 | "scripts": { 38 | "test": "mocha", 39 | "lint": "gulp lint", 40 | "coverage": "nyc npm test && nyc report", 41 | "coveralls": "nyc npm test && nyc report --reporter=lcov" 42 | }, 43 | "files": [ 44 | "index.js", 45 | "lib" 46 | ], 47 | "repository": "jonkemp/gulp-useref", 48 | "keywords": [ 49 | "gulpplugin", 50 | "html", 51 | "scripts", 52 | "css", 53 | "optimize", 54 | "concat" 55 | ], 56 | "author": "Jonathan Kemp (http://jonkemp.com/)", 57 | "license": "MIT" 58 | } 59 | -------------------------------------------------------------------------------- /test/.tmp/css/one.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } -------------------------------------------------------------------------------- /test/.tmp/css/two.css: -------------------------------------------------------------------------------- 1 | a, 2 | a:visited { 3 | color: #003F87; 4 | } 5 | a:hover, 6 | a:focus, 7 | a:active { 8 | color: #CCC; 9 | } -------------------------------------------------------------------------------- /test/.tmp/scripts/anotherone.js: -------------------------------------------------------------------------------- 1 | var samurai = function(){}; 2 | samurai(); -------------------------------------------------------------------------------- /test/.tmp/scripts/module1.js: -------------------------------------------------------------------------------- 1 | var x = 'abc'; 2 | console.log(x); -------------------------------------------------------------------------------- /test/.tmp/scripts/module2.js: -------------------------------------------------------------------------------- 1 | function ninja(){} 2 | ninja(); -------------------------------------------------------------------------------- /test/.tmp/scripts/that.js: -------------------------------------------------------------------------------- 1 | function ninja(){} 2 | ninja(); -------------------------------------------------------------------------------- /test/.tmp/scripts/this.js: -------------------------------------------------------------------------------- 1 | var x = 'abc'; 2 | console.log(x); -------------------------------------------------------------------------------- /test/.tmp/scripts/yetonemore.js: -------------------------------------------------------------------------------- 1 | var o = {}; 2 | o.whatever = function(){}; 3 | o.whatever(); -------------------------------------------------------------------------------- /test/expected/01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test/expected/02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/expected/03.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/expected/04.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/expected/css/ordered.css: -------------------------------------------------------------------------------- 1 | .z { 2 | /* */ 3 | } 4 | 5 | .a { 6 | /* */ 7 | } 8 | -------------------------------------------------------------------------------- /test/expected/custom-blocks.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | customResult 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/expected/noconcat-css.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/expected/noconcat-js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/fixtures/01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/fixtures/02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/03.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/fixtures/04.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /test/fixtures/05.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/fixtures/06.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/07.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/fixtures/08.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/fixtures/09.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/fixtures/10.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/11.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/fixtures/12.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/fixtures/absolute-search-path.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/alternate-search-paths.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/fixtures/bad-path.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.01.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.02.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.03.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.03.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.04.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.04.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.05.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.05.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.06.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.06.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.07.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.07.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.08.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.08.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.09.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.09.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.10.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.10.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.11.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.11.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.12.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.12.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.13.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.13.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.14.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.14.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.15.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.15.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.16.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.16.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.17.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.17.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.18.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.18.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.19.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.19.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.20.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.20.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.21.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.21.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.22.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.22.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.23.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.23.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.24.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.24.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.25.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.25.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.26.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.26.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.27.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.27.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.28.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.28.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.29.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.29.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.30.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.30.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.31.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.31.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.32.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.32.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.33.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.33.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.34.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.34.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.35.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.35.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.36.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.36.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.37.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.37.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.38.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.38.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.39.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.39.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.40.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.40.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.41.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.41.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.42.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.42.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.43.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.43.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.44.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.44.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.45.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.45.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.46.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.46.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.47.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.47.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.48.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.48.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.49.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.49.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.50.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.50.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.51.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.51.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.52.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.52.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.53.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.53.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.54.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.54.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.55.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.55.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.56.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonkemp/gulp-useref/d7871c735030598f721b61fa1db1241c20d05651/test/fixtures/bulk/useref.56.css -------------------------------------------------------------------------------- /test/fixtures/bulk/useref.56.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /test/fixtures/css/a.css: -------------------------------------------------------------------------------- 1 | .a { 2 | /* */ 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/css/four.css: -------------------------------------------------------------------------------- 1 | #page { 2 | margin: 0 1em; 3 | } 4 | #header { 5 | margin: 1em 0 2em; 6 | } -------------------------------------------------------------------------------- /test/fixtures/css/one.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } -------------------------------------------------------------------------------- /test/fixtures/css/three.css: -------------------------------------------------------------------------------- 1 | .clearfix:after { 2 | content: ""; 3 | display:table; 4 | clear:both; 5 | } 6 | .ir { 7 | text-indent: 100%; 8 | white-space:nowrap; 9 | overflow:hidden; 10 | } -------------------------------------------------------------------------------- /test/fixtures/css/two.css: -------------------------------------------------------------------------------- 1 | a, 2 | a:visited { 3 | color: #003F87; 4 | } 5 | a:hover, 6 | a:focus, 7 | a:active { 8 | color: #CCC; 9 | } -------------------------------------------------------------------------------- /test/fixtures/css/z.css: -------------------------------------------------------------------------------- 1 | .z { 2 | /* */ 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/custom-blocks.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | someContent 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/nonexistent.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test/fixtures/order.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test/fixtures/relative/child/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/fixtures/relative/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/fixtures/relative/styles/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } -------------------------------------------------------------------------------- /test/fixtures/remote-path.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/scripts/anotherone.js: -------------------------------------------------------------------------------- 1 | var samurai = function(){}; 2 | samurai(); -------------------------------------------------------------------------------- /test/fixtures/scripts/that.js: -------------------------------------------------------------------------------- 1 | function ninja(){} 2 | ninja(); -------------------------------------------------------------------------------- /test/fixtures/scripts/this.js: -------------------------------------------------------------------------------- 1 | var x = 'abc'; 2 | console.log(x); -------------------------------------------------------------------------------- /test/fixtures/scripts/yetonemore.js: -------------------------------------------------------------------------------- 1 | var o = {}; 2 | o.whatever = function(){}; 3 | o.whatever(); -------------------------------------------------------------------------------- /test/fixtures/templates1/component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/fixtures/templates2/component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/mock-all.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* global describe, it */ 3 | 4 | const should = require('should'); 5 | const path = require('path'); 6 | const gulp = require('gulp'); 7 | const useref = require('../index'); 8 | const through = require('through2'); 9 | const once = require('async-once'); 10 | 11 | describe('bulk files', function () { 12 | this.timeout(5000); 13 | 14 | it('should handle all files', done => { 15 | let seriesFn; 16 | const mockGulpDest = require('mock-gulp-dest')(gulp); 17 | 18 | function bulk() { 19 | return gulp.src('test/fixtures/bulk/useref.*.html') 20 | .pipe(useref()) 21 | .pipe(gulp.dest('dest', { cwd: 'test' })); 22 | } 23 | 24 | seriesFn = gulp.series(bulk, once(() => { 25 | mockGulpDest.cwd().should.equal(__dirname); 26 | mockGulpDest.basePath().should.equal(path.join(__dirname, 'dest')); 27 | mockGulpDest.assertDestContains([ 28 | 'useref.01.html', 29 | 'useref.02.html', 30 | 'useref.03.html', 31 | 'useref.04.html', 32 | 'useref.05.html', 33 | 'useref.06.html', 34 | 'useref.07.html', 35 | 'useref.08.html', 36 | 'useref.09.html', 37 | 'useref.10.html', 38 | 'useref.11.html', 39 | 'useref.12.html', 40 | 'useref.13.html', 41 | 'useref.14.html', 42 | 'useref.15.html', 43 | 'useref.16.html', 44 | 'useref.17.html', 45 | 'useref.18.html', 46 | 'useref.19.html', 47 | 'useref.20.html', 48 | 'useref.21.html', 49 | 'useref.22.html', 50 | 'useref.23.html', 51 | 'useref.24.html', 52 | 'useref.25.html', 53 | 'useref.26.html', 54 | 'useref.27.html', 55 | 'useref.28.html', 56 | 'useref.29.html', 57 | 'useref.30.html', 58 | 'useref.31.html', 59 | 'useref.32.html', 60 | 'useref.33.html', 61 | 'useref.34.html', 62 | 'useref.35.html', 63 | 'useref.36.html', 64 | 'useref.37.html', 65 | 'useref.38.html', 66 | 'useref.39.html', 67 | 'useref.40.html', 68 | 'useref.41.html', 69 | 'useref.42.html', 70 | 'useref.43.html', 71 | 'useref.44.html', 72 | 'useref.45.html', 73 | 'useref.46.html', 74 | 'useref.47.html', 75 | 'useref.48.html', 76 | 'useref.49.html', 77 | 'useref.50.html', 78 | 'useref.51.html', 79 | 'useref.52.html', 80 | 'useref.53.html', 81 | 'useref.54.html', 82 | 'useref.55.html', 83 | 'useref.01.min.css', 84 | 'useref.02.min.css', 85 | 'useref.03.min.css', 86 | 'useref.04.min.css', 87 | 'useref.05.min.css', 88 | 'useref.06.min.css', 89 | 'useref.07.min.css', 90 | 'useref.08.min.css', 91 | 'useref.09.min.css', 92 | 'useref.10.min.css', 93 | 'useref.11.min.css', 94 | 'useref.12.min.css', 95 | 'useref.13.min.css', 96 | 'useref.14.min.css', 97 | 'useref.15.min.css', 98 | 'useref.16.min.css', 99 | 'useref.17.min.css', 100 | 'useref.18.min.css', 101 | 'useref.19.min.css', 102 | 'useref.20.min.css', 103 | 'useref.21.min.css', 104 | 'useref.22.min.css', 105 | 'useref.23.min.css', 106 | 'useref.24.min.css', 107 | 'useref.25.min.css', 108 | 'useref.26.min.css', 109 | 'useref.27.min.css', 110 | 'useref.28.min.css', 111 | 'useref.29.min.css', 112 | 'useref.30.min.css', 113 | 'useref.31.min.css', 114 | 'useref.32.min.css', 115 | 'useref.33.min.css', 116 | 'useref.34.min.css', 117 | 'useref.35.min.css', 118 | 'useref.36.min.css', 119 | 'useref.37.min.css', 120 | 'useref.38.min.css', 121 | 'useref.39.min.css', 122 | 'useref.40.min.css', 123 | 'useref.41.min.css', 124 | 'useref.42.min.css', 125 | 'useref.43.min.css', 126 | 'useref.44.min.css', 127 | 'useref.45.min.css', 128 | 'useref.46.min.css', 129 | 'useref.47.min.css', 130 | 'useref.48.min.css', 131 | 'useref.49.min.css', 132 | 'useref.50.min.css', 133 | 'useref.51.min.css', 134 | 'useref.52.min.css', 135 | 'useref.53.min.css', 136 | 'useref.54.min.css', 137 | 'useref.55.min.css' 138 | ]); 139 | 140 | done(); 141 | })); 142 | 143 | seriesFn(); 144 | }); 145 | 146 | it('should handle all assets', done => { 147 | let seriesFn; 148 | const mockGulpDest = require('mock-gulp-dest')(gulp); 149 | 150 | function bulk() { 151 | return gulp.src('test/fixtures/bulk/useref.56.html') 152 | .pipe(useref({ noconcat: true })) 153 | .pipe(gulp.dest('dest', { cwd: 'test' })); 154 | } 155 | 156 | seriesFn = gulp.series(bulk, once(() => { 157 | mockGulpDest.cwd().should.equal(__dirname); 158 | mockGulpDest.basePath().should.equal(path.join(__dirname, 'dest')); 159 | mockGulpDest.assertDestContains([ 160 | 'useref.56.html', 161 | 'useref.01.css', 162 | 'useref.02.css', 163 | 'useref.03.css', 164 | 'useref.04.css', 165 | 'useref.05.css', 166 | 'useref.06.css', 167 | 'useref.07.css', 168 | 'useref.08.css', 169 | 'useref.09.css', 170 | 'useref.10.css', 171 | 'useref.11.css', 172 | 'useref.12.css', 173 | 'useref.13.css', 174 | 'useref.14.css', 175 | 'useref.15.css', 176 | 'useref.16.css', 177 | 'useref.17.css', 178 | 'useref.18.css', 179 | 'useref.19.css', 180 | 'useref.20.css', 181 | 'useref.21.css', 182 | 'useref.22.css', 183 | 'useref.23.css', 184 | 'useref.24.css', 185 | 'useref.25.css', 186 | 'useref.26.css', 187 | 'useref.27.css', 188 | 'useref.28.css', 189 | 'useref.29.css', 190 | 'useref.30.css', 191 | 'useref.31.css', 192 | 'useref.32.css', 193 | 'useref.33.css', 194 | 'useref.34.css', 195 | 'useref.35.css', 196 | 'useref.36.css', 197 | 'useref.37.css', 198 | 'useref.38.css', 199 | 'useref.39.css', 200 | 'useref.40.css', 201 | 'useref.41.css', 202 | 'useref.42.css', 203 | 'useref.43.css', 204 | 'useref.44.css', 205 | 'useref.45.css', 206 | 'useref.46.css', 207 | 'useref.47.css', 208 | 'useref.48.css', 209 | 'useref.49.css', 210 | 'useref.50.css', 211 | 'useref.51.css', 212 | 'useref.52.css', 213 | 'useref.53.css', 214 | 'useref.54.css', 215 | 'useref.55.css', 216 | 'useref.56.css' 217 | ]); 218 | 219 | done(); 220 | })); 221 | 222 | seriesFn(); 223 | }); 224 | 225 | it('should not end the stream prematurely', done => { 226 | let fileCount = 0; 227 | 228 | gulp.src('test/fixtures/04.html') 229 | .pipe(useref()) 230 | .pipe(through.obj({ highWaterMark: 1 }, (newFile, enc, callback) => { 231 | fileCount++; 232 | setTimeout(callback, 750); 233 | }, cb => { 234 | fileCount.should.equal(5); 235 | done(); 236 | cb(); 237 | })); 238 | }); 239 | }); 240 | -------------------------------------------------------------------------------- /test/mock-relative.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* global describe, it */ 3 | 4 | const should = require('should'); 5 | const path = require('path'); 6 | const once = require('async-once'); 7 | 8 | describe('relative files', function () { 9 | this.timeout(5000); 10 | 11 | it('should handle relative files', done => { 12 | let seriesFn; 13 | const gulp = require('gulp'); 14 | const mockGulpDest = require('mock-gulp-dest')(gulp); 15 | const useref = require('../index'); 16 | 17 | function relative() { 18 | return gulp.src('test/fixtures/relative/**/*.html') 19 | .pipe(useref()) 20 | .pipe(gulp.dest('fixtures/relative/styles', { cwd: 'test' })); 21 | } 22 | 23 | seriesFn = gulp.series(relative, once(() => { 24 | mockGulpDest.cwd().should.equal(__dirname); 25 | mockGulpDest.basePath().should.equal(path.join(__dirname, 'fixtures/relative/styles')); 26 | mockGulpDest.assertDestContains([ 27 | 'bundle.css' 28 | ]); 29 | 30 | done(); 31 | })); 32 | 33 | seriesFn(); 34 | }); 35 | 36 | it('should handle relative files when base is set', done => { 37 | let seriesFn; 38 | const gulp = require('gulp'); 39 | const mockGulpDest = require('mock-gulp-dest')(gulp); 40 | const useref = require('../index'); 41 | 42 | function relativeBase() { 43 | return gulp.src(['test/fixtures/templates1/**/*.html', 'test/fixtures/templates2/**/*.html']) 44 | .pipe(useref({ 45 | searchPath: 'test/fixtures', 46 | base: 'test/fixtures' 47 | })) 48 | .pipe(gulp.dest('test/dist')); 49 | } 50 | 51 | seriesFn = gulp.series(relativeBase, once(() => { 52 | mockGulpDest.basePath().should.equal(path.join(__dirname, 'dist')); 53 | mockGulpDest.assertDestContains([ 54 | 'css/bundle.css', 55 | 'css/combined.css' 56 | ]); 57 | 58 | done(); 59 | })); 60 | 61 | seriesFn(); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* global describe, it */ 3 | const should = require('should'); 4 | const fs = require('fs'); 5 | const path = require('path'); 6 | const Vinyl = require('vinyl'); 7 | const es = require('event-stream'); 8 | const useref = require('../index'); 9 | const gulp = require('gulp'); 10 | const rename = require('gulp-rename'); 11 | const through = require('through2'); 12 | 13 | function getFile(filePath) { 14 | return new Vinyl({ 15 | path: filePath, 16 | cwd: __dirname, 17 | base: path.dirname(filePath), 18 | contents: fs.readFileSync(filePath) 19 | }); 20 | } 21 | 22 | function getFixture(filePath) { 23 | return getFile(path.join('test', 'fixtures', filePath)); 24 | } 25 | 26 | function getExpected(filePath) { 27 | return getFile(path.join('test', 'expected', filePath)); 28 | } 29 | 30 | function compare(name, expectedName, done) { 31 | const stream = useref({ noAssets: true }); 32 | 33 | stream.on('data', newFile => { 34 | if (path.basename(newFile.path) === name) { 35 | should(String(getExpected(expectedName).contents)).eql(String(newFile.contents)); 36 | } 37 | }); 38 | 39 | stream.on('end', () => { 40 | done(); 41 | }); 42 | 43 | stream.write(getFixture(name)); 44 | 45 | stream.end(); 46 | } 47 | 48 | describe('useref()', function() { 49 | this.timeout(5000); 50 | 51 | it('file should pass through', done => { 52 | let a = 0; 53 | 54 | const fakeFile = new Vinyl({ 55 | path: '/test/fixture/file.js', 56 | cwd: '/test/', 57 | base: '/test/fixture/', 58 | contents: Buffer.from('wadup();') 59 | }); 60 | 61 | const stream = useref(); 62 | stream.on('data', newFile => { 63 | should.exist(newFile.contents); 64 | newFile.path.should.equal('/test/fixture/file.js'); 65 | newFile.relative.should.equal('file.js'); 66 | ++a; 67 | }); 68 | 69 | stream.once('end', () => { 70 | a.should.equal(1); 71 | done(); 72 | }); 73 | 74 | stream.write(fakeFile); 75 | stream.end(); 76 | }); 77 | 78 | it('should let null files pass through', done => { 79 | const stream = useref({ noAssets: true }); 80 | let n = 0; 81 | 82 | stream.pipe(es.through(file => { 83 | should.equal(file.path, 'null.md'); 84 | should.equal(file.contents, null); 85 | n++; 86 | }, () => { 87 | should.equal(n, 1); 88 | done(); 89 | })); 90 | 91 | stream.write(new Vinyl({ 92 | path: 'null.md', 93 | contents: null 94 | })); 95 | 96 | stream.end(); 97 | }); 98 | 99 | it('should emit error on streamed file', done => { 100 | gulp.src(path.join('test', 'fixtures', '01.html'), { buffer: false }) 101 | .pipe(useref({ noAssets: true })) 102 | .on('error', ({message}) => { 103 | message.should.equal('Streaming not supported'); 104 | done(); 105 | }); 106 | }); 107 | 108 | it('should replace reference in css block and return replaced files', done => { 109 | compare('01.html', '01.html', done); 110 | }); 111 | 112 | it('should replace reference in js block and return replaced files', done => { 113 | compare('02.html', '02.html', done); 114 | }); 115 | 116 | it('should handle comments and whitespace in blocks', done => { 117 | compare('03.html', '03.html', done); 118 | }); 119 | 120 | it('should handle multiple blocks', done => { 121 | compare('04.html', '04.html', done); 122 | }); 123 | 124 | it('should handle custom blocks', done => { 125 | const stream = useref({ 126 | noAssets: true, 127 | custom(content, target) { 128 | return content === 'someContent' ? target : content; 129 | } 130 | }); 131 | 132 | stream.on('data', ({contents}) => { 133 | getExpected('custom-blocks.html').contents.toString().should.equal(contents.toString()); 134 | }); 135 | 136 | stream.on('end', done); 137 | 138 | stream.write(getFixture('custom-blocks.html')); 139 | stream.end(); 140 | }); 141 | 142 | it('should concat CSS assets and pass them through', done => { 143 | let a = 0; 144 | 145 | const testFile = getFixture('01.html'); 146 | 147 | const stream = useref(); 148 | 149 | stream.on('data', newFile => { 150 | should.exist(newFile.contents); 151 | if (a === 1) { 152 | newFile.path.should.equal(path.normalize('./test/fixtures/css/combined.css')); 153 | } 154 | ++a; 155 | }); 156 | 157 | stream.once('end', () => { 158 | a.should.equal(2); 159 | done(); 160 | }); 161 | 162 | stream.write(testFile); 163 | 164 | stream.end(); 165 | }); 166 | 167 | it('should concat CSS assets with newLine option', done => { 168 | let a = 0; 169 | const testFile = getFixture('01.html'); 170 | const separator = '\r\n'; 171 | const stream = useref({newLine: separator}); 172 | const buffer1 = Buffer.from(fs.readFileSync(path.join('test', 'fixtures', 'css', 'one.css'))); 173 | const buffer2 = Buffer.from(separator); 174 | const buffer3 = Buffer.from(fs.readFileSync(path.join('test', 'fixtures', 'css', 'two.css'))); 175 | const bufferFinal = Buffer.concat([buffer1, buffer2, buffer3]); 176 | const fileFinal = new Vinyl({ contents: bufferFinal }); 177 | 178 | stream.on('data', newFile => { 179 | if (a === 1) { 180 | newFile.path.should.equal(path.normalize('./test/fixtures/css/combined.css')); 181 | newFile.contents.toString().should.equal(fileFinal.contents.toString()); 182 | } 183 | ++a; 184 | }); 185 | 186 | stream.once('end', () => { 187 | a.should.equal(2); 188 | done(); 189 | }); 190 | 191 | stream.write(testFile); 192 | 193 | stream.end(); 194 | }); 195 | 196 | it('should concat CSS assets but skip newLine option if semicolon', done => { 197 | let a = 0; 198 | const testFile = getFixture('01.html'); 199 | const separator = ';'; 200 | const stream = useref({newLine: separator}); 201 | const buffer1 = Buffer.from(fs.readFileSync(path.join('test', 'fixtures', 'css', 'one.css'))); 202 | const buffer2 = Buffer.from('\n'); 203 | const buffer3 = Buffer.from(fs.readFileSync(path.join('test', 'fixtures', 'css', 'two.css'))); 204 | const bufferFinal = Buffer.concat([buffer1, buffer2, buffer3]); 205 | const fileFinal = new Vinyl({ contents: bufferFinal }); 206 | 207 | stream.on('data', newFile => { 208 | if (a === 1) { 209 | newFile.path.should.equal(path.normalize('./test/fixtures/css/combined.css')); 210 | newFile.contents.toString().should.equal(fileFinal.contents.toString()); 211 | } 212 | ++a; 213 | }); 214 | 215 | stream.once('end', () => { 216 | a.should.equal(2); 217 | done(); 218 | }); 219 | 220 | stream.write(testFile); 221 | 222 | stream.end(); 223 | }); 224 | 225 | it('should skip concatenation and pass CSS assets through with noconcat option', done => { 226 | let a = 0; 227 | 228 | const testFile = getFixture('01.html'); 229 | 230 | const stream = useref({ noconcat: true }); 231 | 232 | stream.on('data', newFile => { 233 | should.exist(newFile.contents); 234 | 235 | if (a === 0) { 236 | getExpected('noconcat-css.html').contents.toString().should.equal(newFile.contents.toString()); 237 | } else if (a === 1) { 238 | path.normalize(newFile.path).should.equal(path.join(__dirname, './fixtures/css/one.css')); 239 | } else if (a === 2) { 240 | path.normalize(newFile.path).should.equal(path.join(__dirname, './fixtures/css/two.css')); 241 | } 242 | ++a; 243 | }); 244 | 245 | stream.once('end', () => { 246 | a.should.equal(3); 247 | done(); 248 | }); 249 | 250 | stream.write(testFile); 251 | 252 | stream.end(); 253 | }); 254 | 255 | it('should concat JS assets and pass them through', done => { 256 | let a = 0; 257 | 258 | const testFile = getFixture('02.html'); 259 | 260 | const stream = useref(); 261 | 262 | stream.on('data', newFile => { 263 | should.exist(newFile.contents); 264 | if (a === 1) { 265 | newFile.path.should.equal(path.normalize('./test/fixtures/scripts/combined.js')); 266 | } 267 | ++a; 268 | }); 269 | 270 | stream.once('end', () => { 271 | a.should.equal(2); 272 | done(); 273 | }); 274 | 275 | stream.write(testFile); 276 | 277 | stream.end(); 278 | }); 279 | 280 | it('should concat JS assets with newLine option', done => { 281 | let a = 0; 282 | const testFile = getFixture('02.html'); 283 | const separator = '\r\n'; 284 | const stream = useref({newLine: separator}); 285 | const buffer1 = Buffer.from(fs.readFileSync(path.join('test', 'fixtures', 'scripts', 'this.js'))); 286 | const buffer2 = Buffer.from(separator); 287 | const buffer3 = Buffer.from(fs.readFileSync(path.join('test', 'fixtures', 'scripts', 'that.js'))); 288 | const bufferFinal = Buffer.concat([buffer1, buffer2, buffer3]); 289 | const fileFinal = new Vinyl({ contents: bufferFinal }); 290 | 291 | stream.on('data', newFile => { 292 | if (a === 1) { 293 | newFile.path.should.equal(path.normalize('./test/fixtures/scripts/combined.js')); 294 | newFile.contents.toString().should.equal(fileFinal.contents.toString()); 295 | } 296 | ++a; 297 | }); 298 | 299 | stream.once('end', () => { 300 | a.should.equal(2); 301 | done(); 302 | }); 303 | 304 | stream.write(testFile); 305 | 306 | stream.end(); 307 | }); 308 | 309 | it('should concat JS assets with newLine option if semicolon', done => { 310 | let a = 0; 311 | const testFile = getFixture('02.html'); 312 | const separator = ';'; 313 | const stream = useref({newLine: separator}); 314 | const buffer1 = Buffer.from(fs.readFileSync(path.join('test', 'fixtures', 'scripts', 'this.js'))); 315 | const buffer2 = Buffer.from(separator); 316 | const buffer3 = Buffer.from(fs.readFileSync(path.join('test', 'fixtures', 'scripts', 'that.js'))); 317 | const bufferFinal = Buffer.concat([buffer1, buffer2, buffer3]); 318 | const fileFinal = new Vinyl({ contents: bufferFinal }); 319 | 320 | stream.on('data', newFile => { 321 | if (a === 1) { 322 | newFile.path.should.equal(path.normalize('./test/fixtures/scripts/combined.js')); 323 | newFile.contents.toString().should.equal(fileFinal.contents.toString()); 324 | } 325 | ++a; 326 | }); 327 | 328 | stream.once('end', () => { 329 | a.should.equal(2); 330 | done(); 331 | }); 332 | 333 | stream.write(testFile); 334 | 335 | stream.end(); 336 | }); 337 | 338 | it('should skip concatenation and pass JS assets through with noconcat option', done => { 339 | let a = 0; 340 | 341 | const testFile = getFixture('02.html'); 342 | 343 | const stream = useref({ noconcat: true }); 344 | 345 | stream.on('data', newFile => { 346 | should.exist(newFile.contents); 347 | 348 | if (a === 0) { 349 | getExpected('noconcat-js.html').contents.toString().should.equal(newFile.contents.toString()); 350 | } else if (a === 1) { 351 | path.normalize(newFile.path).should.equal(path.join(__dirname, './fixtures/scripts/this.js')); 352 | } else if (a === 2) { 353 | path.normalize(newFile.path).should.equal(path.join(__dirname, './fixtures/scripts/that.js')); 354 | } 355 | ++a; 356 | }); 357 | 358 | stream.once('end', () => { 359 | a.should.equal(3); 360 | done(); 361 | }); 362 | 363 | stream.write(testFile); 364 | 365 | stream.end(); 366 | }); 367 | 368 | it('should handle an alternate css search path', done => { 369 | let a = 0; 370 | 371 | const testFile = getFixture('05.html'); 372 | 373 | const stream = useref(); 374 | 375 | stream.on('data', newFile => { 376 | should.exist(newFile.contents); 377 | if (a === 1) { 378 | newFile.path.should.equal(path.normalize('./test/fixtures/css/combined.css')); 379 | } 380 | ++a; 381 | }); 382 | 383 | stream.once('end', () => { 384 | a.should.equal(2); 385 | done(); 386 | }); 387 | 388 | stream.write(testFile); 389 | 390 | stream.end(); 391 | }); 392 | 393 | it('should handle an alternate js search path', done => { 394 | let a = 0; 395 | 396 | const testFile = getFixture('06.html'); 397 | 398 | const stream = useref(); 399 | 400 | stream.on('data', newFile => { 401 | should.exist(newFile.contents); 402 | if (a === 1) { 403 | newFile.path.should.equal(path.normalize('./test/fixtures/scripts/combined.js')); 404 | } 405 | ++a; 406 | }); 407 | 408 | stream.once('end', () => { 409 | a.should.equal(2); 410 | done(); 411 | }); 412 | 413 | stream.write(testFile); 414 | 415 | stream.end(); 416 | }); 417 | 418 | it('should handle an alternate js search path with file separator', done => { 419 | let a = 0; 420 | 421 | const testFile = getFixture('12.html'); 422 | 423 | const stream = useref(); 424 | 425 | stream.on('data', newFile => { 426 | should.exist(newFile.contents); 427 | if (a === 1) { 428 | newFile.path.should.equal(path.normalize('./test/fixtures/scripts/combined.js')); 429 | } 430 | ++a; 431 | }); 432 | 433 | stream.once('end', () => { 434 | a.should.equal(2); 435 | done(); 436 | }); 437 | 438 | stream.write(testFile); 439 | 440 | stream.end(); 441 | }); 442 | 443 | it('should get the alternate search path from options via string', done => { 444 | let a = 0; 445 | 446 | const testFile = getFixture('07.html'); 447 | 448 | const stream = useref({ 449 | searchPath: '.tmp' 450 | }); 451 | 452 | stream.on('data', newFile => { 453 | should.exist(newFile.contents); 454 | switch (newFile.path) { 455 | case path.normalize('./test/fixtures/scripts/main.js'): 456 | newFile.path.should.equal(path.normalize('./test/fixtures/scripts/main.js')); 457 | break; 458 | case path.normalize('./test/fixtures/css/combined.css'): 459 | newFile.path.should.equal(path.normalize('./test/fixtures/css/combined.css')); 460 | break; 461 | } 462 | ++a; 463 | }); 464 | 465 | stream.once('end', () => { 466 | a.should.equal(3); 467 | done(); 468 | }); 469 | 470 | stream.write(testFile); 471 | 472 | stream.end(); 473 | }); 474 | 475 | it('should get the alternate search path from options via array', done => { 476 | let a = 0; 477 | 478 | const testFile = getFixture('07.html'); 479 | 480 | const stream = useref({ 481 | searchPath: ['.tmp'] 482 | }); 483 | 484 | stream.on('data', newFile => { 485 | should.exist(newFile.contents); 486 | switch (newFile.path) { 487 | case path.normalize('./test/fixtures/scripts/main.js'): 488 | newFile.path.should.equal(path.normalize('./test/fixtures/scripts/main.js')); 489 | break; 490 | case path.normalize('./test/fixtures/css/combined.css'): 491 | newFile.path.should.equal(path.normalize('./test/fixtures/css/combined.css')); 492 | break; 493 | } 494 | ++a; 495 | }); 496 | 497 | stream.once('end', () => { 498 | a.should.equal(3); 499 | done(); 500 | }); 501 | 502 | stream.write(testFile); 503 | 504 | stream.end(); 505 | }); 506 | 507 | it('should get the alternate search paths from options via array', done => { 508 | let a = 0; 509 | 510 | const testFile = getFixture('alternate-search-paths.html'); 511 | 512 | const stream = useref({ 513 | searchPath: ['.tmp', 'fixtures'] 514 | }); 515 | 516 | stream.on('data', newFile => { 517 | should.exist(newFile.contents); 518 | switch (newFile.path) { 519 | case path.normalize('./test/fixtures/scripts/main.js'): 520 | newFile.path.should.equal(path.normalize('./test/fixtures/scripts/main.js')); 521 | break; 522 | case path.normalize('./test/fixtures/css/combined.css'): 523 | newFile.path.should.equal(path.normalize('./test/fixtures/css/combined.css')); 524 | break; 525 | } 526 | ++a; 527 | }); 528 | 529 | stream.once('end', () => { 530 | a.should.equal(3); 531 | done(); 532 | }); 533 | 534 | stream.write(testFile); 535 | 536 | stream.end(); 537 | }); 538 | 539 | it('should get the alternate search paths from options with brace expansion', done => { 540 | let a = 0; 541 | 542 | const testFile = getFixture('alternate-search-paths.html'); 543 | 544 | const stream = useref({ 545 | searchPath: '{.tmp,fixtures}' 546 | }); 547 | 548 | stream.on('data', newFile => { 549 | should.exist(newFile.contents); 550 | switch (newFile.path) { 551 | case path.normalize('./test/fixtures/scripts/main.js'): 552 | newFile.path.should.equal(path.normalize('./test/fixtures/scripts/main.js')); 553 | break; 554 | case path.normalize('./test/fixtures/css/combined.css'): 555 | newFile.path.should.equal(path.normalize('./test/fixtures/css/combined.css')); 556 | break; 557 | } 558 | ++a; 559 | }); 560 | 561 | stream.once('end', () => { 562 | a.should.equal(3); 563 | done(); 564 | }); 565 | 566 | stream.write(testFile); 567 | 568 | stream.end(); 569 | }); 570 | 571 | it('should get assets with parent directory reference using brace expansion', done => { 572 | let a = 0; 573 | 574 | const testFile = getFixture('07.html'); 575 | 576 | const stream = useref({ 577 | searchPath: '{.{,t{,m}}p,../another/search/path}' 578 | }); 579 | 580 | stream.on('data', newFile => { 581 | should.exist(newFile.contents); 582 | switch (newFile.path) { 583 | case path.normalize('./test/fixtures/scripts/main.js'): 584 | newFile.path.should.equal(path.normalize('./test/fixtures/scripts/main.js')); 585 | break; 586 | case path.normalize('./test/fixtures/css/combined.css'): 587 | newFile.path.should.equal(path.normalize('./test/fixtures/css/combined.css')); 588 | break; 589 | } 590 | ++a; 591 | }); 592 | 593 | stream.once('end', () => { 594 | a.should.equal(3); 595 | done(); 596 | }); 597 | 598 | stream.write(testFile); 599 | 600 | stream.end(); 601 | }); 602 | 603 | it('should handle an alternate search path in multiple build blocks', done => { 604 | let a = 0; 605 | 606 | const testFile = getFixture('08.html'); 607 | 608 | const stream = useref(); 609 | 610 | stream.on('data', newFile => { 611 | const assetpath = [ 612 | './test/fixtures/css/combined.css', 613 | './test/fixtures/scripts/combined.min.js', 614 | './test/fixtures/scripts/combined2.min.js' 615 | ]; 616 | 617 | assetpath.forEach(filepath => { 618 | if (newFile.path === path.normalize(filepath)) { 619 | should.exist(newFile.contents); 620 | newFile.path.should.equal(path.normalize(filepath)); 621 | ++a; 622 | } 623 | }); 624 | }); 625 | 626 | stream.once('end', () => { 627 | a.should.equal(3); 628 | done(); 629 | }); 630 | 631 | stream.write(testFile); 632 | 633 | stream.end(); 634 | }); 635 | 636 | it('should ignore build blocks with no assets', done => { 637 | let a = 0; 638 | 639 | const testFile = getFixture('09.html'); 640 | 641 | const stream = useref(); 642 | 643 | stream.on('data', newFile => { 644 | should.exist(newFile.contents); 645 | newFile.path.should.not.equal(path.normalize('./test/fixtures/css/vendor.css')); 646 | ++a; 647 | }); 648 | 649 | stream.once('end', () => { 650 | a.should.equal(1); 651 | done(); 652 | }); 653 | 654 | stream.write(testFile); 655 | 656 | stream.end(); 657 | }); 658 | 659 | it('should understand absolute search paths', done => { 660 | let a = 0; 661 | 662 | const testFile = getFixture('absolute-search-path.html'); 663 | 664 | const searchPath = path.join(__dirname, 'fixtures', 'css'); 665 | 666 | const stream = useref({ 667 | searchPath 668 | }); 669 | 670 | stream.on('data', newFile => { 671 | should.exist(newFile.contents); 672 | if (a === 1) { 673 | newFile.path.should.equal(path.normalize('./test/fixtures/css/combined.css')); 674 | } 675 | ++a; 676 | }); 677 | 678 | stream.once('end', () => { 679 | a.should.equal(2); 680 | done(); 681 | }); 682 | 683 | stream.write(testFile); 684 | 685 | stream.end(); 686 | }); 687 | 688 | it('should not explode on custom blocks', done => { 689 | const stream = useref(); 690 | 691 | stream.on('end', () => { 692 | done(); 693 | }); 694 | 695 | stream.resume(); 696 | 697 | stream.write(getFixture('custom-blocks.html')); 698 | stream.end(); 699 | }); 700 | 701 | it('should work with relative paths', done => { 702 | let a = 0; 703 | 704 | const testFile = getFixture('10.html'); 705 | 706 | const stream = useref(); 707 | 708 | stream.on('data', newFile => { 709 | should.exist(newFile.contents); 710 | if (a === 1) { 711 | path.normalize(newFile.path).should.equal(path.normalize('./test/fixtures/scripts/combined.js')); 712 | } 713 | ++a; 714 | }); 715 | 716 | stream.once('end', () => { 717 | a.should.equal(2); 718 | done(); 719 | }); 720 | 721 | stream.write(testFile); 722 | 723 | stream.end(); 724 | }); 725 | 726 | it('should ignore absolute urls', done => { 727 | let a = 0; 728 | 729 | const testFile = getFixture('remote-path.html'); 730 | 731 | const stream = useref(); 732 | 733 | stream.on('data', newFile => { 734 | should.exist(newFile.contents); 735 | if (a === 1) { 736 | path.normalize(newFile.path).should.equal(path.normalize('./test/fixtures/css/combined.css')); 737 | } 738 | ++a; 739 | }); 740 | 741 | stream.once('end', () => { 742 | a.should.equal(2); 743 | done(); 744 | }); 745 | 746 | stream.write(testFile); 747 | 748 | stream.end(); 749 | }); 750 | 751 | it('should transform paths when transformPath function is set', done => { 752 | let a = 0; 753 | 754 | const testFile = getFixture('bad-path.html'); 755 | 756 | const stream = useref({ 757 | transformPath(filePath) { 758 | return filePath.replace('/rootpath',''); 759 | } 760 | }); 761 | 762 | stream.on('data', newFile => { 763 | should.exist(newFile.contents); 764 | if (a === 1) { 765 | path.normalize(newFile.path).should.equal(path.normalize('./test/fixtures/css/combined.css')); 766 | } 767 | ++a; 768 | }); 769 | 770 | stream.once('end', () => { 771 | a.should.equal(2); 772 | done(); 773 | }); 774 | 775 | stream.write(testFile); 776 | 777 | stream.end(); 778 | }); 779 | 780 | it('should return the assets in the order they were found', done => { 781 | const testOrderFile = getFixture('order.html'); 782 | 783 | const stream = useref(); 784 | 785 | stream.on('data',newFile => { 786 | if (newFile.path === path.normalize('./test/fixtures/css/ordered.css')) { 787 | should(String(getExpected('css/ordered.css').contents)).eql(String(newFile.contents)); 788 | 789 | done(); 790 | } 791 | }); 792 | 793 | stream.write(testOrderFile); 794 | 795 | stream.end(); 796 | }); 797 | 798 | it('should output assets to a folder relative to the cwd', done => { 799 | let a = 0; 800 | 801 | const testFile = getFixture('02.html'); 802 | 803 | const stream = useref({ base: 'app' }); 804 | 805 | stream.on('data', newFile => { 806 | should.exist(newFile.contents); 807 | if (a === 1) { 808 | path.normalize(newFile.path).should.equal(path.normalize('./app/scripts/combined.js')); 809 | } 810 | ++a; 811 | }); 812 | 813 | stream.once('end', () => { 814 | a.should.equal(2); 815 | done(); 816 | }); 817 | 818 | stream.write(testFile); 819 | 820 | stream.end(); 821 | }); 822 | 823 | it('should find assets relative to the root', done => { 824 | let a = 0; 825 | 826 | const testFile = getFixture(path.join('relative', 'child', 'index.html')); 827 | 828 | const stream = useref(); 829 | 830 | stream.on('data', newFile => { 831 | should.exist(newFile.contents); 832 | if (a === 1) { 833 | path.normalize(newFile.path).should.equal(path.normalize('./test/fixtures/relative/styles/bundle.css')); 834 | } 835 | ++a; 836 | }); 837 | 838 | stream.once('end', () => { 839 | a.should.equal(2); 840 | done(); 841 | }); 842 | 843 | stream.write(testFile); 844 | 845 | stream.end(); 846 | }); 847 | 848 | it('should set file.base when asked', done => { 849 | let a = 0; 850 | 851 | const testFile = getFixture(path.join('templates1', 'component.html')); 852 | 853 | const stream = useref({ 854 | searchPath: 'fixtures', 855 | base: 'fixtures' 856 | }); 857 | 858 | stream.on('data', newFile => { 859 | should.exist(newFile.contents); 860 | if (a === 1) { 861 | path.normalize(newFile.path).should.equal(path.normalize('./fixtures/css/bundle.css')); 862 | path.normalize(newFile.relative).should.equal(path.normalize('css/bundle.css')); 863 | } 864 | ++a; 865 | }); 866 | 867 | stream.once('end', () => { 868 | a.should.equal(2); 869 | done(); 870 | }); 871 | 872 | stream.write(testFile); 873 | 874 | stream.end(); 875 | }); 876 | 877 | it('should support external streams', done => { 878 | const extStream1 = gulp.src('test/fixtures/scripts/that.js') 879 | .pipe(rename('renamedthat.js')); 880 | 881 | const extStream2 = gulp.src('test/fixtures/scripts/yetonemore.js') 882 | .pipe(rename('renamedyet.js')); 883 | 884 | let fileCount = 0; 885 | 886 | const assets = useref({ 887 | noconcat: true, 888 | additionalStreams: [extStream1, extStream2] 889 | }); 890 | 891 | gulp.src('test/fixtures/11.html') 892 | .pipe(assets) 893 | .pipe(through.obj((newFile, enc, callback) => { 894 | const assetpath = [ 895 | `${__dirname}/fixtures/11.html`, 896 | `${__dirname}/fixtures/scripts/this.js`, 897 | `${__dirname}/fixtures/scripts/anotherone.js`, 898 | `${__dirname}/fixtures/scripts/renamedthat.js`, 899 | `${__dirname}/fixtures/scripts/renamedyet.js` 900 | ]; 901 | 902 | assetpath.forEach(filepath => { 903 | if (newFile.path === path.normalize(filepath)) { 904 | should.exist(newFile.contents); 905 | newFile.path.should.equal(path.normalize(filepath)); 906 | fileCount++; 907 | } 908 | }); 909 | callback(); 910 | }, () => { 911 | fileCount.should.equal(5); 912 | done(); 913 | })); 914 | }); 915 | }); 916 | 917 | describe('on error', () => { 918 | it('should emit an error if one of the assets is not found', done => { 919 | const testNonExistentFile = getFixture('nonexistent.html'); 920 | const stream = useref(); 921 | 922 | stream.on('error', err => { 923 | err.should.match(/File not found with singular glob/); 924 | done(); 925 | }); 926 | 927 | stream.write(testNonExistentFile); 928 | stream.end(); 929 | 930 | }); 931 | }); 932 | --------------------------------------------------------------------------------