├── .eslintignore ├── .eslintrc.js ├── .github ├── CODEOWNERS └── FUNDING.yml ├── .gitignore ├── .prettierrc ├── .travis.yml ├── LICENSE ├── README.md ├── index.js ├── package-lock.json ├── package.json ├── test.js └── tests └── fixtures ├── babel_class_component.js ├── es6_class_component.js └── function_class_component.js /.eslintignore: -------------------------------------------------------------------------------- 1 | # Development files 2 | /node_modules 3 | 4 | # This file is autogenerated and shouldn't be linted 5 | /tests/fixtures/babel_class_component.js 6 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | commonjs: true, 5 | es6: true, 6 | node: true, 7 | }, 8 | parserOptions: { 9 | ecmaVersion: 2017, 10 | }, 11 | extends: 'eslint:recommended', 12 | rules: { 13 | 'prefer-const': 'error', 14 | 'no-var': 'error', 15 | indent: ['error', 2], 16 | 'linebreak-style': ['error', 'unix'], 17 | quotes: ['error', 'single'], 18 | semi: ['error', 'never'], 19 | indent: 'off', 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @MithrilJS/Committers 2 | /.github/ @MithrilJS/Admins 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | open_collective: mithriljs 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Development files 2 | /node_modules 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": false, 3 | "printWidth": 80, 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "trailingComma": "es5", 7 | "arrowParens": "avoid", 8 | "semi": false 9 | } 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - node 5 | - 8 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Stephan Hoyer 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 | mithril-node-render 2 | =================== 3 | [![zulip, join chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://mithril.zulipchat.com) 4 | [![Build Status](https://travis-ci.org/MithrilJS/mithril-node-render.svg?branch=master)](https://travis-ci.org/MithrilJS/mithril-node-render) 5 | [![rethink.js](https://img.shields.io/badge/rethink-js-yellow.svg)](https://github.com/rethinkjs/manifest) 6 | ![no dependencies](https://img.shields.io/badge/dependencies-none-brightgreen) 7 | 8 | Use mithril views to render server side 9 | 10 | Demo 11 | ---- 12 | 13 | [Usage Example](https://github.com/StephanHoyer/mithril-isomorphic-example/) 14 | 15 | Installation 16 | ------------ 17 | 18 | ``` 19 | npm install mithril-node-render 20 | ``` 21 | 22 | Usage 23 | ----- 24 | 25 | ```javascript 26 | // Make Mithril happy 27 | if (!global.window) { 28 | global.window = global.document = global.requestAnimationFrame = undefined 29 | } 30 | 31 | var m = require('mithril') 32 | var render = require('mithril-node-render') 33 | 34 | render(m('span', 'huhu')).then(function (html) { 35 | // html === 'huhu' 36 | }) 37 | 38 | var html = render.sync(m('span', 'huhu')) 39 | // html === 'huhu' 40 | ``` 41 | 42 | Async components 43 | ---------------- 44 | 45 | As you see the rendering is asynchronous. It lets you await certain data from within `oninit` hooks. 46 | 47 | ```javascript 48 | var myAsyncComponent = { 49 | oninit: function (node, waitFor) { 50 | waitFor(new Promise(function (resolve) { 51 | node.state.foo = 'bar' 52 | resolve() 53 | })) 54 | }, 55 | view: function (node) { 56 | return m('div', node.state.foo) 57 | } 58 | } 59 | 60 | render(myAsyncComponent).then(function (html) { 61 | // html === '
bar
' 62 | }) 63 | ``` 64 | 65 | Sync rendering 66 | -------------- 67 | 68 | You can also render synchronously. You just don't get the `waitFor` callback. 69 | 70 | ```js 71 | var myAsyncComponent = { 72 | oninit: function (node, waitFor) { 73 | // waitFor === undefined 74 | new Promise(function (resolve) { 75 | node.state.foo = 'bar' 76 | resolve() 77 | }) 78 | }, 79 | view: function (node) { 80 | return m('div', node.state.foo) 81 | } 82 | } 83 | 84 | var html = render.sync(myAsyncComponent) 85 | // html === '
bar
' 86 | ``` 87 | 88 | Options 89 | ------- 90 | 91 | Optionally pass in options as an object: `render(component, options)`. 92 | 93 | The following options are supported: 94 | 95 | **escapeAttribute(value)** 96 | `Default: render.escapeAttribute` 97 | A filter function for attribute values. Receives value, returns what is printed. 98 | 99 | **escapeText(value)** 100 | `Default: render.escapeText` 101 | A filter function for string nodes. Receives value, returns what is printed. 102 | 103 | **strict** 104 | `Default: false` 105 | Set this to true to close all empty tags automatically. Default is standard HTML mode where tags like `
` and `` are allowed to implicitly close themselves. This should be set to `true` if you're rendering XML-compatible HTML documents. 106 | 107 | **xml** 108 | `Default: false` 109 | Set this to true to render as generic XML instead of (possibly XML-compatible) HTML. Default is HTML mode, where children of void elements are ignored. This implies `strict: true`. 110 | 111 | 112 | See also 113 | -------- 114 | 115 | * [Blog post](https://gist.github.com/StephanHoyer/bddccd9e159828867d2a) about isomorphic mithril applications 116 | * [Usage Example](https://github.com/StephanHoyer/mithril-isomorphic-example/blob/master/README.md) 117 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const m = require('mithril/hyperscript') 4 | const Vnode = require('mithril/render/vnode') 5 | 6 | const VOID_TAGS = new RegExp( 7 | '^(?:' + 8 | 'area|' + 9 | 'base|' + 10 | 'br|' + 11 | 'col|' + 12 | 'command|' + 13 | 'embed|' + 14 | 'hr|' + 15 | 'img|' + 16 | 'input|' + 17 | 'keygen|' + 18 | 'link|' + 19 | 'meta|' + 20 | 'param|' + 21 | 'source|' + 22 | 'track|' + 23 | 'wbr|' + 24 | '!doctype' + 25 | ')$', 26 | 'i' 27 | ) 28 | 29 | const hasOwn = {}.hasOwnProperty 30 | 31 | function toStyleKey(str) { 32 | if (str[0] === '-' && str[1] === '-') { 33 | return str 34 | } 35 | return str 36 | .replace(/\W+/g, '-') 37 | .replace(/([a-z\d])([A-Z])/g, '$1-$2') 38 | .toLowerCase() 39 | } 40 | 41 | function replaceHtml(m) { 42 | if (m === '&') return '&' 43 | if (m === '<') return '<' 44 | return '>' 45 | } 46 | 47 | function replaceAttribute(m) { 48 | if (m === '&') return '&' 49 | if (m === '<') return '<' 50 | if (m === '>') return '>' 51 | return '"' 52 | } 53 | 54 | const defaults = { 55 | escapeText(s) { 56 | return s.replace(/[&<>]/g, replaceHtml) 57 | }, 58 | 59 | escapeAttribute(s) { 60 | return s.replace(/[&<>"]/g, replaceAttribute) 61 | }, 62 | } 63 | 64 | function bindOpt(options, key) { 65 | return options[key] ? options[key].bind(options) : defaults[key] 66 | } 67 | 68 | // Using a generator so I can just yield promises that need awaited. Can't just 69 | // use `async`/`await` since this is used for both sync and async renders. At 70 | // least I have generators (read: coroutines), or I'd have to implement this 71 | // using a giant pushdown automaton. :-) 72 | function* tryRender(view, attrs, options, allowAwait) { 73 | // Fast-path a very simple case. Also lets me perform some renderer 74 | // optimizations later. 75 | if (view == null) return '' 76 | if (view.view || typeof view === 'function') { 77 | // root component 78 | view = m(view, attrs) 79 | options = options || {} 80 | } else { 81 | options = attrs || {} 82 | } 83 | const hooks = [] 84 | let result = '' 85 | const escapeAttribute = bindOpt(options, 'escapeAttribute') 86 | const escapeText = bindOpt(options, 'escapeText') 87 | const xml = !!options.xml 88 | const strict = xml || !!options.strict 89 | 90 | function write(value) { 91 | result = '' + result + value 92 | } 93 | 94 | function* setHooks(source, vnode) { 95 | const promises = [] 96 | let waitFor 97 | if (allowAwait) 98 | waitFor = p => { 99 | promises.push(p) 100 | } 101 | if (source.oninit) { 102 | source.oninit.call(vnode.state, vnode, waitFor) 103 | } 104 | if (source.onremove) { 105 | hooks.push(source.onremove.bind(vnode.state, vnode)) 106 | } 107 | if (promises.length) yield promises 108 | } 109 | 110 | function createAttrString(view) { 111 | for (const key in view.attrs) { 112 | if (hasOwn.call(view.attrs, key)) { 113 | let value = view.attrs[key] 114 | if (value == null || typeof value === 'function') continue 115 | const name = key === 'className' ? 'class' : key 116 | 117 | if (name === 'style' && typeof value === 'object') { 118 | const styles = value 119 | const props = [] 120 | for (const key of Object.keys(styles)) { 121 | const prop = styles[key] 122 | if (prop) props.push(`${toStyleKey(key)}:${prop}`) 123 | } 124 | if (!props.length) continue 125 | value = props.join(';') 126 | } 127 | 128 | if (typeof value === 'boolean') { 129 | if (xml) value = value ? 'true' : 'false' 130 | else if (!value) continue 131 | else value = '' 132 | } else { 133 | value = '' + value 134 | } 135 | 136 | write(` ${name}`) 137 | if (strict || value !== '') { 138 | write(`="${escapeAttribute(value)}"`) 139 | } 140 | } 141 | } 142 | } 143 | 144 | function* renderComponent(vnode) { 145 | if (typeof vnode.tag !== 'function') { 146 | vnode.state = Object.create(vnode.tag) 147 | } else if (vnode.tag.prototype && vnode.tag.prototype.view) { 148 | vnode.state = new vnode.tag(vnode) 149 | } else { 150 | vnode.state = vnode.tag(vnode) 151 | } 152 | 153 | yield* setHooks(vnode.state, vnode) 154 | if (vnode.attrs != null) yield* setHooks(vnode.attrs, vnode) 155 | vnode.instance = Vnode.normalize(vnode.state.view(vnode)) 156 | if (vnode.instance != null) yield* renderNode(vnode.instance) 157 | } 158 | 159 | function* renderElement(vnode) { 160 | write(`<${vnode.tag}`) 161 | createAttrString(vnode) 162 | // Don't write children for void HTML elements 163 | if (!xml && VOID_TAGS.test(vnode.tag)) { 164 | write(strict ? '/>' : '>') 165 | } else { 166 | write('>') 167 | if (vnode.text != null) { 168 | const text = '' + vnode.text 169 | if (text !== '') write(escapeText(text)) 170 | } else { 171 | yield* renderChildren(vnode.children) 172 | } 173 | write(``) 174 | } 175 | } 176 | 177 | function* renderChildren(vnodes) { 178 | for (const v of vnodes) { 179 | if (v != null) yield* renderNode(v) 180 | } 181 | } 182 | 183 | function* renderNode(vnode) { 184 | if (vnode == null) return 185 | if (typeof vnode.tag === 'string') { 186 | vnode.state = {} 187 | if (vnode.attrs != null) yield* setHooks(vnode.attrs, vnode) 188 | switch (vnode.tag) { 189 | case '#': 190 | write(escapeText('' + vnode.children)) 191 | break 192 | case '<': 193 | write(vnode.children) 194 | break 195 | case '[': 196 | yield* renderChildren(vnode.children) 197 | break 198 | default: 199 | yield* renderElement(vnode) 200 | } 201 | } else { 202 | yield* renderComponent(vnode) 203 | } 204 | } 205 | 206 | yield* renderNode(Vnode.normalize(view)) 207 | for (const hook of hooks) hook() 208 | return result.concat() // hint to flatten 209 | } 210 | 211 | module.exports = async (view, attrs, options) => { 212 | const iter = tryRender(view, attrs, options, true) 213 | // eslint-disable-next-line no-constant-condition 214 | while (true) { 215 | const { done, value } = iter.next() 216 | if (done) return value 217 | await Promise.all(value) 218 | } 219 | } 220 | 221 | module.exports.sync = (view, attrs, options) => { 222 | return tryRender(view, attrs, options, false).next().value 223 | } 224 | 225 | module.exports.escapeText = defaults.escapeText 226 | module.exports.escapeAttribute = defaults.escapeAttribute 227 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mithril-node-render", 3 | "version": "3.0.2", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@eslint-community/eslint-utils": { 8 | "version": "4.4.0", 9 | "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", 10 | "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", 11 | "dev": true, 12 | "requires": { 13 | "eslint-visitor-keys": "^3.3.0" 14 | } 15 | }, 16 | "@eslint-community/regexpp": { 17 | "version": "4.5.0", 18 | "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", 19 | "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==", 20 | "dev": true 21 | }, 22 | "@eslint/eslintrc": { 23 | "version": "2.0.2", 24 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", 25 | "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", 26 | "dev": true, 27 | "requires": { 28 | "ajv": "^6.12.4", 29 | "debug": "^4.3.2", 30 | "espree": "^9.5.1", 31 | "globals": "^13.19.0", 32 | "ignore": "^5.2.0", 33 | "import-fresh": "^3.2.1", 34 | "js-yaml": "^4.1.0", 35 | "minimatch": "^3.1.2", 36 | "strip-json-comments": "^3.1.1" 37 | }, 38 | "dependencies": { 39 | "ignore": { 40 | "version": "5.2.4", 41 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", 42 | "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", 43 | "dev": true 44 | }, 45 | "minimatch": { 46 | "version": "3.1.2", 47 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 48 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 49 | "dev": true, 50 | "requires": { 51 | "brace-expansion": "^1.1.7" 52 | } 53 | } 54 | } 55 | }, 56 | "@eslint/js": { 57 | "version": "8.38.0", 58 | "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", 59 | "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==", 60 | "dev": true 61 | }, 62 | "@humanwhocodes/config-array": { 63 | "version": "0.11.8", 64 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", 65 | "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", 66 | "dev": true, 67 | "requires": { 68 | "@humanwhocodes/object-schema": "^1.2.1", 69 | "debug": "^4.1.1", 70 | "minimatch": "^3.0.5" 71 | }, 72 | "dependencies": { 73 | "minimatch": { 74 | "version": "3.1.2", 75 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 76 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 77 | "dev": true, 78 | "requires": { 79 | "brace-expansion": "^1.1.7" 80 | } 81 | } 82 | } 83 | }, 84 | "@humanwhocodes/module-importer": { 85 | "version": "1.0.1", 86 | "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", 87 | "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", 88 | "dev": true 89 | }, 90 | "@humanwhocodes/object-schema": { 91 | "version": "1.2.1", 92 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", 93 | "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", 94 | "dev": true 95 | }, 96 | "@nodelib/fs.scandir": { 97 | "version": "2.1.5", 98 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 99 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 100 | "dev": true, 101 | "requires": { 102 | "@nodelib/fs.stat": "2.0.5", 103 | "run-parallel": "^1.1.9" 104 | } 105 | }, 106 | "@nodelib/fs.stat": { 107 | "version": "2.0.5", 108 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 109 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 110 | "dev": true 111 | }, 112 | "@nodelib/fs.walk": { 113 | "version": "1.2.8", 114 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 115 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 116 | "dev": true, 117 | "requires": { 118 | "@nodelib/fs.scandir": "2.1.5", 119 | "fastq": "^1.6.0" 120 | } 121 | }, 122 | "acorn": { 123 | "version": "8.8.2", 124 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", 125 | "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", 126 | "dev": true 127 | }, 128 | "acorn-jsx": { 129 | "version": "5.3.2", 130 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 131 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 132 | "dev": true 133 | }, 134 | "ajv": { 135 | "version": "6.12.6", 136 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 137 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 138 | "dev": true, 139 | "requires": { 140 | "fast-deep-equal": "^3.1.1", 141 | "fast-json-stable-stringify": "^2.0.0", 142 | "json-schema-traverse": "^0.4.1", 143 | "uri-js": "^4.2.2" 144 | } 145 | }, 146 | "ansi-regex": { 147 | "version": "5.0.1", 148 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 149 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 150 | "dev": true 151 | }, 152 | "ansi-styles": { 153 | "version": "4.3.0", 154 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 155 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 156 | "dev": true, 157 | "requires": { 158 | "color-convert": "^2.0.1" 159 | } 160 | }, 161 | "argparse": { 162 | "version": "2.0.1", 163 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 164 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 165 | "dev": true 166 | }, 167 | "balanced-match": { 168 | "version": "1.0.0", 169 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 170 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 171 | "dev": true 172 | }, 173 | "brace-expansion": { 174 | "version": "1.1.11", 175 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 176 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 177 | "dev": true, 178 | "requires": { 179 | "balanced-match": "^1.0.0", 180 | "concat-map": "0.0.1" 181 | } 182 | }, 183 | "builtin-modules": { 184 | "version": "1.1.1", 185 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 186 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", 187 | "dev": true 188 | }, 189 | "callsites": { 190 | "version": "3.1.0", 191 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 192 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 193 | "dev": true 194 | }, 195 | "chalk": { 196 | "version": "4.1.2", 197 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 198 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 199 | "dev": true, 200 | "requires": { 201 | "ansi-styles": "^4.1.0", 202 | "supports-color": "^7.1.0" 203 | } 204 | }, 205 | "color-convert": { 206 | "version": "2.0.1", 207 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 208 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 209 | "dev": true, 210 | "requires": { 211 | "color-name": "~1.1.4" 212 | } 213 | }, 214 | "color-name": { 215 | "version": "1.1.4", 216 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 217 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 218 | "dev": true 219 | }, 220 | "concat-map": { 221 | "version": "0.0.1", 222 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 223 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 224 | "dev": true 225 | }, 226 | "contains-path": { 227 | "version": "0.1.0", 228 | "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", 229 | "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", 230 | "dev": true 231 | }, 232 | "cross-spawn": { 233 | "version": "7.0.3", 234 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 235 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 236 | "dev": true, 237 | "requires": { 238 | "path-key": "^3.1.0", 239 | "shebang-command": "^2.0.0", 240 | "which": "^2.0.1" 241 | } 242 | }, 243 | "debug": { 244 | "version": "4.3.4", 245 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 246 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 247 | "dev": true, 248 | "requires": { 249 | "ms": "2.1.2" 250 | } 251 | }, 252 | "deep-is": { 253 | "version": "0.1.4", 254 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 255 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 256 | "dev": true 257 | }, 258 | "doctrine": { 259 | "version": "3.0.0", 260 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 261 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 262 | "dev": true, 263 | "requires": { 264 | "esutils": "^2.0.2" 265 | } 266 | }, 267 | "error-ex": { 268 | "version": "1.3.2", 269 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 270 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 271 | "dev": true, 272 | "requires": { 273 | "is-arrayish": "^0.2.1" 274 | } 275 | }, 276 | "escape-string-regexp": { 277 | "version": "4.0.0", 278 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 279 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 280 | "dev": true 281 | }, 282 | "eslint": { 283 | "version": "8.38.0", 284 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", 285 | "integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==", 286 | "dev": true, 287 | "requires": { 288 | "@eslint-community/eslint-utils": "^4.2.0", 289 | "@eslint-community/regexpp": "^4.4.0", 290 | "@eslint/eslintrc": "^2.0.2", 291 | "@eslint/js": "8.38.0", 292 | "@humanwhocodes/config-array": "^0.11.8", 293 | "@humanwhocodes/module-importer": "^1.0.1", 294 | "@nodelib/fs.walk": "^1.2.8", 295 | "ajv": "^6.10.0", 296 | "chalk": "^4.0.0", 297 | "cross-spawn": "^7.0.2", 298 | "debug": "^4.3.2", 299 | "doctrine": "^3.0.0", 300 | "escape-string-regexp": "^4.0.0", 301 | "eslint-scope": "^7.1.1", 302 | "eslint-visitor-keys": "^3.4.0", 303 | "espree": "^9.5.1", 304 | "esquery": "^1.4.2", 305 | "esutils": "^2.0.2", 306 | "fast-deep-equal": "^3.1.3", 307 | "file-entry-cache": "^6.0.1", 308 | "find-up": "^5.0.0", 309 | "glob-parent": "^6.0.2", 310 | "globals": "^13.19.0", 311 | "grapheme-splitter": "^1.0.4", 312 | "ignore": "^5.2.0", 313 | "import-fresh": "^3.0.0", 314 | "imurmurhash": "^0.1.4", 315 | "is-glob": "^4.0.0", 316 | "is-path-inside": "^3.0.3", 317 | "js-sdsl": "^4.1.4", 318 | "js-yaml": "^4.1.0", 319 | "json-stable-stringify-without-jsonify": "^1.0.1", 320 | "levn": "^0.4.1", 321 | "lodash.merge": "^4.6.2", 322 | "minimatch": "^3.1.2", 323 | "natural-compare": "^1.4.0", 324 | "optionator": "^0.9.1", 325 | "strip-ansi": "^6.0.1", 326 | "strip-json-comments": "^3.1.0", 327 | "text-table": "^0.2.0" 328 | }, 329 | "dependencies": { 330 | "find-up": { 331 | "version": "5.0.0", 332 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 333 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 334 | "dev": true, 335 | "requires": { 336 | "locate-path": "^6.0.0", 337 | "path-exists": "^4.0.0" 338 | } 339 | }, 340 | "ignore": { 341 | "version": "5.2.4", 342 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", 343 | "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", 344 | "dev": true 345 | }, 346 | "locate-path": { 347 | "version": "6.0.0", 348 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 349 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 350 | "dev": true, 351 | "requires": { 352 | "p-locate": "^5.0.0" 353 | } 354 | }, 355 | "minimatch": { 356 | "version": "3.1.2", 357 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 358 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 359 | "dev": true, 360 | "requires": { 361 | "brace-expansion": "^1.1.7" 362 | } 363 | }, 364 | "p-limit": { 365 | "version": "3.1.0", 366 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 367 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 368 | "dev": true, 369 | "requires": { 370 | "yocto-queue": "^0.1.0" 371 | } 372 | }, 373 | "p-locate": { 374 | "version": "5.0.0", 375 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 376 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 377 | "dev": true, 378 | "requires": { 379 | "p-limit": "^3.0.2" 380 | } 381 | }, 382 | "path-exists": { 383 | "version": "4.0.0", 384 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 385 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 386 | "dev": true 387 | } 388 | } 389 | }, 390 | "eslint-config-standard": { 391 | "version": "10.2.1", 392 | "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", 393 | "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", 394 | "dev": true 395 | }, 396 | "eslint-import-resolver-node": { 397 | "version": "0.3.2", 398 | "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", 399 | "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", 400 | "dev": true, 401 | "requires": { 402 | "debug": "^2.6.9", 403 | "resolve": "^1.5.0" 404 | }, 405 | "dependencies": { 406 | "debug": { 407 | "version": "2.6.9", 408 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 409 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 410 | "dev": true, 411 | "requires": { 412 | "ms": "2.0.0" 413 | } 414 | }, 415 | "ms": { 416 | "version": "2.0.0", 417 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 418 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 419 | "dev": true 420 | } 421 | } 422 | }, 423 | "eslint-module-utils": { 424 | "version": "2.4.1", 425 | "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", 426 | "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", 427 | "dev": true, 428 | "requires": { 429 | "debug": "^2.6.8", 430 | "pkg-dir": "^2.0.0" 431 | }, 432 | "dependencies": { 433 | "debug": { 434 | "version": "2.6.9", 435 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 436 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 437 | "dev": true, 438 | "requires": { 439 | "ms": "2.0.0" 440 | } 441 | }, 442 | "ms": { 443 | "version": "2.0.0", 444 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 445 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 446 | "dev": true 447 | } 448 | } 449 | }, 450 | "eslint-plugin-import": { 451 | "version": "2.8.0", 452 | "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", 453 | "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", 454 | "dev": true, 455 | "requires": { 456 | "builtin-modules": "^1.1.1", 457 | "contains-path": "^0.1.0", 458 | "debug": "^2.6.8", 459 | "doctrine": "1.5.0", 460 | "eslint-import-resolver-node": "^0.3.1", 461 | "eslint-module-utils": "^2.1.1", 462 | "has": "^1.0.1", 463 | "lodash.cond": "^4.3.0", 464 | "minimatch": "^3.0.3", 465 | "read-pkg-up": "^2.0.0" 466 | }, 467 | "dependencies": { 468 | "debug": { 469 | "version": "2.6.9", 470 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 471 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 472 | "dev": true, 473 | "requires": { 474 | "ms": "2.0.0" 475 | } 476 | }, 477 | "doctrine": { 478 | "version": "1.5.0", 479 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", 480 | "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", 481 | "dev": true, 482 | "requires": { 483 | "esutils": "^2.0.2", 484 | "isarray": "^1.0.0" 485 | } 486 | }, 487 | "ms": { 488 | "version": "2.0.0", 489 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 490 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 491 | "dev": true 492 | } 493 | } 494 | }, 495 | "eslint-plugin-node": { 496 | "version": "5.2.1", 497 | "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", 498 | "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", 499 | "dev": true, 500 | "requires": { 501 | "ignore": "^3.3.6", 502 | "minimatch": "^3.0.4", 503 | "resolve": "^1.3.3", 504 | "semver": "5.3.0" 505 | }, 506 | "dependencies": { 507 | "semver": { 508 | "version": "5.3.0", 509 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", 510 | "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", 511 | "dev": true 512 | } 513 | } 514 | }, 515 | "eslint-plugin-promise": { 516 | "version": "3.6.0", 517 | "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz", 518 | "integrity": "sha512-YQzM6TLTlApAr7Li8vWKR+K3WghjwKcYzY0d2roWap4SLK+kzuagJX/leTetIDWsFcTFnKNJXWupDCD6aZkP2Q==", 519 | "dev": true 520 | }, 521 | "eslint-plugin-standard": { 522 | "version": "3.0.1", 523 | "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", 524 | "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", 525 | "dev": true 526 | }, 527 | "eslint-scope": { 528 | "version": "7.2.0", 529 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", 530 | "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", 531 | "dev": true, 532 | "requires": { 533 | "esrecurse": "^4.3.0", 534 | "estraverse": "^5.2.0" 535 | } 536 | }, 537 | "eslint-visitor-keys": { 538 | "version": "3.4.0", 539 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", 540 | "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", 541 | "dev": true 542 | }, 543 | "espree": { 544 | "version": "9.5.1", 545 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", 546 | "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", 547 | "dev": true, 548 | "requires": { 549 | "acorn": "^8.8.0", 550 | "acorn-jsx": "^5.3.2", 551 | "eslint-visitor-keys": "^3.4.0" 552 | } 553 | }, 554 | "esquery": { 555 | "version": "1.5.0", 556 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", 557 | "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", 558 | "dev": true, 559 | "requires": { 560 | "estraverse": "^5.1.0" 561 | } 562 | }, 563 | "esrecurse": { 564 | "version": "4.3.0", 565 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 566 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 567 | "dev": true, 568 | "requires": { 569 | "estraverse": "^5.2.0" 570 | } 571 | }, 572 | "estraverse": { 573 | "version": "5.3.0", 574 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 575 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 576 | "dev": true 577 | }, 578 | "esutils": { 579 | "version": "2.0.3", 580 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 581 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 582 | "dev": true 583 | }, 584 | "fast-deep-equal": { 585 | "version": "3.1.3", 586 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 587 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 588 | "dev": true 589 | }, 590 | "fast-json-stable-stringify": { 591 | "version": "2.1.0", 592 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 593 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 594 | "dev": true 595 | }, 596 | "fast-levenshtein": { 597 | "version": "2.0.6", 598 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 599 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", 600 | "dev": true 601 | }, 602 | "fastq": { 603 | "version": "1.15.0", 604 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", 605 | "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", 606 | "dev": true, 607 | "requires": { 608 | "reusify": "^1.0.4" 609 | } 610 | }, 611 | "file-entry-cache": { 612 | "version": "6.0.1", 613 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 614 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 615 | "dev": true, 616 | "requires": { 617 | "flat-cache": "^3.0.4" 618 | } 619 | }, 620 | "find-up": { 621 | "version": "2.1.0", 622 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", 623 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", 624 | "dev": true, 625 | "requires": { 626 | "locate-path": "^2.0.0" 627 | } 628 | }, 629 | "flat-cache": { 630 | "version": "3.0.4", 631 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 632 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 633 | "dev": true, 634 | "requires": { 635 | "flatted": "^3.1.0", 636 | "rimraf": "^3.0.2" 637 | } 638 | }, 639 | "flatted": { 640 | "version": "3.2.7", 641 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", 642 | "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", 643 | "dev": true 644 | }, 645 | "fs.realpath": { 646 | "version": "1.0.0", 647 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 648 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 649 | "dev": true 650 | }, 651 | "function-bind": { 652 | "version": "1.1.1", 653 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 654 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 655 | "dev": true 656 | }, 657 | "glob": { 658 | "version": "7.1.4", 659 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", 660 | "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", 661 | "dev": true, 662 | "requires": { 663 | "fs.realpath": "^1.0.0", 664 | "inflight": "^1.0.4", 665 | "inherits": "2", 666 | "minimatch": "^3.0.4", 667 | "once": "^1.3.0", 668 | "path-is-absolute": "^1.0.0" 669 | } 670 | }, 671 | "glob-parent": { 672 | "version": "6.0.2", 673 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 674 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 675 | "dev": true, 676 | "requires": { 677 | "is-glob": "^4.0.3" 678 | } 679 | }, 680 | "globals": { 681 | "version": "13.20.0", 682 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", 683 | "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", 684 | "dev": true, 685 | "requires": { 686 | "type-fest": "^0.20.2" 687 | } 688 | }, 689 | "graceful-fs": { 690 | "version": "4.2.2", 691 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", 692 | "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", 693 | "dev": true 694 | }, 695 | "grapheme-splitter": { 696 | "version": "1.0.4", 697 | "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", 698 | "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", 699 | "dev": true 700 | }, 701 | "has": { 702 | "version": "1.0.3", 703 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 704 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 705 | "dev": true, 706 | "requires": { 707 | "function-bind": "^1.1.1" 708 | } 709 | }, 710 | "has-flag": { 711 | "version": "4.0.0", 712 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 713 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 714 | "dev": true 715 | }, 716 | "hosted-git-info": { 717 | "version": "2.8.9", 718 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", 719 | "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", 720 | "dev": true 721 | }, 722 | "ignore": { 723 | "version": "3.3.10", 724 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", 725 | "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", 726 | "dev": true 727 | }, 728 | "import-fresh": { 729 | "version": "3.3.0", 730 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 731 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 732 | "dev": true, 733 | "requires": { 734 | "parent-module": "^1.0.0", 735 | "resolve-from": "^4.0.0" 736 | } 737 | }, 738 | "imurmurhash": { 739 | "version": "0.1.4", 740 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 741 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", 742 | "dev": true 743 | }, 744 | "inflight": { 745 | "version": "1.0.6", 746 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 747 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 748 | "dev": true, 749 | "requires": { 750 | "once": "^1.3.0", 751 | "wrappy": "1" 752 | } 753 | }, 754 | "inherits": { 755 | "version": "2.0.4", 756 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 757 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 758 | "dev": true 759 | }, 760 | "is-arrayish": { 761 | "version": "0.2.1", 762 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 763 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", 764 | "dev": true 765 | }, 766 | "is-extglob": { 767 | "version": "2.1.1", 768 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 769 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 770 | "dev": true 771 | }, 772 | "is-glob": { 773 | "version": "4.0.3", 774 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 775 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 776 | "dev": true, 777 | "requires": { 778 | "is-extglob": "^2.1.1" 779 | } 780 | }, 781 | "is-path-inside": { 782 | "version": "3.0.3", 783 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", 784 | "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", 785 | "dev": true 786 | }, 787 | "isarray": { 788 | "version": "1.0.0", 789 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 790 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 791 | "dev": true 792 | }, 793 | "isexe": { 794 | "version": "2.0.0", 795 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 796 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 797 | "dev": true 798 | }, 799 | "js-sdsl": { 800 | "version": "4.4.0", 801 | "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", 802 | "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", 803 | "dev": true 804 | }, 805 | "js-yaml": { 806 | "version": "4.1.0", 807 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 808 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 809 | "dev": true, 810 | "requires": { 811 | "argparse": "^2.0.1" 812 | } 813 | }, 814 | "json-schema-traverse": { 815 | "version": "0.4.1", 816 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 817 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 818 | "dev": true 819 | }, 820 | "json-stable-stringify-without-jsonify": { 821 | "version": "1.0.1", 822 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 823 | "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", 824 | "dev": true 825 | }, 826 | "levn": { 827 | "version": "0.4.1", 828 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 829 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 830 | "dev": true, 831 | "requires": { 832 | "prelude-ls": "^1.2.1", 833 | "type-check": "~0.4.0" 834 | } 835 | }, 836 | "load-json-file": { 837 | "version": "2.0.0", 838 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", 839 | "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", 840 | "dev": true, 841 | "requires": { 842 | "graceful-fs": "^4.1.2", 843 | "parse-json": "^2.2.0", 844 | "pify": "^2.0.0", 845 | "strip-bom": "^3.0.0" 846 | } 847 | }, 848 | "locate-path": { 849 | "version": "2.0.0", 850 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", 851 | "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", 852 | "dev": true, 853 | "requires": { 854 | "p-locate": "^2.0.0", 855 | "path-exists": "^3.0.0" 856 | } 857 | }, 858 | "lodash.cond": { 859 | "version": "4.5.2", 860 | "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", 861 | "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", 862 | "dev": true 863 | }, 864 | "lodash.merge": { 865 | "version": "4.6.2", 866 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 867 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 868 | "dev": true 869 | }, 870 | "minimatch": { 871 | "version": "3.1.2", 872 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 873 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 874 | "dev": true, 875 | "requires": { 876 | "brace-expansion": "^1.1.7" 877 | } 878 | }, 879 | "mithril": { 880 | "version": "2.0.4", 881 | "resolved": "https://registry.npmjs.org/mithril/-/mithril-2.0.4.tgz", 882 | "integrity": "sha512-mgw+DMZlhMS4PpprF6dl7ZoeZq5GGcAuWnrg5e12MvaGauc4jzWsDZtVGRCktsiQczOEUr2K5teKbE5k44RlOg==", 883 | "dev": true 884 | }, 885 | "ms": { 886 | "version": "2.1.2", 887 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 888 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 889 | "dev": true 890 | }, 891 | "natural-compare": { 892 | "version": "1.4.0", 893 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 894 | "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", 895 | "dev": true 896 | }, 897 | "normalize-package-data": { 898 | "version": "2.5.0", 899 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", 900 | "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", 901 | "dev": true, 902 | "requires": { 903 | "hosted-git-info": "^2.1.4", 904 | "resolve": "^1.10.0", 905 | "semver": "2 || 3 || 4 || 5", 906 | "validate-npm-package-license": "^3.0.1" 907 | } 908 | }, 909 | "once": { 910 | "version": "1.4.0", 911 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 912 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 913 | "dev": true, 914 | "requires": { 915 | "wrappy": "1" 916 | } 917 | }, 918 | "optionator": { 919 | "version": "0.9.1", 920 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 921 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 922 | "dev": true, 923 | "requires": { 924 | "deep-is": "^0.1.3", 925 | "fast-levenshtein": "^2.0.6", 926 | "levn": "^0.4.1", 927 | "prelude-ls": "^1.2.1", 928 | "type-check": "^0.4.0", 929 | "word-wrap": "^1.2.3" 930 | } 931 | }, 932 | "ospec": { 933 | "version": "4.0.1", 934 | "resolved": "https://registry.npmjs.org/ospec/-/ospec-4.0.1.tgz", 935 | "integrity": "sha512-iHx5jkuXh/hU4eEFFf6FH/4vj5RH7041jhuJw7WnqIPHDJgEXkSBdmuD644I/qQm8s5aZEPOpSoVagGCr8ebag==", 936 | "dev": true, 937 | "requires": { 938 | "glob": "^7.1.3" 939 | } 940 | }, 941 | "p-limit": { 942 | "version": "1.3.0", 943 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", 944 | "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", 945 | "dev": true, 946 | "requires": { 947 | "p-try": "^1.0.0" 948 | } 949 | }, 950 | "p-locate": { 951 | "version": "2.0.0", 952 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", 953 | "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", 954 | "dev": true, 955 | "requires": { 956 | "p-limit": "^1.1.0" 957 | } 958 | }, 959 | "p-try": { 960 | "version": "1.0.0", 961 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", 962 | "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", 963 | "dev": true 964 | }, 965 | "parent-module": { 966 | "version": "1.0.1", 967 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 968 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 969 | "dev": true, 970 | "requires": { 971 | "callsites": "^3.0.0" 972 | } 973 | }, 974 | "parse-json": { 975 | "version": "2.2.0", 976 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", 977 | "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", 978 | "dev": true, 979 | "requires": { 980 | "error-ex": "^1.2.0" 981 | } 982 | }, 983 | "path-exists": { 984 | "version": "3.0.0", 985 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 986 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 987 | "dev": true 988 | }, 989 | "path-is-absolute": { 990 | "version": "1.0.1", 991 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 992 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 993 | "dev": true 994 | }, 995 | "path-key": { 996 | "version": "3.1.1", 997 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 998 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 999 | "dev": true 1000 | }, 1001 | "path-parse": { 1002 | "version": "1.0.7", 1003 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1004 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 1005 | "dev": true 1006 | }, 1007 | "path-type": { 1008 | "version": "2.0.0", 1009 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", 1010 | "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", 1011 | "dev": true, 1012 | "requires": { 1013 | "pify": "^2.0.0" 1014 | } 1015 | }, 1016 | "pify": { 1017 | "version": "2.3.0", 1018 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 1019 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 1020 | "dev": true 1021 | }, 1022 | "pkg-dir": { 1023 | "version": "2.0.0", 1024 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", 1025 | "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", 1026 | "dev": true, 1027 | "requires": { 1028 | "find-up": "^2.1.0" 1029 | } 1030 | }, 1031 | "prelude-ls": { 1032 | "version": "1.2.1", 1033 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 1034 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 1035 | "dev": true 1036 | }, 1037 | "punycode": { 1038 | "version": "2.3.0", 1039 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", 1040 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", 1041 | "dev": true 1042 | }, 1043 | "queue-microtask": { 1044 | "version": "1.2.3", 1045 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 1046 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1047 | "dev": true 1048 | }, 1049 | "read-pkg": { 1050 | "version": "2.0.0", 1051 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", 1052 | "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", 1053 | "dev": true, 1054 | "requires": { 1055 | "load-json-file": "^2.0.0", 1056 | "normalize-package-data": "^2.3.2", 1057 | "path-type": "^2.0.0" 1058 | } 1059 | }, 1060 | "read-pkg-up": { 1061 | "version": "2.0.0", 1062 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", 1063 | "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", 1064 | "dev": true, 1065 | "requires": { 1066 | "find-up": "^2.0.0", 1067 | "read-pkg": "^2.0.0" 1068 | } 1069 | }, 1070 | "resolve": { 1071 | "version": "1.12.0", 1072 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", 1073 | "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", 1074 | "dev": true, 1075 | "requires": { 1076 | "path-parse": "^1.0.6" 1077 | } 1078 | }, 1079 | "resolve-from": { 1080 | "version": "4.0.0", 1081 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1082 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1083 | "dev": true 1084 | }, 1085 | "reusify": { 1086 | "version": "1.0.4", 1087 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1088 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1089 | "dev": true 1090 | }, 1091 | "rimraf": { 1092 | "version": "3.0.2", 1093 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1094 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1095 | "dev": true, 1096 | "requires": { 1097 | "glob": "^7.1.3" 1098 | } 1099 | }, 1100 | "run-parallel": { 1101 | "version": "1.2.0", 1102 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 1103 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1104 | "dev": true, 1105 | "requires": { 1106 | "queue-microtask": "^1.2.2" 1107 | } 1108 | }, 1109 | "semver": { 1110 | "version": "5.7.1", 1111 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1112 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1113 | "dev": true 1114 | }, 1115 | "shebang-command": { 1116 | "version": "2.0.0", 1117 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1118 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1119 | "dev": true, 1120 | "requires": { 1121 | "shebang-regex": "^3.0.0" 1122 | } 1123 | }, 1124 | "shebang-regex": { 1125 | "version": "3.0.0", 1126 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1127 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1128 | "dev": true 1129 | }, 1130 | "spdx-correct": { 1131 | "version": "3.1.0", 1132 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", 1133 | "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", 1134 | "dev": true, 1135 | "requires": { 1136 | "spdx-expression-parse": "^3.0.0", 1137 | "spdx-license-ids": "^3.0.0" 1138 | } 1139 | }, 1140 | "spdx-exceptions": { 1141 | "version": "2.2.0", 1142 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", 1143 | "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", 1144 | "dev": true 1145 | }, 1146 | "spdx-expression-parse": { 1147 | "version": "3.0.0", 1148 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", 1149 | "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", 1150 | "dev": true, 1151 | "requires": { 1152 | "spdx-exceptions": "^2.1.0", 1153 | "spdx-license-ids": "^3.0.0" 1154 | } 1155 | }, 1156 | "spdx-license-ids": { 1157 | "version": "3.0.5", 1158 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", 1159 | "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", 1160 | "dev": true 1161 | }, 1162 | "strip-ansi": { 1163 | "version": "6.0.1", 1164 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1165 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1166 | "dev": true, 1167 | "requires": { 1168 | "ansi-regex": "^5.0.1" 1169 | } 1170 | }, 1171 | "strip-bom": { 1172 | "version": "3.0.0", 1173 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 1174 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", 1175 | "dev": true 1176 | }, 1177 | "strip-json-comments": { 1178 | "version": "3.1.1", 1179 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1180 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1181 | "dev": true 1182 | }, 1183 | "supports-color": { 1184 | "version": "7.2.0", 1185 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1186 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1187 | "dev": true, 1188 | "requires": { 1189 | "has-flag": "^4.0.0" 1190 | } 1191 | }, 1192 | "text-table": { 1193 | "version": "0.2.0", 1194 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1195 | "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", 1196 | "dev": true 1197 | }, 1198 | "type-check": { 1199 | "version": "0.4.0", 1200 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 1201 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 1202 | "dev": true, 1203 | "requires": { 1204 | "prelude-ls": "^1.2.1" 1205 | } 1206 | }, 1207 | "type-fest": { 1208 | "version": "0.20.2", 1209 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 1210 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 1211 | "dev": true 1212 | }, 1213 | "uri-js": { 1214 | "version": "4.4.1", 1215 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 1216 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 1217 | "dev": true, 1218 | "requires": { 1219 | "punycode": "^2.1.0" 1220 | } 1221 | }, 1222 | "validate-npm-package-license": { 1223 | "version": "3.0.4", 1224 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", 1225 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", 1226 | "dev": true, 1227 | "requires": { 1228 | "spdx-correct": "^3.0.0", 1229 | "spdx-expression-parse": "^3.0.0" 1230 | } 1231 | }, 1232 | "which": { 1233 | "version": "2.0.2", 1234 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1235 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1236 | "dev": true, 1237 | "requires": { 1238 | "isexe": "^2.0.0" 1239 | } 1240 | }, 1241 | "word-wrap": { 1242 | "version": "1.2.4", 1243 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", 1244 | "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", 1245 | "dev": true 1246 | }, 1247 | "wrappy": { 1248 | "version": "1.0.2", 1249 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1250 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1251 | "dev": true 1252 | }, 1253 | "yocto-queue": { 1254 | "version": "0.1.0", 1255 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 1256 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 1257 | "dev": true 1258 | } 1259 | } 1260 | } 1261 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mithril-node-render", 3 | "version": "3.0.2", 4 | "description": "Node rending of mithril views", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node test.js && eslint index.js test.js" 8 | }, 9 | "keywords": [ 10 | "mithril", 11 | "node", 12 | "render", 13 | "template" 14 | ], 15 | "author": "Stephan Hoyer ", 16 | "license": "MIT", 17 | "peerDependencies": { 18 | "mithril": "^2.0.4" 19 | }, 20 | "devDependencies": { 21 | "eslint": "8.38.0", 22 | "eslint-config-standard": "10.2.1", 23 | "eslint-plugin-import": "2.8.0", 24 | "eslint-plugin-node": "5.2.1", 25 | "eslint-plugin-promise": "3.6.0", 26 | "eslint-plugin-standard": "3.0.1", 27 | "mithril": "2.0.4", 28 | "ospec": "4.0.1" 29 | }, 30 | "repository": "MithrilJS/mithril-node-render", 31 | "bugs": "https://github.com/MithrilJS/mithril-node-render/issues", 32 | "homepage": "https://github.com/MithrilJS/mithril-node-render#readme" 33 | } 34 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const o = require('ospec') 4 | const m = require('mithril/hyperscript') 5 | const render = require('./index') 6 | 7 | const ES6ClassComponent = require('./tests/fixtures/es6_class_component') 8 | const BabelClassComponent = require('./tests/fixtures/babel_class_component') 9 | const FunctionClassComponent = require('./tests/fixtures/function_class_component') 10 | 11 | o.spec('render', () => { 12 | o('should render tag', () => { 13 | o(render.sync(m('span', 'content'))).equals('content') 14 | }) 15 | o('should render classname', () => { 16 | o(render.sync(m('.foo', 'content'))).equals( 17 | '
content
' 18 | )() 19 | }) 20 | 21 | o('should render id', () => { 22 | o(render.sync(m('#bar', 'content'))).equals('
content
')() 23 | }) 24 | 25 | o('should render short nodes when no children', () => { 26 | o(render.sync(m('br'))).equals('
')() 27 | }) 28 | 29 | o( 30 | 'should render short nodes when no children and tag name is uppercase', 31 | () => { 32 | o(render.sync(m('HR'))).equals('
')() 33 | } 34 | ) 35 | 36 | o('should render short node doctype', () => { 37 | o(render.sync(m('!doctype'))).equals('')() 38 | }) 39 | 40 | o('should render short node doctype HTML5', () => { 41 | o(render.sync(m('!doctype', { html: true }))).equals('')() 42 | }) 43 | 44 | o('should render attributes', () => { 45 | o( 46 | render.sync(m('span', { 'data-foo': 'bar', selected: 'selected' })) 47 | ).equals('')() 48 | }) 49 | 50 | o('should render string', () => { 51 | o(render.sync(m('ul', 'huhu'))).equals('')() 52 | }) 53 | 54 | o('should render arrays', () => { 55 | o(render.sync([m('span', 'foo'), m('div', 'bar')])).equals( 56 | 'foo
bar
' 57 | )() 58 | }) 59 | 60 | o('should render nested arrays', () => { 61 | o(render.sync(m('div', [[m('span', 'foo'), m('div', 'bar')]]))).equals( 62 | '
foo
bar
' 63 | )() 64 | }) 65 | 66 | o('should render children', () => { 67 | o(render.sync(m('span', m('div')))).equals('
')() 68 | }) 69 | 70 | o('should not render events', () => { 71 | o(render.sync(m('span', { onmousemove() {} }))).equals('')() 72 | }) 73 | 74 | o('should render simple styles', () => { 75 | o( 76 | render.sync( 77 | m('div', { style: { height: '20px', color: '', width: '10px' } }) 78 | ) 79 | ).equals('
') 80 | }) 81 | 82 | o('should render camelcase styles', () => { 83 | o( 84 | render.sync(m('span', { style: { paddingLeft: '10px', color: 'red' } })) 85 | ).equals('') 86 | }) 87 | 88 | o('should respect css vars', () => { 89 | o( 90 | render.sync( 91 | m('span', { style: { '--some-var': '10px', '--someVar': 'red' } }) 92 | ) 93 | ).equals('') 94 | }) 95 | 96 | o('should render numbers as text nodes', () => { 97 | o(render.sync(m('div', [1, m('span'), '2']))).equals( 98 | '
12
' 99 | ) 100 | }) 101 | 102 | o('renders attributes', () => { 103 | o(render.sync(m('div', 0))).equals('
0
') 104 | o(render.sync(m('div', false))).equals('
') 105 | o(render.sync(m('div', { a: true }))).equals('
') 106 | o(render.sync(m('div', { a: false }))).equals('
') 107 | o(render.sync(m('div', { a: undefined }))).equals('
') 108 | o(render.sync(m('div', { a: 1 }))).equals('
') 109 | o(render.sync(m('div', { key: 1 }))).equals('
') 110 | o(render.sync(m('div', { style: null }))).equals('
') 111 | o(render.sync(m('div', { style: '' }))).equals('
') 112 | o(render.sync(m('div', { style: { color: '' } }))).equals('
') 113 | o(render.sync(m('div', { style: { height: '20px', color: '' } }))).equals( 114 | '
' 115 | ) 116 | 117 | o( 118 | render.sync( 119 | m('div', { style: { height: '20px', color: '', width: '10px' } }) 120 | ) 121 | ).equals('
') 122 | o(render.sync(m('div', { a: 'foo' }))).equals('
') 123 | o(render.sync(m('div', m.trust('')))).equals( 124 | '
' 125 | ) 126 | o(render.sync(m('div', ''))).equals( 127 | '
<foo></foo>
' 128 | ) 129 | o(render.sync(m('div', { style: '">
' 131 | ) 132 | o( 133 | render.sync(m('div', { style: '">
') 139 | o(render.sync(m('pre', 'var = ' + JSON.stringify({ foo: 1 })))).equals( 140 | '
var = {"foo":1}
' 141 | ) 142 | }) 143 | 144 | o('renders svg xlink:href correctly', () => { 145 | o(render.sync(m('svg', m('use', { href: 'fooga.com' })))).equals( 146 | '' 147 | ) 148 | o(render.sync(m('svg', m('use', { 'xlink:href': 'fooga.com' })))).equals( 149 | '' 150 | ) 151 | }) 152 | 153 | o('should render closed input-tag', () => { 154 | o(render.sync(m('input'), { strict: true })).equals('') 155 | o(render.sync(m('input'), { strict: true, xml: true })).equals( 156 | '' 157 | ) 158 | }) 159 | o('should render closed div-tag', () => { 160 | o(render.sync(m('div'), { strict: true })).equals('
') 161 | o(render.sync(m('div'), { strict: true, xml: true })).equals('
') 162 | }) 163 | }) 164 | 165 | o.spec('components', () => { 166 | let myComponent, onremove 167 | 168 | o.beforeEach(() => { 169 | onremove = o.spy() 170 | myComponent = { 171 | oninit(node) { 172 | node.state.foo = 'bar' 173 | }, 174 | onremove, 175 | view(node) { 176 | return m('div', ['hello', node.state.foo, node.attrs.foo]) 177 | }, 178 | } 179 | }) 180 | 181 | o('embedded', () => { 182 | o(onremove.callCount).equals(0) 183 | o(render.sync(m('div', m(myComponent)))).equals( 184 | '
hellobar
' 185 | ) 186 | o(onremove.callCount).equals(1) 187 | o(render.sync(m('span', m(myComponent, { foo: 'foz' })))).equals( 188 | '
hellobarfoz
' 189 | ) 190 | o( 191 | render.sync( 192 | m( 193 | 'div', 194 | m({ 195 | oninit() {}, 196 | view() { 197 | return m('span', 'huhu') 198 | }, 199 | }) 200 | ) 201 | ) 202 | ).equals('
huhu
') 203 | o( 204 | render.sync( 205 | m( 206 | 'div', 207 | m({ 208 | view() { 209 | return m('span', 'huhu') 210 | }, 211 | }) 212 | ) 213 | ) 214 | ).equals('
huhu
') 215 | }) 216 | 217 | o('as root', () => { 218 | o(render.sync(myComponent)).equals('
hellobar
') 219 | o(render.sync(myComponent, { foo: '-attr-foo' })).equals( 220 | '
hellobar-attr-foo
' 221 | ) 222 | }) 223 | 224 | o('with children', () => { 225 | const parentComponent = { 226 | view(node) { 227 | return m('div', node.children) 228 | }, 229 | } 230 | 231 | o(render.sync(m(parentComponent, 'howdy'))).equals('
howdy
') 232 | o(render.sync(m(parentComponent, m('span', 'howdy')))).equals( 233 | '
howdy
' 234 | ) 235 | o( 236 | render.sync(m(parentComponent, [m('span', 'foo'), m('span', 'bar')])) 237 | ).equals('
foobar
') 238 | o(render.sync(m(parentComponent, m.trust('trust me')))).equals( 239 | '
trust me
' 240 | ) 241 | o(render.sync(m(parentComponent, m(myComponent, { foo: 'foz' })))).equals( 242 | '
hellobarfoz
' 243 | ) 244 | }) 245 | 246 | o('quouting html content right', () => { 247 | const component = { 248 | view() { 249 | return m('span', ['huh', '> >']) 250 | }, 251 | } 252 | const out = render.sync(component) 253 | o(out).equals('huh> >') 254 | }) 255 | }) 256 | 257 | const classComponents = { 258 | es6: ES6ClassComponent, 259 | babel: BabelClassComponent, 260 | function: FunctionClassComponent, 261 | } 262 | for (const type in classComponents) { 263 | o.spec('component of ' + type + ' class', () => { 264 | const classComponent = classComponents[type] 265 | 266 | o('embedded', () => { 267 | o(render.sync(m('div', m(classComponent)))).equals( 268 | '
hellobar
' 269 | ) 270 | o(render.sync(m('span', m(classComponent, { foo: 'foz' })))).equals( 271 | '
hellobarfoz
' 272 | ) 273 | }) 274 | 275 | o('as root', () => { 276 | o(render.sync(classComponent)).equals('
hellobar
') 277 | o(render.sync(classComponent, { foo: '-attr-foo' })).equals( 278 | '
hellobar-attr-foo
' 279 | ) 280 | }) 281 | }) 282 | } 283 | 284 | o('`this` in component', () => { 285 | const oninit = o.spy() 286 | const myComponent = { 287 | oninit(vnode) { 288 | oninit() 289 | o(this).equals(vnode.state)( 290 | 'vnode.state should be the context in `oninit`' 291 | ) 292 | o(this.foo).equals(undefined)('this.foo should be undefined initially') 293 | this.foo = 5 294 | o(vnode.state.bar).equals(4)( 295 | 'component properties should be copied to the state' 296 | ) 297 | }, 298 | view(vnode) { 299 | o(this).equals(vnode.state)( 300 | 'vnode.state should be the context in the view' 301 | ) 302 | return m('div', 'hello') 303 | }, 304 | onremove(vnode) { 305 | o(this).equals(vnode.state)( 306 | 'vnode.state should be the context in `onremove`' 307 | ) 308 | }, 309 | bar: 4, 310 | } 311 | 312 | o(render.sync([m(myComponent), m(myComponent)])).equals( 313 | '
hello
hello
' 314 | ) 315 | 316 | o(oninit.callCount).equals(2)( 317 | 'the component should have been initialized twice' 318 | ) 319 | }) 320 | 321 | o('lifecycle hooks as attributes on elements', () => { 322 | let initialized, removed 323 | render.sync( 324 | m('p', { 325 | oninit(vnode) { 326 | initialized = true 327 | o(this).equals(vnode.state)( 328 | 'vnode.state should be the context in `oninit`' 329 | ) 330 | }, 331 | onremove(vnode) { 332 | removed = true 333 | o(this).equals(vnode.state)( 334 | 'vnode.state should be the context in `onremove`' 335 | ) 336 | }, 337 | }) 338 | ) 339 | o(initialized).equals(true)('attr.oninit should run') 340 | o(removed).equals(true)('attr.onremove should run') 341 | }) 342 | 343 | o('lifecycle hooks as attributes on components', () => { 344 | let attrInitialized = false 345 | let attrRemoved = false 346 | let tagInitialized = false 347 | let tagRemoved = false 348 | const myComponent = { 349 | oninit() { 350 | o(attrInitialized).equals(false)( 351 | '`attr.oninit()` should run after `tag.oninit()`' 352 | ) 353 | tagInitialized = true 354 | }, 355 | view() { 356 | return m('p', 'p') 357 | }, 358 | onremove() { 359 | o(attrRemoved).equals(false)( 360 | '`attr.onremove()` should run after `tag.onremove()`' 361 | ) 362 | tagRemoved = true 363 | }, 364 | } 365 | o( 366 | render.sync( 367 | m(myComponent, { 368 | oninit(vnode) { 369 | o(this).equals(vnode.state)( 370 | 'vnode.state should be the context in `attr.oninit`' 371 | ) 372 | attrInitialized = true 373 | o(tagInitialized).equals(true)( 374 | '`attr.oninit()` should run after `tag.oninit()`' 375 | ) 376 | }, 377 | onremove(vnode) { 378 | o(this).equals(vnode.state)( 379 | 'vnode.state should be the context in `attr.onremove`' 380 | ) 381 | attrRemoved = true 382 | o(tagRemoved).equals(true)( 383 | '`attr.onremove()` should run after `tag.onremove()`' 384 | ) 385 | }, 386 | }) 387 | ) 388 | ).equals('

