├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── file-loader.js ├── index.js ├── lib ├── attributeParser.js ├── macroParser.js └── macros.js ├── package.json ├── test ├── attributeTest.js ├── lib │ ├── WebpackLoaderMock.js │ ├── loadOutput.js │ ├── loadTemplate.js │ └── toText.js ├── loaderTest.js ├── macroTest.js └── templates │ ├── absolute-image.html │ ├── custom-attributes.html │ ├── custom-macro.html │ ├── custom-tags.html │ ├── dynamic-attribute-with-parseDynamicRoutes.html │ ├── dynamic-attribute-with-root.html │ ├── dynamic-attribute.html │ ├── image.html │ ├── include.html │ ├── macro.html │ ├── macro_argument_list.html │ ├── macro_boolean_args.html │ ├── macro_escaped.html │ ├── macro_in_query.html │ ├── macro_numeric_args.html │ ├── macro_object_args.html │ ├── macro_string_args.html │ ├── output │ ├── absolute-image-with-root.txt │ ├── absolute-image.txt │ ├── custom-attributes.txt │ ├── custom-macro.txt │ ├── custom-tags.txt │ ├── disabled-macro.txt │ ├── dynamic-attribute-with-parseDynamicRoutes.txt │ ├── dynamic-attribute-with-root.txt │ ├── dynamic-attribute.txt │ ├── image.txt │ ├── include.txt │ ├── macro_argument_list.txt │ ├── macro_boolean_args.txt │ ├── macro_escaped.txt │ ├── macro_in_query.txt │ ├── macro_numeric_args.txt │ ├── macro_object_args.txt │ ├── macro_string_args.txt │ ├── require.txt │ ├── require_with_args.txt │ ├── simple-lodash-no-imports.txt │ ├── simple-lodash.txt │ ├── simple-underscore.txt │ ├── simple-with-comment.txt │ ├── simple-with-imports.txt │ └── simple.txt │ ├── require.html │ ├── require_with_args.html │ └── simple.html └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [package.json] 13 | indent_size = 2 14 | 15 | [*.txt] 16 | trim_trailing_whitespace = false 17 | insert_final_newline = false 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Commenting this out is preferred by some people, see 24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 25 | node_modules 26 | 27 | # Users Environment Variables 28 | .lock-wscript 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Emmanuel Antico 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. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | underscore-template-loader 2 | ========================== 3 | 4 | An Underscore.js and Lodash template loader for Webpack 5 | 6 | ### Changelog 7 | 8 |
9 | * 1.1: Support macros through `query` (thx @JimYan, @devlinjunker) 10 | * 1.0: Loader now works with Webpack 4. Still a beta release. 11 | 12 | ### Installation 13 | 14 | ```bash 15 | npm install underscore-template-loader 16 | ``` 17 | 18 | Make sure you have the `underscore` or `lodash` package installed. 19 | 20 | ### Usage 21 | 22 | ```javascript 23 | module.exports = { 24 | //... 25 | module: { 26 | loaders: [ 27 | { test: /\.html$/, loader: "underscore-template-loader" } 28 | ] 29 | }, 30 | }; 31 | ``` 32 | 33 | #### Template engine 34 | 35 | You can specify an engine to specify the library used when you call underscore methods inside the template if you don't want to rely on the global `_` that is used by default. 36 | 37 | ```javascript 38 | module.exports = { 39 | //... 40 | 41 | module: { 42 | loaders: [ 43 | { 44 | test: /\.html$/, 45 | loader: "underscore-template-loader", 46 | query: { 47 | engine: 'lodash', 48 | } 49 | } 50 | ] 51 | } 52 | }; 53 | ``` 54 | 55 | #### Loading templates 56 | 57 | ```html 58 | 59 |

Hello <%=name%>

