├── .gitignore ├── test ├── testfiles │ ├── 08-expected.html │ ├── 09-expected.html │ ├── 18-expected.html │ ├── 19-expected.html │ ├── 25-expected.html │ ├── tmp │ │ └── out.html │ ├── 01-expected.html │ ├── 08.html │ ├── 10-expected.html │ ├── 15-expected.html │ ├── 20-expected.html │ ├── 24.html │ ├── 02-expected.html │ ├── 12-expected.html │ ├── 21-expected.html │ ├── 22-expected.html │ ├── 03-expected.html │ ├── 16-expected.html │ ├── 13-expected.html │ ├── 16-win-expected.html │ ├── 14-expected.html │ ├── 17-expected.html │ ├── 22.html │ ├── 23.html │ ├── 25.html │ ├── 19.html │ ├── 18.html │ ├── 01.html │ ├── 17.html │ ├── 05.html │ ├── 20.html │ ├── 09.html │ ├── 21.html │ ├── 15.html │ ├── 02.html │ ├── 12.html │ ├── 06.html │ ├── 03d.html │ ├── 03e.html │ ├── 03f.html │ ├── 13.html │ ├── 16.html │ ├── 14.html │ ├── 03c.html │ ├── 16-win.html │ ├── 26-expected.jade │ ├── 03.html │ ├── 03b.html │ ├── 04-expected.html │ ├── 10.html │ ├── 26.jade │ ├── 07.html │ └── 04.html └── test.js ├── package.json ├── LICENSE ├── README.md └── src └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /test/testfiles/08-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test/testfiles/09-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/testfiles/18-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/testfiles/19-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/testfiles/25-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | target 5 | 6 | target 7 | 8 | -------------------------------------------------------------------------------- /test/testfiles/tmp/out.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test/testfiles/01-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test/testfiles/08.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/testfiles/10-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
keepthis
6 | 7 | 8 | -------------------------------------------------------------------------------- /test/testfiles/15-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test/testfiles/20-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/testfiles/24.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/testfiles/02-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/testfiles/12-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/testfiles/21-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/testfiles/22-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/testfiles/03-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/testfiles/16-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /test/testfiles/13-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/testfiles/16-win-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /test/testfiles/14-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/testfiles/17-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/testfiles/22.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/testfiles/23.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/testfiles/25.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/testfiles/19.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/testfiles/18.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/testfiles/01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/testfiles/17.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/testfiles/05.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/testfiles/20.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/testfiles/09.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/testfiles/21.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/testfiles/15.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/testfiles/02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/testfiles/12.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/testfiles/06.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/testfiles/03d.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/testfiles/03e.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/testfiles/03f.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/testfiles/13.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/testfiles/16.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/testfiles/14.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/testfiles/03c.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/testfiles/16-win.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/testfiles/26-expected.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html(lang='en') 3 | head 4 | 5 | 6 | 7 | 8 | body 9 | block content 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/testfiles/03.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/testfiles/03b.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/testfiles/04-expected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/testfiles/10.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
keepthis
9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/testfiles/26.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html(lang='en') 3 | head 4 | 5 | //- build:css({.tmp/serve,src}) /styles/vendor.css --> 6 | link(rel='stylesheet', href='/bower_components/some_module/main.css') 7 | //- endbuild --> 8 | 9 | 10 | body 11 | block content 12 | 13 | //- build:js({.tmp/serve,src}) /scripts/vendor.js --> 14 | script(type='text/javascript', src='/bower_components/jquery/dist/jquery.js') 15 | //- endbuild --> 16 | 17 | //- build:js({src,.tmp/serve}) /scripts/app.js --> 18 | script(type='text/javascript', src='/config.js') 19 | //- endbuild --> 20 | -------------------------------------------------------------------------------- /test/testfiles/07.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-useref", 3 | "version": "0.3.15", 4 | "description": "Parse build blocks in HTML files to replace references", 5 | "main": "src/index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "mocha test" 11 | }, 12 | "keywords": [ 13 | "build", 14 | "blocks", 15 | "build", 16 | "comments", 17 | "replace", 18 | "scripts", 19 | "link", 20 | "ref" 21 | ], 22 | "author": "Manuel Cabral (m.cabral@digisfera.pt)", 23 | "license": "MIT", 24 | "dependencies": {}, 25 | "devDependencies": { 26 | "chai": "~1.8.1", 27 | "mocha": "~1.17.0" 28 | }, 29 | "repository": { 30 | "type": "git", 31 | "url": "git://github.com/manuelcabral/useref.git" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/testfiles/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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Digisfera 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 | # useref 2 | 3 | **This project is no longer maintained. Please see [this fork](https://github.com/jonkemp/useref).** 4 | 5 | Parse build blocks in HTML files to replace references. 6 | 7 | Extracted from the grunt plugin [grunt-useref](https://github.com/pajtai/grunt-useref). 8 | 9 | ## Installation 10 | 11 | ``` 12 | npm install node-useref 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | useref = require('node-useref') 19 | var result = useref(inputHtml) 20 | // result = [ replacedHtml, { type: { path: { 'assets': [ replacedFiles] }}} ] 21 | ``` 22 | 23 | 24 | Blocks are expressed as: 25 | 26 | ```html 27 | 28 | ... HTML Markup, list of script / link tags. 29 | 30 | ``` 31 | 32 | - **type**: either `js`, `css` or `remove` 33 | - **alternate search path**: (optional) By default the input files are relative to the treated file. Alternate search path allows one to change that 34 | - **path**: the file path of the optimized file, the target output 35 | - **parameters**: extra parameters that should be added to the tag 36 | 37 | An example of this in completed form can be seen below: 38 | 39 | ```html 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | ``` 60 | 61 | The module would be used with the above sample HTML as follows: 62 | 63 | ```js 64 | var result = useref(sampleHtml) 65 | 66 | // [ 67 | // resultHtml, 68 | // { 69 | // css: { 70 | // 'css/combined.css': { 71 | // 'assets': [ 'css/one.css', 'css/two.css' ] 72 | // } 73 | // }, 74 | // js: { 75 | // 'scripts/combined.js': { 76 | // 'assets': [ 'scripts/one.js', 'scripts/two.js' ] 77 | // }, 78 | // 'scripts/async.js': { 79 | // 'assets': [ 'scripts/three.js', 'scripts/four.js' ] 80 | // } 81 | // } 82 | // } 83 | // ] 84 | ``` 85 | 86 | 87 | The resulting HTML would be: 88 | 89 | ```html 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | ``` 100 | 101 | ## IE Conditional Comments 102 | 103 | Internet Explorer Conditional Comments are preserved. The code below: 104 | 105 | ```html 106 | 107 | 111 | 112 | ``` 113 | 114 | Results in: 115 | 116 | ```html 117 | 120 | ``` 121 | 122 | ### Custom blocks 123 | 124 | Sometimes you need a bit more. If you would like to do custom processing, this is possible with a custom block, as demonstrated below. 125 | 126 | ``` 127 | 128 | 129 | 130 | ``` 131 | 132 | With 133 | 134 | ``` 135 | useref = require('node-useref') 136 | var result = useref(inputHtml, { 137 | // each property corresponds to any blocks with the same name, e.g. "build:import" 138 | import: function (content, target, options, alternateSearchPath) { 139 | // do something with `content` and return the desired HTML to replace the block content 140 | return content.replace('bower_components', target); 141 | } 142 | }); 143 | ``` 144 | 145 | Becomes 146 | 147 | ``` 148 | 149 | ``` 150 | 151 | The handler function gets the following arguments: 152 | 153 | - *content* (String): The content of the custom use block 154 | - *target* (String): The "path" value of the use block definition 155 | - *options* (String): The extra attributes from the use block definition, the developer can parse as JSON or do whatever they want with it 156 | - *alternateSearchPath* (String): The alternate search path that can be used to maintain a coherent interface with standard handlers 157 | 158 | Include a handler for each custom block type. -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /*global module:false, require:false */ 2 | 'use strict'; 3 | 4 | // start build pattern: 5 | // $1 is the type, $2 is the alternate search path, $3 is the destination file name $4 extra attributes 6 | var regbuild = /(?:)|[^\s]+)?\s*(?:(.*))?\s*-->/; 7 | 8 | // end build pattern -- 9 | var regend = /(?:/; 10 | 11 | // IE conditional comment pattern: $1 is the start tag and $2 is the end tag 12 | var regcc = /()/i; 13 | 14 | // script element regular expression 15 | // TODO: Detect 'src' attribute. 16 | var regscript = /|\))<[^<]*)*(?:<\/script>|\))/gmi; 17 | 18 | // css link element regular expression 19 | // TODO: Determine if 'href' attribute is present. 20 | var regcss = /|\))/gmi; 21 | 22 | // Character used to create key for the `sections` object. This should probably be done more elegantly. 23 | var sectionsJoinChar = '\ue000'; 24 | 25 | // strip all comments from HTML except for conditionals 26 | var regComment = /)(.|\n))*-->/g; 27 | 28 | module.exports = function (content, options) { 29 | var blocks = getBlocks(content); 30 | 31 | content = updateReferences(blocks, content, options); 32 | 33 | var replaced = compactContent(blocks); 34 | 35 | return [ content, replaced ]; 36 | }; 37 | 38 | function parseBuildBlock(block) { 39 | var parts = block.match(regbuild); 40 | return parts && { 41 | type: parts[1], 42 | alternateSearchPaths: parts[2], 43 | target: parts[3] && parts[3].trim(), 44 | attbs: parts[4] && parts[4].trim() 45 | } 46 | } 47 | 48 | // Returns a hash object of all the directives for the given html. Results is 49 | // of the following form: 50 | // 51 | // { 52 | // 'css/site.css ':[ 53 | // ' ', 54 | // ' ', 55 | // ' ' 56 | // ], 57 | // 'js/head.js ': [ 58 | // ' ', 59 | // ' ', 60 | // ' ' 61 | // ], 62 | // 'js/site.js ': [ 63 | // ' ', 64 | // ' ', 65 | // ' ', 66 | // ' ' 67 | // ] 68 | // } 69 | // 70 | function getBlocks(body) { 71 | var lines = body.replace(/\r\n/g, '\n').split(/\n/), 72 | block = false, 73 | sections = {}, 74 | sectionIndex = 0, 75 | last, 76 | removeBlockIndex = 0; 77 | 78 | lines.forEach(function (l) { 79 | var build = parseBuildBlock(l), 80 | endbuild = regend.test(l), 81 | sectionKey; 82 | 83 | if (build) { 84 | block = true; 85 | 86 | if(build.type === 'remove') { build.target = String(removeBlockIndex++); } 87 | if(build.attbs) { 88 | sectionKey = [build.type, build.target, build.attbs].join(sectionsJoinChar); 89 | } else if (build.target) { 90 | sectionKey = [build.type, build.target].join(sectionsJoinChar); 91 | } else { 92 | sectionKey = build.type; 93 | } 94 | 95 | if (sections[sectionKey]) { 96 | sectionKey += sectionIndex++; 97 | } 98 | 99 | sections[sectionKey] = last = []; 100 | } 101 | 102 | // switch back block flag when endbuild 103 | if (block && endbuild) { 104 | last.push(l); 105 | block = false; 106 | } 107 | 108 | if (block && last) { 109 | last.push(l); 110 | } 111 | }); 112 | 113 | // sections is an array of lines starting with the build block comment opener, 114 | // including all the references and including the build block comment closer. 115 | return sections; 116 | } 117 | 118 | 119 | // Helpers 120 | // ------- 121 | var helpers = { 122 | // useref and useref:* are used with the blocks parsed from directives 123 | useref: function (content, block, target, type, attbs, alternateSearchPaths, handler) { 124 | var linefeed = /\r\n/g.test(content) ? '\r\n' : '\n', 125 | lines = block.split(linefeed), 126 | ref = '', 127 | indent = (lines[0].match(/^\s*/) || [])[0], 128 | ccmatches = block.match(regcc), 129 | blockContent = lines.slice(1, -1).join(''); 130 | 131 | target = target || 'replace'; 132 | 133 | if (type === 'css') { 134 | 135 | // Check to see if there are any css references at all. 136 | if( blockContent.search(regcss) !== -1 ) 137 | { 138 | if(attbs) { 139 | ref = ''; 140 | } else { 141 | ref = ''; 142 | } 143 | } 144 | 145 | } else if (type === 'js') { 146 | 147 | // Check to see if there are any js references at all. 148 | if( blockContent.search(regscript) !== -1 ) 149 | { 150 | if(attbs) { 151 | ref = ''; 152 | } else { 153 | ref = ''; 154 | } 155 | } 156 | 157 | } else if (type === 'remove') { 158 | ref = ''; 159 | } else if (handler) { 160 | ref = handler(blockContent, target, attbs, alternateSearchPaths); 161 | } 162 | else { 163 | ref = null; 164 | } 165 | 166 | if(ref != null) { 167 | ref = indent + ref; 168 | 169 | // Reserve IE conditional comment if exist 170 | if (ccmatches) { 171 | ref = indent + ccmatches[1] + linefeed + ref + linefeed + indent + ccmatches[2]; 172 | } 173 | 174 | return content.replace(block, ref); 175 | } 176 | else { return content; } 177 | } 178 | }; 179 | 180 | function updateReferences(blocks, content, options) { 181 | 182 | // Determine the linefeed from the content 183 | var linefeed = /\r\n/g.test(content) ? '\r\n' : '\n'; 184 | 185 | // handle blocks 186 | Object.keys(blocks).forEach(function (key) { 187 | var block = blocks[key].join(linefeed), 188 | parsed = parseBuildBlock(block), 189 | handler = options && options[parsed.type]; 190 | 191 | content = helpers.useref(content, block, parsed.target, parsed.type, parsed.attbs, parsed.alternateSearchPaths, handler); 192 | }); 193 | 194 | return content; 195 | } 196 | 197 | function removeComments(lines) { 198 | return lines.join('\n').replace(regComment, '').split('\n'); 199 | } 200 | 201 | function compactContent(blocks) { 202 | 203 | var result = {}; 204 | 205 | Object.keys(blocks).forEach(function (dest) { 206 | // Lines are the included scripts w/o the use blocks 207 | var lines = blocks[dest].slice(1, -1), 208 | parts = dest.split(sectionsJoinChar), 209 | type = parts[0], 210 | // output is the useref block file 211 | output = parts[1], 212 | build = parseBuildBlock(blocks[dest][0]); 213 | 214 | // remove html comment blocks 215 | lines = removeComments(lines); 216 | 217 | // parse out the list of assets to handle, and update the grunt config accordingly 218 | var assets = lines.map(function (tag) { 219 | 220 | // The asset is the string of the referenced source file 221 | var asset = (tag.match(/(href|src)=["']([^'"]+)["']/) || [])[2]; 222 | 223 | // Allow white space and comment in build blocks by checking if this line has an asset or not 224 | if (asset) { 225 | return asset; 226 | } 227 | 228 | }).reduce(function (a, b) { 229 | return b ? a.concat(b) : a; 230 | }, []); 231 | 232 | 233 | result[type] = result[type] || {}; 234 | result[type][output] = { 'assets': assets }; 235 | if (build.alternateSearchPaths) { 236 | // Alternate search path 237 | result[type][output].searchPaths = build.alternateSearchPaths; 238 | } 239 | }); 240 | 241 | return result; 242 | } 243 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | /* global describe, it */ 3 | 'use strict'; 4 | var expect = require('chai').expect; 5 | var fs = require('fs'); 6 | var path = require('path'); 7 | var useRef = require('../src/index'); 8 | 9 | function djoin(p) { 10 | return path.normalize(path.join(__dirname, p)); 11 | } 12 | function fread(f) { 13 | return fs.readFileSync(f, { encoding: 'utf-8'}); 14 | } 15 | 16 | describe('html-ref-replace', function() { 17 | 18 | it('should replace reference in css block and return replaced files', function() { 19 | var result = useRef(fread(djoin('testfiles/01.html'))); 20 | expect(result[0]).to.equal(fread(djoin('testfiles/01-expected.html'))); 21 | expect(result[1]).to.eql({ css: { '/css/combined.css': { 'assets': [ '/css/one.css', '/css/two.css' ] }}}); 22 | }); 23 | 24 | it('should replace reference in js block and return replaced files', function() { 25 | var result = useRef(fread(djoin('testfiles/02.html'))); 26 | expect(result[0]).to.equal(fread(djoin('testfiles/02-expected.html'))); 27 | expect(result[1]).to.eql({ js: { 'scripts/combined.concat.min.js': { 'assets': [ 'scripts/this.js', 'scripts/that.js' ] }}}); 28 | }); 29 | 30 | it('should remove `remove` block', function() { 31 | var result = useRef(fread(djoin('testfiles/09.html'))); 32 | expect(result[0]).to.equal(fread(djoin('testfiles/09-expected.html'))); 33 | expect(result[1]).to.eql({ remove: { '0': { 'assets': [ 'scripts/this.js', 'scripts/that.js' ] }}}); 34 | }); 35 | 36 | it('should remove multiple `remove` blocks', function() { 37 | var result = useRef(fread(djoin('testfiles/10.html'))); 38 | expect(result[0]).to.equal(fread(djoin('testfiles/10-expected.html'))); 39 | expect(result[1]).to.eql({ remove: { '0': { 'assets': [ 'scripts/this.js', 'scripts/that.js' ] }, '1': { 'assets': [ '/css/one.css', '/css/two.css' ] } }}); 40 | }); 41 | 42 | it('should handle comments and whitespace in blocks', function() { 43 | var result = useRef(fread(djoin('testfiles/03.html'))); 44 | expect(result[0]).to.equal(fread(djoin('testfiles/03-expected.html'))); 45 | expect(result[1]).to.eql({ js: { 'scripts/combined.concat.min.js': { 'assets': [ 'scripts/this.js', 'scripts/that.js' ] }}}); 46 | }); 47 | 48 | it('should handle comments and whitespace in blocks (without trailing space)', function() { 49 | var result = useRef(fread(djoin('testfiles/03b.html'))); 50 | expect(result[0]).to.equal(fread(djoin('testfiles/03-expected.html'))); 51 | expect(result[1]).to.eql({ js: { 'scripts/combined.concat.min.js': { 'assets': [ 'scripts/this.js', 'scripts/that.js' ] }}}); 52 | }); 53 | 54 | it('should ignore script in comments (multi line)', function() { 55 | var result = useRef(fread(djoin('testfiles/03c.html'))); 56 | expect(result[0]).to.equal(fread(djoin('testfiles/03-expected.html'))); 57 | expect(result[1]).to.eql({ js: { 'scripts/combined.concat.min.js': { 'assets': [ 'scripts/this.js' ] }}}); 58 | }); 59 | 60 | it('should ignore script in comments (single line with "