p

') 389 | o(tagInitialized).equals(true)('tag.oninit should be called') 390 | o(tagRemoved).equals(true)('tag.onremove should be called') 391 | }) 392 | 393 | o('lifecycle hooks of class component', () => { 394 | let initialized, removed 395 | const classComponent = class { 396 | constructor(vnode) { 397 | this.vnode = vnode 398 | } 399 | oninit(vnode) { 400 | initialized = true 401 | o(this).equals(vnode.state)( 402 | 'vnode.state should be the context in `oninit`' 403 | ) 404 | o(this.vnode).equals(vnode)('vnode.state equals passed in constructor') 405 | } 406 | onremove(vnode) { 407 | removed = true 408 | o(this).equals(vnode.state)( 409 | 'vnode.state should be the context in `onremove`' 410 | ) 411 | o(this.vnode).equals(vnode)('vnode.state equals passed in constructor') 412 | } 413 | view(vnode) { 414 | o(this).equals(vnode.state)('vnode.state should be the context in `view`') 415 | o(this.vnode).equals(vnode)('vnode.state equals passed in constructor') 416 | return m('p', 'hello') 417 | } 418 | } 419 | o(render.sync(m(classComponent))).equals('

hello

') 420 | o(initialized).equals(true)('classComponent#oninit should run') 421 | o(removed).equals(true)('classComponent#onremove should run') 422 | }) 423 | 424 | o( 425 | 'onremove hooks should be called once the whole tree has been inititalized', 426 | () => { 427 | let initialized = 0 428 | const onremove = o.spy() 429 | function oninit() { 430 | initialized++ 431 | o(onremove.callCount).equals(0) 432 | } 433 | const attrs = { oninit, onremove } 434 | const myComponent = { 435 | oninit, 436 | view() { 437 | return m('p', attrs, 'p') 438 | }, 439 | onremove, 440 | } 441 | render.sync([m(myComponent, attrs), m(myComponent, attrs)]) 442 | 443 | /* 444 | We just rendered two components, and each has three sets of hooks defined: 445 | one on the component object, one passed as component attributes, and one passed 446 | as attributes in the view. => 2 × 3 === 6 447 | */ 448 | o(initialized).equals(6)('oninit should run six times') 449 | o(onremove.callCount).equals(6)('onremove should run six times') 450 | } 451 | ) 452 | 453 | o('hooks are called top-down, depth-first on elements', () => { 454 | /* 455 | Suppose a tree with the following structure: two levels of depth, 456 | two components on the first depth level, the first one having a 457 | single child on level 2. 458 | 459 | +-- p 460 | | +-- a 461 | | 462 | +-- ul 463 | 464 | */ 465 | let pInit = false 466 | let aInit = false 467 | let ulInit = false 468 | let pRemoved = false 469 | let aRemoved = false 470 | let ulRemoved = false 471 | const html = render.sync([ 472 | m( 473 | 'p', 474 | { 475 | oninit() { 476 | pInit = true 477 | o(aInit).equals(false) 478 | o(ulInit).equals(false) 479 | }, 480 | onremove() { 481 | pRemoved = true 482 | o(aRemoved).equals(false) 483 | o(ulRemoved).equals(false) 484 | }, 485 | }, 486 | m( 487 | 'a', 488 | { 489 | oninit() { 490 | aInit = true 491 | o(pInit).equals(true) 492 | o(ulInit).equals(false) 493 | }, 494 | onremove() { 495 | aRemoved = true 496 | o(pRemoved).equals(true) 497 | o(ulRemoved).equals(false) 498 | }, 499 | }, 500 | 'q' 501 | ) 502 | ), 503 | m( 504 | 'ul', 505 | { 506 | oninit() { 507 | ulInit = true 508 | o(pInit).equals(true) 509 | o(aInit).equals(true) 510 | }, 511 | onremove() { 512 | ulRemoved = true 513 | o(pRemoved).equals(true) 514 | o(aRemoved).equals(true) 515 | }, 516 | }, 517 | 'r' 518 | ), 519 | ]) 520 | o(html).equals('