60 | ``` 61 | 62 | ```javascript 63 | var compiled = require('./hello.html'); 64 | return compiled({name: "world"}); 65 | ``` 66 | 67 | #### Prepending filename comment 68 | 69 | When debugging a large single page app with the DevTools, it's often hard to find the template that contains a bug. With the following config a HTML comment is prepended to the template with the relative path in it (e.g. ``). 70 | 71 | ```javascript 72 | module.exports = { 73 | //... 74 | 75 | module: { 76 | loaders: [ 77 | { 78 | test: /\.html$/, 79 | loader: "underscore-template-loader", 80 | query: { 81 | prependFilenameComment: __dirname, 82 | } 83 | } 84 | ] 85 | } 86 | }; 87 | ``` 88 | 89 | #### Template settings 90 | 91 | You can override the delimiters used to determine data to injected (HTML-escaped or not) or code to evaluate in the templates. 92 | 93 | ```javascript 94 | module.exports = { 95 | //... 96 | 97 | module: { 98 | loaders: [ 99 | //... 100 | { 101 | test: /\.html$/, 102 | loader: "underscore-template-loader", 103 | query: { 104 | interpolate: '\\{\\[(.+?)\\]\\}', 105 | evaluate: '\\{%([\\s\\S]+?)%\\}', 106 | escape: '\\{\\{(.+?)\\}\\}' 107 | } 108 | } 109 | ] 110 | } 111 | }; 112 | ``` 113 | 114 | #### Template imports 115 | 116 | [`_.templateSettings.imports`](https://lodash.com/docs#templateSettings-imports) automatically includes variables or functions in your templates. This is useful when you have utility functions that you want to make available to all templates without explicitly passing them in every time the template is used. 117 | 118 | ```html 119 | 120 |

<%= greet(name) %>

121 | ``` 122 | 123 | ```javascript 124 | var _ = require('lodash'); 125 | // Imports must be defined before the template is required 126 | _.templateSettings.imports = { 127 | greet: function(name) { 128 | return 'Hello, ' + name + '!'; 129 | }, 130 | }; 131 | var compiled = require('./hello.html'); 132 | return compiled({name: "world"}); 133 | ``` 134 | 135 | This is enabled by default when `lodash` is the engine used, but can be explicitly toggled using `withImports` option. 136 | 137 | ```javascript 138 | module.exports = { 139 | //... 140 | 141 | module: { 142 | loaders: [ 143 | //... 144 | { 145 | test: /\.html$/, 146 | loader: "underscore-template-loader", 147 | query: { 148 | withImports: true, 149 | } 150 | } 151 | ] 152 | } 153 | }; 154 | ``` 155 | 156 | #### Images 157 | 158 | In order to load images you must install either the *file-loader* or the *url-loader* package. 159 | 160 | ```javascript 161 | module.exports = { 162 | //... 163 | 164 | module: { 165 | loaders: [ 166 | { test: /\.html$/, loader: "underscore-template-loader" }, 167 | { test: /\.jpg$/, loader: "file-loader" }, 168 | { test: /\.png$/, loader: "url-loader?mimetype=image/png" }, 169 | ] 170 | } 171 | }; 172 | ``` 173 | 174 | ```html 175 | 176 | 177 | 178 | 179 | 180 | ``` 181 | 182 | Images with an absolute path are not translated unless a `root` option is defined 183 | 184 | ```html 185 | 186 | 187 | 188 | 189 | 190 | ``` 191 | 192 | In order to deactivate image processing define `attributes` as an empty array. 193 | 194 | ```javascript 195 | module.exports = { 196 | //... 197 | 198 | module: { 199 | loaders: [ 200 | { 201 | test: /\.html$/, 202 | loader: "underscore-template-loader", 203 | query: { 204 | attributes: [] 205 | } 206 | } 207 | ] 208 | } 209 | }; 210 | ``` 211 | 212 | You could also add which attributes need to be processed in the form of pairs *tag:attribute*. 213 | 214 | ```javascript 215 | module.exports = { 216 | //... 217 | 218 | module: { 219 | loaders: [ 220 | //... 221 | { 222 | test: /\.html$/, 223 | loader: "underscore-template-loader", 224 | query: { 225 | attributes: ['img:src', 'x-img:src'] 226 | } 227 | } 228 | ] 229 | } 230 | }; 231 | ``` 232 | 233 | Dynamic attributes won't be afected by this behaviour by default. 234 | 235 | ```html 236 | 237 | 238 | ``` 239 | 240 | In order to append the root directory you'll need to specify the `parseDynamicRoutes` argument. 241 | 242 | ```javascript 243 | module.exports = { 244 | //... 245 | 246 | module: { 247 | loaders: [ 248 | { 249 | test: /\.html$/, 250 | loader: "underscore-template-loader", 251 | query: { 252 | root: "myapp", 253 | parseDynamicRoutes: true 254 | } 255 | } 256 | ] 257 | } 258 | }; 259 | ``` 260 | 261 | ```html 262 | 263 | 264 | ``` 265 | 266 | ### Macros 267 | 268 | Macros allow additional features like including templates or inserting custom text in compiled templates. 269 | 270 | #### The *require* macro 271 | 272 | The `require` macro expects a path to a underscore template. The macro is then translated into a webpack require expression that evaluates the template using the same arguments. 273 | 274 | ```html 275 |

Profile

276 | 277 | Name: <%=name%> 278 |
279 | Surname: <%=surname%> 280 |
281 | @require('profile-details.html') 282 |
283 | ``` 284 | 285 | This macro also supports an object literal as an additional argument. 286 | 287 | ```html 288 |
289 | @require('header.html', {"title": "First Section"}) 290 |
291 | ``` 292 | 293 | #### The *include* macro 294 | 295 | While the `require` macro expects a resource that returns a function, the `include` macro can be used for resources that return plain text. For example, we can include text loaded through the `html-loader` directly in our template. 296 | 297 | ```html 298 |
299 |

Introduction

300 | @include('intro.htm') 301 |

Authors

302 | @include('authors.htm') 303 |
304 | ``` 305 | 306 | #### *br* and *nl* 307 | 308 | The `br` and `nl` macros insert a `
` tag and a new line respectively. They accept a optional argument with the amount of strings to insert. 309 | 310 | ```html 311 |

Lorem ipsum

312 | @br(3) 313 |

Sit amet

314 | @nl() 315 | ``` 316 | 317 | #### Custom macros 318 | 319 | We can include additional macros by defining them in the webpack configuration file. Remember that the value returned by a macro is inserted as plain javascript, so in order to insert a custom text we need to use nested quotes. For example, let's say that we want a macro that includes a copyright string in our template. 320 | 321 | ```javascript 322 | // File: webpack.config.js 323 | const webpack = require('webpack'); 324 | 325 | module.exports = { 326 | // ... 327 | 328 | module: { 329 | loaders: { 330 | // ... 331 | { test: /\.html$/, loader: "underscore-template-loader" }, 332 | } 333 | }, 334 | 335 | plugins: [ 336 | // ... 337 | new webpack.LoaderOptionsPlugin({ 338 | options: { 339 | macros: { 340 | copyright: function () { 341 | return "'

Copyright FakeCorp 2014 - 2018

'"; 342 | }, 343 | }, 344 | }, 345 | }), 346 | ], 347 | } 348 | ``` 349 | 350 | We then invoke this macro from within the template as usual. 351 | 352 | ```html 353 | 356 | ``` 357 | 358 | #### Disabling macros 359 | 360 | You can disable macros if you are a bit unsure about their usage or just simply want faster processing. This is achieved by setting the `parseMacros` options to false. 361 | 362 | ```javascript 363 | module.exports = { 364 | // ... 365 | 366 | module: { 367 | loaders: { 368 | // ... 369 | { 370 | test: /\.html$/, 371 | loader: "underscore-template-loader", 372 | query: { 373 | parseMacros: false 374 | } 375 | }, 376 | } 377 | } 378 | } 379 | ``` 380 | 381 | #### Arguments 382 | 383 | Macros can accept an arbitrary number of arguments of different types: boolean, strings, numbers an object literals are supported. 384 | 385 | ```javascript 386 | // File: webpack.config.js 387 | module.exports = { 388 | // ... 389 | 390 | module: { 391 | loaders: { 392 | // ... 393 | { test: /\.html$/, loader: "underscore-template-loader" }, 394 | } 395 | }, 396 | 397 | macros: { 398 | header: function (size, content) { 399 | return "'" + content + "'"; 400 | } 401 | } 402 | } 403 | ``` 404 | 405 | ```html 406 | @header(1, 'Welcome') 407 |

Lorem ipsum

408 | @header(3, 'Contents') 409 |

Sit amet

410 | ``` 411 | 412 | #### Escaping 413 | 414 | Macro expressions can be escaped with the `\` character. 415 | 416 | ```html 417 | @br(3) 418 | \@nl() 419 | @br() 420 | ``` 421 | 422 | Translates to 423 | 424 | ```html 425 |


426 | @nl() 427 |
428 | ``` 429 | 430 | ### Just an example of requiring template with dynamic arguments 431 | 432 | ```javascript 433 | <% 434 | const title = 'Some ' + 'title'; 435 | const headFileName = htmlWebpackPlugin.options.headFileName || 'head.ejs'; 436 | 437 | function objExtend(args, obj) { 438 | args = Array.prototype.slice.call(args); 439 | args[0] = Object.assign(obj, args[0]); 440 | return args; 441 | }; 442 | %> 443 | 444 | <%= require(`./structure/${headFileName}`).apply(null, objExtend(arguments, { title })) %> 445 | ``` 446 | 447 | #### Known issues 448 | 449 | * Trying to use different template settings (interpolate, escape, evaluate) for different extensions. Underscore / Lodash template settings are defined globally. 450 | 451 | ### License 452 | 453 | Released under the MIT license. 454 | -------------------------------------------------------------------------------- /file-loader.js: -------------------------------------------------------------------------------- 1 | /* This loader returns the filename if no loader takes care of the file */ 2 | 'use strict'; 3 | 4 | var loaderUtils = require('loader-utils'); 5 | 6 | module.exports = function (source) { 7 | if (this.cacheable) { 8 | this.cacheable(); 9 | } 10 | var query = this.query instanceof Object ? this.query : loaderUtils.parseQuery(this.query || '?'); 11 | 12 | var allLoadersButThisOne = this.loaders.filter(function(loader) { 13 | return loader.module !== module.exports; 14 | }); 15 | // This loader shouldn't kick in if there is any other loader 16 | if (allLoadersButThisOne.length > 0) { 17 | return source; 18 | } 19 | 20 | return 'module.exports = ' + JSON.stringify(query.url); 21 | }; 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var loaderUtils = require('loader-utils'); 3 | var attributeParser = require('./lib/attributeParser'); 4 | var macroParser = require('./lib/macroParser'); 5 | 6 | // Try getting underscore first, then lodash 7 | var _; 8 | try { 9 | _ = require('underscore'); 10 | } catch (e) { 11 | _ = require('lodash'); 12 | } 13 | 14 | // Extendable arguments 15 | var macros = _.extend({}, require('./lib/macros')); 16 | 17 | module.exports = function(content) { 18 | this.cacheable && this.cacheable(); 19 | var callback = this.async(); 20 | 21 | // Default arguments 22 | var root, 23 | parseMacros = true, 24 | engine = false, 25 | withImports = false, 26 | attributes = ['img:src'], 27 | parseDynamicRoutes = false; 28 | 29 | // Parse arguments 30 | var query = this.query instanceof Object ? this.query : loaderUtils.parseQuery(this.query || '?'); 31 | 32 | if (_.isObject(query)) { 33 | root = query.root; 34 | 35 | // Apply template settings 36 | _.each(_.pick(query, 'interpolate', 'escape', 'evaluate'), function(value, key) { 37 | _.templateSettings[key] = new RegExp(value, 'g'); 38 | }); 39 | 40 | // Apply template variable 41 | if (query.variable !== undefined) { 42 | _.templateSettings.variable = query.variable; 43 | } 44 | 45 | // Set tag+attribute to parse for external resources 46 | if (query.attributes !== undefined) { 47 | attributes = _.isArray(query.attributes) ? query.attributes : []; 48 | } 49 | 50 | // Parse / ignore macros 51 | if (query.parseMacros !== undefined) { 52 | parseMacros = !!query.parseMacros; 53 | } 54 | 55 | // Template engine 56 | if (query.engine !== undefined) { 57 | engine = query.engine; 58 | } 59 | 60 | // Template settings imports (on by default for lodash) 61 | if (query.withImports !== undefined) { 62 | withImports = query.withImports; 63 | } else if (engine === 'lodash') { 64 | withImports = true; 65 | } 66 | 67 | // Prepend a html comment with the filename in it 68 | if (query.prependFilenameComment) { 69 | var filenameRelative = path.relative(query.prependFilenameComment, this.resource); 70 | content = "\n\n" + content; 71 | } 72 | 73 | // Check if dynamic routes must be parsed 74 | if (query.parseDynamicRoutes !== undefined) { 75 | parseDynamicRoutes = !!query.parseDynamicRoutes; 76 | } 77 | 78 | // support macros in loader options. because it isn't support customer options from webpack@4 79 | if (_.isObject(query.macros)) { 80 | _.extend(macros, query.macros); 81 | } 82 | } 83 | 84 | // Include additional macros 85 | if (this.options && _.isObject(this.options.macros)) { 86 | _.extend(macros, this.options.macros); 87 | } 88 | 89 | // Parse macros 90 | if (parseMacros) { 91 | var macrosContext = macroParser(content, function (macro) { 92 | return _.isFunction(macros[macro]); 93 | }, 'MACRO'); 94 | content = macrosContext.replaceMatches(content); 95 | } 96 | 97 | // Parse attributes 98 | var attributesContext = attributeParser(content, function (tag, attr) { 99 | return attributes.indexOf(tag + ':' + attr) != -1; 100 | }, 'ATTRIBUTE', root, parseDynamicRoutes); 101 | content = attributesContext.replaceMatches(content); 102 | 103 | // Compile template 104 | var source = _.template(content).source; 105 | 106 | // Resolve macros 107 | if (parseMacros) { 108 | source = macrosContext.resolveMacros(source, macros); 109 | } 110 | 111 | // Resolve attributes 112 | source = attributesContext.resolveAttributes(source); 113 | 114 | // Build the module export, optionally with template imports 115 | if (withImports) { 116 | source = 'module.exports = Function(_.keys(_.templateSettings.imports), \'return \' + ' + source + '.toString()).apply(undefined, _.values(_.templateSettings.imports));\n'; 117 | } else { 118 | source = 'module.exports = ' + source + ';\n'; 119 | } 120 | 121 | // Explicitly require the engine, otherwise it will rely on the global _ 122 | if (engine) { 123 | source = 'var _ = require(\'' + engine + '\');\n' + source; 124 | } 125 | 126 | callback(null, source); 127 | }; 128 | 129 | module.exports._ = _; 130 | -------------------------------------------------------------------------------- /lib/attributeParser.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var url = require('url'); 3 | var Parser = require("fastparse"); 4 | var loaderUtils = require('loader-utils'); 5 | 6 | try { 7 | var _ = require('underscore'); 8 | } catch (e) { 9 | var _ = require('lodash'); 10 | } 11 | 12 | // Reminder: path.isAbsolute is not available in 0.10.x 13 | var pathIsAbsolute = function (attrValue) { 14 | return path.resolve(attrValue) == path.normalize(attrValue); 15 | }; 16 | 17 | // Checks whether a string contains a template expression 18 | var isTemplate = function (content) { 19 | // Test against regex list 20 | var interpolateTest = _.templateSettings.interpolate.test(content); 21 | 22 | if (interpolateTest) { 23 | _.templateSettings.interpolate.lastIndex = 0; 24 | return true; 25 | } 26 | 27 | var evaluateTest = _.templateSettings.evaluate.test(content); 28 | 29 | if (evaluateTest) { 30 | _.templateSettings.evaluate.lastIndex = 0; 31 | return true; 32 | } 33 | 34 | var escapeTest = _.templateSettings.escape.test(content); 35 | _.templateSettings.escape.lastIndex = 0; 36 | return escapeTest; 37 | }; 38 | 39 | // AttributeContext class 40 | var AttributeContext = function (isRelevantTagAttr, usid, root, parseDynamicRoutes) { 41 | this.currentDirective = null; 42 | this.matches = []; 43 | this.isRelevantTagAttr = isRelevantTagAttr; 44 | this.usid = usid; 45 | this.ident = function () { 46 | return "____" + usid + Math.random() + "____"; 47 | }; 48 | this.data = {}; 49 | this.root = root; 50 | this.parseDynamicRoutes = parseDynamicRoutes; 51 | }; 52 | 53 | AttributeContext.prototype.replaceMatches = function(content) { 54 | var self = this; 55 | content = [content]; 56 | this.matches.reverse(); 57 | 58 | this.matches.forEach(function (match) { 59 | if (isTemplate(match.value)) { 60 | // Replace attribute value 61 | // This is used if it contains a template expression and both the "root" and "parseDynamicRoutes" 62 | // were defined 63 | if (pathIsAbsolute(match.value) && self.root !== undefined) { 64 | var x = content.pop(); 65 | content.push(x.substr(match.start + match.length)); 66 | content.push(match.expression); 67 | content.push(x.substr(0, match.start)); 68 | } 69 | } else { 70 | // Ignore if path is absolute and no root path has been defined 71 | if (pathIsAbsolute(match.value) && self.root === undefined) { 72 | return; 73 | } 74 | 75 | // Ignore if is a URL 76 | if (!loaderUtils.isUrlRequest(match.value, self.root)) { 77 | return; 78 | } 79 | 80 | var uri = url.parse(match.value); 81 | if (uri.hash !== null && uri.hash !== undefined) { 82 | uri.hash = null; 83 | match.value = uri.format(); 84 | match.length = match.value.length; 85 | } 86 | 87 | do { 88 | var ident = self.ident(); 89 | } while (self.data[ident]); 90 | 91 | self.data[ident] = match; 92 | 93 | var x = content.pop(); 94 | content.push(x.substr(match.start + match.length)); 95 | content.push(ident); 96 | content.push(x.substr(0, match.start)); 97 | } 98 | }); 99 | 100 | content.reverse(); 101 | return content.join(''); 102 | }; 103 | 104 | AttributeContext.prototype.resolveAttributes = function (content) { 105 | var regex = new RegExp('____' + this.usid + '[0-9\\.]+____', 'g'); 106 | var self = this; 107 | 108 | return content.replace(regex, function (match) { 109 | if (!self.data[match]) { 110 | return match; 111 | } 112 | 113 | var url = self.data[match].value; 114 | 115 | // REMOVED custom file-loader usage to allow webpack to handle requested url properly 116 | return "' + require(" + JSON.stringify(loaderUtils.urlToRequest(url, self.root)) + ") + '"; 117 | }); 118 | }; 119 | 120 | // Process a tag attribute 121 | var processMatch = function (match, strUntilValue, name, value, index) { 122 | var self = this; 123 | var expression = value; 124 | 125 | if (!this.isRelevantTagAttr(this.currentTag, name)) { 126 | return; 127 | } 128 | 129 | // Try and set "root" directory when a dynamic attribute is found 130 | if (isTemplate(value)) { 131 | if (pathIsAbsolute(value) && self.root !== undefined && self.parseDynamicRoutes) { 132 | // Generate new value for replacement 133 | expression = loaderUtils.urlToRequest(value, self.root); 134 | } 135 | } 136 | 137 | this.matches.push({ 138 | start: index + strUntilValue.length, 139 | length: value.length, 140 | value: value, 141 | expression: expression 142 | }); 143 | }; 144 | 145 | // Parser configuration 146 | var specs = { 147 | outside: { 148 | "": true, 149 | "": true, 150 | "<[!\\?].*?>": true, 151 | "<\/[^>]+>": true, 152 | "<([a-zA-Z\\-:]+)\\s*": function (match, tagName) { 153 | this.currentTag = tagName; 154 | return 'inside'; 155 | } 156 | }, 157 | 158 | inside: { 159 | "\\s+": true, // Eat up whitespace 160 | ">": 'outside', // End of attributes 161 | "(([a-zA-Z\\-]+)\\s*=\\s*\")([^\"]*)\"": processMatch, 162 | "(([a-zA-Z\\-]+)\\s*=\\s*\')([^\']*)\'": processMatch, 163 | "(([a-zA-Z\\-]+)\\s*=\\s*)([^\\s>]+)": processMatch 164 | } 165 | }; 166 | 167 | var parser = new Parser(specs); 168 | 169 | module.exports = function parse(html, isRelevantTagAttr, usid, root, parseDynamicRoutes) { 170 | var context = new AttributeContext(isRelevantTagAttr, usid, root, parseDynamicRoutes); 171 | return parser.parse('outside', html, context); 172 | }; 173 | -------------------------------------------------------------------------------- /lib/macroParser.js: -------------------------------------------------------------------------------- 1 | var Parser = require("fastparse"); 2 | 3 | // Macro class 4 | var Macro = function (name, index, length) { 5 | this.name = name; 6 | this.start = index; 7 | this.length = length; 8 | this.args = []; 9 | }; 10 | 11 | Macro.prototype.getArguments = function() { 12 | var args = []; 13 | 14 | this.args.forEach(function (arg) { 15 | args.push(arg.value); 16 | }); 17 | 18 | return args; 19 | }; 20 | 21 | // MacroContext class 22 | var MacroContext = function (isMacroAvailable, usid) { 23 | this.currentMacro = null; 24 | this.matches = []; 25 | this.isMacroAvailable = isMacroAvailable; 26 | this.usid = usid; 27 | this.ident = function () { 28 | return "____" + usid + Math.random() + "____"; 29 | }; 30 | this.data = {}; 31 | }; 32 | 33 | MacroContext.prototype.replaceMatches = function(content) { 34 | var self = this; 35 | content = [content]; 36 | this.matches.reverse(); 37 | 38 | this.matches.forEach(function (match) { 39 | do { 40 | var ident = self.ident(); 41 | } while (self.data[ident]); 42 | 43 | self.data[ident] = match; 44 | 45 | var x = content.pop(); 46 | content.push(x.substr(match.start + match.length)); 47 | content.push(ident); 48 | content.push(x.substr(0, match.start)); 49 | }); 50 | 51 | content.reverse(); 52 | return content.join(''); 53 | }; 54 | 55 | MacroContext.prototype.resolveMacros = function (content, macros) { 56 | var regex = new RegExp('____' + this.usid + '[0-9\\.]+____', 'g'); 57 | var self = this; 58 | 59 | // Replace macro expressions 60 | content = content.replace(regex, function (match) { 61 | if (!self.data[match]) { 62 | return match; 63 | } 64 | 65 | var macro = self.data[match]; 66 | return "' + " + macros[macro.name].apply(null, macro.getArguments()) + " + '"; 67 | }); 68 | 69 | // Replace escaped macros 70 | content = content.replace(/\\+(@\w+)/, function (match, expr) { 71 | return expr; 72 | }); 73 | 74 | return content; 75 | }; 76 | 77 | // Parses a macro string argument 78 | var processStringArg = function (match, value, index, length) { 79 | if (!this.currentMacro) return; 80 | this.currentMacro.args.push({ 81 | start: index + value.length, 82 | index: index, 83 | length: length, 84 | value: value 85 | }); 86 | }; 87 | 88 | // Parses a macro numeric argument 89 | var processNumArg = function (match, value, index, length) { 90 | if (!this.currentMacro) return; 91 | this.currentMacro.args.push({ 92 | start: index + value.length, 93 | index: index, 94 | length: length, 95 | value: parseFloat(value) 96 | }); 97 | }; 98 | 99 | // Parses a macro boolean argument 100 | var processBooleanArg = function (match, value, index, length) { 101 | if (!this.currentMacro) return; 102 | this.currentMacro.args.push({ 103 | start: index + value.length, 104 | index: index, 105 | length: length, 106 | value: value === 'true' 107 | }); 108 | }; 109 | 110 | var processObjectArg = function (match, value, index, length) { 111 | if (!this.currentMacro) return; 112 | this.currentMacro.args.push({ 113 | start: index + value.length, 114 | index: index, 115 | length: length, 116 | value: JSON.parse(value) 117 | }); 118 | }; 119 | 120 | // Parser configuration 121 | var specs = { 122 | outside: { 123 | "^@(\\w+)\\(|([^\\\\])@(\\w+)\\(": function (match, name, prefix, _name, index, length) { 124 | var name = name || _name; 125 | 126 | if (!this.isMacroAvailable(name)) { 127 | this.currentMacro = null; 128 | return 'inside'; 129 | } 130 | 131 | var macro = new Macro(name, prefix ? index + 1 : index, length); 132 | this.matches.push(macro); 133 | this.currentMacro = macro; 134 | return 'inside'; 135 | } 136 | }, 137 | 138 | inside: { 139 | "\\)": function (match, index) { 140 | if (this.currentMacro !== null) { 141 | this.currentMacro.length = 1 + index - this.currentMacro.start; 142 | } 143 | return 'outside'; 144 | }, 145 | "\'([^\']*)\'": processStringArg, 146 | "\"([^\"]*)\"": processStringArg, 147 | "\\s*([\\d|\\.]+)\\s*": processNumArg, 148 | "\\s*(true|false)\\s*": processBooleanArg, 149 | "\\s*({.+})\\s*": processObjectArg, 150 | "\\s+": true 151 | } 152 | }; 153 | 154 | var parser = new Parser(specs); 155 | 156 | module.exports = function parse(html, isMacroAvailable, usid) { 157 | var context = new MacroContext(isMacroAvailable, usid); 158 | return parser.parse('outside', html, context); 159 | }; 160 | -------------------------------------------------------------------------------- /lib/macros.js: -------------------------------------------------------------------------------- 1 | var loaderUtils = require('loader-utils'); 2 | 3 | var strRepeat = function (str, times) { 4 | var result = ''; 5 | 6 | for (var i = 0; i < times; i++) { 7 | result += str; 8 | } 9 | 10 | return result; 11 | }; 12 | 13 | // Used to translate require macros to override arguments 14 | var objExtend = function (args, obj) {args = Array.prototype.slice.call(args);var _a = args.slice(1); _a.unshift(Object.assign(obj, args[0])); return _a;}; 15 | 16 | // Default macros 17 | module.exports = { 18 | require: function (resourcePath, args) { 19 | var argsExpr = args ? '(' + objExtend + ')' + '(arguments, ' + JSON.stringify(args) + ')' : 'arguments'; 20 | return "require(" + JSON.stringify(loaderUtils.urlToRequest(resourcePath)) + ").apply(null," + argsExpr + ")"; 21 | }, 22 | 23 | include: function (resourcePath) { 24 | return "require(" + JSON.stringify(loaderUtils.urlToRequest(resourcePath)) + ")"; 25 | }, 26 | 27 | br: function (times) { 28 | var str = strRepeat('
', typeof(times) == 'undefined' ? 1 : parseInt(times)); 29 | return "'" + str + "'"; 30 | }, 31 | 32 | nl: function (times) { 33 | var str = strRepeat('\\n', typeof(times) == 'undefined' ? 1 : parseInt(times)); 34 | return "'" + str + "'"; 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "underscore-template-loader", 3 | "version": "1.1.0", 4 | "description": "An Underscore and Lodash template loader for Webpack", 5 | "main": "index.js", 6 | "homepage": "https://github.com/emaphp/underscore-template-loader", 7 | "bugs": { 8 | "url": "https://github.com/emaphp/underscore-template-loader/issues" 9 | }, 10 | "license": "MIT", 11 | "author": { 12 | "name": "Emmanuel Antico", 13 | "email": "emmanuel.antico@gmail.com" 14 | }, 15 | "contributors": [ 16 | { 17 | "name": "Tommy Dugger (cerinman)" 18 | }, 19 | { 20 | "name": "Kees Kluskens (SpaceK33z)" 21 | }, 22 | { 23 | "name": "Pascal (pascalpp)" 24 | }, 25 | { 26 | "name": "Jan Nicklas (jantimon)" 27 | }, 28 | { 29 | "name": "Keith McKnight (kmck)" 30 | }, 31 | { 32 | "name": "JimYan" 33 | } 34 | ], 35 | "repository": { 36 | "type": "git", 37 | "url": "https://github.com/emaphp/underscore-template-loader.git" 38 | }, 39 | "dependencies": { 40 | "fastparse": "^1.1.2", 41 | "loader-utils": "^2.0.0" 42 | }, 43 | "devDependencies": { 44 | "chai": "^4.3.4", 45 | "chai-string": "^1.5.0", 46 | "istanbul": "^0.3.18", 47 | "mocha": "^8.3.2", 48 | "underscore": "^1.12.1" 49 | }, 50 | "scripts": { 51 | "push:local": "yalc push --private --replace --update", 52 | "test": "mocha", 53 | "cover": "istanbul cover node_modules/mocha/bin/_mocha" 54 | }, 55 | "keywords": [ 56 | "underscore", 57 | "lodash", 58 | "template", 59 | "webpack", 60 | "loader" 61 | ], 62 | "readmeFilename": "README.md", 63 | "eslintConfig": { 64 | "env": { 65 | "node": true 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /test/attributeTest.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var chai = require('chai'); 3 | var assert = chai.assert; 4 | chai.use(require('chai-string')); 5 | 6 | var attributeParser = require('../lib/attributeParser'); 7 | var attributes = ['img:src', 'link:href']; 8 | 9 | // Helper to test the attributeParser. 10 | function testMatch(name, html, result) { 11 | it('should parse ' + name, function() { 12 | // The loader has an absolute path so we have to use a placeholder: 13 | 14 | var parsed = attributeParser(html, function(tag, attr) { 15 | return attributes.indexOf(tag + ':' + attr) != -1; 16 | }, 'ATTRIBUTE', '/asdf/'); 17 | 18 | // We are only interested in the `value` property of `matches`. 19 | var values = parsed.matches.map(function(match) { return match.value; }); 20 | assert.deepEqual(values, result); 21 | }); 22 | } 23 | 24 | // Helper to test the replaceMatches function. 25 | function replaceMatch(html) { 26 | return attributeParser(html, function(tag, attr) { 27 | return attributes.indexOf(tag + ':' + attr) != -1; 28 | }, 'ATTRIBUTE').replaceMatches(html); 29 | } 30 | 31 | // Testcases based on https://github.com/webpack/html-loader/blob/master/test/parserTest.js 32 | describe('attribute parser', function() { 33 | testMatch('normal', 'Text ', ['image.png', 'image2.png']); 34 | testMatch('single-quotes', "Text ", ['image.png', 'image2.png']); 35 | testMatch('whitespace', 'T ex t ', ['image.png', 'image2.png']); 36 | testMatch('whitespace2', 'Text < img src="image.png" >', []); 37 | testMatch('wrong <', 'Text <', ['image.png']); 38 | testMatch("wrong >", 'Text >', ['image.png']); 39 | testMatch('no quot', '', ['image.png']); 40 | testMatch('first tag', '', ['image.png']); 41 | testMatch('comment', '', []); 42 | testMatch('comment2', '', []); 43 | testMatch('comment3', '-->', []); 44 | testMatch('comment4', '-->', ['image.png']); 45 | testMatch('tags', '', ['image.png', 'style.css']); 46 | testMatch('cdata', ']]>', ['image2.png']); 47 | testMatch('doctype', '', ['image.png']); 48 | 49 | it('should replace image paths', function() { 50 | var html = ''; 51 | var result = replaceMatch(html); 52 | assert.startsWith(result, ''; 57 | var result = replaceMatch(html); 58 | assert.endsWith(result, '____#asdf">'); 59 | }); 60 | 61 | it('should not replace urls', function() { 62 | var html = ''; 63 | var result = replaceMatch(html); 64 | assert.equal(result, html); 65 | }); 66 | }); 67 | -------------------------------------------------------------------------------- /test/lib/WebpackLoaderMock.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | 4 | function WebpackLoaderMock (options) { 5 | this.context = options.context || ''; 6 | this.query = options.query; 7 | this.options = options.options || {}; 8 | this.resource = options.resource; 9 | this._asyncCallback = options.async; 10 | this._resolveStubs = options.resolveStubs || {}; 11 | } 12 | 13 | WebpackLoaderMock.prototype.async = function () { 14 | return this._asyncCallback; 15 | }; 16 | 17 | module.exports = WebpackLoaderMock; 18 | -------------------------------------------------------------------------------- /test/lib/loadOutput.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | 4 | function loadOutput(outputPath) { 5 | return fs.readFileSync(path.join(path.dirname(__dirname), 'templates/output', outputPath)) 6 | .toString() 7 | .replace(/%%LOADER%%/g, require.resolve('../../file-loader.js')); 8 | } 9 | 10 | module.exports = loadOutput; 11 | -------------------------------------------------------------------------------- /test/lib/loadTemplate.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | 4 | function loadTemplate(templatePath) { 5 | return fs.readFileSync(path.join(path.dirname(__dirname), 'templates', templatePath)).toString(); 6 | } 7 | 8 | module.exports = loadTemplate; 9 | -------------------------------------------------------------------------------- /test/lib/toText.js: -------------------------------------------------------------------------------- 1 | // Transforms a value to an expected text 2 | function toText (value) { 3 | if (value instanceof Array) { 4 | return value.map(toText).join(','); 5 | } else if (value instanceof Object) { 6 | var str = ''; 7 | for (var k in value) { 8 | str += ('<' + k + '>' + toText(value[k]) + ''); 9 | } 10 | return str; 11 | } else { 12 | return value + ''; 13 | } 14 | } 15 | 16 | module.exports = toText; 17 | -------------------------------------------------------------------------------- /test/loaderTest.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var chai = require('chai'); 4 | var assert = chai.assert; 5 | chai.use(require('chai-string')); 6 | 7 | var loader = require('../'); 8 | var WebpackLoaderMock = require('./lib/WebpackLoaderMock'); 9 | var loadTemplate = require('./lib/loadTemplate'); 10 | var loadOutput = require('./lib/loadOutput'); 11 | 12 | function testTemplate(loader, template, options, testFn) { 13 | loader.call(new WebpackLoaderMock({ 14 | query: options.query || '?', 15 | resource: path.join(__dirname, 'templates', template), 16 | options: options.options, 17 | async: function (err, source) { 18 | testFn(source); 19 | } 20 | }), loadTemplate(template)); 21 | } 22 | 23 | describe('loader', function () { 24 | it('should load simple underscore template', function (done) { 25 | testTemplate(loader, 'simple.html', {}, function (output) { 26 | // Copy and paste the result of `console.log(output)` to templates/output/simple.txt 27 | assert.equal(output, loadOutput('simple.txt')); 28 | done(); 29 | }); 30 | }); 31 | 32 | it('should prepend html comment', function (done) { 33 | testTemplate(loader, 'simple.html', { 34 | query: { 35 | prependFilenameComment: __dirname 36 | } 37 | }, function (output) { 38 | assert.equal(output, loadOutput('simple-with-comment.txt')); 39 | done(); 40 | }); 41 | }); 42 | 43 | it('should use underscore as the engine when specified', function (done) { 44 | testTemplate(loader, 'simple.html', { 45 | query: { 46 | engine: 'underscore' 47 | } 48 | }, function (output) { 49 | assert.equal(output, loadOutput('simple-underscore.txt')); 50 | done(); 51 | }); 52 | }); 53 | 54 | it('should use lodash as the engine when specified and include imports automatically', function (done) { 55 | testTemplate(loader, 'simple.html', { 56 | query: { 57 | engine: 'lodash' 58 | } 59 | }, function (output) { 60 | assert.equal(output, loadOutput('simple-lodash.txt')); 61 | done(); 62 | }); 63 | }); 64 | 65 | it('should include the template imports when withImports is true', function (done) { 66 | testTemplate(loader, 'simple.html', { 67 | query: { 68 | withImports: true 69 | } 70 | }, function (output) { 71 | assert.equal(output, loadOutput('simple-with-imports.txt')); 72 | done(); 73 | }); 74 | }); 75 | 76 | it('should NOT include template imports when withImports is false', function (done) { 77 | testTemplate(loader, 'simple.html', { 78 | query: { 79 | engine: 'lodash', 80 | withImports: false 81 | } 82 | }, function (output) { 83 | assert.equal(output, loadOutput('simple-lodash-no-imports.txt')); 84 | done(); 85 | }); 86 | }); 87 | 88 | it('should be possible to require a template', function (done) { 89 | testTemplate(loader, 'require.html', {}, function (output) { 90 | assert.equal(output, loadOutput('require.txt')); 91 | done(); 92 | }); 93 | }); 94 | 95 | it('should be possible to require a template with custom args', function (done) { 96 | testTemplate(loader, 'require_with_args.html', {}, function (output) { 97 | assert.equal(output, loadOutput('require_with_args.txt')); 98 | done(); 99 | }); 100 | }); 101 | 102 | it('should be possible to include a template', function (done) { 103 | testTemplate(loader, 'include.html', {}, function (output) { 104 | assert.equal(output, loadOutput('include.txt')); 105 | done(); 106 | }); 107 | }); 108 | 109 | it('should require an image', function (done) { 110 | testTemplate(loader, 'image.html', {}, function (output) { 111 | assert.equal(output, loadOutput('image.txt')); 112 | done(); 113 | }); 114 | }); 115 | 116 | it('should require given custom attributes', function (done) { 117 | testTemplate(loader, 'custom-attributes.html', { 118 | query: { 119 | attributes: ['img:src', 'link:href'] 120 | } 121 | }, function (output) { 122 | assert.equal(output, loadOutput('custom-attributes.txt')); 123 | done(); 124 | }); 125 | }); 126 | 127 | it('should not parse an absolute image without root option given', function (done) { 128 | testTemplate(loader, 'absolute-image.html', {}, function (output) { 129 | assert.equal(output, loadOutput('absolute-image.txt')); 130 | done(); 131 | }); 132 | }); 133 | 134 | it('should parse an absolute image if root option is given', function (done) { 135 | testTemplate(loader, 'absolute-image.html', { 136 | query: { 137 | root: '/bar' 138 | } 139 | }, function (output) { 140 | assert.equal(output, loadOutput('absolute-image-with-root.txt')); 141 | done(); 142 | }); 143 | }); 144 | 145 | it('should leave dynamic attributes unaltered', function (done) { 146 | testTemplate(loader, 'dynamic-attribute.html', { 147 | query: { 148 | } 149 | }, function (output) { 150 | assert.equal(output, loadOutput('dynamic-attribute.txt')); 151 | done(); 152 | }); 153 | }); 154 | 155 | it('should leave dynamic attributes unaltered with root', function (done) { 156 | testTemplate(loader, 'dynamic-attribute-with-root.html', { 157 | query: { 158 | root: '/bar' 159 | } 160 | }, function (output) { 161 | assert.equal(output, loadOutput('dynamic-attribute-with-root.txt')); 162 | done(); 163 | }); 164 | }); 165 | 166 | it('should parse dynamic attributes with parseDynamicRoutes', function (done) { 167 | testTemplate(loader, 'dynamic-attribute-with-parseDynamicRoutes.html', { 168 | query: { 169 | root: 'myapp', 170 | parseDynamicRoutes: true 171 | } 172 | }, function (output) { 173 | assert.equal(output, loadOutput('dynamic-attribute-with-parseDynamicRoutes.txt')); 174 | done(); 175 | }); 176 | }); 177 | 178 | // FIXME: Changing the underscore tags changes it globally 179 | it('should allow custom underscore tags', function (done) { 180 | testTemplate(loader, 'custom-tags.html', { 181 | query: { 182 | interpolate: '\\{\\[(.+?)\\]\\}', 183 | evaluate: '\\{%([\\s\\S]+?)%\\}', 184 | escape: '\\{\\{(.+?)\\}\\}' 185 | } 186 | }, function (output) { 187 | assert.equal(output, loadOutput('custom-tags.txt')); 188 | done(); 189 | }); 190 | }); 191 | }); 192 | -------------------------------------------------------------------------------- /test/macroTest.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var chai = require('chai'); 4 | var assert = chai.assert; 5 | chai.use(require('chai-string')); 6 | 7 | var loader = require('../'); 8 | var WebpackLoaderMock = require('./lib/WebpackLoaderMock'); 9 | var loadTemplate = require('./lib/loadTemplate'); 10 | var loadOutput = require('./lib/loadOutput'); 11 | var toText = require('./lib/toText.js'); 12 | 13 | function testTemplate(loader, template, options, testFn) { 14 | loader.call(new WebpackLoaderMock({ 15 | query: options.query || '?', 16 | resource: path.join(__dirname, 'templates', template), 17 | options: options.options, 18 | async: function (err, source) { 19 | testFn(source); 20 | } 21 | }), loadTemplate(template)); 22 | } 23 | 24 | describe('macro', function () { 25 | it('should be parsed', function (done) { 26 | testTemplate(loader, 'custom-macro.html', { 27 | options: { 28 | macros: { 29 | foo: function () { 30 | return '"

bar

"'; 31 | } 32 | } 33 | } 34 | }, function (output) { 35 | assert.equal(output, loadOutput('custom-macro.txt')); 36 | done(); 37 | }); 38 | }); 39 | 40 | it('should receive boolean arguments', function (done) { 41 | testTemplate(loader, 'macro_boolean_args.html', { 42 | options: { 43 | macros: { 44 | bool_test: function (arg) { 45 | assert.typeOf(arg, 'boolean'); 46 | return arg ? '"

TRUE

"' : '"

FALSE

"'; 47 | } 48 | } 49 | } 50 | }, function (output) { 51 | assert.equal(output, loadOutput('macro_boolean_args.txt')); 52 | done(); 53 | }); 54 | }); 55 | 56 | it('should receive numeric arguments', function (done) { 57 | testTemplate(loader, 'macro_numeric_args.html', { 58 | options: { 59 | macros: { 60 | num_test: function (arg) { 61 | assert.typeOf(arg, 'number'); 62 | return '"

' + arg + '

"'; 63 | } 64 | } 65 | } 66 | }, function (output) { 67 | assert.equal(output, loadOutput('macro_numeric_args.txt')); 68 | done(); 69 | }); 70 | }); 71 | 72 | it('should receive string arguments', function (done) { 73 | testTemplate(loader, 'macro_string_args.html', { 74 | options: { 75 | macros: { 76 | str_test: function (arg) { 77 | assert.typeOf(arg, 'string'); 78 | return '"

' + arg.toUpperCase() + '

"'; 79 | } 80 | } 81 | } 82 | }, function (output) { 83 | assert.equal(output, loadOutput('macro_string_args.txt')); 84 | done(); 85 | }); 86 | }); 87 | 88 | it('should receive object arguments', function(done) { 89 | testTemplate(loader, 'macro_object_args.html', { 90 | options: { 91 | macros: { 92 | object_test: function(arg) { 93 | assert.typeOf(arg, 'object'); 94 | return '"' + toText(arg) + '"'; 95 | } 96 | } 97 | } 98 | }, function(output) { 99 | assert.equal(output.trimRight(), loadOutput('macro_object_args.txt').trimRight()); 100 | done(); 101 | }); 102 | }); 103 | 104 | it('should receive argument list', function (done) { 105 | testTemplate(loader, 'macro_argument_list.html', { 106 | options: { 107 | macros: { 108 | numbers: function (first, second, third) { 109 | assert.typeOf(first, 'number'); 110 | assert.typeOf(second, 'number'); 111 | assert.typeOf(third, 'number'); 112 | 113 | var output = ''; 114 | for (var i = 0; i < arguments.length; i++) { 115 | output += '

' + arguments[i] + '

'; 116 | } 117 | return '"' + output + '"'; 118 | }, 119 | 120 | booleans: function (first, second, third) { 121 | assert.typeOf(first, 'boolean'); 122 | assert.typeOf(second, 'boolean'); 123 | assert.typeOf(third, 'boolean'); 124 | 125 | var output = ''; 126 | for (var i = 0; i < arguments.length; i++) { 127 | output += '

' + (arguments[i] ? 'TRUE' : 'FALSE') + '

'; 128 | } 129 | return '"' + output + '"'; 130 | }, 131 | 132 | strings: function (first, second, third) { 133 | assert.typeOf(first, 'string'); 134 | assert.typeOf(second, 'string'); 135 | assert.typeOf(third, 'string'); 136 | 137 | var output = ''; 138 | for (var i = 0; i < arguments.length; i++) { 139 | output += '

' + arguments[i].toLowerCase().replace(/"/g, "\\\"") + '

'; 140 | } 141 | return '"' + output + '"'; 142 | }, 143 | 144 | mixed: function () { 145 | assert.equal(arguments.length, 6); 146 | assert.typeOf(arguments[0], 'boolean'); 147 | assert.typeOf(arguments[1], 'number'); 148 | assert.typeOf(arguments[2], 'string'); 149 | assert.typeOf(arguments[3], 'boolean'); 150 | assert.typeOf(arguments[4], 'string'); 151 | assert.typeOf(arguments[5], 'number'); 152 | 153 | var output = ''; 154 | 155 | for (var i = 0; i < arguments.length; i++) { 156 | var type = typeof(arguments[i]); 157 | 158 | if (type == 'string') { 159 | output += '

' + arguments[i].toLowerCase().replace(/"/g, "\\\"") + '

'; 160 | } else if (type == 'number') { 161 | output += '

' + arguments[i] + '

'; 162 | } else if (type == 'boolean') { 163 | output += '

' + (arguments[i] ? 'TRUE' : 'FALSE') + '

'; 164 | } 165 | } 166 | 167 | return '"' + output + '"'; 168 | 169 | } 170 | } 171 | } 172 | }, function (output) { 173 | assert.equal(output, loadOutput('macro_argument_list.txt')); 174 | done(); 175 | }); 176 | }); 177 | 178 | it('should not be evaluated', function (done) { 179 | testTemplate(loader, 'macro.html', { 180 | query: { 181 | parseMacros: false 182 | } 183 | }, function (output) { 184 | assert.equal(output, loadOutput('disabled-macro.txt')); 185 | done(); 186 | }); 187 | }); 188 | 189 | it('should be replaced when escaped', function (done) { 190 | testTemplate(loader, 'macro_escaped.html', { 191 | options: { 192 | macros: { 193 | unescaped: function () { 194 | return '"

Ok

"'; 195 | } 196 | } 197 | } 198 | }, function (output) { 199 | assert.equal(output, loadOutput('macro_escaped.txt')); 200 | done(); 201 | }); 202 | }); 203 | 204 | it('support macros in query', function (done) { 205 | testTemplate(loader, 'macro_in_query.html', { 206 | query: { 207 | macros: { 208 | testquery: function () { 209 | return '"Ok"'; 210 | } 211 | } 212 | } 213 | }, function (output) { 214 | assert.equal(output, loadOutput('macro_in_query.txt')); 215 | done(); 216 | }); 217 | }); 218 | }); 219 | -------------------------------------------------------------------------------- /test/templates/absolute-image.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test/templates/custom-attributes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /test/templates/custom-macro.html: -------------------------------------------------------------------------------- 1 | What, @foo(3) 2 | -------------------------------------------------------------------------------- /test/templates/custom-tags.html: -------------------------------------------------------------------------------- 1 | {{title}}{%description%}{[image]} 2 | -------------------------------------------------------------------------------- /test/templates/dynamic-attribute-with-parseDynamicRoutes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /test/templates/dynamic-attribute-with-root.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /test/templates/dynamic-attribute.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /test/templates/image.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test/templates/include.html: -------------------------------------------------------------------------------- 1 | Hello, @include('./bar.html') 2 | -------------------------------------------------------------------------------- /test/templates/macro.html: -------------------------------------------------------------------------------- 1 | Hi. 2 | @br(3) 3 | @nl(2) 4 | -------------------------------------------------------------------------------- /test/templates/macro_argument_list.html: -------------------------------------------------------------------------------- 1 | @numbers(1 3.534 000000000000000005) 2 | @booleans(true false true) 3 | @strings('Lorem' "Ipsum" '"Sit"' "'Amet'") 4 | @mixed(false 423.429 "Hello world" true 'Lorem' 00000000003) -------------------------------------------------------------------------------- /test/templates/macro_boolean_args.html: -------------------------------------------------------------------------------- 1 | @bool_test(true) 2 |
3 | @bool_test(false) -------------------------------------------------------------------------------- /test/templates/macro_escaped.html: -------------------------------------------------------------------------------- 1 | \@escaped(1 2 3) 2 | @unescaped() 3 | \@unescaped() -------------------------------------------------------------------------------- /test/templates/macro_in_query.html: -------------------------------------------------------------------------------- 1 | @testquery() -------------------------------------------------------------------------------- /test/templates/macro_numeric_args.html: -------------------------------------------------------------------------------- 1 | @num_test(5) 2 |
3 | @num_test(6.71) 4 |
5 | @num_test(00000000000000002) -------------------------------------------------------------------------------- /test/templates/macro_object_args.html: -------------------------------------------------------------------------------- 1 | @object_test({"a": 1, "b": "20", "c": "300", "d": true}) 2 |
3 | @object_test({"a": [], "b": [ 1, "20" ], "c": { "name": "emma", "role": "dev"} })dont' parse this 4 | -------------------------------------------------------------------------------- /test/templates/macro_string_args.html: -------------------------------------------------------------------------------- 1 | @str_test('Lorem ipsum') 2 |
3 | @str_test("Sit amet") -------------------------------------------------------------------------------- /test/templates/output/absolute-image-with-root.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='\n'; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/absolute-image.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='\n'; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/custom-attributes.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='\n\n'; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/custom-macro.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='What, ' + "

bar

" + '\n'; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/custom-tags.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+=''+ 5 | ((__t=(title))==null?'':_.escape(__t))+ 6 | ''; 7 | description 8 | __p+=''+ 9 | ((__t=(image))==null?'':__t)+ 10 | '\n'; 11 | } 12 | return __p; 13 | }; 14 | -------------------------------------------------------------------------------- /test/templates/output/disabled-macro.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='Hi.\n@br(3)\n@nl(2)\n'; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/dynamic-attribute-with-parseDynamicRoutes.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='\n\n'; 9 | } 10 | return __p; 11 | }; 12 | -------------------------------------------------------------------------------- /test/templates/output/dynamic-attribute-with-root.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='\n\n'; 9 | } 10 | return __p; 11 | }; 12 | -------------------------------------------------------------------------------- /test/templates/output/dynamic-attribute.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='\n\n'; 9 | } 10 | return __p; 11 | }; 12 | -------------------------------------------------------------------------------- /test/templates/output/image.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='\n'; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/include.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='Hello, ' + require("./bar.html") + '\n'; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/macro_argument_list.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='' + "

1

3.534

5

" + '\n' + "

TRUE

FALSE

TRUE

" + '\n' + "

lorem

ipsum

\"sit\"

'amet'

" + '\n' + "

FALSE

423.429

hello world

TRUE

lorem

3

" + ''; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/macro_boolean_args.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='' + "

TRUE

" + '\n
\n' + "

FALSE

" + ''; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/macro_escaped.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='@escaped(1 2 3)\n' + "

Ok

" + '\n\\@unescaped()'; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/macro_in_query.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='' + "Ok" + ''; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/macro_numeric_args.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='' + "

5

" + '\n
\n' + "

6.71

" + '\n
\n' + "

2

" + ''; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/macro_object_args.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='' + "120300true" + '\n
\n' + "1,20emmadev" + 'dont\' parse this\n'; 5 | } 6 | return __p; 7 | }; 8 | 9 | -------------------------------------------------------------------------------- /test/templates/output/macro_string_args.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='' + "

LOREM IPSUM

" + '\n
\n' + "

SIT AMET

" + ''; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/require.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='Hello, ' + require("./bar.html").apply(null,arguments) + '\n'; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/require_with_args.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='Hello, ' + require("./bar.html").apply(null,(function (args, obj) {args = Array.prototype.slice.call(args);var _a = args.slice(1); _a.unshift(Object.assign(obj, args[0])); return _a;})(arguments, {"name":"emma","role":"dev"})) + '\n'; 5 | } 6 | return __p; 7 | }; 8 | -------------------------------------------------------------------------------- /test/templates/output/simple-lodash-no-imports.txt: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | module.exports = function(obj){ 3 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 4 | with(obj||{}){ 5 | __p+='

'+ 6 | ((__t=(title))==null?'':_.escape(__t))+ 7 | '

\n

A simple template

\n\n'; 8 | if (description) { 9 | __p+='\n

'+ 10 | ((__t=(description))==null?'':_.escape(__t))+ 11 | '

\n'; 12 | } 13 | __p+='\n'; 14 | } 15 | return __p; 16 | }; 17 | -------------------------------------------------------------------------------- /test/templates/output/simple-lodash.txt: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | module.exports = Function(_.keys(_.templateSettings.imports), 'return ' + function(obj){ 3 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 4 | with(obj||{}){ 5 | __p+='

'+ 6 | ((__t=(title))==null?'':_.escape(__t))+ 7 | '

\n

A simple template

\n\n'; 8 | if (description) { 9 | __p+='\n

'+ 10 | ((__t=(description))==null?'':_.escape(__t))+ 11 | '

\n'; 12 | } 13 | __p+='\n'; 14 | } 15 | return __p; 16 | }.toString()).apply(undefined, _.values(_.templateSettings.imports)); 17 | -------------------------------------------------------------------------------- /test/templates/output/simple-underscore.txt: -------------------------------------------------------------------------------- 1 | var _ = require('underscore'); 2 | module.exports = function(obj){ 3 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 4 | with(obj||{}){ 5 | __p+='

'+ 6 | ((__t=(title))==null?'':_.escape(__t))+ 7 | '

\n

A simple template

\n\n'; 8 | if (description) { 9 | __p+='\n

'+ 10 | ((__t=(description))==null?'':_.escape(__t))+ 11 | '

\n'; 12 | } 13 | __p+='\n'; 14 | } 15 | return __p; 16 | }; 17 | -------------------------------------------------------------------------------- /test/templates/output/simple-with-comment.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='\n\n

'+ 5 | ((__t=(title))==null?'':_.escape(__t))+ 6 | '

\n

A simple template

\n\n'; 7 | if (description) { 8 | __p+='\n

'+ 9 | ((__t=(description))==null?'':_.escape(__t))+ 10 | '

\n'; 11 | } 12 | __p+='\n'; 13 | } 14 | return __p; 15 | }; 16 | -------------------------------------------------------------------------------- /test/templates/output/simple-with-imports.txt: -------------------------------------------------------------------------------- 1 | module.exports = Function(_.keys(_.templateSettings.imports), 'return ' + function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='

'+ 5 | ((__t=(title))==null?'':_.escape(__t))+ 6 | '

\n

A simple template

\n\n'; 7 | if (description) { 8 | __p+='\n

'+ 9 | ((__t=(description))==null?'':_.escape(__t))+ 10 | '

\n'; 11 | } 12 | __p+='\n'; 13 | } 14 | return __p; 15 | }.toString()).apply(undefined, _.values(_.templateSettings.imports)); 16 | -------------------------------------------------------------------------------- /test/templates/output/simple.txt: -------------------------------------------------------------------------------- 1 | module.exports = function(obj){ 2 | var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; 3 | with(obj||{}){ 4 | __p+='

'+ 5 | ((__t=(title))==null?'':_.escape(__t))+ 6 | '

\n

A simple template

\n\n'; 7 | if (description) { 8 | __p+='\n

'+ 9 | ((__t=(description))==null?'':_.escape(__t))+ 10 | '

\n'; 11 | } 12 | __p+='\n'; 13 | } 14 | return __p; 15 | }; 16 | -------------------------------------------------------------------------------- /test/templates/require.html: -------------------------------------------------------------------------------- 1 | Hello, @require('./bar.html') 2 | -------------------------------------------------------------------------------- /test/templates/require_with_args.html: -------------------------------------------------------------------------------- 1 | Hello, @require('./bar.html', {"name": "emma", "role": "dev"}) 2 | -------------------------------------------------------------------------------- /test/templates/simple.html: -------------------------------------------------------------------------------- 1 |

<%-title%>

2 |

A simple template

3 | 4 | <%if (description) {%> 5 |

<%-description%>

6 | <%}%> 7 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@ungap/promise-all-settled@1.1.2": 6 | version "1.1.2" 7 | resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" 8 | integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== 9 | 10 | abbrev@1: 11 | version "1.1.1" 12 | resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" 13 | integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== 14 | 15 | abbrev@1.0.x: 16 | version "1.0.9" 17 | resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" 18 | integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= 19 | 20 | amdefine@>=0.0.4: 21 | version "1.0.1" 22 | resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" 23 | integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= 24 | 25 | ansi-colors@4.1.1: 26 | version "4.1.1" 27 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" 28 | integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== 29 | 30 | ansi-regex@^3.0.0: 31 | version "3.0.0" 32 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 33 | integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= 34 | 35 | ansi-regex@^5.0.0: 36 | version "5.0.0" 37 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" 38 | integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== 39 | 40 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 41 | version "4.3.0" 42 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 43 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 44 | dependencies: 45 | color-convert "^2.0.1" 46 | 47 | anymatch@~3.1.1: 48 | version "3.1.1" 49 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" 50 | integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== 51 | dependencies: 52 | normalize-path "^3.0.0" 53 | picomatch "^2.0.4" 54 | 55 | argparse@^1.0.7: 56 | version "1.0.10" 57 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 58 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 59 | dependencies: 60 | sprintf-js "~1.0.2" 61 | 62 | argparse@^2.0.1: 63 | version "2.0.1" 64 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 65 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 66 | 67 | assertion-error@^1.1.0: 68 | version "1.1.0" 69 | resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" 70 | integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== 71 | 72 | async@1.x: 73 | version "1.5.2" 74 | resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" 75 | integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= 76 | 77 | balanced-match@^1.0.0: 78 | version "1.0.0" 79 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 80 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 81 | 82 | big.js@^5.2.2: 83 | version "5.2.2" 84 | resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" 85 | integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== 86 | 87 | binary-extensions@^2.0.0: 88 | version "2.2.0" 89 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 90 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 91 | 92 | brace-expansion@^1.0.0, brace-expansion@^1.1.7: 93 | version "1.1.11" 94 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 95 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 96 | dependencies: 97 | balanced-match "^1.0.0" 98 | concat-map "0.0.1" 99 | 100 | braces@~3.0.2: 101 | version "3.0.2" 102 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 103 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 104 | dependencies: 105 | fill-range "^7.0.1" 106 | 107 | browser-stdout@1.3.1: 108 | version "1.3.1" 109 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 110 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== 111 | 112 | camelcase@^6.0.0: 113 | version "6.2.0" 114 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" 115 | integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== 116 | 117 | chai-string@^1.5.0: 118 | version "1.5.0" 119 | resolved "https://registry.yarnpkg.com/chai-string/-/chai-string-1.5.0.tgz#0bdb2d8a5f1dbe90bc78ec493c1c1c180dd4d3d2" 120 | integrity sha512-sydDC3S3pNAQMYwJrs6dQX0oBQ6KfIPuOZ78n7rocW0eJJlsHPh2t3kwW7xfwYA/1Bf6/arGtSUo16rxR2JFlw== 121 | 122 | chai@^4.3.4: 123 | version "4.3.4" 124 | resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" 125 | integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== 126 | dependencies: 127 | assertion-error "^1.1.0" 128 | check-error "^1.0.2" 129 | deep-eql "^3.0.1" 130 | get-func-name "^2.0.0" 131 | pathval "^1.1.1" 132 | type-detect "^4.0.5" 133 | 134 | chalk@^4.0.0: 135 | version "4.1.0" 136 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" 137 | integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== 138 | dependencies: 139 | ansi-styles "^4.1.0" 140 | supports-color "^7.1.0" 141 | 142 | check-error@^1.0.2: 143 | version "1.0.2" 144 | resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" 145 | integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= 146 | 147 | chokidar@3.5.1: 148 | version "3.5.1" 149 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" 150 | integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== 151 | dependencies: 152 | anymatch "~3.1.1" 153 | braces "~3.0.2" 154 | glob-parent "~5.1.0" 155 | is-binary-path "~2.1.0" 156 | is-glob "~4.0.1" 157 | normalize-path "~3.0.0" 158 | readdirp "~3.5.0" 159 | optionalDependencies: 160 | fsevents "~2.3.1" 161 | 162 | cliui@^7.0.2: 163 | version "7.0.4" 164 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" 165 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== 166 | dependencies: 167 | string-width "^4.2.0" 168 | strip-ansi "^6.0.0" 169 | wrap-ansi "^7.0.0" 170 | 171 | color-convert@^2.0.1: 172 | version "2.0.1" 173 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 174 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 175 | dependencies: 176 | color-name "~1.1.4" 177 | 178 | color-name@~1.1.4: 179 | version "1.1.4" 180 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 181 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 182 | 183 | concat-map@0.0.1: 184 | version "0.0.1" 185 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 186 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 187 | 188 | debug@4.3.1: 189 | version "4.3.1" 190 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" 191 | integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== 192 | dependencies: 193 | ms "2.1.2" 194 | 195 | decamelize@^4.0.0: 196 | version "4.0.0" 197 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" 198 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== 199 | 200 | deep-eql@^3.0.1: 201 | version "3.0.1" 202 | resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" 203 | integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== 204 | dependencies: 205 | type-detect "^4.0.0" 206 | 207 | deep-is@~0.1.2: 208 | version "0.1.3" 209 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" 210 | integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= 211 | 212 | diff@5.0.0: 213 | version "5.0.0" 214 | resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" 215 | integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== 216 | 217 | emoji-regex@^8.0.0: 218 | version "8.0.0" 219 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 220 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 221 | 222 | emojis-list@^3.0.0: 223 | version "3.0.0" 224 | resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" 225 | integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== 226 | 227 | escalade@^3.1.1: 228 | version "3.1.1" 229 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 230 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 231 | 232 | escape-string-regexp@4.0.0: 233 | version "4.0.0" 234 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 235 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 236 | 237 | escodegen@1.7.x: 238 | version "1.7.1" 239 | resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.7.1.tgz#30ecfcf66ca98dc67cd2fd162abeb6eafa8ce6fc" 240 | integrity sha1-MOz89mypjcZ80v0WKr626vqM5vw= 241 | dependencies: 242 | esprima "^1.2.2" 243 | estraverse "^1.9.1" 244 | esutils "^2.0.2" 245 | optionator "^0.5.0" 246 | optionalDependencies: 247 | source-map "~0.2.0" 248 | 249 | esprima@2.5.x: 250 | version "2.5.0" 251 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.5.0.tgz#f387a46fd344c1b1a39baf8c20bfb43b6d0058cc" 252 | integrity sha1-84ekb9NEwbGjm6+MIL+0O20AWMw= 253 | 254 | esprima@^1.2.2: 255 | version "1.2.5" 256 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.2.5.tgz#0993502feaf668138325756f30f9a51feeec11e9" 257 | integrity sha1-CZNQL+r2aBODJXVvMPmlH+7sEek= 258 | 259 | esprima@^4.0.0: 260 | version "4.0.1" 261 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 262 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 263 | 264 | estraverse@^1.9.1: 265 | version "1.9.3" 266 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" 267 | integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= 268 | 269 | esutils@^2.0.2: 270 | version "2.0.3" 271 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 272 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 273 | 274 | fast-levenshtein@~1.0.0: 275 | version "1.0.7" 276 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-1.0.7.tgz#0178dcdee023b92905193af0959e8a7639cfdcb9" 277 | integrity sha1-AXjc3uAjuSkFGTrwlZ6KdjnP3Lk= 278 | 279 | fastparse@^1.1.2: 280 | version "1.1.2" 281 | resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" 282 | integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== 283 | 284 | fileset@0.2.x: 285 | version "0.2.1" 286 | resolved "https://registry.yarnpkg.com/fileset/-/fileset-0.2.1.tgz#588ef8973c6623b2a76df465105696b96aac8067" 287 | integrity sha1-WI74lzxmI7KnbfRlEFaWuWqsgGc= 288 | dependencies: 289 | glob "5.x" 290 | minimatch "2.x" 291 | 292 | fill-range@^7.0.1: 293 | version "7.0.1" 294 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 295 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 296 | dependencies: 297 | to-regex-range "^5.0.1" 298 | 299 | find-up@5.0.0: 300 | version "5.0.0" 301 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 302 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 303 | dependencies: 304 | locate-path "^6.0.0" 305 | path-exists "^4.0.0" 306 | 307 | flat@^5.0.2: 308 | version "5.0.2" 309 | resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" 310 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== 311 | 312 | fs.realpath@^1.0.0: 313 | version "1.0.0" 314 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 315 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 316 | 317 | fsevents@~2.3.1: 318 | version "2.3.2" 319 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 320 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 321 | 322 | get-caller-file@^2.0.5: 323 | version "2.0.5" 324 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 325 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 326 | 327 | get-func-name@^2.0.0: 328 | version "2.0.0" 329 | resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" 330 | integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= 331 | 332 | glob-parent@~5.1.0: 333 | version "5.1.2" 334 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 335 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 336 | dependencies: 337 | is-glob "^4.0.1" 338 | 339 | glob@5.x: 340 | version "5.0.15" 341 | resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" 342 | integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= 343 | dependencies: 344 | inflight "^1.0.4" 345 | inherits "2" 346 | minimatch "2 || 3" 347 | once "^1.3.0" 348 | path-is-absolute "^1.0.0" 349 | 350 | glob@7.1.6: 351 | version "7.1.6" 352 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 353 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 354 | dependencies: 355 | fs.realpath "^1.0.0" 356 | inflight "^1.0.4" 357 | inherits "2" 358 | minimatch "^3.0.4" 359 | once "^1.3.0" 360 | path-is-absolute "^1.0.0" 361 | 362 | growl@1.10.5: 363 | version "1.10.5" 364 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" 365 | integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== 366 | 367 | handlebars@^4.0.1: 368 | version "4.7.7" 369 | resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" 370 | integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== 371 | dependencies: 372 | minimist "^1.2.5" 373 | neo-async "^2.6.0" 374 | source-map "^0.6.1" 375 | wordwrap "^1.0.0" 376 | optionalDependencies: 377 | uglify-js "^3.1.4" 378 | 379 | has-flag@^1.0.0: 380 | version "1.0.0" 381 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" 382 | integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= 383 | 384 | has-flag@^4.0.0: 385 | version "4.0.0" 386 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 387 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 388 | 389 | he@1.2.0: 390 | version "1.2.0" 391 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 392 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 393 | 394 | inflight@^1.0.4: 395 | version "1.0.6" 396 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 397 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 398 | dependencies: 399 | once "^1.3.0" 400 | wrappy "1" 401 | 402 | inherits@2: 403 | version "2.0.4" 404 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 405 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 406 | 407 | is-binary-path@~2.1.0: 408 | version "2.1.0" 409 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 410 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 411 | dependencies: 412 | binary-extensions "^2.0.0" 413 | 414 | is-extglob@^2.1.1: 415 | version "2.1.1" 416 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 417 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 418 | 419 | is-fullwidth-code-point@^2.0.0: 420 | version "2.0.0" 421 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 422 | integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= 423 | 424 | is-fullwidth-code-point@^3.0.0: 425 | version "3.0.0" 426 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 427 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 428 | 429 | is-glob@^4.0.1, is-glob@~4.0.1: 430 | version "4.0.1" 431 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" 432 | integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== 433 | dependencies: 434 | is-extglob "^2.1.1" 435 | 436 | is-number@^7.0.0: 437 | version "7.0.0" 438 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 439 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 440 | 441 | is-plain-obj@^2.1.0: 442 | version "2.1.0" 443 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" 444 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 445 | 446 | isexe@^2.0.0: 447 | version "2.0.0" 448 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 449 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 450 | 451 | istanbul@^0.3.18: 452 | version "0.3.22" 453 | resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.3.22.tgz#3e164d85021fe19c985d1f0e7ef0c3e22d012eb6" 454 | integrity sha1-PhZNhQIf4ZyYXR8OfvDD4i0BLrY= 455 | dependencies: 456 | abbrev "1.0.x" 457 | async "1.x" 458 | escodegen "1.7.x" 459 | esprima "2.5.x" 460 | fileset "0.2.x" 461 | handlebars "^4.0.1" 462 | js-yaml "3.x" 463 | mkdirp "0.5.x" 464 | nopt "3.x" 465 | once "1.x" 466 | resolve "1.1.x" 467 | supports-color "^3.1.0" 468 | which "^1.1.1" 469 | wordwrap "^1.0.0" 470 | 471 | js-yaml@3.x: 472 | version "3.14.1" 473 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" 474 | integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== 475 | dependencies: 476 | argparse "^1.0.7" 477 | esprima "^4.0.0" 478 | 479 | js-yaml@4.0.0: 480 | version "4.0.0" 481 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.0.0.tgz#f426bc0ff4b4051926cd588c71113183409a121f" 482 | integrity sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q== 483 | dependencies: 484 | argparse "^2.0.1" 485 | 486 | json5@^2.1.2: 487 | version "2.2.0" 488 | resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" 489 | integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== 490 | dependencies: 491 | minimist "^1.2.5" 492 | 493 | levn@~0.2.5: 494 | version "0.2.5" 495 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.2.5.tgz#ba8d339d0ca4a610e3a3f145b9caf48807155054" 496 | integrity sha1-uo0znQykphDjo/FFucr0iAcVUFQ= 497 | dependencies: 498 | prelude-ls "~1.1.0" 499 | type-check "~0.3.1" 500 | 501 | loader-utils@^2.0.0: 502 | version "2.0.0" 503 | resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" 504 | integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== 505 | dependencies: 506 | big.js "^5.2.2" 507 | emojis-list "^3.0.0" 508 | json5 "^2.1.2" 509 | 510 | locate-path@^6.0.0: 511 | version "6.0.0" 512 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 513 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 514 | dependencies: 515 | p-locate "^5.0.0" 516 | 517 | log-symbols@4.0.0: 518 | version "4.0.0" 519 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" 520 | integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== 521 | dependencies: 522 | chalk "^4.0.0" 523 | 524 | "minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.4: 525 | version "3.0.4" 526 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 527 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 528 | dependencies: 529 | brace-expansion "^1.1.7" 530 | 531 | minimatch@2.x: 532 | version "2.0.10" 533 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" 534 | integrity sha1-jQh8OcazjAAbl/ynzm0OHoCvusc= 535 | dependencies: 536 | brace-expansion "^1.0.0" 537 | 538 | minimist@^1.2.5: 539 | version "1.2.5" 540 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" 541 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 542 | 543 | mkdirp@0.5.x: 544 | version "0.5.5" 545 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" 546 | integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== 547 | dependencies: 548 | minimist "^1.2.5" 549 | 550 | mocha@^8.3.2: 551 | version "8.3.2" 552 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.3.2.tgz#53406f195fa86fbdebe71f8b1c6fb23221d69fcc" 553 | integrity sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg== 554 | dependencies: 555 | "@ungap/promise-all-settled" "1.1.2" 556 | ansi-colors "4.1.1" 557 | browser-stdout "1.3.1" 558 | chokidar "3.5.1" 559 | debug "4.3.1" 560 | diff "5.0.0" 561 | escape-string-regexp "4.0.0" 562 | find-up "5.0.0" 563 | glob "7.1.6" 564 | growl "1.10.5" 565 | he "1.2.0" 566 | js-yaml "4.0.0" 567 | log-symbols "4.0.0" 568 | minimatch "3.0.4" 569 | ms "2.1.3" 570 | nanoid "3.1.20" 571 | serialize-javascript "5.0.1" 572 | strip-json-comments "3.1.1" 573 | supports-color "8.1.1" 574 | which "2.0.2" 575 | wide-align "1.1.3" 576 | workerpool "6.1.0" 577 | yargs "16.2.0" 578 | yargs-parser "20.2.4" 579 | yargs-unparser "2.0.0" 580 | 581 | ms@2.1.2: 582 | version "2.1.2" 583 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 584 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 585 | 586 | ms@2.1.3: 587 | version "2.1.3" 588 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 589 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 590 | 591 | nanoid@3.1.20: 592 | version "3.1.20" 593 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" 594 | integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw== 595 | 596 | neo-async@^2.6.0: 597 | version "2.6.2" 598 | resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" 599 | integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== 600 | 601 | nopt@3.x: 602 | version "3.0.6" 603 | resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" 604 | integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= 605 | dependencies: 606 | abbrev "1" 607 | 608 | normalize-path@^3.0.0, normalize-path@~3.0.0: 609 | version "3.0.0" 610 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 611 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 612 | 613 | once@1.x, once@^1.3.0: 614 | version "1.4.0" 615 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 616 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 617 | dependencies: 618 | wrappy "1" 619 | 620 | optionator@^0.5.0: 621 | version "0.5.0" 622 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.5.0.tgz#b75a8995a2d417df25b6e4e3862f50aa88651368" 623 | integrity sha1-t1qJlaLUF98ltuTjhi9QqohlE2g= 624 | dependencies: 625 | deep-is "~0.1.2" 626 | fast-levenshtein "~1.0.0" 627 | levn "~0.2.5" 628 | prelude-ls "~1.1.1" 629 | type-check "~0.3.1" 630 | wordwrap "~0.0.2" 631 | 632 | p-limit@^3.0.2: 633 | version "3.1.0" 634 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 635 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 636 | dependencies: 637 | yocto-queue "^0.1.0" 638 | 639 | p-locate@^5.0.0: 640 | version "5.0.0" 641 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 642 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 643 | dependencies: 644 | p-limit "^3.0.2" 645 | 646 | path-exists@^4.0.0: 647 | version "4.0.0" 648 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 649 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 650 | 651 | path-is-absolute@^1.0.0: 652 | version "1.0.1" 653 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 654 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 655 | 656 | pathval@^1.1.1: 657 | version "1.1.1" 658 | resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" 659 | integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== 660 | 661 | picomatch@^2.0.4, picomatch@^2.2.1: 662 | version "2.2.2" 663 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" 664 | integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== 665 | 666 | prelude-ls@~1.1.0, prelude-ls@~1.1.1, prelude-ls@~1.1.2: 667 | version "1.1.2" 668 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" 669 | integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= 670 | 671 | randombytes@^2.1.0: 672 | version "2.1.0" 673 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 674 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 675 | dependencies: 676 | safe-buffer "^5.1.0" 677 | 678 | readdirp@~3.5.0: 679 | version "3.5.0" 680 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" 681 | integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== 682 | dependencies: 683 | picomatch "^2.2.1" 684 | 685 | require-directory@^2.1.1: 686 | version "2.1.1" 687 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 688 | integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= 689 | 690 | resolve@1.1.x: 691 | version "1.1.7" 692 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" 693 | integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= 694 | 695 | safe-buffer@^5.1.0: 696 | version "5.2.1" 697 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 698 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 699 | 700 | serialize-javascript@5.0.1: 701 | version "5.0.1" 702 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" 703 | integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== 704 | dependencies: 705 | randombytes "^2.1.0" 706 | 707 | source-map@^0.6.1: 708 | version "0.6.1" 709 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 710 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 711 | 712 | source-map@~0.2.0: 713 | version "0.2.0" 714 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" 715 | integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= 716 | dependencies: 717 | amdefine ">=0.0.4" 718 | 719 | sprintf-js@~1.0.2: 720 | version "1.0.3" 721 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 722 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 723 | 724 | "string-width@^1.0.2 || 2": 725 | version "2.1.1" 726 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 727 | integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== 728 | dependencies: 729 | is-fullwidth-code-point "^2.0.0" 730 | strip-ansi "^4.0.0" 731 | 732 | string-width@^4.1.0, string-width@^4.2.0: 733 | version "4.2.2" 734 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" 735 | integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== 736 | dependencies: 737 | emoji-regex "^8.0.0" 738 | is-fullwidth-code-point "^3.0.0" 739 | strip-ansi "^6.0.0" 740 | 741 | strip-ansi@^4.0.0: 742 | version "4.0.0" 743 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 744 | integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= 745 | dependencies: 746 | ansi-regex "^3.0.0" 747 | 748 | strip-ansi@^6.0.0: 749 | version "6.0.0" 750 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" 751 | integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== 752 | dependencies: 753 | ansi-regex "^5.0.0" 754 | 755 | strip-json-comments@3.1.1: 756 | version "3.1.1" 757 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 758 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 759 | 760 | supports-color@8.1.1: 761 | version "8.1.1" 762 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 763 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 764 | dependencies: 765 | has-flag "^4.0.0" 766 | 767 | supports-color@^3.1.0: 768 | version "3.2.3" 769 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" 770 | integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= 771 | dependencies: 772 | has-flag "^1.0.0" 773 | 774 | supports-color@^7.1.0: 775 | version "7.2.0" 776 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 777 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 778 | dependencies: 779 | has-flag "^4.0.0" 780 | 781 | to-regex-range@^5.0.1: 782 | version "5.0.1" 783 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 784 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 785 | dependencies: 786 | is-number "^7.0.0" 787 | 788 | type-check@~0.3.1: 789 | version "0.3.2" 790 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" 791 | integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= 792 | dependencies: 793 | prelude-ls "~1.1.2" 794 | 795 | type-detect@^4.0.0, type-detect@^4.0.5: 796 | version "4.0.8" 797 | resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" 798 | integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== 799 | 800 | uglify-js@^3.1.4: 801 | version "3.13.1" 802 | resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.1.tgz#2749d4b8b5b7d67460b4a418023ff73c3fefa60a" 803 | integrity sha512-EWhx3fHy3M9JbaeTnO+rEqzCe1wtyQClv6q3YWq0voOj4E+bMZBErVS1GAHPDiRGONYq34M1/d8KuQMgvi6Gjw== 804 | 805 | underscore@^1.12.1: 806 | version "1.12.1" 807 | resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" 808 | integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== 809 | 810 | which@2.0.2: 811 | version "2.0.2" 812 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 813 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 814 | dependencies: 815 | isexe "^2.0.0" 816 | 817 | which@^1.1.1: 818 | version "1.3.1" 819 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 820 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 821 | dependencies: 822 | isexe "^2.0.0" 823 | 824 | wide-align@1.1.3: 825 | version "1.1.3" 826 | resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" 827 | integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== 828 | dependencies: 829 | string-width "^1.0.2 || 2" 830 | 831 | wordwrap@^1.0.0: 832 | version "1.0.0" 833 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" 834 | integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= 835 | 836 | wordwrap@~0.0.2: 837 | version "0.0.3" 838 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" 839 | integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= 840 | 841 | workerpool@6.1.0: 842 | version "6.1.0" 843 | resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.0.tgz#a8e038b4c94569596852de7a8ea4228eefdeb37b" 844 | integrity sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg== 845 | 846 | wrap-ansi@^7.0.0: 847 | version "7.0.0" 848 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 849 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 850 | dependencies: 851 | ansi-styles "^4.0.0" 852 | string-width "^4.1.0" 853 | strip-ansi "^6.0.0" 854 | 855 | wrappy@1: 856 | version "1.0.2" 857 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 858 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 859 | 860 | y18n@^5.0.5: 861 | version "5.0.5" 862 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" 863 | integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== 864 | 865 | yargs-parser@20.2.4: 866 | version "20.2.4" 867 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" 868 | integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== 869 | 870 | yargs-parser@^20.2.2: 871 | version "20.2.7" 872 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a" 873 | integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw== 874 | 875 | yargs-unparser@2.0.0: 876 | version "2.0.0" 877 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" 878 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== 879 | dependencies: 880 | camelcase "^6.0.0" 881 | decamelize "^4.0.0" 882 | flat "^5.0.2" 883 | is-plain-obj "^2.1.0" 884 | 885 | yargs@16.2.0: 886 | version "16.2.0" 887 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" 888 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== 889 | dependencies: 890 | cliui "^7.0.2" 891 | escalade "^3.1.1" 892 | get-caller-file "^2.0.5" 893 | require-directory "^2.1.1" 894 | string-width "^4.2.0" 895 | y18n "^5.0.5" 896 | yargs-parser "^20.2.2" 897 | 898 | yocto-queue@^0.1.0: 899 | version "0.1.0" 900 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 901 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 902 | --------------------------------------------------------------------------------