q

') 521 | o(pInit && ulInit && aInit && pRemoved && ulRemoved && aRemoved).equals(true) 522 | }) 523 | 524 | o.spec('async', () => { 525 | o('render object components', async () => { 526 | const oninitSpy = o.spy() 527 | const viewSpy = o.spy() 528 | const myAsyncComponent = { 529 | oninit(vnode, waitFor) { 530 | this.foo = 'bar' 531 | oninitSpy() 532 | waitFor( 533 | Promise.resolve().then(() => { 534 | this.foo = 'baz' 535 | }) 536 | ) 537 | }, 538 | view() { 539 | viewSpy() 540 | return m('div', this.foo) 541 | }, 542 | } 543 | 544 | const p = render(myAsyncComponent) 545 | o(oninitSpy.callCount).equals(1) 546 | o(viewSpy.callCount).equals(0) 547 | const html = await p 548 | o(html).equals('
baz
') 549 | o(oninitSpy.callCount).equals(1) 550 | o(viewSpy.callCount).equals(1) 551 | }) 552 | 553 | o('render nodes', async () => { 554 | const oninitSpy = o.spy() 555 | const html = await render( 556 | m( 557 | 'span', 558 | { 559 | oninit(node, waitFor) { 560 | waitFor( 561 | new Promise(resolve => { 562 | oninitSpy() 563 | setTimeout(resolve, 10) 564 | }) 565 | ) 566 | }, 567 | }, 568 | 'foo' 569 | ) 570 | ) 571 | o(html).equals('foo') 572 | o(oninitSpy.callCount).equals(1) 573 | }) 574 | 575 | o('render object components sync', () => { 576 | const waitFors = [] 577 | const myAsyncComponent = { 578 | oninit(vnode, waitFor) { 579 | waitFors.push(waitFor) 580 | this.foo = 'bar' 581 | return Promise.resolve().then(() => { 582 | this.foo = 'baz' 583 | }) 584 | }, 585 | view() { 586 | return m('div', this.foo) 587 | }, 588 | } 589 | 590 | const html = render.sync(myAsyncComponent) 591 | o(waitFors).deepEquals([undefined]) 592 | o(html).equals('
bar
') 593 | }) 594 | 595 | o('render nodes sync', () => { 596 | const waitFors = [] 597 | const oninitSpy = o.spy() 598 | const html = render.sync( 599 | m( 600 | 'span', 601 | { 602 | oninit(node, waitFor) { 603 | waitFors.push(waitFor) 604 | return new Promise(resolve => { 605 | oninitSpy() 606 | setTimeout(resolve, 10) 607 | }) 608 | }, 609 | }, 610 | 'foo' 611 | ) 612 | ) 613 | o(waitFors).deepEquals([undefined]) 614 | o(html).equals('foo') 615 | o(oninitSpy.callCount).equals(1) 616 | }) 617 | }) 618 | 619 | o('render closure components', () => { 620 | const closureComponent = () => { 621 | return { 622 | view() { 623 | return m('p', 'p') 624 | }, 625 | } 626 | } 627 | o(render.sync(closureComponent())).equals('

p

') 628 | }) 629 | 630 | o.run() 631 | -------------------------------------------------------------------------------- /tests/fixtures/babel_class_component.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function _instanceof(left, right) { if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } } 4 | 5 | function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 6 | 7 | function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } 8 | 9 | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } 10 | 11 | var m = require('mithril/hyperscript'); 12 | 13 | var BabelClassComponent = 14 | /*#__PURE__*/ 15 | function () { 16 | function BabelClassComponent(vnode) { 17 | _classCallCheck(this, BabelClassComponent); 18 | 19 | this.vnode = vnode; 20 | } 21 | 22 | _createClass(BabelClassComponent, [{ 23 | key: "oninit", 24 | value: function oninit() { 25 | this.vnode.state.foo = 'bar'; 26 | } 27 | }, { 28 | key: "view", 29 | value: function view() { 30 | return m('div', ['hello', this.vnode.state.foo, this.vnode.attrs.foo]); 31 | } 32 | }]); 33 | 34 | return BabelClassComponent; 35 | }(); 36 | 37 | module.exports = BabelClassComponent; 38 | -------------------------------------------------------------------------------- /tests/fixtures/es6_class_component.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const m = require('mithril/hyperscript') 3 | 4 | class ES6ClassComponent { 5 | constructor (vnode) { 6 | this.vnode = vnode 7 | } 8 | 9 | oninit () { 10 | this.vnode.state.foo = 'bar' 11 | } 12 | 13 | view () { 14 | return m('div', ['hello', this.vnode.state.foo, this.vnode.attrs.foo]) 15 | } 16 | } 17 | 18 | module.exports = ES6ClassComponent 19 | -------------------------------------------------------------------------------- /tests/fixtures/function_class_component.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const m = require('mithril/hyperscript') 4 | 5 | function ClassComponent (vnode) { 6 | this.vnode = vnode 7 | } 8 | 9 | ClassComponent.prototype.oninit = function oninit () { 10 | this.vnode.state.foo = 'bar' 11 | } 12 | 13 | ClassComponent.prototype.view = function view () { 14 | return m('div', ['hello', this.vnode.state.foo, this.vnode.attrs.foo]) 15 | } 16 | 17 | module.exports = ClassComponent 18 | --------------------------------------------------------------------------------