diff --git a/.babelrc b/.babelrc index 4f4194d..98d9142 100644 --- a/.babelrc +++ b/.babelrc @@ -1,13 +1,13 @@ { + "plugins": ["@babel/plugin-syntax-dynamic-import"], "env": { "test": { + "plugins": ["dynamic-import-node"], "presets": [ [ "@babel/env", { - "targets": { - "node": "current" - } + "targets": { "node": "current" } }] ] } - } + }, } diff --git a/.circleci/config.yml b/.circleci/config.yml index f4dca5c..df16198 100755 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,8 +1,15 @@ version: 2 + +defaults: &defaults + working_directory: ~/project + docker: + - image: circleci/node:latest + environment: + NODE_ENV: test + jobs: - build: - docker: - - image: circleci/node + setup: + <<: *defaults steps: # Checkout repository - checkout @@ -22,17 +29,60 @@ jobs: paths: - "node_modules" - # Lint + # Persist workspace + - persist_to_workspace: + root: ~/project + paths: + - node_modules + + lint: + <<: *defaults + steps: + - checkout + - attach_workspace: + at: ~/project - run: name: Lint command: yarn lint - # Test + audit: + <<: *defaults + steps: + - checkout + - attach_workspace: + at: ~/project - run: - name: Test - command: yarn test + name: Security Audit + command: yarn audit - # Coverage + test-unit: + <<: *defaults + steps: + - checkout + - attach_workspace: + at: ~/project - run: - name: Coverage - command: yarn codecov + name: Unit Tests + command: yarn test:unit --coverage && yarn coverage + + test-e2e: + docker: + - image: circleci/node:latest-browsers + steps: + - checkout + - attach_workspace: + at: ~/project + - run: + name: E2E Tests + command: yarn test:e2e + +workflows: + version: 2 + + commit: + jobs: + - setup + - lint: { requires: [setup] } + - audit: { requires: [setup] } + - test-unit: { requires: [lint] } + - test-e2e: { requires: [lint] } diff --git a/.gitignore b/.gitignore index 003e265..1ae8e09 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ package-lock.json # built code lib es +.vue-meta # examples yarn lock examples/yarn.lock diff --git a/examples/package.json b/examples/package.json index 498f975..b9c557a 100644 --- a/examples/package.json +++ b/examples/package.json @@ -22,6 +22,7 @@ "devDependencies": { "@babel/core": "^7.3.3", "@babel/node": "^7.2.2", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/preset-env": "^7.3.1", "babel-loader": "^8.0.5", "babel-plugin-dynamic-import-node": "^2.2.0", diff --git a/examples/vuex/router.js b/examples/vuex/router.js index 677b408..063a2fb 100644 --- a/examples/vuex/router.js +++ b/examples/vuex/router.js @@ -1,12 +1,13 @@ import Vue from 'vue' import Router from 'vue-router' import Meta from 'vue-meta' -import Home from './views/Home.vue' -import Post from './views/Post.vue' Vue.use(Router) Vue.use(Meta) +const Home = () => import('./views/Home.vue') +const Post = () => import('./views/Post.vue') + export default new Router({ mode: 'history', base: '/vuex', diff --git a/jest.config.js b/jest.config.js index a1bb29f..953f0fa 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,5 @@ module.exports = { - testEnvironment: 'node', + testEnvironment: 'jest-environment-jsdom-global', expand: true, diff --git a/package.json b/package.json index 0bf406b..9f0e0da 100644 --- a/package.json +++ b/package.json @@ -44,9 +44,8 @@ "typings": "types/index.d.ts", "scripts": { "build": "yarn build:other && yarn build:es", - "build:es": "rimraf es && babel src --env-name es --out-dir es --ignore 'src/browser.js'", + "build:es": "rimraf es && babel src --env-name es --out-dir es", "build:other": "rimraf lib && rollup -c scripts/rollup.config.js", - "codecov": "codecov", "dev": "cd examples && yarn dev && cd ..", "docs": "vuepress dev --host 0.0.0.0 --port 3000 docs", "docs:build": "vuepress build docs", @@ -54,30 +53,33 @@ "prerelease": "git checkout master && git pull -r", "release": "yarn lint && yarn test && yarn build && standard-version", "postrelease": "git push origin master --follow-tags && yarn publish", - "test": "jest" + "test": "yarn test:unit && yarn test:e2e", + "test:e2e": "jest test/e2e", + "test:unit": "jest test/unit" }, "dependencies": { - "deepmerge": "^3.2.0", - "lodash.isplainobject": "^4.0.6", - "lodash.uniqueid": "^4.0.1" + "deepmerge": "^3.2.0" }, "resolutions": { "webpack-dev-middleware": "3.6.0" }, "devDependencies": { "@babel/cli": "^7.2.3", - "@babel/core": "^7.3.3", + "@babel/core": "^7.3.4", "@babel/node": "^7.2.2", - "@babel/preset-env": "^7.3.1", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", + "@babel/preset-env": "^7.3.4", + "@nuxt/babel-preset-app": "^2.4.5", "@nuxtjs/eslint-config": "^0.0.1", "@vue/server-test-utils": "^1.0.0-beta.29", "@vue/test-utils": "^1.0.0-beta.29", "babel-core": "^7.0.0-bridge", "babel-eslint": "^10.0.1", - "babel-jest": "^24.1.0", + "babel-jest": "^24.4.0", "babel-loader": "^8.0.5", + "babel-plugin-dynamic-import-node": "^2.2.0", "codecov": "^3.2.0", - "eslint": "^5.14.1", + "eslint": "^5.15.1", "eslint-config-standard": "^12.0.0", "eslint-plugin-import": "^2.16.0", "eslint-plugin-jest": "^22.3.0", @@ -85,16 +87,22 @@ "eslint-plugin-promise": "^4.0.1", "eslint-plugin-standard": "^4.0.0", "eslint-plugin-vue": "^5.2.2", - "esm": "^3.2.5", - "jest": "^24.1.0", - "jsdom": "^13.2.0", - "jsdom-global": "^3.0.2", + "esm": "^3.2.14", + "fs-extra": "^7.0.1", + "is-wsl": "^1.1.0", + "jest": "^24.4.0", + "jest-environment-jsdom": "^24.4.0", + "jest-environment-jsdom-global": "^1.1.1", + "jsdom": "^14.0.0", + "lodash": "^4.17.11", + "puppeteer-core": "^1.13.0", "rimraf": "^2.6.3", - "rollup": "^1.2.2", + "rollup": "^1.6.0", "rollup-plugin-buble": "^0.19.6", - "rollup-plugin-commonjs": "^9.2.0", + "rollup-plugin-commonjs": "^9.2.1", "rollup-plugin-json": "^3.1.0", - "rollup-plugin-node-resolve": "^4.0.0", + "rollup-plugin-node-resolve": "^4.0.1", + "rollup-plugin-replace": "^2.1.0", "rollup-plugin-terser": "^4.0.4", "standard-version": "^5.0.1", "vue": "^2.6.8", diff --git a/scripts/rollup.config.js b/scripts/rollup.config.js index e6a2d0f..7176a11 100644 --- a/scripts/rollup.config.js +++ b/scripts/rollup.config.js @@ -2,7 +2,9 @@ import commonjs from 'rollup-plugin-commonjs' import nodeResolve from 'rollup-plugin-node-resolve' import json from 'rollup-plugin-json' import buble from 'rollup-plugin-buble' +import replace from 'rollup-plugin-replace' import { terser } from 'rollup-plugin-terser' +import defaultsDeep from 'lodash/defaultsDeep' const pkg = require('../package.json') @@ -13,42 +15,71 @@ const banner = `/** */ `.replace(/ {4}/gm, '').trim() -const baseConfig = { - input: 'src/browser.js', - output: { - file: pkg.web, - format: 'umd', - name: 'VueMeta', - sourcemap: false, - banner - }, - plugins: [ - json(), - nodeResolve(), - commonjs(), - buble(), - ] +function rollupConfig({ + plugins = [], + ...config + }) { + + const replaceConfig = { + exclude: 'node_modules/**', + delimiters: ['', ''], + values: { + // replaceConfig needs to have some values + 'const polyfill = process.env.NODE_ENV === \'test\'': 'const polyfill = false', + } + } + + if (!config.output.format || config.output.format === 'umd') { + replaceConfig.values = { + 'const polyfill = process.env.NODE_ENV === \'test\'': 'const polyfill = true', + } + } + + return defaultsDeep({}, config, { + input: 'src/browser.js', + output: { + name: 'VueMeta', + format: 'umd', + sourcemap: false, + banner + }, + plugins: [ + json(), + nodeResolve(), + replace(replaceConfig) + ].concat(plugins), + }) } -export default [{ - ...baseConfig, -}, { - ...baseConfig, - output: { - ...baseConfig.output, - file: pkg.web.replace('.js', '.min.js'), - }, - plugins: [ - ...baseConfig.plugins, - terser() - ] -}, { - ...baseConfig, - input: 'src/index.js', - output: { - ...baseConfig.output, - file: pkg.main, - format: 'cjs' - }, - external: Object.keys(pkg.dependencies) -}] +export default [ + rollupConfig({ + output: { + file: pkg.web, + }, + plugins: [ + commonjs(), + buble() + ] + }), + rollupConfig({ + output: { + file: pkg.web.replace('.js', '.min.js'), + }, + plugins: [ + commonjs(), + buble(), + terser() + ] + }), + rollupConfig({ + input: 'src/index.js', + output: { + file: pkg.main, + format: 'cjs' + }, + plugins: [ + commonjs() + ], + external: Object.keys(pkg.dependencies) + }) +] diff --git a/src/browser.js b/src/browser.js index 2567240..73693f0 100644 --- a/src/browser.js +++ b/src/browser.js @@ -1,9 +1,9 @@ import { version } from '../package.json' import createMixin from './shared/mixin' -import setOptions from './shared/options' -import { isUndefined } from './shared/typeof' +import { setOptions } from './shared/options' +import { isUndefined } from './utils/is-type' import $meta from './client/$meta' -import { hasMetaInfo } from './shared/hasMetaInfo' +import { hasMetaInfo } from './shared/meta-helpers' /** * Plugin install function. diff --git a/src/client/$meta.js b/src/client/$meta.js index c9c7c47..1d60d3f 100644 --- a/src/client/$meta.js +++ b/src/client/$meta.js @@ -1,3 +1,4 @@ +import { getOptions } from '../shared/options' import { pause, resume } from '../shared/pausing' import refresh from './refresh' @@ -12,6 +13,7 @@ export default function _$meta(options = {}) { */ return function $meta() { return { + getOptions: () => getOptions(options), refresh: _refresh.bind(this), inject, pause: pause.bind(this), diff --git a/src/client/batchUpdate.js b/src/client/batchUpdate.js index 909000d..6e9a7a9 100644 --- a/src/client/batchUpdate.js +++ b/src/client/batchUpdate.js @@ -1,4 +1,4 @@ -import { hasGlobalWindow } from '../shared/window' +import { hasGlobalWindow } from '../utils/window' // fallback to timers if rAF not present const stopUpdate = (hasGlobalWindow ? window.cancelAnimationFrame : null) || clearTimeout @@ -15,9 +15,7 @@ const startUpdate = (hasGlobalWindow ? window.requestAnimationFrame : null) || ( * @return {Number} id - a new ID */ export default function batchUpdate(id, callback) { - if (id) { - stopUpdate(id) - } + stopUpdate(id) return startUpdate(() => { id = null diff --git a/src/client/refresh.js b/src/client/refresh.js index 8896240..3d6020b 100644 --- a/src/client/refresh.js +++ b/src/client/refresh.js @@ -1,16 +1,9 @@ import getMetaInfo from '../shared/getMetaInfo' -import { isFunction } from '../shared/typeof' +import { isFunction } from '../utils/is-type' +import { clientSequences } from '../shared/escaping' import updateClientMetaInfo from './updateClientMetaInfo' export default function _refresh(options = {}) { - const escapeSequences = [ - [/&/g, '\u0026'], - [//g, '\u003e'], - [/"/g, '\u0022'], - [/'/g, '\u0027'] - ] - /** * When called, will update the current meta info with new meta info. * Useful when updating meta info as the result of an asynchronous @@ -22,12 +15,12 @@ export default function _refresh(options = {}) { * @return {Object} - new meta info */ return function refresh() { - const metaInfo = getMetaInfo(options, this.$root, escapeSequences) + const metaInfo = getMetaInfo(options, this.$root, clientSequences) const tags = updateClientMetaInfo(options, metaInfo) // emit "event" with new info if (tags && isFunction(metaInfo.changed)) { - metaInfo.changed.call(this, metaInfo, tags.addedTags, tags.removedTags) + metaInfo.changed(metaInfo, tags.addedTags, tags.removedTags) } return { vm: this, metaInfo, tags } diff --git a/src/client/updateClientMetaInfo.js b/src/client/updateClientMetaInfo.js index e7bb46a..9f15607 100644 --- a/src/client/updateClientMetaInfo.js +++ b/src/client/updateClientMetaInfo.js @@ -1,7 +1,9 @@ import { metaInfoOptionKeys, metaInfoAttributeKeys } from '../shared/constants' +import { isArray } from '../utils/is-type' +import { includes } from '../utils/array' import { updateAttribute, updateTag, updateTitle } from './updaters' -const getTag = (tags, tag) => { +function getTag(tags, tag) { if (!tags[tag]) { tags[tag] = document.getElementsByTagName(tag)[0] } @@ -22,49 +24,53 @@ export default function updateClientMetaInfo(options = {}, newInfo) { const htmlTag = getTag(tags, 'html') - // if this is not a server render, then update - if (htmlTag.getAttribute(ssrAttribute) === null) { - // initialize tracked changes - const addedTags = {} - const removedTags = {} - - for (const type in newInfo) { - // ignore these - if (metaInfoOptionKeys.includes(type)) { - continue - } - - if (type === 'title') { - // update the title - updateTitle(newInfo.title) - continue - } - - if (metaInfoAttributeKeys.includes(type)) { - const tagName = type.substr(0, 4) - updateAttribute(options, newInfo[type], getTag(tags, tagName)) - continue - } - - const { oldTags, newTags } = updateTag( - options, - type, - newInfo[type], - getTag(tags, 'head'), - getTag(tags, 'body') - ) - - if (newTags.length) { - addedTags[type] = newTags - removedTags[type] = oldTags - } - } - - return { addedTags, removedTags } - } else { - // remove the server render attribute so we can update on changes + // if this is a server render, then dont update + if (htmlTag.hasAttribute(ssrAttribute)) { + // remove the server render attribute so we can update on (next) changes htmlTag.removeAttribute(ssrAttribute) + return false } - return false + // initialize tracked changes + const addedTags = {} + const removedTags = {} + + for (const type in newInfo) { + // ignore these + if (includes(metaInfoOptionKeys, type)) { + continue + } + + if (type === 'title') { + // update the title + updateTitle(newInfo.title) + continue + } + + if (includes(metaInfoAttributeKeys, type)) { + const tagName = type.substr(0, 4) + updateAttribute(options, newInfo[type], getTag(tags, tagName)) + continue + } + + // tags should always be an array, ignore if it isnt + if (!isArray(newInfo[type])) { + continue + } + + const { oldTags, newTags } = updateTag( + options, + type, + newInfo[type], + getTag(tags, 'head'), + getTag(tags, 'body') + ) + + if (newTags.length) { + addedTags[type] = newTags + removedTags[type] = oldTags + } + } + + return { addedTags, removedTags } } diff --git a/src/client/updaters/attribute.js b/src/client/updaters/attribute.js index 4808f74..cb68f70 100644 --- a/src/client/updaters/attribute.js +++ b/src/client/updaters/attribute.js @@ -1,3 +1,7 @@ +import { booleanHtmlAttributes } from '../../shared/constants' +import { toArray, includes } from '../../utils/array' +import { isArray } from '../../utils/is-type' + /** * Updates the document's html tag attributes * @@ -7,15 +11,18 @@ export default function updateAttribute({ attribute } = {}, attrs, tag) { const vueMetaAttrString = tag.getAttribute(attribute) const vueMetaAttrs = vueMetaAttrString ? vueMetaAttrString.split(',') : [] - const toRemove = Array.from(vueMetaAttrs) + const toRemove = toArray(vueMetaAttrs) const keepIndexes = [] for (const attr in attrs) { if (attrs.hasOwnProperty(attr)) { - const value = attrs[attr] || '' - tag.setAttribute(attr, value) + const value = includes(booleanHtmlAttributes, attr) + ? '' + : isArray(attrs[attr]) ? attrs[attr].join(' ') : attrs[attr] - if (!vueMetaAttrs.includes(attr)) { + tag.setAttribute(attr, value || '') + + if (!includes(vueMetaAttrs, attr)) { vueMetaAttrs.push(attr) } @@ -25,7 +32,7 @@ export default function updateAttribute({ attribute } = {}, attrs, tag) { } const removedAttributesCount = toRemove - .filter((el, index) => !keepIndexes.includes(index)) + .filter((el, index) => !includes(keepIndexes, index)) .reduce((acc, attr) => { tag.removeAttribute(attr) return acc + 1 diff --git a/src/client/updaters/tag.js b/src/client/updaters/tag.js index 7167d8b..09f645d 100644 --- a/src/client/updaters/tag.js +++ b/src/client/updaters/tag.js @@ -1,4 +1,5 @@ -import { isUndefined } from '../../shared/typeof' +import { isUndefined } from '../../utils/is-type' +import { toArray, includes } from '../../utils/array' /** * Updates meta tags inside and on the client. Borrowed from `react-helmet`: @@ -9,8 +10,9 @@ import { isUndefined } from '../../shared/typeof' * @return {Object} - a representation of what tags changed */ export default function updateTag({ attribute, tagIDKeyName } = {}, type, tags, headTag, bodyTag) { - const oldHeadTags = Array.from(headTag.querySelectorAll(`${type}[${attribute}]`)) - const oldBodyTags = Array.from(bodyTag.querySelectorAll(`${type}[${attribute}][data-body="true"]`)) + const oldHeadTags = toArray(headTag.querySelectorAll(`${type}[${attribute}]`)) + const oldBodyTags = toArray(bodyTag.querySelectorAll(`${type}[${attribute}][data-body="true"]`)) + const dataAttributes = [tagIDKeyName, 'body'] const newTags = [] if (tags.length > 1) { @@ -20,13 +22,13 @@ export default function updateTag({ attribute, tagIDKeyName } = {}, type, tags, const found = [] tags = tags.filter((x) => { const k = JSON.stringify(x) - const res = !found.includes(k) + const res = !includes(found, k) found.push(k) return res }) } - if (tags && tags.length) { + if (tags.length) { tags.forEach((tag) => { const newElement = document.createElement(type) newElement.setAttribute(attribute, 'true') @@ -44,13 +46,12 @@ export default function updateTag({ attribute, tagIDKeyName } = {}, type, tags, } else { newElement.appendChild(document.createTextNode(tag.cssText)) } - } else if ([tagIDKeyName, 'body'].includes(attr)) { - const _attr = `data-${attr}` + } else { + const _attr = includes(dataAttributes, attr) + ? `data-${attr}` + : attr const value = isUndefined(tag[attr]) ? '' : tag[attr] newElement.setAttribute(_attr, value) - } else { - const value = isUndefined(tag[attr]) ? '' : tag[attr] - newElement.setAttribute(attr, value) } } } diff --git a/src/index.js b/src/index.js index 5ed7470..303c73d 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,8 @@ import { version } from '../package.json' import createMixin from './shared/mixin' -import setOptions from './shared/options' +import { setOptions } from './shared/options' import $meta from './server/$meta' -import { hasMetaInfo } from './shared/hasMetaInfo' +import { hasMetaInfo } from './shared/meta-helpers' /** * Plugin install function. diff --git a/src/server/$meta.js b/src/server/$meta.js index cd700b1..42694a6 100644 --- a/src/server/$meta.js +++ b/src/server/$meta.js @@ -1,5 +1,6 @@ -import refresh from '../client/refresh' +import { getOptions } from '../shared/options' import { pause, resume } from '../shared/pausing' +import refresh from '../client/refresh' import inject from './inject' export default function _$meta(options = {}) { @@ -13,6 +14,7 @@ export default function _$meta(options = {}) { */ return function $meta() { return { + getOptions: () => getOptions(options), refresh: _refresh.bind(this), inject: _inject.bind(this), pause: pause.bind(this), diff --git a/src/server/generators/attribute.js b/src/server/generators/attribute.js index 03e29bf..ff0933e 100644 --- a/src/server/generators/attribute.js +++ b/src/server/generators/attribute.js @@ -1,5 +1,5 @@ import { booleanHtmlAttributes } from '../../shared/constants' -import { isUndefined } from '../../shared/typeof' +import { isUndefined, isArray } from '../../utils/is-type' /** * Generates tag attributes for use on the server. @@ -20,7 +20,7 @@ export default function attributeGenerator({ attribute } = {}, type, data) { attributeStr += isUndefined(data[attr]) || booleanHtmlAttributes.includes(attr) ? attr - : `${attr}="${data[attr]}"` + : `${attr}="${isArray(data[attr]) ? data[attr].join(' ') : data[attr]}"` attributeStr += ' ' } diff --git a/src/server/generators/tag.js b/src/server/generators/tag.js index ae481de..e6ea38b 100644 --- a/src/server/generators/tag.js +++ b/src/server/generators/tag.js @@ -1,5 +1,5 @@ import { booleanHtmlAttributes, tagsWithoutEndTag, tagsWithInnerContent, tagAttributeAsInnerContent } from '../../shared/constants' -import { isUndefined } from '../../shared/typeof' +import { isUndefined } from '../../utils/is-type' /** * Generates meta, base, link, style, script, noscript tags for use on the server diff --git a/src/server/inject.js b/src/server/inject.js index f094198..fa58e8c 100644 --- a/src/server/inject.js +++ b/src/server/inject.js @@ -1,16 +1,9 @@ import getMetaInfo from '../shared/getMetaInfo' import { metaInfoOptionKeys } from '../shared/constants' +import { serverSequences } from '../shared/escaping' import generateServerInjector from './generateServerInjector' export default function _inject(options = {}) { - const escapeSequences = [ - [/&/g, '&'], - [//g, '>'], - [/"/g, '"'], - [/'/g, '''] - ] - /** * Converts the state of the meta info object such that each item * can be compiled to a tag string on the server @@ -20,7 +13,7 @@ export default function _inject(options = {}) { */ return function inject() { // get meta info with sensible defaults - const metaInfo = getMetaInfo(options, this.$root, escapeSequences) + const metaInfo = getMetaInfo(options, this.$root, serverSequences) // generate server injectors for (const key in metaInfo) { diff --git a/src/shared/constants.js b/src/shared/constants.js index 42bcc0c..ead0b93 100644 --- a/src/shared/constants.js +++ b/src/shared/constants.js @@ -2,6 +2,24 @@ * These are constant variables used throughout the application. */ +// set some sane defaults +export const defaultInfo = { + title: '', + titleChunk: '', + titleTemplate: '%s', + htmlAttrs: {}, + bodyAttrs: {}, + headAttrs: {}, + base: [], + link: [], + meta: [], + style: [], + script: [], + noscript: [], + __dangerouslyDisableSanitizers: [], + __dangerouslyDisableSanitizersByTagID: {} +} + // This is the name of the component option that contains all the information that // gets converted to the various meta tags & attributes for the page. export const keyName = 'metaInfo' @@ -26,6 +44,15 @@ export const metaTemplateKeyName = 'template' // This is the key name for the content-holding property export const contentKeyName = 'content' +export const defaultOptions = { + keyName, + attribute, + ssrAttribute, + tagIDKeyName, + contentKeyName, + metaTemplateKeyName +} + // List of metaInfo property keys which are configuration options (and dont generate html) export const metaInfoOptionKeys = [ 'titleChunk', @@ -35,6 +62,12 @@ export const metaInfoOptionKeys = [ '__dangerouslyDisableSanitizersByTagID' ] +// The metaInfo property keys which are used to disable escaping +export const disableOptionKeys = [ + '__dangerouslyDisableSanitizers', + '__dangerouslyDisableSanitizersByTagID' +] + // List of metaInfo property keys which only generates attributes and no tags export const metaInfoAttributeKeys = [ 'htmlAttrs', @@ -55,6 +88,7 @@ export const tagAttributeAsInnerContent = ['innerHTML', 'cssText'] // from: https://github.com/kangax/html-minifier/blob/gh-pages/src/htmlminifier.js#L202 export const booleanHtmlAttributes = [ 'allowfullscreen', + 'amp', 'async', 'autofocus', 'autoplay', diff --git a/src/shared/escaping.js b/src/shared/escaping.js new file mode 100644 index 0000000..fe28a28 --- /dev/null +++ b/src/shared/escaping.js @@ -0,0 +1,70 @@ +import { isString, isArray, isObject } from '../utils/is-type' +import { includes } from '../utils/array' +import { metaInfoOptionKeys, disableOptionKeys } from './constants' + +export const serverSequences = [ + [/&/g, '&'], + [//g, '>'], + [/"/g, '"'], + [/'/g, '''] +] + +export const clientSequences = [ + [/&/g, '\u0026'], + [//g, '\u003e'], + [/"/g, '\u0022'], + [/'/g, '\u0027'] +] + +// sanitizes potentially dangerous characters +export function escape(info, options, escapeOptions) { + const { tagIDKeyName } = options + const { doEscape = v => v } = escapeOptions + const escaped = {} + + for (const key in info) { + const value = info[key] + + // no need to escape configuration options + if (includes(metaInfoOptionKeys, key)) { + escaped[key] = value + continue + } + + let [ disableKey ] = disableOptionKeys + if (escapeOptions[disableKey] && includes(escapeOptions[disableKey], key)) { + // this info[key] doesnt need to escaped if the option is listed in __dangerouslyDisableSanitizers + escaped[key] = value + continue + } + + const tagId = info[tagIDKeyName] + if (tagId) { + disableKey = disableOptionKeys[1] + + // keys which are listed in __dangerouslyDisableSanitizersByTagID for the current vmid do not need to be escaped + if (escapeOptions[disableKey] && escapeOptions[disableKey][tagId] && includes(escapeOptions[disableKey][tagId], key)) { + escaped[key] = value + continue + } + } + + if (isString(value)) { + escaped[key] = doEscape(value) + } else if (isArray(value)) { + escaped[key] = value.map((v) => { + return isObject(v) + ? escape(v, options, escapeOptions) + : doEscape(v) + }) + } else if (isObject(value)) { + escaped[key] = escape(value, options, escapeOptions) + } else { + escaped[key] = value + } + } + + return escaped +} diff --git a/src/shared/getComponentOption.js b/src/shared/getComponentOption.js index f468520..16485a0 100644 --- a/src/shared/getComponentOption.js +++ b/src/shared/getComponentOption.js @@ -1,7 +1,8 @@ -import deepmerge from 'deepmerge' -import uniqueId from 'lodash.uniqueid' -import { isUndefined, isFunction, isObject } from './typeof' -import uniqBy from './uniqBy' +import { isFunction, isObject } from '../utils/is-type' +import { findIndex } from '../utils/array' +import { merge } from './merge' +import { applyTemplate } from './template' +import { inMetaInfoBranch } from './meta-helpers' /** * Returns the `opts.option` $option value of the given `opts.component`. @@ -17,15 +18,16 @@ import uniqBy from './uniqBy' * @param {Object} [result={}] - result so far * @return {Object} result - final aggregated result */ -export default function getComponentOption({ component, deep, arrayMerge, keyName, metaTemplateKeyName, tagIDKeyName, contentKeyName } = {}, result = {}) { - const { $options } = component +export default function getComponentOption(options = {}, component, result = {}) { + const { keyName, metaTemplateKeyName, tagIDKeyName } = options + const { $options, $children } = component if (component._inactive) { return result } // only collect option data if it exists - if (!isUndefined($options[keyName]) && $options[keyName] !== null) { + if ($options[keyName]) { let data = $options[keyName] // if option is a function, replace it with it's result @@ -33,46 +35,42 @@ export default function getComponentOption({ component, deep, arrayMerge, keyNam data = data.call(component) } - if (isObject(data)) { - // merge with existing options - result = deepmerge(result, data, { arrayMerge }) - } else { - result = data + // ignore data if its not an object, then we keep our previous result + if (!isObject(data)) { + return result } + + // merge with existing options + result = merge(result, data, options) } // collect & aggregate child options if deep = true - if (deep && component.$children.length) { - component.$children.forEach((childComponent) => { - result = getComponentOption({ - component: childComponent, - keyName, - deep, - arrayMerge - }, result) + if ($children.length) { + $children.forEach((childComponent) => { + // check if the childComponent is in a branch + // return otherwise so we dont walk all component branches unnecessarily + if (!inMetaInfoBranch(childComponent)) { + return + } + + result = getComponentOption(options, childComponent, result) }) } - if (metaTemplateKeyName && result.hasOwnProperty('meta')) { - result.meta = Object.keys(result.meta).map((metaKey) => { - const metaObject = result.meta[metaKey] - if (!metaObject.hasOwnProperty(metaTemplateKeyName) || !metaObject.hasOwnProperty(contentKeyName) || isUndefined(metaObject[metaTemplateKeyName])) { - return result.meta[metaKey] - } + if (metaTemplateKeyName && result.meta) { + // apply templates if needed + result.meta.forEach(metaObject => applyTemplate(options, metaObject)) - const template = metaObject[metaTemplateKeyName] - delete metaObject[metaTemplateKeyName] - - if (template) { - metaObject.content = isFunction(template) ? template(metaObject.content) : template.replace(/%s/g, metaObject.content) - } - - return metaObject + // remove meta items with duplicate vmid's + result.meta = result.meta.filter((metaItem, index, arr) => { + return ( + // keep meta item if it doesnt has a vmid + !metaItem.hasOwnProperty(tagIDKeyName) || + // or if it's the first item in the array with this vmid + index === findIndex(arr, item => item[tagIDKeyName] === metaItem[tagIDKeyName]) + ) }) - result.meta = uniqBy( - result.meta, - metaObject => metaObject.hasOwnProperty(tagIDKeyName) ? metaObject[tagIDKeyName] : uniqueId() - ) } + return result } diff --git a/src/shared/getMetaInfo.js b/src/shared/getMetaInfo.js index 08f8eaa..a94d79a 100644 --- a/src/shared/getMetaInfo.js +++ b/src/shared/getMetaInfo.js @@ -1,12 +1,9 @@ -import deepmerge from 'deepmerge' -import isPlainObject from 'lodash.isplainobject' -import { isFunction, isString } from './typeof' -import isArray from './isArray' +import { ensureIsArray } from '../utils/ensure' +import { applyTemplate } from './template' +import { defaultInfo, disableOptionKeys } from './constants' +import { escape } from './escaping' import getComponentOption from './getComponentOption' -const applyTemplate = (component, template, chunk) => - isFunction(template) ? template.call(component, chunk) : template.replace(/%s/g, chunk) - /** * Returns the correct meta info for the given component * (child components will overwrite parent meta info) @@ -14,75 +11,9 @@ const applyTemplate = (component, template, chunk) => * @param {Object} component - the Vue instance to get meta info from * @return {Object} - returned meta info */ -export default function getMetaInfo({ keyName, tagIDKeyName, metaTemplateKeyName, contentKeyName } = {}, component, escapeSequences = []) { - // set some sane defaults - const defaultInfo = { - title: '', - titleChunk: '', - titleTemplate: '%s', - htmlAttrs: {}, - bodyAttrs: {}, - headAttrs: {}, - meta: [], - base: [], - link: [], - style: [], - script: [], - noscript: [], - __dangerouslyDisableSanitizers: [], - __dangerouslyDisableSanitizersByTagID: {} - } - +export default function getMetaInfo(options = {}, component, escapeSequences = []) { // collect & aggregate all metaInfo $options - let info = getComponentOption({ - deep: true, - component, - keyName, - metaTemplateKeyName, - tagIDKeyName, - contentKeyName, - arrayMerge(target, source) { - // we concat the arrays without merging objects contained in, - // but we check for a `vmid` property on each object in the array - // using an O(1) lookup associative array exploit - // note the use of "for in" - we are looping through arrays here, not - // plain objects - const destination = [] - - for (const targetIndex in target) { - const targetItem = target[targetIndex] - let shared = false - - for (const sourceIndex in source) { - const sourceItem = source[sourceIndex] - - if (targetItem[tagIDKeyName] && targetItem[tagIDKeyName] === sourceItem[tagIDKeyName]) { - const targetTemplate = targetItem[metaTemplateKeyName] - const sourceTemplate = sourceItem[metaTemplateKeyName] - - if (targetTemplate && !sourceTemplate) { - sourceItem[contentKeyName] = applyTemplate(component, targetTemplate, sourceItem[contentKeyName]) - } - - // If template defined in child but content in parent - if (targetTemplate && sourceTemplate && !sourceItem[contentKeyName]) { - sourceItem[contentKeyName] = applyTemplate(component, sourceTemplate, targetItem[contentKeyName]) - delete sourceItem[metaTemplateKeyName] - } - - shared = true - break - } - } - - if (!shared) { - destination.push(targetItem) - } - } - - return destination.concat(source) - } - }) + let info = getComponentOption(options, component, defaultInfo) // Remove all "template" tags from meta @@ -92,8 +23,8 @@ export default function getMetaInfo({ keyName, tagIDKeyName, metaTemplateKeyName } // replace title with populated template - if (info.titleTemplate) { - info.title = applyTemplate(component, info.titleTemplate, info.titleChunk || '') + if (info.titleTemplate && info.titleTemplate !== '%s') { + applyTemplate({ component, contentKeyName: 'title' }, info, info.titleTemplate, info.titleChunk || '') } // convert base tag to an array so it can be handled the same way @@ -102,47 +33,24 @@ export default function getMetaInfo({ keyName, tagIDKeyName, metaTemplateKeyName info.base = Object.keys(info.base).length ? [info.base] : [] } - const ref = info.__dangerouslyDisableSanitizers - const refByTagID = info.__dangerouslyDisableSanitizersByTagID + const escapeOptions = { + doEscape: value => escapeSequences.reduce((val, [v, r]) => val.replace(v, r), value) + } - // sanitizes potentially dangerous characters - const escape = info => Object.keys(info).reduce((escaped, key) => { - let isDisabled = ref && ref.includes(key) - const tagID = info[tagIDKeyName] - - if (!isDisabled && tagID) { - isDisabled = refByTagID && refByTagID[tagID] && refByTagID[tagID].includes(key) - } - - const val = info[key] - escaped[key] = val - - if (key === '__dangerouslyDisableSanitizers' || key === '__dangerouslyDisableSanitizersByTagID') { - return escaped - } - - if (!isDisabled) { - if (isString(val)) { - escaped[key] = escapeSequences.reduce((val, [v, r]) => val.replace(v, r), val) - } else if (isPlainObject(val)) { - escaped[key] = escape(val) - } else if (isArray(val)) { - escaped[key] = val.map(escape) - } else { - escaped[key] = val + disableOptionKeys.forEach((disableKey, index) => { + if (index === 0) { + ensureIsArray(info, disableKey) + } else if (index === 1) { + for (const key in info[disableKey]) { + ensureIsArray(info[disableKey], key) } - } else { - escaped[key] = val } - return escaped - }, {}) - - // merge with defaults - info = deepmerge(defaultInfo, info) + escapeOptions[disableKey] = info[disableKey] + }) // begin sanitization - info = escape(info) + info = escape(info, options, escapeOptions) return info } diff --git a/src/shared/hasMetaInfo.js b/src/shared/hasMetaInfo.js deleted file mode 100644 index 975f762..0000000 --- a/src/shared/hasMetaInfo.js +++ /dev/null @@ -1,3 +0,0 @@ -export function hasMetaInfo(vm = this) { - return vm && !!vm._vueMeta -} diff --git a/src/shared/isArray.js b/src/shared/isArray.js deleted file mode 100644 index 698b037..0000000 --- a/src/shared/isArray.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * checks if passed argument is an array - * @param {any} arr - the object to check - * @return {Boolean} - true if `arr` is an array - */ -export default function isArray(arr) { - return Array.isArray - ? Array.isArray(arr) - : Object.prototype.toString.call(arr) === '[object Array]' -} diff --git a/src/shared/merge.js b/src/shared/merge.js new file mode 100644 index 0000000..b7b5349 --- /dev/null +++ b/src/shared/merge.js @@ -0,0 +1,91 @@ +import deepmerge from 'deepmerge' +import { findIndex } from '../utils/array' +import { applyTemplate } from './template' +import { metaInfoAttributeKeys } from './constants' + +export function arrayMerge({ component, tagIDKeyName, metaTemplateKeyName, contentKeyName }, target, source) { + // we concat the arrays without merging objects contained in, + // but we check for a `vmid` property on each object in the array + // using an O(1) lookup associative array exploit + const destination = [] + + target.forEach((targetItem, targetIndex) => { + // no tagID so no need to check for duplicity + if (!targetItem[tagIDKeyName]) { + destination.push(targetItem) + return + } + + const sourceIndex = findIndex(source, item => item[tagIDKeyName] === targetItem[tagIDKeyName]) + const sourceItem = source[sourceIndex] + + // source doesnt contain any duplicate vmid's, we can keep targetItem + if (sourceIndex === -1) { + destination.push(targetItem) + return + } + + // when sourceItem explictly defines contentKeyName or innerHTML as undefined, its + // an indication that we need to skip the default behaviour or child has preference over parent + // which means we keep the targetItem and ignore/remove the sourceItem + if ((sourceItem.hasOwnProperty(contentKeyName) && sourceItem[contentKeyName] === undefined) || + (sourceItem.hasOwnProperty('innerHTML') && sourceItem.innerHTML === undefined)) { + destination.push(targetItem) + // remove current index from source array so its not concatenated to destination below + source.splice(sourceIndex, 1) + return + } + + // we now know that targetItem is a duplicate and we should ignore it in favor of sourceItem + + // if source specifies null as content then ignore both the target as the source + if (sourceItem[contentKeyName] === null || sourceItem.innerHTML === null) { + // remove current index from source array so its not concatenated to destination below + source.splice(sourceIndex, 1) + return + } + + // now we only need to check if the target has a template to combine it with the source + const targetTemplate = targetItem[metaTemplateKeyName] + if (!targetTemplate) { + return + } + + const sourceTemplate = sourceItem[metaTemplateKeyName] + + if (!sourceTemplate) { + // use parent template and child content + applyTemplate({ component, metaTemplateKeyName, contentKeyName }, sourceItem, targetTemplate) + } else if (!sourceItem[contentKeyName]) { + // use child template and parent content + applyTemplate({ component, metaTemplateKeyName, contentKeyName }, sourceItem, undefined, targetItem[contentKeyName]) + } + }) + + return destination.concat(source) +} + +export function merge(target, source, options = {}) { + // remove properties explicitly set to false so child components can + // optionally _not_ overwrite the parents content + // (for array properties this is checked in arrayMerge) + if (source.hasOwnProperty('title') && source.title === undefined) { + delete source.title + } + + metaInfoAttributeKeys.forEach((attrKey) => { + if (!source[attrKey]) { + return + } + + for (const key in source[attrKey]) { + if (source[attrKey].hasOwnProperty(key) && source[attrKey][key] === undefined) { + delete source[attrKey][key] + } + } + }) + + return deepmerge(target, source, { + arrayMerge: (t, s) => arrayMerge(options, t, s) + }) +} diff --git a/src/shared/meta-helpers.js b/src/shared/meta-helpers.js new file mode 100644 index 0000000..d1d7ac2 --- /dev/null +++ b/src/shared/meta-helpers.js @@ -0,0 +1,11 @@ +import { isUndefined, isObject } from '../utils/is-type' + +// Vue $root instance has a _vueMeta object property, otherwise its a boolean true +export function hasMetaInfo(vm = this) { + return vm && (vm._vueMeta === true || isObject(vm._vueMeta)) +} + +// a component is in a metaInfo branch when itself has meta info or one of its (grand-)children has +export function inMetaInfoBranch(vm = this) { + return vm && !isUndefined(vm._vueMeta) +} diff --git a/src/shared/mixin.js b/src/shared/mixin.js index 8bd2795..362cc7b 100644 --- a/src/shared/mixin.js +++ b/src/shared/mixin.js @@ -1,6 +1,8 @@ import triggerUpdate from '../client/triggerUpdate' -import { isUndefined, isFunction } from './typeof' -import { ensuredPush } from './ensure' +import { isUndefined, isFunction } from '../utils/is-type' +import { ensuredPush } from '../utils/ensure' +import { hasMetaInfo } from './meta-helpers' +import { addNavGuards } from './nav-guards' export default function createMixin(Vue, options) { // for which Vue lifecycle hooks should the metaInfo be refreshed @@ -13,10 +15,10 @@ export default function createMixin(Vue, options) { get() { // Show deprecation warning once when devtools enabled if (Vue.config.devtools && !this.$root._vueMeta.hasMetaInfoDeprecationWarningShown) { - console.warn('VueMeta DeprecationWarning: _hasMetaInfo has been deprecated and will be removed in a future version. Please import hasMetaInfo and use hasMetaInfo(vm) instead') // eslint-disable-line no-console + console.warn('VueMeta DeprecationWarning: _hasMetaInfo has been deprecated and will be removed in a future version. Please use hasMetaInfo(vm) instead') // eslint-disable-line no-console this.$root._vueMeta.hasMetaInfoDeprecationWarningShown = true } - return !!this._vueMeta + return hasMetaInfo(this) } }) @@ -28,8 +30,18 @@ export default function createMixin(Vue, options) { this.$root._vueMeta = {} } + // to speed up updates we keep track of branches which have a component with vue-meta info defined + // if _vueMeta = true it has info, if _vueMeta = false a child has info if (!this._vueMeta) { this._vueMeta = true + + let p = this.$parent + while (p && p !== this.$root) { + if (isUndefined(p._vueMeta)) { + p._vueMeta = false + } + p = p.$parent + } } // coerce function-style metaInfo to a computed prop so we can observe @@ -55,44 +67,37 @@ export default function createMixin(Vue, options) { // force an initial refresh on page load and prevent other lifecycleHooks // to triggerUpdate until this initial refresh is finished // this is to make sure that when a page is opened in an inactive tab which - // has throttled rAF/timers we still immeditately set the page title + // has throttled rAF/timers we still immediately set the page title if (isUndefined(this.$root._vueMeta.initialized)) { this.$root._vueMeta.initialized = this.$isServer if (!this.$root._vueMeta.initialized) { - const $rootMeta = this.$root.$meta() - ensuredPush(this.$options, 'mounted', () => { if (!this.$root._vueMeta.initialized) { // refresh meta in nextTick so all child components have loaded this.$nextTick(function () { - $rootMeta.refresh() + this.$root.$meta().refresh() this.$root._vueMeta.initialized = true }) } }) - // add vue-router navigation guard to prevent multiple updates during navigation - // only usefull on the client side - if (options.refreshOnceOnNavigation && this.$root.$router) { - const $router = this.$root.$router - $router.beforeEach((to, from, next) => { - $rootMeta.pause() - next() - }) - - $router.afterEach(() => { - const { vm, metaInfo } = $rootMeta.resume() - if (metaInfo && metaInfo.afterNavigation && isFunction(metaInfo.afterNavigation)) { - metaInfo.afterNavigation.call(vm, metaInfo) - } - }) + // add the navigation guards if they havent been added yet + if (options.refreshOnceOnNavigation) { + addNavGuards(this) } } } // do not trigger refresh on the server side if (!this.$isServer) { + // add the navigation guards if they havent been added yet + // if metaInfo is defined as a function, this does call the computed fn redundantly + // but as Vue internally caches the results of computed props it shouldnt hurt performance + if (!options.refreshOnceOnNavigation && this.$options[options.keyName].afterNavigation) { + addNavGuards(this) + } + // no need to add this hooks on server side updateOnLifecycleHook.forEach((lifecycleHook) => { ensuredPush(this.$options, lifecycleHook, () => triggerUpdate(this, lifecycleHook)) @@ -103,12 +108,14 @@ export default function createMixin(Vue, options) { // Wait that element is hidden before refreshing meta tags (to support animations) const interval = setInterval(() => { if (this.$el && this.$el.offsetParent !== null) { + /* istanbul ignore next line */ return } clearInterval(interval) if (!this.$parent) { + /* istanbul ignore next line */ return } diff --git a/src/shared/nav-guards.js b/src/shared/nav-guards.js new file mode 100644 index 0000000..edbae81 --- /dev/null +++ b/src/shared/nav-guards.js @@ -0,0 +1,26 @@ +import { isFunction } from '../utils/is-type' + +export function addNavGuards(vm) { + // return when nav guards already added or no router exists + if (vm.$root._vueMeta.navGuards || !vm.$root.$router) { + /* istanbul ignore next */ + return + } + + vm.$root._vueMeta.navGuards = true + + const $router = vm.$root.$router + const $meta = vm.$root.$meta() + + $router.beforeEach((to, from, next) => { + $meta.pause() + next() + }) + + $router.afterEach(() => { + const { metaInfo } = $meta.resume() + if (metaInfo && metaInfo.afterNavigation && isFunction(metaInfo.afterNavigation)) { + metaInfo.afterNavigation(metaInfo) + } + }) +} diff --git a/src/shared/options.js b/src/shared/options.js index eb81847..deb8079 100644 --- a/src/shared/options.js +++ b/src/shared/options.js @@ -1,25 +1,7 @@ -import { isObject, isFunction } from './typeof' +import { isObject } from '../utils/is-type' +import { defaultOptions } from './constants' -import { - keyName, - attribute, - ssrAttribute, - tagIDKeyName, - metaTemplateKeyName, - contentKeyName -} from './constants' - -// set some default options -const defaultOptions = { - keyName, - contentKeyName, - metaTemplateKeyName, - attribute, - ssrAttribute, - tagIDKeyName -} - -export default function setOptions(options) { +export function setOptions(options) { // combine options options = isObject(options) ? options : {} @@ -29,15 +11,13 @@ export default function setOptions(options) { } } - if (options.afterNavigation && !isFunction(options.afterNavigation)) { - console.warn(`afterNavigation should be a function, received ${typeof options.afterNavigation} instead`) // eslint-disable-line no-console - options.afterNavigation = void 0 - return options - } - - if (options.afterNavigation && !options.refreshOnceOnNavigation) { - options.refreshOnceOnNavigation = true - } - return options } + +export function getOptions(options) { + const optionsCopy = {} + for (const key in options) { + optionsCopy[key] = options[key] + } + return optionsCopy +} diff --git a/src/shared/template.js b/src/shared/template.js new file mode 100644 index 0000000..1de07b0 --- /dev/null +++ b/src/shared/template.js @@ -0,0 +1,23 @@ +import { isUndefined, isFunction } from '../utils/is-type' + +export function applyTemplate({ component, metaTemplateKeyName, contentKeyName }, headObject, template, chunk) { + if (isUndefined(template)) { + template = headObject[metaTemplateKeyName] + delete headObject[metaTemplateKeyName] + } + + // return early if no template defined + if (!template) { + return false + } + + if (isUndefined(chunk)) { + chunk = headObject[contentKeyName] + } + + headObject[contentKeyName] = isFunction(template) + ? template.call(component, chunk) + : template.replace(/%s/g, chunk) + + return true +} diff --git a/src/shared/uniqBy.js b/src/shared/uniqBy.js deleted file mode 100644 index c3257d9..0000000 --- a/src/shared/uniqBy.js +++ /dev/null @@ -1,7 +0,0 @@ -export default function uniqBy(inputArray, predicate) { - return inputArray - .filter((x, i, arr) => i === arr.length - 1 - ? true - : predicate(x) !== predicate(arr[i + 1]) - ) -} diff --git a/src/utils/array.js b/src/utils/array.js new file mode 100644 index 0000000..7ac529c --- /dev/null +++ b/src/utils/array.js @@ -0,0 +1,45 @@ +/* + * To reduce build size, this file provides simple polyfills without + * overly excessive type checking and without modifying + * the global Array.prototype + * The polyfills are automatically removed in the commonjs build + * Also, only files in client/ & shared/ should use these functions + * files in server/ still use normal js function + */ + +// this const is replaced by rollup to true for umd builds +// which means the polyfills are removed for other build formats +const polyfill = process.env.NODE_ENV === 'test' + +export function findIndex(array, predicate) { + if (polyfill && !Array.prototype.findIndex) { + // idx needs to be a Number, for..in returns string + for (let idx = 0; idx < array.length; idx++) { + if (predicate.call(arguments[2], array[idx], idx, array)) { + return idx + } + } + return -1 + } + return array.findIndex(predicate, arguments[2]) +} + +export function toArray(arg) { + if (polyfill && !Array.from) { + return Array.prototype.slice.call(arg) + } + return Array.from(arg) +} + +export function includes(array, value) { + if (polyfill && !Array.prototype.includes) { + for (const idx in array) { + if (array[idx] === value) { + return true + } + } + + return false + } + return array.includes(value) +} diff --git a/src/shared/ensure.js b/src/utils/ensure.js similarity index 80% rename from src/shared/ensure.js rename to src/utils/ensure.js index 3054549..865ac3e 100644 --- a/src/shared/ensure.js +++ b/src/utils/ensure.js @@ -1,5 +1,4 @@ -import isArray from './isArray' -import { isObject } from './typeof' +import { isArray, isObject } from './is-type' export function ensureIsArray(arg, key) { if (!key || !isObject(arg)) { diff --git a/src/shared/typeof.js b/src/utils/is-type.js similarity index 57% rename from src/shared/typeof.js rename to src/utils/is-type.js index c6b39b2..83dfeb3 100644 --- a/src/shared/typeof.js +++ b/src/utils/is-type.js @@ -1,3 +1,12 @@ +/** + * checks if passed argument is an array + * @param {any} arg - the object to check + * @return {Boolean} - true if `arg` is an array + */ +export function isArray(arg) { + return Array.isArray(arg) +} + export function isUndefined(arg) { return typeof arg === 'undefined' } diff --git a/src/shared/window.js b/src/utils/window.js similarity index 80% rename from src/shared/window.js rename to src/utils/window.js index 118705e..d31dbab 100644 --- a/src/shared/window.js +++ b/src/utils/window.js @@ -1,4 +1,4 @@ -import { isUndefined } from './typeof' +import { isUndefined } from './is-type' export function hasGlobalWindowFn() { try { diff --git a/test/components.test.js b/test/components.test.js deleted file mode 100644 index fa8c037..0000000 --- a/test/components.test.js +++ /dev/null @@ -1,97 +0,0 @@ -import _getMetaInfo from '../src/shared/getMetaInfo' -import { mount, defaultOptions, loadVueMetaPlugin } from './utils' - -import GoodbyeWorld from './fixtures/goodbye-world.vue' -import HelloWorld from './fixtures/hello-world.vue' -import KeepAlive from './fixtures/keep-alive.vue' -import Changed from './fixtures/changed.vue' - -const getMetaInfo = component => _getMetaInfo(defaultOptions, component) - -describe('client', () => { - let Vue - - beforeAll(() => (Vue = loadVueMetaPlugin())) - - test('meta-info refreshed on component\'s data change', () => { - const wrapper = mount(HelloWorld, { localVue: Vue }) - - let metaInfo = getMetaInfo(wrapper.vm) - expect(metaInfo.title).toEqual('Hello World') - wrapper.setData({ title: 'Goodbye World' }) - - metaInfo = getMetaInfo(wrapper.vm) - expect(metaInfo.title).toEqual('Goodbye World') - }) - - test('child meta-info removed when child is toggled', () => { - const wrapper = mount(GoodbyeWorld, { localVue: Vue }) - - let metaInfo = getMetaInfo(wrapper.vm) - expect(metaInfo.title).toEqual('Hello World') - - wrapper.setData({ childVisible: false }) - - metaInfo = getMetaInfo(wrapper.vm) - expect(metaInfo.title).toEqual('Goodbye World') - - wrapper.setData({ childVisible: true }) - - metaInfo = getMetaInfo(wrapper.vm) - expect(metaInfo.title).toEqual('Hello World') - }) - - test('child meta-info removed when keep-alive child is toggled', () => { - const wrapper = mount(KeepAlive, { localVue: Vue }) - - let metaInfo = getMetaInfo(wrapper.vm) - expect(metaInfo.title).toEqual('Hello World') - - wrapper.setData({ childVisible: false }) - - metaInfo = getMetaInfo(wrapper.vm) - expect(metaInfo.title).toEqual('Alive World') - - wrapper.setData({ childVisible: true }) - - metaInfo = getMetaInfo(wrapper.vm) - expect(metaInfo.title).toEqual('Hello World') - }) - - test('meta-info is removed when destroyed', () => { - const parentComponent = new Vue({ render: h => h('div') }) - const wrapper = mount(HelloWorld, { localVue: Vue, parentComponent }) - - let metaInfo = getMetaInfo(wrapper.vm.$parent) - expect(metaInfo.title).toEqual('Hello World') - wrapper.destroy() - - jest.runAllTimers() - metaInfo = getMetaInfo(wrapper.vm.$parent) - expect(metaInfo.title).toEqual('') - }) - - test('meta-info can be rendered with inject', () => { - const wrapper = mount(HelloWorld, { localVue: Vue }) - - const metaInfo = wrapper.vm.$meta().inject() - expect(metaInfo.title.text()).toEqual('Hello World') - }) - - test('changed function is called', () => { - const parentComponent = new Vue({ render: h => h('div') }) - const wrapper = mount(Changed, { localVue: Vue, parentComponent }) - - let context - const changed = jest.fn(function () { - context = this - }) - wrapper.setData({ changed }) - wrapper.setData({ childVisible: true }) - - wrapper.vm.$parent.$meta().refresh() - expect(changed).toHaveBeenCalledTimes(1) - // TODO: this isnt what the docs say - expect(context._uid).not.toBe(wrapper.vm._uid) - }) -}) diff --git a/test/fixtures/changed.vue b/test/components/changed.vue similarity index 63% rename from test/fixtures/changed.vue rename to test/components/changed.vue index 20a6de5..4d2c02d 100644 --- a/test/fixtures/changed.vue +++ b/test/components/changed.vue @@ -11,16 +11,24 @@ export default { components: { HelloWorld }, + props: { + changed: { + type: Function + } + }, metaInfo() { return { - changed: this.changed + changed: this._changed } }, data() { return { childVisible: false, - changed: () => {} + _changed: () => {} } + }, + mounted() { + this._changed = this.changed.bind(this) } } diff --git a/test/fixtures/goodbye-world.vue b/test/components/goodbye-world.vue similarity index 100% rename from test/fixtures/goodbye-world.vue rename to test/components/goodbye-world.vue diff --git a/test/fixtures/hello-world.vue b/test/components/hello-world.vue similarity index 100% rename from test/fixtures/hello-world.vue rename to test/components/hello-world.vue diff --git a/test/fixtures/keep-alive.vue b/test/components/keep-alive.vue similarity index 100% rename from test/fixtures/keep-alive.vue rename to test/components/keep-alive.vue diff --git a/test/e2e/browser.test.js b/test/e2e/browser.test.js new file mode 100644 index 0000000..460a89e --- /dev/null +++ b/test/e2e/browser.test.js @@ -0,0 +1,79 @@ +import Browser from '../utils/browser' +import { buildFixture } from '../utils/build' + +const browser = new Browser() + +describe('basic browser with ssr page', () => { + let page = null + let url + let html + + beforeAll(async () => { + const fixture = await buildFixture('basic') + url = fixture.url + html = fixture.html + + await browser.start({ + // slowMo: 50, + // headless: false + }) + }) + + // Stop browser + afterAll(async () => { + if (page) await page.close() + await browser.close() + }) + + test('validate ssr', () => { + const htmlTag = html.match(/]+)>/)[0] + expect(htmlTag).toContain('data-vue-meta-server-rendered') + expect(htmlTag).toContain(' lang="en" ') + expect(htmlTag).toContain(' amp ') + expect(htmlTag).not.toContain('allowfullscreen') + expect(html.match(/]*>(.*?)<\/title>/)[1]).toBe('Home | Vue Meta Test') + expect(html.match(/]+type="application\/ld\+json"[^>]*>(.*?) JSON.parse(sanitizeCheck[0])).not.toThrow() + expect(() => JSON.parse(sanitizeCheck[1])).toThrow() + expect(() => JSON.parse(sanitizeCheck[2])).not.toThrow() + }) + + test('Open /', async () => { + page = await browser.page(url) + + expect(await page.$attr('html', 'data-vue-meta-server-rendered')).toBe(null) + expect(await page.$attr('html', 'lang')).toBe('en') + expect(await page.$attr('html', 'amp')).toBe('') + expect(await page.$attr('html', 'allowfullscreen')).toBe(null) + expect(await page.$attr('head', 'test')).toBe('true') + expect(await page.$text('h1')).toBe('Basic') + expect(await page.$text('title')).toBe('Home | Vue Meta Test') + expect(await page.$$eval('meta', metas => metas.length)).toBe(2) + + let sanitizeCheck = await page.$$text('script') + sanitizeCheck.push(...(await page.$$text('noscript'))) + sanitizeCheck = sanitizeCheck.filter(v => !!v) + + expect(sanitizeCheck.length).toBe(3) + expect(() => JSON.parse(sanitizeCheck[0])).not.toThrow() + expect(() => JSON.parse(sanitizeCheck[1])).not.toThrow() + expect(() => JSON.parse(sanitizeCheck[2])).not.toThrow() + }) + + test('/about', async () => { + const { hook } = await page.vueMeta.navigate('/about', false) + await hook + expect(await page.$text('title')).toBe('About') + expect(await page.$$eval('meta', metas => metas.length)).toBe(1) + }) +}) diff --git a/test/escaping.test.js b/test/escaping.test.js deleted file mode 100644 index 347813e..0000000 --- a/test/escaping.test.js +++ /dev/null @@ -1,37 +0,0 @@ -import _getMetaInfo from '../src/shared/getMetaInfo' -import { defaultOptions, loadVueMetaPlugin } from './utils' - -const getMetaInfo = (component, escapeSequences) => _getMetaInfo(defaultOptions, component, escapeSequences) - -describe('escaping', () => { - let Vue - - beforeAll(() => (Vue = loadVueMetaPlugin())) - - test('special chars are escaped unless disabled', () => { - const component = new Vue({ - metaInfo: { - title: 'Hello & Goodbye', - script: [{ innerHTML: 'Hello & Goodbye' }], - __dangerouslyDisableSanitizers: ['script'] - } - }) - - expect(getMetaInfo(component, [[/&/g, '&']])).toEqual({ - title: 'Hello & Goodbye', - titleChunk: 'Hello & Goodbye', - titleTemplate: '%s', - htmlAttrs: {}, - headAttrs: {}, - bodyAttrs: {}, - meta: [], - base: [], - link: [], - style: [], - script: [{ innerHTML: 'Hello & Goodbye' }], - noscript: [], - __dangerouslyDisableSanitizers: ['script'], - __dangerouslyDisableSanitizersByTagID: {} - }) - }) -}) diff --git a/test/fixtures/app.template.html b/test/fixtures/app.template.html new file mode 100644 index 0000000..531cf99 --- /dev/null +++ b/test/fixtures/app.template.html @@ -0,0 +1,17 @@ + + + + {{ meta.text() }} + {{ title.text() }} + {{ link.text() }} + {{ style.text() }} + {{ webpackAssets }} + {{ script.text() }} + {{ noscript.text() }} + + + {{ app }} + {{ script.text({ body: true }) }} + {{ noscript.text({ body: true }) }} + + diff --git a/test/fixtures/app.vue b/test/fixtures/app.vue deleted file mode 100644 index 5e7cd91..0000000 --- a/test/fixtures/app.vue +++ /dev/null @@ -1,33 +0,0 @@ - - - - diff --git a/test/fixtures/basic/App.vue b/test/fixtures/basic/App.vue new file mode 100644 index 0000000..6a25e78 --- /dev/null +++ b/test/fixtures/basic/App.vue @@ -0,0 +1,21 @@ + + + diff --git a/test/fixtures/basic/client.js b/test/fixtures/basic/client.js new file mode 100644 index 0000000..96a4f08 --- /dev/null +++ b/test/fixtures/basic/client.js @@ -0,0 +1,10 @@ +import Vue from 'vue' +import VueMeta from '../../../src/browser' +import App from './App.vue' +import createRouter from './router' + +Vue.use(VueMeta) + +App.router = createRouter() + +new Vue(App).$mount('#app') diff --git a/test/fixtures/basic/router.js b/test/fixtures/basic/router.js new file mode 100644 index 0000000..0dcc535 --- /dev/null +++ b/test/fixtures/basic/router.js @@ -0,0 +1,18 @@ +import Vue from 'vue' +import Router from 'vue-router' + +Vue.use(Router) + +const Home = () => import('./views/home.vue') +const Post = () => import('./views/about.vue') + +export default function createRouter() { + return new Router({ + mode: 'hash', + base: '/', + routes: [ + { path: '/', component: Home }, + { path: '/about', component: Post } + ] + }) +} diff --git a/test/fixtures/basic/server.js b/test/fixtures/basic/server.js new file mode 100644 index 0000000..4ddc030 --- /dev/null +++ b/test/fixtures/basic/server.js @@ -0,0 +1,10 @@ +import Vue from 'vue' +import VueMeta from '../../../src' +import App from './App.vue' +import createRouter from './router' + +Vue.use(VueMeta) + +App.router = createRouter() + +export default new Vue(App) diff --git a/test/fixtures/basic/views/about.vue b/test/fixtures/basic/views/about.vue new file mode 100644 index 0000000..e6388ae --- /dev/null +++ b/test/fixtures/basic/views/about.vue @@ -0,0 +1,16 @@ + + + diff --git a/test/fixtures/basic/views/home.vue b/test/fixtures/basic/views/home.vue new file mode 100644 index 0000000..d0ea32c --- /dev/null +++ b/test/fixtures/basic/views/home.vue @@ -0,0 +1,37 @@ + + + diff --git a/test/getComponentOptions.test.js b/test/getComponentOptions.test.js deleted file mode 100644 index ba04fb2..0000000 --- a/test/getComponentOptions.test.js +++ /dev/null @@ -1,76 +0,0 @@ -import getComponentOption from '../src/shared/getComponentOption' -import { getVue } from './utils' - -describe('getComponentOption', () => { - let Vue - - beforeAll(() => (Vue = getVue())) - - it('returns an empty object when no matching options are found', () => { - const component = new Vue() - const mergedOption = getComponentOption({ component, keyName: 'noop' }) - expect(mergedOption).toEqual({}) - }) - - it('fetches the given option from the given component', () => { - const component = new Vue({ someOption: 'foo' }) - const mergedOption = getComponentOption({ component, keyName: 'someOption' }) - expect(mergedOption).toEqual('foo') - }) - - it('calls a function option, injecting the component as context', () => { - const component = new Vue({ - name: 'Foobar', - someFunc() { - return this.$options.name - } - }) - const mergedOption = getComponentOption({ component, keyName: 'someFunc' }) - // TODO: Should this be foobar or Foobar - expect(mergedOption).toEqual('Foobar') - }) - - it('fetches deeply nested component options and merges them', () => { - Vue.component('merge-child', { render: h => h('div'), foo: { bar: 'baz' } }) - - const component = new Vue({ - foo: { fizz: 'buzz' }, - el: document.createElement('div'), - render: h => h('div', null, [h('merge-child')]) - }) - - const mergedOption = getComponentOption({ component, keyName: 'foo', deep: true }) - expect(mergedOption).toEqual({ bar: 'baz', fizz: 'buzz' }) - }) - - it('allows for a custom array merge strategy', () => { - Vue.component('array-child', { - render: h => h('div'), - foo: [ - { name: 'flower', content: 'rose' } - ] - }) - - const component = new Vue({ - foo: [ - { name: 'flower', content: 'tulip' } - ], - el: document.createElement('div'), - render: h => h('div', null, [h('array-child')]) - }) - - const mergedOption = getComponentOption({ - component, - keyName: 'foo', - deep: true, - arrayMerge(target, source) { - return target.concat(source) - } - }) - - expect(mergedOption).toEqual([ - { name: 'flower', content: 'tulip' }, - { name: 'flower', content: 'rose' } - ]) - }) -}) diff --git a/test/unit/components.test.js b/test/unit/components.test.js new file mode 100644 index 0000000..f909afe --- /dev/null +++ b/test/unit/components.test.js @@ -0,0 +1,196 @@ +import _getMetaInfo from '../../src/shared/getMetaInfo' +import { mount, loadVueMetaPlugin, vmTick } from '../utils' +import { defaultOptions } from '../../src/shared/constants' + +import GoodbyeWorld from '../components/goodbye-world.vue' +import HelloWorld from '../components/hello-world.vue' +import KeepAlive from '../components/keep-alive.vue' +import Changed from '../components/changed.vue' + +const getMetaInfo = component => _getMetaInfo(defaultOptions, component) + +jest.mock('../../src/utils/window', () => ({ + hasGlobalWindow: false +})) + +describe('client', () => { + let Vue + let html + + beforeAll(() => { + Vue = loadVueMetaPlugin() + + // force using timers, jest cant mock rAF + delete window.requestAnimationFrame + delete window.cancelAnimationFrame + + html = document.createElement('html') + document._getElementsByTagName = document.getElementsByTagName + jest.spyOn(document, 'getElementsByTagName').mockImplementation((tag) => { + if (tag === 'html') { + return [html] + } + + return document._getElementsByTagName(tag) + }) + }) + + test('meta-info refreshed on component\'s data change', () => { + const wrapper = mount(HelloWorld, { localVue: Vue }) + + let metaInfo = getMetaInfo(wrapper.vm) + expect(metaInfo.title).toEqual('Hello World') + wrapper.setData({ title: 'Goodbye World' }) + + metaInfo = getMetaInfo(wrapper.vm) + expect(metaInfo.title).toEqual('Goodbye World') + }) + + test('child meta-info removed when child is toggled', () => { + const wrapper = mount(GoodbyeWorld, { localVue: Vue }) + + let metaInfo = getMetaInfo(wrapper.vm) + expect(metaInfo.title).toEqual('Hello World') + + wrapper.setData({ childVisible: false }) + + metaInfo = getMetaInfo(wrapper.vm) + expect(metaInfo.title).toEqual('Goodbye World') + + wrapper.setData({ childVisible: true }) + + metaInfo = getMetaInfo(wrapper.vm) + expect(metaInfo.title).toEqual('Hello World') + }) + + test('child meta-info removed when keep-alive child is toggled', () => { + const wrapper = mount(KeepAlive, { localVue: Vue }) + + let metaInfo = getMetaInfo(wrapper.vm) + expect(metaInfo.title).toEqual('Hello World') + + wrapper.setData({ childVisible: false }) + + metaInfo = getMetaInfo(wrapper.vm) + expect(metaInfo.title).toEqual('Alive World') + + wrapper.setData({ childVisible: true }) + + metaInfo = getMetaInfo(wrapper.vm) + expect(metaInfo.title).toEqual('Hello World') + }) + + test('meta-info is removed when destroyed', () => { + const parentComponent = new Vue({ render: h => h('div') }) + const wrapper = mount(HelloWorld, { localVue: Vue, parentComponent }) + + let metaInfo = getMetaInfo(wrapper.vm.$parent) + expect(metaInfo.title).toEqual('Hello World') + wrapper.destroy() + + jest.runAllTimers() + metaInfo = getMetaInfo(wrapper.vm.$parent) + expect(metaInfo.title).toEqual('') + }) + + test('meta-info can be rendered with inject', () => { + const wrapper = mount(HelloWorld, { localVue: Vue }) + + const metaInfo = wrapper.vm.$meta().inject() + expect(metaInfo.title.text()).toEqual('Hello World') + }) + + test('doesnt update when ssr attribute is set', () => { + html.setAttribute(defaultOptions.ssrAttribute, 'true') + const wrapper = mount(HelloWorld, { localVue: Vue }) + + const { tags } = wrapper.vm.$meta().refresh() + expect(tags).toBe(false) + }) + + test('changed function is called', async () => { + let context + const changed = jest.fn(function () { + context = this + }) + + const wrapper = mount(Changed, { localVue: Vue, propsData: { changed } }) + + await vmTick(wrapper.vm) + expect(wrapper.vm.$root._vueMeta.initialized).toBe(true) + // TODO: does changed need to run on initialization? + expect(changed).toHaveBeenCalledTimes(1) + + wrapper.setData({ childVisible: true }) + jest.runAllTimers() + + expect(changed).toHaveBeenCalledTimes(2) + expect(context._uid).toBe(wrapper.vm._uid) + }) + + test('afterNavigation function is called with refreshOnce: true', () => { + const Vue = loadVueMetaPlugin(false, { refreshOnceOnNavigation: true }) + const afterNavigation = jest.fn() + const component = Vue.component('nav-component', { + render: h => h('div'), + metaInfo: { afterNavigation } + }) + + const guards = {} + const wrapper = mount(component, { + localVue: Vue, + mocks: { + $router: { + beforeEach(fn) { + guards.before = fn + }, + afterEach(fn) { + guards.after = fn + } + } + } + }) + + expect(guards.before).toBeDefined() + expect(guards.after).toBeDefined() + + guards.before(null, null, () => {}) + expect(wrapper.vm.$root._vueMeta.paused).toBe(true) + + guards.after() + expect(afterNavigation).toHaveBeenCalled() + }) + + test('afterNavigation function is called with refreshOnce: false', () => { + const Vue = loadVueMetaPlugin(false, { refreshOnceOnNavigation: false }) + const afterNavigation = jest.fn() + const component = Vue.component('nav-component', { + render: h => h('div'), + metaInfo: { afterNavigation } + }) + + const guards = {} + const wrapper = mount(component, { + localVue: Vue, + mocks: { + $router: { + beforeEach(fn) { + guards.before = fn + }, + afterEach(fn) { + guards.after = fn + } + } + } + }) + + expect(guards.before).toBeDefined() + expect(guards.after).toBeDefined() + + guards.before(null, null, () => {}) + expect(wrapper.vm.$root._vueMeta.paused).toBe(true) + + guards.after() + expect(afterNavigation).toHaveBeenCalled() + }) +}) diff --git a/test/unit/escaping.test.js b/test/unit/escaping.test.js new file mode 100644 index 0000000..f9c26f0 --- /dev/null +++ b/test/unit/escaping.test.js @@ -0,0 +1,74 @@ +import _getMetaInfo from '../../src/shared/getMetaInfo' +import { loadVueMetaPlugin } from '../utils' +import { defaultOptions } from '../../src/shared/constants' + +const getMetaInfo = (component, escapeSequences) => _getMetaInfo(defaultOptions, component, escapeSequences) + +describe('escaping', () => { + let Vue + + beforeAll(() => (Vue = loadVueMetaPlugin())) + + test('special chars are escaped unless disabled', () => { + const component = new Vue({ + metaInfo: { + htmlAttrs: { key: 1 }, + title: 'Hello & Goodbye', + script: [{ innerHTML: 'Hello & Goodbye' }], + __dangerouslyDisableSanitizers: ['script'] + } + }) + + expect(getMetaInfo(component, [[/&/g, '&']])).toEqual({ + title: 'Hello & Goodbye', + titleChunk: 'Hello & Goodbye', + titleTemplate: '%s', + htmlAttrs: { + key: 1 + }, + headAttrs: {}, + bodyAttrs: {}, + meta: [], + base: [], + link: [], + style: [], + script: [{ innerHTML: 'Hello & Goodbye' }], + noscript: [], + __dangerouslyDisableSanitizers: ['script'], + __dangerouslyDisableSanitizersByTagID: {} + }) + }) + + test('special chars are escaped unless disabled by vmid', () => { + const component = new Vue({ + metaInfo: { + title: 'Hello', + script: [ + { vmid: 'yescape', innerHTML: 'Hello & Goodbye' }, + { vmid: 'noscape', innerHTML: 'Hello & Goodbye' } + ], + __dangerouslyDisableSanitizersByTagID: { noscape: ['innerHTML'] } + } + }) + + expect(getMetaInfo(component, [[/&/g, '&']])).toEqual({ + title: 'Hello', + titleChunk: 'Hello', + titleTemplate: '%s', + htmlAttrs: {}, + headAttrs: {}, + bodyAttrs: {}, + meta: [], + base: [], + link: [], + style: [], + script: [ + { innerHTML: 'Hello & Goodbye', vmid: 'yescape' }, + { innerHTML: 'Hello & Goodbye', vmid: 'noscape' } + ], + noscript: [], + __dangerouslyDisableSanitizers: [], + __dangerouslyDisableSanitizersByTagID: { noscape: ['innerHTML'] } + }) + }) +}) diff --git a/test/generators.test.js b/test/unit/generators.test.js similarity index 88% rename from test/generators.test.js rename to test/unit/generators.test.js index 3bdcd57..5692242 100644 --- a/test/generators.test.js +++ b/test/unit/generators.test.js @@ -1,6 +1,6 @@ -import _generateServerInjector from '../src/server/generateServerInjector' -import { defaultOptions } from './utils' -import metaInfoData from './utils/meta-info-data' +import _generateServerInjector from '../../src/server/generateServerInjector' +import { defaultOptions } from '../../src/shared/constants' +import metaInfoData from '../utils/meta-info-data' const generateServerInjector = (type, data) => _generateServerInjector(defaultOptions, type, data) diff --git a/test/unit/getComponentOptions.test.js b/test/unit/getComponentOptions.test.js new file mode 100644 index 0000000..5d482b7 --- /dev/null +++ b/test/unit/getComponentOptions.test.js @@ -0,0 +1,127 @@ +import getComponentOption from '../../src/shared/getComponentOption' +import { inMetaInfoBranch } from '../../src/shared/meta-helpers' +import { mount, getVue, loadVueMetaPlugin } from '../utils' + +describe('getComponentOption', () => { + let Vue + + beforeAll(() => (Vue = getVue())) + + test('returns an empty object when no matching options are found', () => { + const component = new Vue() + const mergedOption = getComponentOption({ keyName: 'noop' }, component) + expect(mergedOption).toEqual({}) + }) + + test('fetches the given option from the given component', () => { + const component = new Vue({ someOption: { foo: 'bar' } }) + const mergedOption = getComponentOption({ keyName: 'someOption' }, component) + expect(mergedOption.foo).toBeDefined() + expect(mergedOption.foo).toEqual('bar') + }) + + test('calls a function option, injecting the component as context', () => { + const component = new Vue({ + name: 'Foobar', + someFunc() { + return { opt: this.$options.name } + } + }) + const mergedOption = getComponentOption({ keyName: 'someFunc' }, component) + // TODO: Should this be foobar or Foobar + expect(mergedOption.opt).toBeDefined() + expect(mergedOption.opt).toEqual('Foobar') + }) + + test('fetches deeply nested component options and merges them', () => { + const localVue = loadVueMetaPlugin(true, { keyName: 'foo' }) + localVue.component('merge-child', { render: h => h('div'), foo: { bar: 'baz' } }) + + const component = localVue.component('parent', { + foo: { fizz: 'buzz' }, + render: h => h('div', null, [h('merge-child')]) + }) + + const wrapper = mount(component, { localVue }) + + const mergedOption = getComponentOption({ keyName: 'foo' }, wrapper.vm) + expect(mergedOption).toEqual({ bar: 'baz', fizz: 'buzz' }) + }) + + /* this undocumented functionality has been removed + test('allows for a custom array merge strategy', () => { + const localVue = loadVueMetaPlugin(false, { keyName: 'foo' }) + localVue.component('array-child', { + render: h => h('div'), + foo: { + meta: [ + { name: 'flower', content: 'rose' } + ] + } + }) + + const component = localVue.component('parent', { + foo: { + meta: [ + { name: 'flower', content: 'tulip' } + ] + }, + render: h => h('div', null, [h('array-child')]) + }) + + const wrapper = mount(component, { localVue }) + + const mergedOption = getComponentOption({ + component: wrapper.vm, + keyName: 'foo', + arrayMerge(target, source) { + return target.concat(source) + } + }) + + expect(mergedOption).toEqual({ meta: [ + { name: 'flower', content: 'tulip' }, + { name: 'flower', content: 'rose' } + ] }) + }) */ + + test('only traverses branches with metaInfo components', () => { + const localVue = loadVueMetaPlugin(false, { keyName: 'foo' }) + + localVue.component('meta-child', { + foo: { bar: 'baz' }, + render(h) { + return h('div', this.$slots.default) + } + }) + + localVue.component('nometa-child', { + render(h) { + return h('div', this.$slots.default) + } + }) + + const component = localVue.component('parent', { + render: h => h('div', null, [ + h('meta-child', null, [ h('nometa-child') ]), + h('nometa-child', null, [ h('meta-child') ]), + h('nometa-child') + ]) + }) + + const wrapper = mount(component, { localVue }) + + const mergedOption = getComponentOption({ keyName: 'foo' }, wrapper.vm) + + expect(mergedOption).toEqual({ bar: 'baz' }) + expect(wrapper.vm.$children[0]._vueMeta).toBe(true) + expect(wrapper.vm.$children[1]._vueMeta).toBe(false) + expect(wrapper.vm.$children[2]._vueMeta).toBeUndefined() + + expect(inMetaInfoBranch(wrapper.vm.$children[0])).toBe(true) + expect(inMetaInfoBranch(wrapper.vm.$children[0].$children[0])).toBe(false) + expect(inMetaInfoBranch(wrapper.vm.$children[1])).toBe(true) + expect(inMetaInfoBranch(wrapper.vm.$children[1].$children[0])).toBe(true) + expect(inMetaInfoBranch(wrapper.vm.$children[2])).toBe(false) + }) +}) diff --git a/test/getMetaInfo.test.js b/test/unit/getMetaInfo.test.js similarity index 71% rename from test/getMetaInfo.test.js rename to test/unit/getMetaInfo.test.js index 416c180..0ae0e2c 100644 --- a/test/getMetaInfo.test.js +++ b/test/unit/getMetaInfo.test.js @@ -1,5 +1,6 @@ -import _getMetaInfo from '../src/shared/getMetaInfo' -import { defaultOptions, loadVueMetaPlugin } from './utils' +import _getMetaInfo from '../../src/shared/getMetaInfo' +import { loadVueMetaPlugin } from '../utils' +import { defaultOptions } from '../../src/shared/constants' const getMetaInfo = component => _getMetaInfo(defaultOptions, component) @@ -117,7 +118,7 @@ describe('getMetaInfo', () => { { vmid: 'a', property: 'a', - content: 'b' + content: 'a' } ], base: [], @@ -482,8 +483,6 @@ describe('getMetaInfo', () => { }) }) - // TODO: Still failing :( Child template won't be applied if child has no content as well - test('properly uses meta templates with one-level-deep nested children template', () => { Vue.component('merge-child', { render: h => h('div'), @@ -592,4 +591,233 @@ describe('getMetaInfo', () => { __dangerouslyDisableSanitizersByTagID: {} }) }) + + test('properly uses meta templates with one-level-deep nested children when parent has no template', () => { + Vue.component('merge-child', { + render: h => h('div'), + metaInfo: { + title: 'Hello', + meta: [ + { + vmid: 'og:title', + property: 'og:title', + content: 'An important title!', + template: chunk => `${chunk} - My page` + } + ] + } + }) + + const component = new Vue({ + metaInfo: { + meta: [ + { + vmid: 'og:title', + property: 'og:title', + content: 'Test title' + } + ] + }, + el: document.createElement('div'), + render: h => h('div', null, [h('merge-child')]) + }) + + expect(getMetaInfo(component)).toEqual({ + title: 'Hello', + titleChunk: 'Hello', + titleTemplate: '%s', + htmlAttrs: {}, + headAttrs: {}, + bodyAttrs: {}, + meta: [ + { + vmid: 'og:title', + property: 'og:title', + content: 'An important title! - My page' + } + ], + base: [], + link: [], + style: [], + script: [], + noscript: [], + __dangerouslyDisableSanitizers: [], + __dangerouslyDisableSanitizersByTagID: {} + }) + }) + + test('no errors when metaInfo returns nothing', () => { + const component = new Vue({ + metaInfo() {}, + el: document.createElement('div'), + render: h => h('div', null, []) + }) + + expect(getMetaInfo(component)).toEqual({ + title: '', + titleChunk: '', + titleTemplate: '%s', + htmlAttrs: {}, + headAttrs: {}, + bodyAttrs: {}, + meta: [], + base: [], + link: [], + style: [], + script: [], + noscript: [], + __dangerouslyDisableSanitizers: [], + __dangerouslyDisableSanitizersByTagID: {} + }) + }) + + test('child can indicate its content should be ignored', () => { + Vue.component('merge-child', { + render: h => h('div'), + metaInfo: { + title: undefined, + bodyAttrs: { + class: undefined + }, + meta: [ + { + vmid: 'og:title', + content: undefined + } + ] + } + }) + + const component = new Vue({ + metaInfo: { + title: 'Hello', + bodyAttrs: { + class: 'class' + }, + meta: [ + { + vmid: 'og:title', + property: 'og:title', + content: 'Test title', + template: chunk => `${chunk} - My page` + } + ] + }, + el: document.createElement('div'), + render: h => h('div', null, [h('merge-child')]) + }) + + expect(getMetaInfo(component)).toEqual({ + title: 'Hello', + titleChunk: 'Hello', + titleTemplate: '%s', + bodyAttrs: { + class: 'class' + }, + headAttrs: {}, + htmlAttrs: {}, + meta: [ + { + vmid: 'og:title', + property: 'og:title', + content: 'Test title - My page' + } + ], + base: [], + link: [], + style: [], + script: [], + noscript: [], + __dangerouslyDisableSanitizers: [], + __dangerouslyDisableSanitizersByTagID: {} + }) + }) + + test('child can indicate to remove parent vmids', () => { + Vue.component('merge-child', { + render: h => h('div'), + metaInfo: { + title: 'Hi', + meta: [ + { + vmid: 'og:title', + content: null + } + ] + } + }) + + const component = new Vue({ + metaInfo: { + title: 'Hello', + meta: [ + { + vmid: 'og:title', + property: 'og:title', + content: 'Test title', + template: chunk => `${chunk} - My page` + } + ] + }, + el: document.createElement('div'), + render: h => h('div', null, [h('merge-child')]) + }) + + expect(getMetaInfo(component)).toEqual({ + title: 'Hi', + titleChunk: 'Hi', + titleTemplate: '%s', + htmlAttrs: {}, + headAttrs: {}, + bodyAttrs: {}, + meta: [], + base: [], + link: [], + style: [], + script: [], + noscript: [], + __dangerouslyDisableSanitizers: [], + __dangerouslyDisableSanitizersByTagID: {} + }) + }) + + test('attribute values can be an array', () => { + Vue.component('merge-child', { + render: h => h('div'), + metaInfo: { + bodyAttrs: { + class: ['foo'] + } + } + }) + + const component = new Vue({ + metaInfo: { + bodyAttrs: { + class: ['bar'] + } + }, + el: document.createElement('div'), + render: h => h('div', null, [h('merge-child')]) + }) + + expect(getMetaInfo(component)).toEqual({ + title: '', + titleChunk: '', + titleTemplate: '%s', + htmlAttrs: {}, + headAttrs: {}, + bodyAttrs: { + class: ['bar', 'foo'] + }, + meta: [], + base: [], + link: [], + style: [], + script: [], + noscript: [], + __dangerouslyDisableSanitizers: [], + __dangerouslyDisableSanitizersByTagID: {} + }) + }) }) diff --git a/test/plugin-browser.test.js b/test/unit/plugin-browser.test.js similarity index 78% rename from test/plugin-browser.test.js rename to test/unit/plugin-browser.test.js index 6f5b30e..606a2b1 100644 --- a/test/plugin-browser.test.js +++ b/test/unit/plugin-browser.test.js @@ -1,10 +1,11 @@ -import triggerUpdate from '../src/client/triggerUpdate' -import batchUpdate from '../src/client/batchUpdate' -import { mount, defaultOptions, vmTick, VueMetaBrowserPlugin, loadVueMetaPlugin } from './utils' +import triggerUpdate from '../../src/client/triggerUpdate' +import batchUpdate from '../../src/client/batchUpdate' +import { mount, vmTick, VueMetaBrowserPlugin, loadVueMetaPlugin } from '../utils' +import { defaultOptions } from '../../src/shared/constants' -jest.mock('../src/client/triggerUpdate') -jest.mock('../src/client/batchUpdate') -jest.mock('../package.json', () => ({ +jest.mock('../../src/client/triggerUpdate') +jest.mock('../../src/client/batchUpdate') +jest.mock('../../package.json', () => ({ version: 'test-version' })) @@ -20,9 +21,14 @@ describe('plugin', () => { expect(instance.$meta().inject).toEqual(expect.any(Function)) expect(instance.$meta().refresh).toEqual(expect.any(Function)) + expect(instance.$meta().getOptions).toEqual(expect.any(Function)) expect(instance.$meta().inject()).toBeUndefined() expect(instance.$meta().refresh()).toBeDefined() + + const options = instance.$meta().getOptions() + expect(options).toBeDefined() + expect(options.keyName).toBe(defaultOptions.keyName) }) test('component has _hasMetaInfo set to true', () => { @@ -42,8 +48,8 @@ describe('plugin', () => { }) test('updates can be paused and resumed', async () => { - const _triggerUpdate = jest.requireActual('../src/client/triggerUpdate').default - const _batchUpdate = jest.requireActual('../src/client/batchUpdate').default + const _triggerUpdate = jest.requireActual('../../src/client/triggerUpdate').default + const _batchUpdate = jest.requireActual('../../src/client/batchUpdate').default const triggerUpdateSpy = triggerUpdate.mockImplementation(_triggerUpdate) const batchUpdateSpy = batchUpdate.mockImplementation(_batchUpdate) diff --git a/test/plugin-server.test.js b/test/unit/plugin-server.test.js similarity index 74% rename from test/plugin-server.test.js rename to test/unit/plugin-server.test.js index b989d7d..d0f35db 100644 --- a/test/plugin-server.test.js +++ b/test/unit/plugin-server.test.js @@ -1,6 +1,7 @@ -import { mount, defaultOptions, VueMetaServerPlugin, loadVueMetaPlugin } from './utils' +import { mount, VueMetaServerPlugin, loadVueMetaPlugin } from '../utils' +import { defaultOptions } from '../../src/shared/constants' -jest.mock('../package.json', () => ({ +jest.mock('../../package.json', () => ({ version: 'test-version' })) @@ -13,6 +14,17 @@ describe('plugin', () => { test('is loaded', () => { const instance = new Vue() expect(instance.$meta).toEqual(expect.any(Function)) + + expect(instance.$meta().inject).toEqual(expect.any(Function)) + expect(instance.$meta().refresh).toEqual(expect.any(Function)) + expect(instance.$meta().getOptions).toEqual(expect.any(Function)) + + expect(instance.$meta().inject()).toBeDefined() + expect(instance.$meta().refresh()).toBeDefined() + + const options = instance.$meta().getOptions() + expect(options).toBeDefined() + expect(options.keyName).toBe(defaultOptions.keyName) }) test('component has _hasMetaInfo set to true', () => { diff --git a/test/unit/shared.test.js b/test/unit/shared.test.js new file mode 100644 index 0000000..118a11a --- /dev/null +++ b/test/unit/shared.test.js @@ -0,0 +1,14 @@ +import { setOptions } from '../../src/shared/options' +import { defaultOptions } from '../../src/shared/constants' + +describe('shared', () => { + test('can use setOptions', () => { + const keyName = 'MY KEY' + let options = { keyName } + options = setOptions(options) + + expect(options.keyName).toBe(keyName) + expect(options.contentKeyName).toBeDefined() + expect(options.contentKeyName).toBe(defaultOptions.contentKeyName) + }) +}) diff --git a/test/updaters.test.js b/test/unit/updaters.test.js similarity index 93% rename from test/updaters.test.js rename to test/unit/updaters.test.js index bbee40a..e24d136 100644 --- a/test/updaters.test.js +++ b/test/unit/updaters.test.js @@ -1,6 +1,6 @@ -import _updateClientMetaInfo from '../src/client/updateClientMetaInfo' -import { defaultOptions } from './utils' -import metaInfoData from './utils/meta-info-data' +import _updateClientMetaInfo from '../../src/client/updateClientMetaInfo' +import { defaultOptions } from '../../src/shared/constants' +import metaInfoData from '../utils/meta-info-data' const updateClientMetaInfo = (type, data) => _updateClientMetaInfo(defaultOptions, { [type]: data }) diff --git a/test/unit/utils.test.js b/test/unit/utils.test.js new file mode 100644 index 0000000..8f897e3 --- /dev/null +++ b/test/unit/utils.test.js @@ -0,0 +1,63 @@ +/** + * @jest-environment node + */ +import { findIndex, includes, toArray } from '../../src/utils/array' +import { ensureIsArray } from '../../src/utils/ensure' +import { hasGlobalWindowFn } from '../../src/utils/window' + +describe('shared', () => { + afterEach(() => jest.restoreAllMocks()) + + test('ensureIsArray ensures var is array', () => { + let a = { p: 1 } + expect(ensureIsArray(a)).toEqual([]) + + a = 1 + expect(ensureIsArray(a)).toEqual([]) + + a = [1] + expect(ensureIsArray(a)).toBe(a) + }) + + test('ensureIsArray ensures obj prop is array', () => { + const a = { p: 1 } + expect(ensureIsArray(a, 'p')).toEqual({ p: [] }) + }) + + test('no error when window is not defined', () => { + expect(hasGlobalWindowFn()).toBe(false) + }) + + /* eslint-disable no-extend-native */ + test('findIndex polyfill', () => { + const _findIndex = Array.prototype.findIndex + Array.prototype.findIndex = false + + const arr = [1, 2, 3] + expect(findIndex(arr, v => v === 2)).toBe(1) + expect(findIndex(arr, v => v === 4)).toBe(-1) + + Array.prototype.findIndex = _findIndex + }) + + test('includes polyfill', () => { + const _includes = Array.prototype.includes + Array.prototype.includes = false + + const arr = [1, 2, 3] + expect(includes(arr, 2)).toBe(true) + expect(includes(arr, 4)).toBe(false) + + Array.prototype.includes = _includes + }) + + test('from/toArray polyfill', () => { + const _from = Array.from + Array.from = false + + expect(toArray('foo')).toEqual(['f', 'o', 'o']) + + Array.from = _from + }) + /* eslint-enable no-extend-native */ +}) diff --git a/test/utils/browser.js b/test/utils/browser.js new file mode 100644 index 0000000..def5b19 --- /dev/null +++ b/test/utils/browser.js @@ -0,0 +1,99 @@ +import puppeteer from 'puppeteer-core' + +import ChromeDetector from './chrome' + +export default class Browser { + constructor() { + this.detector = new ChromeDetector() + } + + async start(options = {}) { + // https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions + const _opts = { + args: [ + '--no-sandbox', + '--disable-setuid-sandbox' + ], + executablePath: process.env.PUPPETEER_EXECUTABLE_PATH, + ...options + } + + if (!_opts.executablePath) { + _opts.executablePath = this.detector.detect() + } + + this.browser = await puppeteer.launch(_opts) + } + + async close() { + if (!this.browser) return + await this.browser.close() + } + + async page(url, globalName = 'vueMeta') { + if (!this.browser) throw new Error('Please call start() before page(url)') + const page = await this.browser.newPage() + + // pass on console messages + const typeMap = { + debug: 'debug', + warning: 'warn', + error: 'error' + } + page.on('console', (msg) => { + if (typeMap[msg.type()]) { + console[typeMap[msg.type()]](msg.text()) // eslint-disable-line no-console + } + }) + + await page.goto(url) + page.$globalHandle = `window.$${globalName}` + await page.waitForFunction(`!!${page.$globalHandle}`) + page.html = () => page.evaluate(() => window.document.documentElement.outerHTML) + page.$text = (selector, trim) => page.$eval(selector, (el, trim) => { + return trim ? el.textContent.replace(/^\s+|\s+$/g, '') : el.textContent + }, trim) + page.$$text = (selector, trim) => + page.$$eval(selector, (els, trim) => els.map((el) => { + return trim ? el.textContent.replace(/^\s+|\s+$/g, '') : el.textContent + }), trim) + page.$attr = (selector, attr) => + page.$eval(selector, (el, attr) => el.getAttribute(attr), attr) + page.$$attr = (selector, attr) => + page.$$eval( + selector, + (els, attr) => els.map(el => el.getAttribute(attr)), + attr + ) + + page.$vueMeta = await page.evaluateHandle(page.$globalHandle) + + page.vueMeta = { + async navigate(path, waitEnd = true) { + const hook = page.evaluate(` + new Promise(resolve => + ${page.$globalHandle}.$once('routeChanged', resolve) + ).then(() => new Promise(resolve => setTimeout(resolve, 50))) + `) + await page.evaluate( + ($vueMeta, path) => $vueMeta.$router.push(path), + page.$vueMeta, + path + ) + if (waitEnd) { + await hook + } + return { hook } + }, + routeData() { + return page.evaluate(($vueMeta) => { + return { + path: $vueMeta.$route.path, + query: $vueMeta.$route.query + } + }, page.$vueMeta) + } + } + return page + } +} diff --git a/test/utils/build.js b/test/utils/build.js new file mode 100644 index 0000000..8c9c51d --- /dev/null +++ b/test/utils/build.js @@ -0,0 +1,114 @@ +import path from 'path' +import fs from 'fs-extra' +import { template } from 'lodash' +import webpack from 'webpack' +import VueLoaderPlugin from 'vue-loader/lib/plugin' +import { createRenderer } from 'vue-server-renderer' + +const renderer = createRenderer() + +export function webpackRun(config) { + const compiler = webpack(config) + + return new Promise((resolve, reject) => { + compiler.run((err, stats) => { + if (err) { + reject(err) + } + + resolve(stats.toJson()) + }) + }) +} + +export async function buildFixture(fixture, config = {}) { + if (!fixture) { + throw new Error('buildFixture should be called with a fixture name') + } + + const fixturePath = path.resolve(__dirname, '..', 'fixtures', fixture) + config.entry = path.resolve(fixturePath, 'client.js') + + if (!config.name) { + config.name = path.basename(path.dirname(config.entry)) + } + + const webpackConfig = createWebpackConfig(config) + // remove old files + await fs.remove(webpackConfig.output.path) + + // run webpack + const webpackStats = await webpackRun(webpackConfig) + + // for test debugging + webpackStats.errors.forEach(e => console.error(e)) // eslint-disable-line no-console + webpackStats.warnings.forEach(e => console.warn(e)) // eslint-disable-line no-console + + const vueApp = await import(path.resolve(fixturePath, 'server')).then(m => m.default || m) + + const templateFile = await fs.readFile(path.resolve(fixturePath, '..', 'app.template.html'), { encoding: 'utf8' }) + const compiled = template(templateFile, { interpolate: /{{([\s\S]+?)}}/g }) + + const webpackAssets = webpackStats.assets.reduce((s, asset) => `${s}\n`, '') + const app = await renderer.renderToString(vueApp) + // !!! run inject after renderToString !!! + const metaInfo = vueApp.$meta().inject() + + const appFile = path.resolve(webpackStats.outputPath, 'index.html') + const html = compiled({ app, webpackAssets, ...metaInfo }) + + await fs.writeFile(appFile, html) + + return { + url: `file://${appFile}`, + appFile, + webpackStats, + html, + metaInfo + } +} + +export function createWebpackConfig(config = {}) { + const publicPath = '.vue-meta' + + return { + mode: 'development', + output: { + path: path.join(path.dirname(config.entry), publicPath), + filename: '[name].js', + chunkFilename: '[id].chunk.js', + publicPath: `/${publicPath}/` + }, + module: { + rules: [ + { test: /\.js$/, exclude: /node_modules/, use: 'babel-loader' }, + { test: /\.vue$/, use: 'vue-loader' } + ] + }, + // Expose __dirname to allow automatically setting basename. + context: __dirname, + node: { + __dirname: true + }, + optimization: { + splitChunks: { + cacheGroups: { + vendor: { + test: /[\\/]node_modules[\\/]/, + name: 'vendor', + chunks: 'all' + } + } + } + }, + plugins: [ + new VueLoaderPlugin() + ], + resolve: { + alias: { + 'vue': 'vue/dist/vue.esm.js' + } + }, + ...config + } +} diff --git a/test/utils/chrome.js b/test/utils/chrome.js new file mode 100644 index 0000000..e6c54f4 --- /dev/null +++ b/test/utils/chrome.js @@ -0,0 +1,264 @@ +/** + * @license Copyright 2016 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + */ +import fs from 'fs' +import path from 'path' +import { execSync, execFileSync } from 'child_process' +import isWsl from 'is-wsl' +import uniq from 'lodash/uniq' + +const newLineRegex = /\r?\n/ + +/** + * This class is based on node-get-chrome + * https://github.com/mrlee23/node-get-chrome + * https://github.com/gwuhaolin/chrome-finder + */ +export default class ChromeDetector { + constructor() { + this.platform = isWsl ? 'wsl' : process.platform + } + + detect(platform = this.platform) { + const handler = this[platform] + if (typeof handler !== 'function') { + throw new Error(`${platform} is not supported.`) + } + return this[platform]()[0] + } + + darwin() { + const suffixes = [ + '/Contents/MacOS/Chromium', + '/Contents/MacOS/Google Chrome Canary', + '/Contents/MacOS/Google Chrome' + ] + const LSREGISTER = + '/System/Library/Frameworks/CoreServices.framework' + + '/Versions/A/Frameworks/LaunchServices.framework' + + '/Versions/A/Support/lsregister' + const installations = [] + const customChromePath = this.resolveChromePath() + if (customChromePath) { + installations.push(customChromePath) + } + execSync( + `${LSREGISTER} -dump` + + " | grep -i '(google chrome\\( canary\\)\\?|chromium).app$'" + + ' | awk \'{$1=""; print $0}\'' + ) + .toString() + .split(newLineRegex) + .forEach((inst) => { + suffixes.forEach((suffix) => { + const execPath = path.join(inst.trim(), suffix) + if (this.canAccess(execPath)) { + installations.push(execPath) + } + }) + }) + // Retains one per line to maintain readability. + // clang-format off + const priorities = [ + { regex: new RegExp(`^${process.env.HOME}/Applications/.*Chrome.app`), weight: 50 }, + { regex: new RegExp(`^${process.env.HOME}/Applications/.*Chrome Canary.app`), weight: 51 }, + { regex: new RegExp(`^${process.env.HOME}/Applications/.*Chromium.app`), weight: 52 }, + { regex: /^\/Applications\/.*Chrome.app/, weight: 100 }, + { regex: /^\/Applications\/.*Chrome Canary.app/, weight: 101 }, + { regex: /^\/Applications\/.*Chromium.app/, weight: 102 }, + { regex: /^\/Volumes\/.*Chrome.app/, weight: -3 }, + { regex: /^\/Volumes\/.*Chrome Canary.app/, weight: -2 }, + { regex: /^\/Volumes\/.*Chromium.app/, weight: -1 } + ] + if (process.env.LIGHTHOUSE_CHROMIUM_PATH) { + priorities.push({ regex: new RegExp(process.env.LIGHTHOUSE_CHROMIUM_PATH), weight: 150 }) + } + if (process.env.CHROME_PATH) { + priorities.push({ regex: new RegExp(process.env.CHROME_PATH), weight: 151 }) + } + // clang-format on + return this.sort(installations, priorities) + } + + /** + * Look for linux executables in 3 ways + * 1. Look into CHROME_PATH env variable + * 2. Look into the directories where .desktop are saved on gnome based distro's + * 3. Look for google-chrome-stable & google-chrome executables by using the which command + */ + linux() { + let installations = [] + // 1. Look into CHROME_PATH env variable + const customChromePath = this.resolveChromePath() + if (customChromePath) { + installations.push(customChromePath) + } + // 2. Look into the directories where .desktop are saved on gnome based distro's + const desktopInstallationFolders = [ + path.join(require('os').homedir(), '.local/share/applications/'), + '/usr/share/applications/' + ] + desktopInstallationFolders.forEach((folder) => { + installations = installations.concat(this.findChromeExecutables(folder)) + }) + // Look for chromium(-browser) & google-chrome(-stable) executables by using the which command + const executables = [ + 'chromium-browser', + 'chromium', + 'google-chrome-stable', + 'google-chrome' + ] + executables.forEach((executable) => { + try { + const chromePath = execFileSync('which', [executable]) + .toString() + .split(newLineRegex)[0] + if (this.canAccess(chromePath)) { + installations.push(chromePath) + } + } catch (e) { + // Not installed. + } + }) + if (!installations.length) { + throw new Error( + 'The environment variable CHROME_PATH must be set to ' + + 'executable of a build of Chromium version 54.0 or later.' + ) + } + const priorities = [ + { regex: /chromium-browser$/, weight: 51 }, + { regex: /chromium$/, weight: 50 }, + { regex: /chrome-wrapper$/, weight: 49 }, + { regex: /google-chrome-stable$/, weight: 48 }, + { regex: /google-chrome$/, weight: 47 } + ] + if (process.env.LIGHTHOUSE_CHROMIUM_PATH) { + priorities.push({ + regex: new RegExp(process.env.LIGHTHOUSE_CHROMIUM_PATH), + weight: 100 + }) + } + if (process.env.CHROME_PATH) { + priorities.push({ regex: new RegExp(process.env.CHROME_PATH), weight: 101 }) + } + return this.sort(uniq(installations.filter(Boolean)), priorities) + } + + wsl() { + // Manually populate the environment variables assuming it's the default config + process.env.LOCALAPPDATA = this.getLocalAppDataPath(process.env.PATH) + process.env.PROGRAMFILES = '/mnt/c/Program Files' + process.env['PROGRAMFILES(X86)'] = '/mnt/c/Program Files (x86)' + return this.win32() + } + + win32() { + const installations = [] + const sep = path.sep + const suffixes = [ + `${sep}Chromium${sep}Application${sep}chrome.exe`, + `${sep}Google${sep}Chrome SxS${sep}Application${sep}chrome.exe`, + `${sep}Google${sep}Chrome${sep}Application${sep}chrome.exe`, + `${sep}chrome-win32${sep}chrome.exe`, + `${sep}Google${sep}Chrome Beta${sep}Application${sep}chrome.exe` + ] + const prefixes = [ + process.env.LOCALAPPDATA, + process.env.PROGRAMFILES, + process.env['PROGRAMFILES(X86)'] + ].filter(Boolean) + const customChromePath = this.resolveChromePath() + if (customChromePath) { + installations.push(customChromePath) + } + prefixes.forEach(prefix => + suffixes.forEach((suffix) => { + const chromePath = path.join(prefix, suffix) + if (this.canAccess(chromePath)) { + installations.push(chromePath) + } + }) + ) + return installations + } + + resolveChromePath() { + if (this.canAccess(process.env.CHROME_PATH)) { + return process.env.CHROME_PATH + } + if (this.canAccess(process.env.LIGHTHOUSE_CHROMIUM_PATH)) { + console.warn( // eslint-disable-line no-console + 'ChromeLauncher', + 'LIGHTHOUSE_CHROMIUM_PATH is deprecated, use CHROME_PATH env variable instead.' + ) + return process.env.LIGHTHOUSE_CHROMIUM_PATH + } + } + + getLocalAppDataPath(path) { + const userRegExp = /\/mnt\/([a-z])\/Users\/([^/:]+)\/AppData\// + const results = userRegExp.exec(path) || [] + return `/mnt/${results[1]}/Users/${results[2]}/AppData/Local` + } + + sort(installations, priorities) { + const defaultPriority = 10 + return installations + .map((inst) => { + for (const pair of priorities) { + if (pair.regex.test(inst)) { + return { path: inst, weight: pair.weight } + } + } + return { path: inst, weight: defaultPriority } + }) + .sort((a, b) => b.weight - a.weight) + .map(pair => pair.path) + } + + canAccess(file) { + if (!file) { + return false + } + try { + fs.accessSync(file) + return true + } catch (e) { + return false + } + } + + findChromeExecutables(folder) { + const argumentsRegex = /(^[^ ]+).*/ // Take everything up to the first space + const chromeExecRegex = '^Exec=/.*/(google-chrome|chrome|chromium)-.*' + const installations = [] + if (this.canAccess(folder)) { + // Output of the grep & print looks like: + // /opt/google/chrome/google-chrome --profile-directory + // /home/user/Downloads/chrome-linux/chrome-wrapper %U + let execPaths + // Some systems do not support grep -R so fallback to -r. + // See https://github.com/GoogleChrome/chrome-launcher/issues/46 for more context. + try { + execPaths = execSync( + `grep -ER "${chromeExecRegex}" ${folder} | awk -F '=' '{print $2}'` + ) + } catch (e) { + execPaths = execSync( + `grep -Er "${chromeExecRegex}" ${folder} | awk -F '=' '{print $2}'` + ) + } + execPaths = execPaths + .toString() + .split(newLineRegex) + .map(execPath => execPath.replace(argumentsRegex, '$1')) + execPaths.forEach( + execPath => this.canAccess(execPath) && installations.push(execPath) + ) + } + return installations + } +} diff --git a/test/utils/index.js b/test/utils/index.js index fee4c7b..1fb19c0 100644 --- a/test/utils/index.js +++ b/test/utils/index.js @@ -1,17 +1,9 @@ import { mount, createLocalVue } from '@vue/test-utils' import { renderToString } from '@vue/server-test-utils' +import { defaultOptions } from '../../src/shared/constants' import VueMetaBrowserPlugin from '../../src/browser' import VueMetaServerPlugin from '../../src' -import { - keyName, - attribute, - ssrAttribute, - tagIDKeyName, - metaTemplateKeyName, - contentKeyName -} from '../../src/shared/constants' - export { mount, renderToString, @@ -19,15 +11,6 @@ export { VueMetaServerPlugin } -export const defaultOptions = { - keyName, - attribute, - ssrAttribute, - tagIDKeyName, - metaTemplateKeyName, - contentKeyName -} - export function getVue() { return createLocalVue() } diff --git a/test/utils/meta-info-data.js b/test/utils/meta-info-data.js index 261b760..67d1593 100644 --- a/test/utils/meta-info-data.js +++ b/test/utils/meta-info-data.js @@ -1,4 +1,4 @@ -import { defaultOptions } from './' +import { defaultOptions } from '../../src/shared/constants' const metaInfoData = { title: { @@ -196,12 +196,12 @@ const metaInfoData = { }, bodyAttrs: { add: { - data: { foo: 'bar' }, - expect: [''] + data: { foo: 'bar', fizz: ['fuzz', 'fozz'] }, + expect: [''] }, change: { data: { foo: 'baz' }, - expect: [''] + expect: [''] }, remove: { data: {}, diff --git a/test/utils/setup.js b/test/utils/setup.js index 79e5d6d..816a227 100644 --- a/test/utils/setup.js +++ b/test/utils/setup.js @@ -1,5 +1,2 @@ -import jsdom from 'jsdom-global' - -jsdom() - jest.useFakeTimers() +jest.setTimeout(15000) diff --git a/yarn.lock b/yarn.lock index 4f40b35..7ca92b7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -54,38 +54,18 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.1.0": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.2.2.tgz#07adba6dde27bb5ad8d8672f15fde3e08184a687" - integrity sha512-59vB0RWt09cAct5EIe58+NzGP4TFSD3Bz//2/ELy3ZeTeKF6VTD1AXlH8BGGbCX0PuobZBsIzO7IAI9PH67eKw== +"@babel/core@^7.1.0", "@babel/core@^7.2.2", "@babel/core@^7.3.4": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.4.tgz#921a5a13746c21e32445bf0798680e9d11a6530b" + integrity sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.2.2" + "@babel/generator" "^7.3.4" "@babel/helpers" "^7.2.0" - "@babel/parser" "^7.2.2" + "@babel/parser" "^7.3.4" "@babel/template" "^7.2.2" - "@babel/traverse" "^7.2.2" - "@babel/types" "^7.2.2" - convert-source-map "^1.1.0" - debug "^4.1.0" - json5 "^2.1.0" - lodash "^4.17.10" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/core@^7.3.3": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.3.tgz#d090d157b7c5060d05a05acaebc048bd2b037947" - integrity sha512-w445QGI2qd0E0GlSnq6huRZWPMmQGCp5gd5ZWS4hagn0EiwzxD5QMFkpchyusAyVC1n27OKXzQ0/88aVU9n4xQ== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.3.3" - "@babel/helpers" "^7.2.0" - "@babel/parser" "^7.3.3" - "@babel/template" "^7.2.2" - "@babel/traverse" "^7.2.2" - "@babel/types" "^7.3.3" + "@babel/traverse" "^7.3.4" + "@babel/types" "^7.3.4" convert-source-map "^1.1.0" debug "^4.1.0" json5 "^2.1.0" @@ -105,29 +85,7 @@ source-map "^0.5.0" trim-right "^1.0.1" -"@babel/generator@^7.0.0", "@babel/generator@^7.2.2": - version "7.3.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.2.tgz#fff31a7b2f2f3dad23ef8e01be45b0d5c2fc0132" - integrity sha512-f3QCuPppXxtZOEm5GWPra/uYUjmNQlu9pbAD8D/9jze4pTY83rTtB1igTBSwvkeNlC5gR24zFFkz+2WHLFQhqQ== - dependencies: - "@babel/types" "^7.3.2" - jsesc "^2.5.1" - lodash "^4.17.10" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@babel/generator@^7.3.3": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.3.tgz#185962ade59a52e00ca2bdfcfd1d58e528d4e39e" - integrity sha512-aEADYwRRZjJyMnKN7llGIlircxTCofm3dtV5pmY6ob18MSIuipHpA2yZWkPlycwu5HJcx/pADS3zssd8eY7/6A== - dependencies: - "@babel/types" "^7.3.3" - jsesc "^2.5.1" - lodash "^4.17.11" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@babel/generator@^7.3.4": +"@babel/generator@^7.0.0", "@babel/generator@^7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e" integrity sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg== @@ -186,6 +144,18 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" +"@babel/helper-create-class-features-plugin@^7.3.0", "@babel/helper-create-class-features-plugin@^7.3.4": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.3.4.tgz#092711a7a3ad8ea34de3e541644c2ce6af1f6f0c" + integrity sha512-uFpzw6L2omjibjxa8VGZsJUPL5wJH0zzGKpoz0ccBkzIa6C8kWNUbiBmQ0rgOKWlHJ6qzmfa6lTiGchiV8SC+g== + dependencies: + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-member-expression-to-functions" "^7.0.0" + "@babel/helper-optimise-call-expression" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.3.4" + "@babel/helper-split-export-declaration" "^7.0.0" + "@babel/helper-define-map@7.0.0-beta.47": version "7.0.0-beta.47" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.0.0-beta.47.tgz#43a9def87c5166dc29630d51b3da9cc4320c131c" @@ -497,17 +467,7 @@ lodash "^4.17.10" v8flags "^3.1.1" -"@babel/parser@^7.0.0", "@babel/parser@^7.2.2", "@babel/parser@^7.2.3": - version "7.3.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.2.tgz#95cdeddfc3992a6ca2a1315191c1679ca32c55cd" - integrity sha512-QzNUC2RO1gadg+fs21fi0Uu0OuGNzRKEmgCxoLNzbCdoprLwjfmZwzUrpUNfJPaVRwBpDY47A17yYEGWyRelnQ== - -"@babel/parser@^7.3.3": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.3.tgz#092d450db02bdb6ccb1ca8ffd47d8774a91aef87" - integrity sha512-xsH1CJoln2r74hR+y7cg2B5JCPaTh+Hd+EbBRk9nWGSNspuo6krjhX0Om6RnRQuIvFq8wVXCLKH3kwKDYhanSg== - -"@babel/parser@^7.3.4": +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.2.2", "@babel/parser@^7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.4.tgz#a43357e4bbf4b92a437fb9e465c192848287f27c" integrity sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ== @@ -540,6 +500,14 @@ "@babel/helper-replace-supers" "7.0.0-beta.47" "@babel/plugin-syntax-class-properties" "7.0.0-beta.47" +"@babel/plugin-proposal-class-properties@^7.3.0": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.3.4.tgz#410f5173b3dc45939f9ab30ca26684d72901405e" + integrity sha512-lUf8D3HLs4yYlAo8zjuneLvfxN7qfKv1Yzbj5vjqaqMJxgJA3Ipwp4VUJ+OrOdz53Wbww6ahwB8UhB2HQyLotA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.3.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-decorators@7.0.0-beta.47": version "7.0.0-beta.47" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.0.0-beta.47.tgz#5e8943c8f8eb3301f911ef0dcd3ed64cf28c723e" @@ -548,6 +516,15 @@ "@babel/helper-plugin-utils" "7.0.0-beta.47" "@babel/plugin-syntax-decorators" "7.0.0-beta.47" +"@babel/plugin-proposal-decorators@^7.3.0": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.3.0.tgz#637ba075fa780b1f75d08186e8fb4357d03a72a7" + integrity sha512-3W/oCUmsO43FmZIqermmq6TKaRSYhmh/vybPfVFwQWdSb8xwki38uAIvknCRzuyHRuYfCYmJzL9or1v0AffPjg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.3.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-decorators" "^7.2.0" + "@babel/plugin-proposal-export-namespace-from@7.0.0-beta.47": version "7.0.0-beta.47" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.0.0-beta.47.tgz#38171dd0fd5f54aee377d338ed41bb92e25d6720" @@ -667,6 +644,13 @@ dependencies: "@babel/helper-plugin-utils" "7.0.0-beta.47" +"@babel/plugin-syntax-decorators@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.2.0.tgz#c50b1b957dcc69e4b1127b65e1c33eef61570c1b" + integrity sha512-38QdqVoXdHUQfTpZo3rQwqQdWtCn5tMv4uV6r2RMfTqNBuv4ZBhz79SfaQWKTVmxHjeFv/DnXVC/+agHCklYWA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-dynamic-import@7.0.0-beta.47": version "7.0.0-beta.47" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.0.0-beta.47.tgz#ee964915014a687701ee8e15c289e31a7c899e60" @@ -674,6 +658,13 @@ dependencies: "@babel/helper-plugin-utils" "7.0.0-beta.47" +"@babel/plugin-syntax-dynamic-import@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" + integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-export-namespace-from@7.0.0-beta.47": version "7.0.0-beta.47" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.0.0-beta.47.tgz#fd446c76c59849f15e6cde235b5b8e153413f21e" @@ -709,6 +700,13 @@ dependencies: "@babel/helper-plugin-utils" "7.0.0-beta.47" +"@babel/plugin-syntax-jsx@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz#0b85a3b4bc7cdf4cc4b8bf236335b907ca22e7c7" + integrity sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-numeric-separator@7.0.0-beta.47": version "7.0.0-beta.47" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.0.0-beta.47.tgz#9f06cb770a94f464b3b2889d2110080bc302fc80" @@ -1104,6 +1102,16 @@ "@babel/helper-module-imports" "7.0.0-beta.47" "@babel/helper-plugin-utils" "7.0.0-beta.47" +"@babel/plugin-transform-runtime@^7.2.0": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.3.4.tgz#57805ac8c1798d102ecd75c03b024a5b3ea9b431" + integrity sha512-PaoARuztAdd5MgeVjAxnIDAIUet5KpogqaefQvPOmPYCxYoaPhautxDh3aO8a4xHsKgT/b9gSxR0BKK1MIewPA== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + resolve "^1.8.1" + semver "^5.5.1" + "@babel/plugin-transform-shorthand-properties@7.0.0-beta.47": version "7.0.0-beta.47" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0-beta.47.tgz#00be44c4fad8fe2c00ed18ea15ea3c88dd519dbb" @@ -1249,7 +1257,7 @@ invariant "^2.2.2" semver "^5.3.0" -"@babel/preset-env@^7.3.1": +"@babel/preset-env@^7.3.1", "@babel/preset-env@^7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.3.4.tgz#887cf38b6d23c82f19b5135298bdb160062e33e1" integrity sha512-2mwqfYMK8weA0g0uBKOt4FE3iEodiHy9/CW0b+nWXcbL+pGzLx8ESYc+j9IIxr6LTDHWKgPm71i9smo02bw+gA== @@ -1346,6 +1354,13 @@ core-js "^2.5.3" regenerator-runtime "^0.11.1" +"@babel/runtime@^7.3.1": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" + integrity sha512-IvfvnMdSaLBateu0jfsYIpZTxAc2cKEXEMiezGGN75QcBcecDUKd3PgLAncT0oOgxKy8dd8hrJKj9MfzgfZd6g== + dependencies: + regenerator-runtime "^0.12.0" + "@babel/template@7.0.0-beta.47": version "7.0.0-beta.47" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.47.tgz#0473970a7c0bee7a1a18c1ca999d3ba5e5bad83d" @@ -1381,22 +1396,7 @@ invariant "^2.2.0" lodash "^4.17.5" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.2.2": - version "7.2.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.2.3.tgz#7ff50cefa9c7c0bd2d81231fdac122f3957748d8" - integrity sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.2.2" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.0.0" - "@babel/parser" "^7.2.3" - "@babel/types" "^7.2.2" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.10" - -"@babel/traverse@^7.3.4": +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.3.4.tgz#1330aab72234f8dea091b08c4f8b9d05c7119e06" integrity sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ== @@ -1420,16 +1420,7 @@ lodash "^4.17.5" to-fast-properties "^2.0.0" -"@babel/types@^7.0.0", "@babel/types@^7.2.2", "@babel/types@^7.3.0", "@babel/types@^7.3.2": - version "7.3.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.2.tgz#424f5be4be633fff33fb83ab8d67e4a8290f5a2f" - integrity sha512-3Y6H8xlUlpbGR+XvawiH0UXehqydTmNmEpozWcXymqwcrwYAl5KMvKtQ+TF6f6E08V6Jur7v/ykdDSF+WDEIXQ== - dependencies: - esutils "^2.0.2" - lodash "^4.17.10" - to-fast-properties "^2.0.0" - -"@babel/types@^7.2.0", "@babel/types@^7.3.4": +"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.0", "@babel/types@^7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.4.tgz#bf482eaeaffb367a28abbf9357a94963235d90ed" integrity sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ== @@ -1438,14 +1429,150 @@ lodash "^4.17.11" to-fast-properties "^2.0.0" -"@babel/types@^7.3.3": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.3.tgz#6c44d1cdac2a7625b624216657d5bc6c107ab436" - integrity sha512-2tACZ80Wg09UnPg5uGAOUvvInaqLk3l/IAhQzlxLQOIXacr6bMsra5SH6AWw/hIDRCSbCdHP2KzSOD+cT7TzMQ== +"@cnakazawa/watch@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef" + integrity sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA== dependencies: - esutils "^2.0.2" - lodash "^4.17.11" - to-fast-properties "^2.0.0" + exec-sh "^0.3.2" + minimist "^1.2.0" + +"@jest/console@^24.3.0": + version "24.3.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.3.0.tgz#7bd920d250988ba0bf1352c4493a48e1cb97671e" + integrity sha512-NaCty/OOei6rSDcbPdMiCbYCI0KGFGPgGO6B09lwWt5QTxnkuhKYET9El5u5z1GAcSxkQmSMtM63e24YabCWqA== + dependencies: + "@jest/source-map" "^24.3.0" + "@types/node" "*" + chalk "^2.0.1" + slash "^2.0.0" + +"@jest/core@^24.4.0": + version "24.4.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.4.0.tgz#ec53510f19dde5aaf4e9e28a3c3426fc0f2a41d6" + integrity sha512-S48krBwigVm3DwLSEtMiiWnWz+G3uGii192LIZYbWULYSOCwQeG7hWb6a3yWBLYuZnATh3W6QMxs7whS0/hQMQ== + dependencies: + "@jest/console" "^24.3.0" + "@jest/reporters" "^24.4.0" + "@jest/test-result" "^24.3.0" + "@jest/transform" "^24.4.0" + "@jest/types" "^24.3.0" + ansi-escapes "^3.0.0" + chalk "^2.0.1" + exit "^0.1.2" + graceful-fs "^4.1.15" + jest-changed-files "^24.3.0" + jest-config "^24.4.0" + jest-haste-map "^24.4.0" + jest-message-util "^24.3.0" + jest-regex-util "^24.3.0" + jest-resolve-dependencies "^24.4.0" + jest-runner "^24.4.0" + jest-runtime "^24.4.0" + jest-snapshot "^24.4.0" + jest-util "^24.3.0" + jest-validate "^24.4.0" + jest-watcher "^24.3.0" + micromatch "^3.1.10" + p-each-series "^1.0.0" + pirates "^4.0.1" + realpath-native "^1.1.0" + rimraf "^2.5.4" + strip-ansi "^5.0.0" + +"@jest/environment@^24.4.0": + version "24.4.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.4.0.tgz#552f0629a9cc2bd015f370b3af77222f069f158f" + integrity sha512-YuPsWWwTS4wkMsvCNXvBZPZQGOVtsVyle9OzHIAdWvV+B9qjs0vA85Il1+FSG0b765VqznPvpfIe1wKoIFOleQ== + dependencies: + "@jest/fake-timers" "^24.3.0" + "@jest/transform" "^24.4.0" + "@jest/types" "^24.3.0" + "@types/node" "*" + jest-mock "^24.3.0" + +"@jest/fake-timers@^24.3.0": + version "24.3.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.3.0.tgz#0a7f8b877b78780c3fa5c3f8683cc0aaf9488331" + integrity sha512-rHwVI17dGMHxHzfAhnZ04+wFznjFfZ246QugeBnbiYr7/bDosPD2P1qeNjWnJUUcfl0HpS6kkr+OB/mqSJxQFg== + dependencies: + "@jest/types" "^24.3.0" + "@types/node" "*" + jest-message-util "^24.3.0" + jest-mock "^24.3.0" + +"@jest/reporters@^24.4.0": + version "24.4.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.4.0.tgz#e1e6ca29593f36088db76a380f04e93e71f09607" + integrity sha512-teO0to16UaYJTLWXCWCa1kBPx/PY4dw2/8I2LPIzk5mNN5km8jyx5jz8D1Yy0nqascVtbpG4+VnSt7E16cnrcw== + dependencies: + "@jest/environment" "^24.4.0" + "@jest/test-result" "^24.3.0" + "@jest/transform" "^24.4.0" + "@jest/types" "^24.3.0" + chalk "^2.0.1" + exit "^0.1.2" + glob "^7.1.2" + istanbul-api "^2.1.1" + istanbul-lib-coverage "^2.0.2" + istanbul-lib-instrument "^3.0.1" + istanbul-lib-source-maps "^3.0.1" + jest-haste-map "^24.4.0" + jest-resolve "^24.4.0" + jest-runtime "^24.4.0" + jest-util "^24.3.0" + jest-worker "^24.4.0" + node-notifier "^5.2.1" + slash "^2.0.0" + source-map "^0.6.0" + string-length "^2.0.0" + +"@jest/source-map@^24.3.0": + version "24.3.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.3.0.tgz#563be3aa4d224caf65ff77edc95cd1ca4da67f28" + integrity sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.1.15" + source-map "^0.6.0" + +"@jest/test-result@^24.3.0": + version "24.3.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.3.0.tgz#4c0b1c9716212111920f7cf8c4329c69bc81924a" + integrity sha512-j7UZ49T8C4CVipEY99nLttnczVTtLyVzFfN20OiBVn7awOs0U3endXSTq7ouPrLR5y4YjI5GDcbcvDUjgeamzg== + dependencies: + "@jest/console" "^24.3.0" + "@jest/types" "^24.3.0" + "@types/istanbul-lib-coverage" "^1.1.0" + +"@jest/transform@^24.4.0": + version "24.4.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.4.0.tgz#2f6b4b5dc7f7673d8fec8bf1040d4236c58c7a60" + integrity sha512-Y928pU6bqWqMlGugRiaWOresox/CIrRuBVdPnYiSoIcRtwNKZujCOkzIzRalcTTxm77wuLjNihcq8OWfdm+Dxg== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^24.3.0" + babel-plugin-istanbul "^5.1.0" + chalk "^2.0.1" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.1.15" + jest-haste-map "^24.4.0" + jest-regex-util "^24.3.0" + jest-util "^24.3.0" + micromatch "^3.1.10" + realpath-native "^1.1.0" + slash "^2.0.0" + source-map "^0.6.1" + write-file-atomic "2.4.1" + +"@jest/types@^24.3.0": + version "24.3.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.3.0.tgz#3f6e117e47248a9a6b5f1357ec645bd364f7ad23" + integrity sha512-VoO1F5tU2n/93QN/zaZ7Q8SeV/Rj+9JJOgbvKbBwy4lenvmdj1iDaQEPXGTKrO6OSvDeb2drTFipZJYxgo6kIQ== + dependencies: + "@types/istanbul-lib-coverage" "^1.1.0" + "@types/yargs" "^12.0.9" "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" @@ -1460,6 +1587,20 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@nuxt/babel-preset-app@^2.4.5": + version "2.4.5" + resolved "https://registry.yarnpkg.com/@nuxt/babel-preset-app/-/babel-preset-app-2.4.5.tgz#707043fe4686b7375df0917cca9134b7681ae9bf" + integrity sha512-Pfpp9++AjTLSvr0EQY00SPacSxw6nvIgARVTiFG8xEkqzUzChx1xz424u4e8mKhu3qEgj9ldcF5iKC5A87RYkw== + dependencies: + "@babel/core" "^7.2.2" + "@babel/plugin-proposal-class-properties" "^7.3.0" + "@babel/plugin-proposal-decorators" "^7.3.0" + "@babel/plugin-syntax-dynamic-import" "^7.2.0" + "@babel/plugin-transform-runtime" "^7.2.0" + "@babel/preset-env" "^7.3.1" + "@babel/runtime" "^7.3.1" + "@vue/babel-preset-jsx" "^1.0.0-beta.2" + "@nuxtjs/eslint-config@^0.0.1": version "0.0.1" resolved "https://registry.yarnpkg.com/@nuxtjs/eslint-config/-/eslint-config-0.0.1.tgz#3aeed1cc6a2e01331c7e6b56bfa7152ce8bb2d90" @@ -1483,20 +1624,58 @@ "@shellscape/koa-send" "^4.1.0" debug "^2.6.8" +"@types/babel__core@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.0.tgz#710f2487dda4dcfd010ca6abb2b4dc7394365c51" + integrity sha512-wJTeJRt7BToFx3USrCDs2BhEi4ijBInTQjOIukj6a/5tEkwpFMVZ+1ppgmE+Q/FQyc5P/VWUbx7I9NELrKruHA== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.0.2.tgz#d2112a6b21fad600d7674274293c85dce0cb47fc" + integrity sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307" + integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.6.tgz#328dd1a8fc4cfe3c8458be9477b219ea158fd7b2" + integrity sha512-XYVgHF2sQ0YblLRMLNPB3CkFMewzFmlDsH/TneZFHUXDlABQgh88uOxuez7ZcXxayLFrqLwtDH1t+FmlFwNZxw== + dependencies: + "@babel/types" "^7.3.0" + "@types/estree@0.0.39": version "0.0.39" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== -"@types/node@*", "@types/node@^10.11.7": - version "10.12.24" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.24.tgz#b13564af612a22a20b5d95ca40f1bffb3af315cf" - integrity sha512-GWWbvt+z9G5otRBW8rssOFgRY87J9N/qbhqfjMZ+gUuL6zoL+Hm6gP/8qQBG4jjimqdaNLCehcVapZ/Fs2WjCQ== +"@types/istanbul-lib-coverage@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.0.tgz#2cc2ca41051498382b43157c8227fea60363f94a" + integrity sha512-ohkhb9LehJy+PA40rDtGAji61NCgdtKLAlFoYp4cnuuQEswwdK3vz9SOIkkyc3wrk8dzjphQApNs56yyXLStaQ== -"@types/semver@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45" - integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ== +"@types/node@*", "@types/node@^11.9.5": + version "11.11.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.1.tgz#9ee55ffce20f72e141863b0036a6e51c6fc09a1f" + integrity sha512-2azXFP9n4aA2QNLkKm/F9pzKxgYj1SMawZ5Eh9iC21RH3XNcFsivLVU2NhpMgQm7YobSByvIol4c42ZFusXFHQ== + +"@types/stack-utils@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" + integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== "@types/strip-bom@^3.0.0": version "3.0.0" @@ -1508,6 +1687,28 @@ resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== +"@types/yargs@^12.0.2", "@types/yargs@^12.0.9": + version "12.0.9" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.9.tgz#693e76a52f61a2f1e7fb48c0eef167b95ea4ffd0" + integrity sha512-sCZy4SxP9rN2w30Hlmg5dtdRwgYQfYRiLo9usw8X9cxlf+H4FqM1xX7+sNH7NNKVdbXMJWqva7iyy+fxh/V7fA== + +"@vue/babel-helper-vue-jsx-merge-props@^1.0.0-beta.2": + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.0.0-beta.2.tgz#f3e20d77b89ddb7a4b9b7a75372f05cd3ac22d92" + integrity sha512-Yj92Q1GcGjjctecBfnBmVqKSlMdyZaVq10hlZB4HSd1DJgu4cWgpEImJSzcJRUCZmas6UigwE7f4IjJuQs+JvQ== + +"@vue/babel-plugin-transform-vue-jsx@^1.0.0-beta.2": + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.0.0-beta.2.tgz#6f7903fe66a34a02163f418c426cf419e862d97e" + integrity sha512-fvAymRZAPHitomRE+jIipWRj0STXNSMqeOSdOFu9Ffjqg9WGOxSdCjORxexManfZ2y5QDv7gzI1xfgprsK3nlw== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.2.0" + "@vue/babel-helper-vue-jsx-merge-props" "^1.0.0-beta.2" + html-tags "^2.0.0" + lodash.kebabcase "^4.1.1" + svg-tags "^1.0.0" + "@vue/babel-preset-app@3.0.0-beta.11": version "3.0.0-beta.11" resolved "https://registry.yarnpkg.com/@vue/babel-preset-app/-/babel-preset-app-3.0.0-beta.11.tgz#c8b889aa73464050f9cd3f9dc621951d85c24508" @@ -1522,6 +1723,53 @@ babel-plugin-dynamic-import-node "^1.2.0" babel-plugin-transform-vue-jsx "^4.0.1" +"@vue/babel-preset-jsx@^1.0.0-beta.2": + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/@vue/babel-preset-jsx/-/babel-preset-jsx-1.0.0-beta.2.tgz#3e5dc2b73da58391c1c7327c2bd2ef154fe4e46e" + integrity sha512-nZoAKBR/h6iPMQ66ieQcIdlpPBmqhtUUcgjBS541jIVxSog1rwzrc00jlsuecLonzUMWPU0PabyitsG74vhN1w== + dependencies: + "@vue/babel-helper-vue-jsx-merge-props" "^1.0.0-beta.2" + "@vue/babel-plugin-transform-vue-jsx" "^1.0.0-beta.2" + "@vue/babel-sugar-functional-vue" "^1.0.0-beta.2" + "@vue/babel-sugar-inject-h" "^1.0.0-beta.2" + "@vue/babel-sugar-v-model" "^1.0.0-beta.2" + "@vue/babel-sugar-v-on" "^1.0.0-beta.2" + +"@vue/babel-sugar-functional-vue@^1.0.0-beta.2": + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.0.0-beta.2.tgz#8831f686e7614f282d5170b902483ef538deef38" + integrity sha512-5qvi4hmExgjtrESDk0vflL69dIxkDAukJcYH9o4663E8Nh12Jpbmr+Ja8WmgkAPtTVhk90UVcVUFCCZLHBmhkQ== + dependencies: + "@babel/plugin-syntax-jsx" "^7.2.0" + +"@vue/babel-sugar-inject-h@^1.0.0-beta.2": + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.0.0-beta.2.tgz#5f92f994bf4b4126fad8633f554e8a426b51b413" + integrity sha512-qGXZ6yE+1trk82xCVJ9j3shsgI+R2ePj3+o8b2Ee7JNaRqQvMfTwpgx5BRlk4q1+CTjvYexdqBS+q4Kg7sSxcg== + dependencies: + "@babel/plugin-syntax-jsx" "^7.2.0" + +"@vue/babel-sugar-v-model@^1.0.0-beta.2": + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.0.0-beta.2.tgz#051d3ae3ef5e70d514e09058ec5790f6a42e8c28" + integrity sha512-63US3IMEtATJzzK2le/Na53Sk2bp3LHfwZ8eMFwbTaz6e2qeV9frBl3ZYaha64ghT4IDSbrDXUmm0J09EAzFfA== + dependencies: + "@babel/plugin-syntax-jsx" "^7.2.0" + "@vue/babel-helper-vue-jsx-merge-props" "^1.0.0-beta.2" + "@vue/babel-plugin-transform-vue-jsx" "^1.0.0-beta.2" + camelcase "^5.0.0" + html-tags "^2.0.0" + svg-tags "^1.0.0" + +"@vue/babel-sugar-v-on@^1.0.0-beta.2": + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.0.0-beta.2.tgz#3e2d122e229b10017f091d178346b601d9245260" + integrity sha512-XH/m3k11EKdMY0MrTg4+hQv8BFM8juzHT95chYkgxDmvDdVJnSCuf9+mcysEJttWD4PVuUGN7EHoIWsIhC0dRw== + dependencies: + "@babel/plugin-syntax-jsx" "^7.2.0" + "@vue/babel-plugin-transform-vue-jsx" "^1.0.0-beta.2" + camelcase "^5.0.0" + "@vue/component-compiler-utils@^2.5.1": version "2.6.0" resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-2.6.0.tgz#aa46d2a6f7647440b0b8932434d22f12371e543b" @@ -1774,7 +2022,7 @@ acorn-globals@^4.1.0, acorn-globals@^4.3.0: acorn "^6.0.1" acorn-walk "^6.0.1" -acorn-jsx@^5.0.0: +acorn-jsx@^5.0.0, acorn-jsx@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== @@ -1789,12 +2037,7 @@ acorn@^5.5.3: resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== -acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.4, acorn@^6.0.7, acorn@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.0.tgz#b0a3be31752c97a0f7013c5f4903b71a05db6818" - integrity sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw== - -acorn@^6.0.5: +acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.4, acorn@^6.0.5, acorn@^6.0.7, acorn@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== @@ -1821,7 +2064,7 @@ ajv-keywords@^3.0.0, ajv-keywords@^3.1.0: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.0.tgz#4b831e7b531415a7cc518cd404e73f6193c6349d" integrity sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw== -ajv@^6.0.1, ajv@^6.1.0: +ajv@^6.0.1, ajv@^6.1.0, ajv@^6.5.5, ajv@^6.9.1: version "6.10.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== @@ -1831,16 +2074,6 @@ ajv@^6.0.1, ajv@^6.1.0: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^6.5.5, ajv@^6.9.1: - version "6.9.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.9.1.tgz#a4d3683d74abc5670e75f0b16520f70a20ea8dc1" - integrity sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA== - dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - algoliasearch@^3.24.5: version "3.32.0" resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-3.32.0.tgz#5818168c26ff921bd0346a919071bac928b747ce" @@ -1899,10 +2132,10 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= -ansi-regex@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9" - integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w== +ansi-regex@^4.0.0, ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== ansi-styles@^2.2.1: version "2.2.1" @@ -2089,11 +2322,11 @@ async@^1.5.2: integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= async@^2.5.0, async@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== + version "2.6.2" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" + integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== dependencies: - lodash "^4.17.10" + lodash "^4.17.11" asynckit@^0.4.0: version "0.4.0" @@ -2184,13 +2417,16 @@ babel-helper-vue-jsx-merge-props@^2.0.3: resolved "https://registry.yarnpkg.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz#22aebd3b33902328e513293a8e4992b384f9f1b6" integrity sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg== -babel-jest@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.1.0.tgz#441e23ef75ded3bd547e300ac3194cef87b55190" - integrity sha512-MLcagnVrO9ybQGLEfZUqnOzv36iQzU7Bj4elm39vCukumLVSfoX+tRy3/jW7lUKc7XdpRmB/jech6L/UCsSZjw== +babel-jest@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.4.0.tgz#6c4029f52175d4f8f138cdad42d2a02fe34ddb03" + integrity sha512-wh23nKbWZf9SeO0GNOQc2QDqaMXOmbaI2Hvbcl6FGqg9zqHwr9Jy0e0ZqsXiJ2Cv8YKqD+eOE2wAGVhq4nzWDQ== dependencies: + "@jest/transform" "^24.4.0" + "@jest/types" "^24.3.0" + "@types/babel__core" "^7.1.0" babel-plugin-istanbul "^5.1.0" - babel-preset-jest "^24.1.0" + babel-preset-jest "^24.3.0" chalk "^2.4.2" slash "^2.0.0" @@ -2228,19 +2464,28 @@ babel-plugin-dynamic-import-node@^1.2.0: dependencies: babel-plugin-syntax-dynamic-import "^6.18.0" +babel-plugin-dynamic-import-node@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.2.0.tgz#c0adfb07d95f4a4495e9aaac6ec386c4d7c2524e" + integrity sha512-fP899ELUnTaBcIzmrW7nniyqqdYWrWuJUyPWHxFa/c7r7hS6KC8FscNfLlBNIoPSc55kYMGEEKjPjJGCLbE1qA== + dependencies: + object.assign "^4.1.0" + babel-plugin-istanbul@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.0.tgz#6892f529eff65a3e2d33d87dc5888ffa2ecd4a30" - integrity sha512-CLoXPRSUWiR8yao8bShqZUIC6qLfZVVY3X1wj+QPNXu0wfmrRRfarh1LYy+dYMVI+bDj0ghy3tuqFFRFZmL1Nw== + version "5.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.1.tgz#7981590f1956d75d67630ba46f0c22493588c893" + integrity sha512-RNNVv2lsHAXJQsEJ5jonQwrJVWK8AcZpG1oxhnjCUaAjL7xahYLANhPUZbzEQHjKy1NMYUwn+0NPKQc8iSY4xQ== dependencies: find-up "^3.0.0" istanbul-lib-instrument "^3.0.0" test-exclude "^5.0.0" -babel-plugin-jest-hoist@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.1.0.tgz#dfecc491fb15e2668abbd690a697a8fd1411a7f8" - integrity sha512-gljYrZz8w1b6fJzKcsfKsipSru2DU2DmQ39aB6nV3xQ0DDv3zpIzKGortA5gknrhNnPN8DweaEgrnZdmbGmhnw== +babel-plugin-jest-hoist@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.3.0.tgz#f2e82952946f6e40bb0a75d266a3790d854c8b5b" + integrity sha512-nWh4N1mVH55Tzhx2isvUN5ebM5CDUvIpXPZYMRazQughie/EqGnbR+czzoQlhUmJG9pPJmYDRhvocotb2THl1w== + dependencies: + "@types/babel__traverse" "^7.0.6" babel-plugin-syntax-dynamic-import@^6.18.0: version "6.18.0" @@ -2285,13 +2530,13 @@ babel-plugin-transform-vue-jsx@^4.0.1: dependencies: esutils "^2.0.2" -babel-preset-jest@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.1.0.tgz#83bc564fdcd4903641af65ec63f2f5de6b04132e" - integrity sha512-FfNLDxFWsNX9lUmtwY7NheGlANnagvxq8LZdl5PKnVG3umP+S/g0XbVBfwtA4Ai3Ri/IMkWabBz3Tyk9wdspcw== +babel-preset-jest@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.3.0.tgz#db88497e18869f15b24d9c0e547d8e0ab950796d" + integrity sha512-VGTV2QYBa/Kn3WCOKdfS31j9qomaXSgJqi65B6o05/1GsJyj9LVhSljM9ro4S+IBGj/ENhNBuH9bpqzztKAQSw== dependencies: "@babel/plugin-syntax-object-rest-spread" "^7.0.0" - babel-plugin-jest-hoist "^24.1.0" + babel-plugin-jest-hoist "^24.3.0" babel-runtime@^6.22.0, babel-runtime@^6.26.0: version "6.26.0" @@ -2567,16 +2812,18 @@ bser@^2.0.0: node-int64 "^0.4.0" buble@^0.19.6: - version "0.19.6" - resolved "https://registry.yarnpkg.com/buble/-/buble-0.19.6.tgz#915909b6bd5b11ee03b1c885ec914a8b974d34d3" - integrity sha512-9kViM6nJA1Q548Jrd06x0geh+BG2ru2+RMDkIHHgJY/8AcyCs34lTHwra9BX7YdPrZXd5aarkpr/SY8bmPgPdg== + version "0.19.7" + resolved "https://registry.yarnpkg.com/buble/-/buble-0.19.7.tgz#1dfd080ab688101aad5388d3304bc82601a244fd" + integrity sha512-YLgWxX/l+NnfotydBlxqCMPR4FREE4ubuHphALz0FxQ7u2hp3BzxTKQ4nKpapOaRJfEm1gukC68KnT2OymRK0g== dependencies: - chalk "^2.4.1" - magic-string "^0.25.1" + acorn "^6.1.1" + acorn-dynamic-import "^4.0.0" + acorn-jsx "^5.0.1" + chalk "^2.4.2" + magic-string "^0.25.2" minimist "^1.2.0" os-homedir "^1.0.1" - regexpu-core "^4.2.0" - vlq "^1.0.0" + regexpu-core "^4.5.4" buffer-from@^1.0.0: version "1.1.1" @@ -2744,9 +2991,9 @@ camelcase@^4.0.0, camelcase@^4.1.0: integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= camelcase@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" - integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== + version "5.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.2.0.tgz#e7522abda5ed94cc0489e1b8466610e88404cf45" + integrity sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ== caniuse-api@^1.5.2: version "1.6.1" @@ -2763,11 +3010,16 @@ caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000943.tgz#63f42807eb2934dfa63d7ae58a213c8017b55fdd" integrity sha512-QbrkeLnFKbNWm2YuDMtZwa8otcNW0dhNHbBkqC7E9q1E5nR/kSa7er9shD3GCvcQh/6QaTFxMWVpYgz+OLjuFQ== -caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000864, caniuse-lite@^1.0.30000939: +caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000864: version "1.0.30000943" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000943.tgz#00b25bd5808edc2ed1cfb53533a6a6ff6ca014ee" integrity sha512-nJMjU4UaesbOHTcmz6VS+qaog++Fdepg4KAya5DL/AZrL/aaAZDGOOQ0AECtsJa09r4cJBdHZMive5mw8lnQ5A== +caniuse-lite@^1.0.30000939: + version "1.0.30000945" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000945.tgz#d51e3750416dd05126d5ac94a9c57d1c26c6fd21" + integrity sha512-PSGwYChNIXJ4FZr9Z9mrVzBCB1TF3yyiRmIDRIdKDHZ6u+1jYH6xeR28XaquxnMwcZVX3f48S9zi7eswO/G1nQ== + capture-exit@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f" @@ -3081,7 +3333,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.5.0, concat-stream@^1.6.0: +concat-stream@1.6.2, concat-stream@^1.5.0, concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -3362,12 +3614,7 @@ copy-webpack-plugin@^4.5.1: p-limit "^1.0.0" serialize-javascript "^1.4.0" -core-js@^2.4.0, core-js@^2.5.7: - version "2.6.4" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.4.tgz#b8897c062c4d769dd30a0ac5c73976c47f92ea0d" - integrity sha512-05qQ5hXShcqGkPZpXEFLIpxayZscVD2kuMBZewxiIPPEagukO4mqgPA9CWhUvFBJfy3ODdK2p9xyHh7FTU9/7A== - -core-js@^2.5.3: +core-js@^2.4.0, core-js@^2.5.3, core-js@^2.5.7: version "2.6.5" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895" integrity sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A== @@ -3528,9 +3775,9 @@ css-selector-tokenizer@^0.7.0: regexpu-core "^1.0.0" css-what@2.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.2.tgz#c0876d9d0480927d7d4920dcd72af3595649554d" - integrity sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ== + version "2.1.3" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" + integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== css@^2.1.0: version "2.2.4" @@ -3604,9 +3851,9 @@ cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0", cssom@^0.3.4: integrity sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A== cssstyle@^1.0.0, cssstyle@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.1.1.tgz#18b038a9c44d65f7a8e428a653b9f6fe42faf5fb" - integrity sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog== + version "1.2.1" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.2.1.tgz#3aceb2759eaf514ac1a21628d723d6043a819495" + integrity sha512-7DYm8qe+gPx/h77QlCyFmX80+fGaE/6A/Ekl0zaszYOubvySO2saYFdQ78P29D0UsULxFKCetDGNaNRUdSF+2A== dependencies: cssom "0.3.x" @@ -3674,7 +3921,7 @@ debug@*, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" -debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.1, debug@^2.6.3, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.1, debug@^2.6.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -3832,10 +4079,10 @@ diacritics@^1.3.0: resolved "https://registry.yarnpkg.com/diacritics/-/diacritics-1.3.0.tgz#3efa87323ebb863e6696cebb0082d48ff3d6f7a1" integrity sha1-PvqHMj67hj5mls67AILUj/PW96E= -diff-sequences@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.0.0.tgz#cdf8e27ed20d8b8d3caccb4e0c0d8fe31a173013" - integrity sha512-46OkIuVGBBnrC0soO/4LHu5LHGHx0uhP65OVz8XOrAJpqiCB2aVIuESvjI1F9oqebuvY8lekS1pt6TN7vt7qsw== +diff-sequences@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.3.0.tgz#0f20e8a1df1abddaf4d9c226680952e64118b975" + integrity sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw== diffie-hellman@^5.0.0: version "5.0.3" @@ -3902,12 +4149,12 @@ dom-event-types@^1.0.0: integrity sha512-2G2Vwi2zXTHBGqXHsJ4+ak/iP0N8Ar+G8a7LiD2oup5o4sQWytwqqrZu/O6hIMV0KMID2PL69OhpshLO0n7UJQ== dom-serializer@0, dom-serializer@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" - integrity sha1-BzxpdUbOB4DOI75KKOKT5AvDDII= + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" + integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== dependencies: - domelementtype "~1.1.1" - entities "~1.1.1" + domelementtype "^1.3.0" + entities "^1.1.1" dom-walk@^0.1.0: version "0.1.1" @@ -3924,11 +4171,6 @@ domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== -domelementtype@~1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - integrity sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs= - domexception@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" @@ -4005,14 +4247,12 @@ ecc-jsbn@~0.1.1: safer-buffer "^2.1.0" editorconfig@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.2.tgz#047be983abb9ab3c2eefe5199cb2b7c5689f0702" - integrity sha512-GWjSI19PVJAM9IZRGOS+YKI8LN+/sjkSjNyvxL5ucqP9/IqtYNXBaQ/6c/hkPNYQHyOHra2KoXZI/JVpuqwmcQ== + version "0.15.3" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" + integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== dependencies: - "@types/node" "^10.11.7" - "@types/semver" "^5.5.0" commander "^2.19.0" - lru-cache "^4.1.3" + lru-cache "^4.1.5" semver "^5.6.0" sigmund "^1.0.1" @@ -4172,9 +4412,9 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escodegen@^1.11.0, escodegen@^1.9.1: - version "1.11.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589" - integrity sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw== + version "1.11.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.1.tgz#c485ff8d6b4cdb89e27f4a856e91f118401ca510" + integrity sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw== dependencies: esprima "^3.1.3" estraverse "^4.2.0" @@ -4270,10 +4510,10 @@ eslint-scope@3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" - integrity sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA== +eslint-scope@^4.0.0, eslint-scope@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.2.tgz#5f10cd6cabb1965bf479fa65745673439e21cb0e" + integrity sha512-5q1+B/ogmHl8+paxtOKx38Z8LtWkVGuNt3+GQNErqwLl6ViNp/gdJGMCjZNxZ8j/VYjDNZ2Fo+eQc1TAVPIzbg== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -4288,10 +4528,10 @@ eslint-visitor-keys@^1.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== -eslint@^5.14.1: - version "5.14.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.14.1.tgz#490a28906be313685c55ccd43a39e8d22efc04ba" - integrity sha512-CyUMbmsjxedx8B0mr79mNOqetvkbij/zrXnFeK2zc3pGRn3/tibjiNAv/3UxFEyfMDjh+ZqTrJrEGBFiGfD5Og== +eslint@^5.15.1: + version "5.15.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.15.1.tgz#8266b089fd5391e0009a047050795b1d73664524" + integrity sha512-NTcm6vQ+PTgN3UBsALw5BMhgO6i5EpIjQF/Xb5tIh3sk9QhrFafujUOczGz4J24JBlzWclSB9Vmx8d+9Z6bFCg== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.9.1" @@ -4299,7 +4539,7 @@ eslint@^5.14.1: cross-spawn "^6.0.5" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^4.0.0" + eslint-scope "^4.0.2" eslint-utils "^1.3.1" eslint-visitor-keys "^1.0.0" espree "^5.0.1" @@ -4330,10 +4570,10 @@ eslint@^5.14.1: table "^5.2.3" text-table "^0.2.0" -esm@^3.2.5: - version "3.2.5" - resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.5.tgz#036e410a2373ea81bfe62166c419ca0b0cf85c09" - integrity sha512-rukU6Nd3agbHQCJWV4rrlZxqpbO3ix8qhUxK1BhKALGS2E465O0BFwgCOqJjNnYfO/I2MwpUBmPsW8DXoe8tcA== +esm@^3.2.14: + version "3.2.15" + resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.15.tgz#a6cf1b209c6718871cb35fd2a3733e7c3befc144" + integrity sha512-GcKZRSlQ/QevC/t94FXYKbUobSTArdLfRBAV6t6HIguoUBfuFGomxSZbsRHySaTppixC9jtmzAX+0GF4tbJaJA== espree@^4.1.0: version "4.1.0" @@ -4392,6 +4632,11 @@ estree-walker@^0.5.2: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.2.tgz#d3850be7529c9580d815600b53126515e146dd39" integrity sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig== +estree-walker@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.0.tgz#5d865327c44a618dde5699f763891ae31f257dae" + integrity sha512-peq1RfVAVzr3PU/jL31RaOjUKLoZJpObQWJJ+LgfcxDUifyLZ1RjPQZTl0pzj2uJ45b7A7XpyppXvxdEqzo4rw== + esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" @@ -4415,12 +4660,10 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -exec-sh@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36" - integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw== - dependencies: - merge "^1.2.0" +exec-sh@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.2.tgz#6738de2eb7c8e671d0366aea0b0db8c6f7d7391b" + integrity sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg== execa@^0.7.0: version "0.7.0" @@ -4493,16 +4736,17 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" -expect@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-24.1.0.tgz#88e73301c4c785cde5f16da130ab407bdaf8c0f2" - integrity sha512-lVcAPhaYkQcIyMS+F8RVwzbm1jro20IG8OkvxQ6f1JfqhVZyyudCwYogQ7wnktlf14iF3ii7ArIUO/mqvrW9Gw== +expect@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-24.4.0.tgz#df52da212bc06831c38fb51a53106ae7a0e7aaf2" + integrity sha512-p3QGkNhxN4WXih12lOx4vuhJpl/ZFD1AWu9lWh8IXNZD10ySSOzDN4Io8zuEOWvzylFkDpU9oQ/KRTZ/Bs9/ag== dependencies: + "@jest/types" "^24.3.0" ansi-styles "^3.2.0" - jest-get-type "^24.0.0" - jest-matcher-utils "^24.0.0" - jest-message-util "^24.0.0" - jest-regex-util "^24.0.0" + jest-get-type "^24.3.0" + jest-matcher-utils "^24.4.0" + jest-message-util "^24.3.0" + jest-regex-util "^24.3.0" extend-shallow@^2.0.1: version "2.0.1" @@ -4561,6 +4805,16 @@ extract-from-css@^0.4.4: dependencies: css "^2.1.0" +extract-zip@^1.6.6: + version "1.6.7" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9" + integrity sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k= + dependencies: + concat-stream "1.6.2" + debug "2.6.9" + mkdirp "0.5.1" + yauzl "2.4.1" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -4610,6 +4864,13 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" +fd-slicer@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" + integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU= + dependencies: + pend "~1.2.0" + figgy-pudding@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" @@ -4672,9 +4933,9 @@ fill-range@^4.0.0: to-regex-range "^2.1.0" find-babel-config@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-1.1.0.tgz#acc01043a6749fec34429be6b64f542ebb5d6355" - integrity sha1-rMAQQ6Z0n+w0Qpvmtk9ULrtdY1U= + version "1.2.0" + resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-1.2.0.tgz#a9b7b317eb5b9860cda9d54740a8c8337a2283a2" + integrity sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA== dependencies: json5 "^0.5.1" path-exists "^3.0.0" @@ -4689,12 +4950,12 @@ find-cache-dir@^1.0.0: pkg-dir "^2.0.0" find-cache-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.0.0.tgz#4c1faed59f45184530fb9d7fa123a4d04a98472d" - integrity sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA== + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== dependencies: commondir "^1.0.1" - make-dir "^1.0.0" + make-dir "^2.0.0" pkg-dir "^3.0.0" find-up@^1.0.0: @@ -4822,6 +5083,15 @@ fs-extra@^5.0.0: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" @@ -4849,7 +5119,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.2.3, fsevents@^1.2.7: +fsevents@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.7.tgz#4851b664a3783e52003b3c66eb0eee1074933aa4" integrity sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw== @@ -5038,9 +5308,9 @@ global@^4.3.2: process "~0.5.1" globals@^11.1.0, globals@^11.7.0: - version "11.10.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.10.0.tgz#1e09776dffda5e01816b3bb4077c8b59c24eaa50" - integrity sha512-0GZF1RiPKU97IHUO5TORo9w1PwrH/NBPl+fS7oMLdaTRiYmYbwK4NWoZWrAdd0/abG9R2BU+OiwyQpTpE6pdfQ== + version "11.11.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.11.0.tgz#dcf93757fa2de5486fbeed7118538adf789e9c2e" + integrity sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw== globals@^9.18.0: version "9.18.0" @@ -5116,7 +5386,7 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -handlebars@^4.0.11, handlebars@^4.1.0: +handlebars@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.0.tgz#0d6a6f34ff1f63cecec8423aa4169827bf787c3a" integrity sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w== @@ -5259,9 +5529,9 @@ home-or-tmp@^3.0.0: integrity sha1-V6j+JM8zzdUkhgoVgh3cJchmcfs= homedir-polyfill@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" - integrity sha1-TCu8inWJmP7r9e1oWA921GdotLw= + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== dependencies: parse-passwd "^1.0.0" @@ -5295,7 +5565,12 @@ html-minifier@^3.2.3: relateurl "0.2.x" uglify-js "3.4.x" -htmlparser2@^3.3.0: +html-tags@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b" + integrity sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos= + +htmlparser2@^3.3.0, htmlparser2@^3.9.1: version "3.10.1" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== @@ -5307,18 +5582,6 @@ htmlparser2@^3.3.0: inherits "^2.0.1" readable-stream "^3.1.1" -htmlparser2@^3.9.1: - version "3.10.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.0.tgz#5f5e422dcf6119c0d983ed36260ce9ded0bee464" - integrity sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ== - dependencies: - domelementtype "^1.3.0" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.0.6" - http-assert@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.4.0.tgz#0e550b4fca6adf121bbeed83248c17e62f593a9a" @@ -5558,11 +5821,6 @@ invert-kv@^2.0.0: resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== -ip-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" - integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= - is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" @@ -5776,11 +6034,6 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - is-obj@^1.0.0, is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" @@ -5932,10 +6185,10 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -istanbul-api@^2.0.8: - version "2.1.0" - resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.1.0.tgz#37ab0c2c3e83065462f5254b94749d6157846c4e" - integrity sha512-+Ygg4t1StoiNlBGc6x0f8q/Bv26FbZqP/+jegzfNpU7Q8o+4ZRoJxJPhBkgE/UonpAjtxnE4zCZIyJX+MwLRMQ== +istanbul-api@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.1.1.tgz#194b773f6d9cbc99a9258446848b0f988951c4d0" + integrity sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw== dependencies: async "^2.6.1" compare-versions "^3.2.1" @@ -5945,7 +6198,7 @@ istanbul-api@^2.0.8: istanbul-lib-instrument "^3.1.0" istanbul-lib-report "^2.0.4" istanbul-lib-source-maps "^3.0.2" - istanbul-reports "^2.1.0" + istanbul-reports "^2.1.1" js-yaml "^3.12.0" make-dir "^1.3.0" minimatch "^3.0.4" @@ -5996,346 +6249,372 @@ istanbul-lib-source-maps@^3.0.1, istanbul-lib-source-maps@^3.0.2: rimraf "^2.6.2" source-map "^0.6.1" -istanbul-reports@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.1.0.tgz#87b8b55cd1901ba1748964c98ddd8900ce306d59" - integrity sha512-azQdSX+dtTtkQEfqq20ICxWi6eOHXyHIgMFw1VOOVi8iIPWeCWRgCyFh/CsBKIhcgskMI8ExXmU7rjXTRCIJ+A== +istanbul-reports@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.1.1.tgz#72ef16b4ecb9a4a7bd0e2001e00f95d1eec8afa9" + integrity sha512-FzNahnidyEPBCI0HcufJoSEoKykesRlFcSzQqjH9x0+LC8tnnE/p/90PBLu8iZTxr8yYZNyTtiAujUqyN+CIxw== dependencies: - handlebars "^4.0.11" + handlebars "^4.1.0" javascript-stringify@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/javascript-stringify/-/javascript-stringify-1.6.0.tgz#142d111f3a6e3dae8f4a9afd77d45855b5a9cce3" integrity sha1-FC0RHzpuPa6PSpr9d9RYVbWpzOM= -jest-changed-files@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.0.0.tgz#c02c09a8cc9ca93f513166bc773741bd39898ff7" - integrity sha512-nnuU510R9U+UX0WNb5XFEcsrMqriSiRLeO9KWDFgPrpToaQm60prfQYpxsXigdClpvNot5bekDY440x9dNGnsQ== +jest-changed-files@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.3.0.tgz#7050ae29aaf1d59437c80f21d5b3cd354e88a499" + integrity sha512-fTq0YAUR6644fgsqLC7Zi2gXA/bAplMRvfXQdutmkwgrCKK6upkj+sgXqsUfUZRm15CVr3YSojr/GRNn71IMvg== dependencies: + "@jest/types" "^24.3.0" execa "^1.0.0" throat "^4.0.0" -jest-cli@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.1.0.tgz#f7cc98995f36e7210cce3cbb12974cbf60940843" - integrity sha512-U/iyWPwOI0T1CIxVLtk/2uviOTJ/OiSWJSe8qt6X1VkbbgP+nrtLJlmT9lPBe4lK78VNFJtrJ7pttcNv/s7yCw== +jest-cli@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.4.0.tgz#3297c2f817611b86ce1250fb5703a28bca201034" + integrity sha512-QQOgpRpXoDqpxhEux/AGyI9XJzVOJ5ppz4Kb9MlA5PvzsyYD3DRk/uiyJgmvBhCCXvcA1CKEl/g/LH0kbKg10Q== dependencies: - ansi-escapes "^3.0.0" + "@jest/core" "^24.4.0" + "@jest/test-result" "^24.3.0" + "@jest/types" "^24.3.0" chalk "^2.0.1" exit "^0.1.2" - glob "^7.1.2" - graceful-fs "^4.1.15" import-local "^2.0.0" is-ci "^2.0.0" - istanbul-api "^2.0.8" - istanbul-lib-coverage "^2.0.2" - istanbul-lib-instrument "^3.0.1" - istanbul-lib-source-maps "^3.0.1" - jest-changed-files "^24.0.0" - jest-config "^24.1.0" - jest-environment-jsdom "^24.0.0" - jest-get-type "^24.0.0" - jest-haste-map "^24.0.0" - jest-message-util "^24.0.0" - jest-regex-util "^24.0.0" - jest-resolve-dependencies "^24.1.0" - jest-runner "^24.1.0" - jest-runtime "^24.1.0" - jest-snapshot "^24.1.0" - jest-util "^24.0.0" - jest-validate "^24.0.0" - jest-watcher "^24.0.0" - jest-worker "^24.0.0" - micromatch "^3.1.10" - node-notifier "^5.2.1" - p-each-series "^1.0.0" - pirates "^4.0.0" + jest-config "^24.4.0" + jest-util "^24.3.0" + jest-validate "^24.4.0" prompts "^2.0.1" - realpath-native "^1.0.0" - rimraf "^2.5.4" - slash "^2.0.0" - string-length "^2.0.0" - strip-ansi "^5.0.0" - which "^1.2.12" + realpath-native "^1.1.0" yargs "^12.0.2" -jest-config@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.1.0.tgz#6ea6881cfdd299bc86cc144ee36d937c97c3850c" - integrity sha512-FbbRzRqtFC6eGjG5VwsbW4E5dW3zqJKLWYiZWhB0/4E5fgsMw8GODLbGSrY5t17kKOtCWb/Z7nsIThRoDpuVyg== +jest-config@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.4.0.tgz#07bf14d43c02aec3bd384121a165a6ee9d8c5ed1" + integrity sha512-H2R6qkfUPck+OlIWsjeShecbqYiEDUvzZfsfgQkx6LVakAORy7wZFptONVF+Qz7iO9Bl6x35cBA2A1o1W+ctDg== dependencies: "@babel/core" "^7.1.0" - babel-jest "^24.1.0" + "@jest/types" "^24.3.0" + babel-jest "^24.4.0" chalk "^2.0.1" glob "^7.1.1" - jest-environment-jsdom "^24.0.0" - jest-environment-node "^24.0.0" - jest-get-type "^24.0.0" - jest-jasmine2 "^24.1.0" - jest-regex-util "^24.0.0" - jest-resolve "^24.1.0" - jest-util "^24.0.0" - jest-validate "^24.0.0" + jest-environment-jsdom "^24.4.0" + jest-environment-node "^24.4.0" + jest-get-type "^24.3.0" + jest-jasmine2 "^24.4.0" + jest-regex-util "^24.3.0" + jest-resolve "^24.4.0" + jest-util "^24.3.0" + jest-validate "^24.4.0" micromatch "^3.1.10" - pretty-format "^24.0.0" - realpath-native "^1.0.2" + pretty-format "^24.4.0" + realpath-native "^1.1.0" -jest-diff@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.0.0.tgz#a3e5f573dbac482f7d9513ac9cfa21644d3d6b34" - integrity sha512-XY5wMpRaTsuMoU+1/B2zQSKQ9RdE9gsLkGydx3nvApeyPijLA8GtEvIcPwISRCer+VDf9W1mStTYYq6fPt8ryA== +jest-diff@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.4.0.tgz#106cd0491cb32da31debbea3e21f094d358dc7d9" + integrity sha512-2GdKN8GOledWkMGXcRCSr3KVTrjZU6vxbfZzwzRlM7gSG8HNIx+eoFXauQNQ5j7q73fZCoPnyS5/uOcXQ3wkWg== dependencies: chalk "^2.0.1" - diff-sequences "^24.0.0" - jest-get-type "^24.0.0" - pretty-format "^24.0.0" + diff-sequences "^24.3.0" + jest-get-type "^24.3.0" + pretty-format "^24.4.0" -jest-docblock@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.0.0.tgz#54d77a188743e37f62181a91a01eb9222289f94e" - integrity sha512-KfAKZ4SN7CFOZpWg4i7g7MSlY0M+mq7K0aMqENaG2vHuhC9fc3vkpU/iNN9sOus7v3h3Y48uEjqz3+Gdn2iptA== +jest-docblock@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.3.0.tgz#b9c32dac70f72e4464520d2ba4aec02ab14db5dd" + integrity sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg== dependencies: detect-newline "^2.1.0" -jest-each@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.0.0.tgz#10987a06b21c7ffbfb7706c89d24c52ed864be55" - integrity sha512-gFcbY4Cu55yxExXMkjrnLXov3bWO3dbPAW7HXb31h/DNWdNc/6X8MtxGff8nh3/MjkF9DpVqnj0KsPKuPK0cpA== +jest-each@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.4.0.tgz#2a0e06d957b31ec9ca4679ed9d4a15ac48299d6b" + integrity sha512-W98N4Ep6BBdCanynA9jdJDUaPvZ9OAnIHNA8mK6kbH7JYdnNQKGvp5ivl/PjCTqiI2wnHKYRI06EjsfOqT8ZFQ== dependencies: + "@jest/types" "^24.3.0" chalk "^2.0.1" - jest-get-type "^24.0.0" - jest-util "^24.0.0" - pretty-format "^24.0.0" + jest-get-type "^24.3.0" + jest-util "^24.3.0" + pretty-format "^24.4.0" -jest-environment-jsdom@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.0.0.tgz#5affa0654d6e44cd798003daa1a8701dbd6e4d11" - integrity sha512-1YNp7xtxajTRaxbylDc2pWvFnfDTH5BJJGyVzyGAKNt/lEULohwEV9zFqTgG4bXRcq7xzdd+sGFws+LxThXXOw== +jest-environment-jsdom-global@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom-global/-/jest-environment-jsdom-global-1.2.0.tgz#dd5b16fe0a0566ee40010d8632be5adf5a5ccb65" + integrity sha512-41cDl0OxzmFY/cnW0COUN+lnt2N2ks1r3V4fAKOnlZ9xIrGy0PNPan+Bz8HP+uQy/8bGV6T7J4Oi7X+h43It6g== + +jest-environment-jsdom@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.4.0.tgz#86e1c494abb1ab58b7aa5791bdb4fa96d709b57b" + integrity sha512-7irZXPZLQF79r97uH9dG9mm76H+27CMSH8TEcF70x6pY4xFJipjjluiXRw1C2lh0o6FrbSQKpkSXncdOw+hY0A== dependencies: - jest-mock "^24.0.0" - jest-util "^24.0.0" + "@jest/environment" "^24.4.0" + "@jest/fake-timers" "^24.3.0" + "@jest/types" "^24.3.0" + jest-mock "^24.3.0" + jest-util "^24.3.0" jsdom "^11.5.1" -jest-environment-node@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.0.0.tgz#330948980656ed8773ce2e04eb597ed91e3c7190" - integrity sha512-62fOFcaEdU0VLaq8JL90TqwI7hLn0cOKOl8vY2n477vRkCJRojiRRtJVRzzCcgFvs6gqU97DNqX5R0BrBP6Rxg== +jest-environment-node@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.4.0.tgz#c10cd617ccc73c1936d46a925e9dcade8709d044" + integrity sha512-ed1TjncsHO+Ird4BDrWwqsMQQM+bg9AFHj0AcCumgzfc+Us6ywWUQUg+5UbKLKnu1EWp5mK7mmbLxLqdz2kc9w== dependencies: - jest-mock "^24.0.0" - jest-util "^24.0.0" + "@jest/environment" "^24.4.0" + "@jest/fake-timers" "^24.3.0" + "@jest/types" "^24.3.0" + jest-mock "^24.3.0" + jest-util "^24.3.0" -jest-get-type@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.0.0.tgz#36e72930b78e33da59a4f63d44d332188278940b" - integrity sha512-z6/Eyf6s9ZDGz7eOvl+fzpuJmN9i0KyTt1no37/dHu8galssxz5ZEgnc1KaV8R31q1khxyhB4ui/X5ZjjPk77w== +jest-get-type@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.3.0.tgz#582cfd1a4f91b5cdad1d43d2932f816d543c65da" + integrity sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow== -jest-haste-map@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.0.0.tgz#e9ef51b2c9257384b4d6beb83bd48c65b37b5e6e" - integrity sha512-CcViJyUo41IQqttLxXVdI41YErkzBKbE6cS6dRAploCeutePYfUimWd3C9rQEWhX0YBOQzvNsC0O9nYxK2nnxQ== +jest-haste-map@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.4.0.tgz#a969ecab8a9521115c5fecec82366d66433c851b" + integrity sha512-X20xhhPBjbz4UVTN9BMBjlFUM/gmi1TmYWWxZUgLg4fZXMIve4RUdA/nS/QgC76ouGgvwb9z52KwZ85bmNx55A== dependencies: + "@jest/types" "^24.3.0" fb-watchman "^2.0.0" graceful-fs "^4.1.15" invariant "^2.2.4" - jest-serializer "^24.0.0" - jest-util "^24.0.0" - jest-worker "^24.0.0" + jest-serializer "^24.4.0" + jest-util "^24.3.0" + jest-worker "^24.4.0" micromatch "^3.1.10" - sane "^3.0.0" + sane "^4.0.3" -jest-jasmine2@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.1.0.tgz#8377324b967037c440f0a549ee0bbd9912055db6" - integrity sha512-H+o76SdSNyCh9fM5K8upK45YTo/DiFx5w2YAzblQebSQmukDcoVBVeXynyr7DDnxh+0NTHYRCLwJVf3tC518wg== +jest-jasmine2@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.4.0.tgz#f1d3749b1fc4a90cbdca1480f0ce932d135b69e5" + integrity sha512-J9A0SKWuUNDmXKU+a3Yj69NmUXK7R3btHHu1ZMpjHKlMoHggVjdzsolpNHELCENBOTXvcLXqEH0Xm+pYRoNfMw== dependencies: "@babel/traverse" "^7.1.0" + "@jest/environment" "^24.4.0" + "@jest/test-result" "^24.3.0" + "@jest/types" "^24.3.0" chalk "^2.0.1" co "^4.6.0" - expect "^24.1.0" + expect "^24.4.0" is-generator-fn "^2.0.0" - jest-each "^24.0.0" - jest-matcher-utils "^24.0.0" - jest-message-util "^24.0.0" - jest-snapshot "^24.1.0" - jest-util "^24.0.0" - pretty-format "^24.0.0" + jest-each "^24.4.0" + jest-matcher-utils "^24.4.0" + jest-message-util "^24.3.0" + jest-runtime "^24.4.0" + jest-snapshot "^24.4.0" + jest-util "^24.3.0" + pretty-format "^24.4.0" throat "^4.0.0" -jest-leak-detector@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.0.0.tgz#78280119fd05ee98317daee62cddb3aa537a31c6" - integrity sha512-ZYHJYFeibxfsDSKowjDP332pStuiFT2xfc5R67Rjm/l+HFJWJgNIOCOlQGeXLCtyUn3A23+VVDdiCcnB6dTTrg== +jest-leak-detector@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.4.0.tgz#f255d2f582b8dda7b960e04a42f7239b7ec6520b" + integrity sha512-PAo0y19ZkWZWYmdoPAQKpYTDt7IGwrTFhIwGmHO1xkRjzAWW8zcCoiMLrFwNSi9rir2ZH7el8gXZ0d2mmU7O9Q== dependencies: - pretty-format "^24.0.0" + pretty-format "^24.4.0" -jest-matcher-utils@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.0.0.tgz#fc9c41cfc49b2c3ec14e576f53d519c37729d579" - integrity sha512-LQTDmO+aWRz1Tf9HJg+HlPHhDh1E1c65kVwRFo5mwCVp5aQDzlkz4+vCvXhOKFjitV2f0kMdHxnODrXVoi+rlA== +jest-matcher-utils@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.4.0.tgz#285a2a5c8414d2f4a62d89ddc4b381730e2b717d" + integrity sha512-JDWrJ1G+GfxtEQlX7DlCV/0sk0uYbnra0jVl3DiDbS0FUX0HeGA1CxRW/U87LB3XNHQydhBKbXgf+pDCiUCn4w== dependencies: chalk "^2.0.1" - jest-diff "^24.0.0" - jest-get-type "^24.0.0" - pretty-format "^24.0.0" + jest-diff "^24.4.0" + jest-get-type "^24.3.0" + pretty-format "^24.4.0" -jest-message-util@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.0.0.tgz#a07a141433b2c992dbaec68d4cbfe470ba289619" - integrity sha512-J9ROJIwz/IeC+eV1XSwnRK4oAwPuhmxEyYx1+K5UI+pIYwFZDSrfZaiWTdq0d2xYFw4Xiu+0KQWsdsQpgJMf3Q== +jest-message-util@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.3.0.tgz#e8f64b63ebc75b1a9c67ee35553752596e70d4a9" + integrity sha512-lXM0YgKYGqN5/eH1NGw4Ix+Pk2I9Y77beyRas7xM24n+XTTK3TbT0VkT3L/qiyS7WkW0YwyxoXnnAaGw4hsEDA== dependencies: "@babel/code-frame" "^7.0.0" + "@jest/test-result" "^24.3.0" + "@jest/types" "^24.3.0" + "@types/stack-utils" "^1.0.1" chalk "^2.0.1" micromatch "^3.1.10" slash "^2.0.0" stack-utils "^1.0.1" -jest-mock@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.0.0.tgz#9a4b53e01d66a0e780f7d857462d063e024c617d" - integrity sha512-sQp0Hu5fcf5NZEh1U9eIW2qD0BwJZjb63Yqd98PQJFvf/zzUTBoUAwv/Dc/HFeNHIw1f3hl/48vNn+j3STaI7A== - -jest-regex-util@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.0.0.tgz#4feee8ec4a358f5bee0a654e94eb26163cb9089a" - integrity sha512-Jv/uOTCuC+PY7WpJl2mpoI+WbY2ut73qwwO9ByJJNwOCwr1qWhEW2Lyi2S9ZewUdJqeVpEBisdEVZSI+Zxo58Q== - -jest-resolve-dependencies@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.1.0.tgz#78f738a2ec59ff4d00751d9da56f176e3f589f6c" - integrity sha512-2VwPsjd3kRPu7qe2cpytAgowCObk5AKeizfXuuiwgm1a9sijJDZe8Kh1sFj6FKvSaNEfCPlBVkZEJa2482m/Uw== +jest-mock@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.3.0.tgz#95a86b6ad474e3e33227e6dd7c4ff6b07e18d3cb" + integrity sha512-AhAo0qjbVWWGvcbW5nChFjR0ObQImvGtU6DodprNziDOt+pP0CBdht/sYcNIOXeim8083QUi9bC8QdKB8PTK4Q== dependencies: - jest-regex-util "^24.0.0" - jest-snapshot "^24.1.0" + "@jest/types" "^24.3.0" -jest-resolve@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.1.0.tgz#42ff0169b0ea47bfdbd0c52a0067ca7d022c7688" - integrity sha512-TPiAIVp3TG6zAxH28u/6eogbwrvZjBMWroSLBDkwkHKrqxB/RIdwkWDye4uqPlZIXWIaHtifY3L0/eO5Z0f2wg== +jest-pnp-resolver@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" + integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== + +jest-regex-util@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.3.0.tgz#d5a65f60be1ae3e310d5214a0307581995227b36" + integrity sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg== + +jest-resolve-dependencies@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.4.0.tgz#296420c04211d2697dfe3141744e7071028ea9b0" + integrity sha512-3ssDSve3iSsIKm5daivq1mrCaBVFAa+TMG4qardNPoi7IJfupDUETIBCXYF9GRtIfNuD/dJOSag4u6oMHRxTGg== dependencies: + "@jest/types" "^24.3.0" + jest-regex-util "^24.3.0" + jest-snapshot "^24.4.0" + +jest-resolve@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.4.0.tgz#5314af3cc9abc8d2de55c6e78edac4253c2f46f3" + integrity sha512-XvMIuDH6wQi76YJfNG40iolXP2l+fA+LLORGgNSZ5VgowCeyV/XVygTN4L3No3GP1cthUdl/ULzWBd2CfYmTkw== + dependencies: + "@jest/types" "^24.3.0" browser-resolve "^1.11.3" chalk "^2.0.1" - realpath-native "^1.0.0" + jest-pnp-resolver "^1.2.1" + realpath-native "^1.1.0" -jest-runner@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.1.0.tgz#3686a2bb89ce62800da23d7fdc3da2c32792943b" - integrity sha512-CDGOkT3AIFl16BLL/OdbtYgYvbAprwJ+ExKuLZmGSCSldwsuU2dEGauqkpvd9nphVdAnJUcP12e/EIlnTX0QXg== +jest-runner@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.4.0.tgz#71ad09858be897cc37da1bf88bf67baaa0219fdb" + integrity sha512-eCuEMDbJknyKEUBWBDebW3GQ6Ty8wwB3YqDjFb4p3UQozA2HarPq0n9N83viq18vvZ/BDrQvW6RLdZaiLipM4Q== dependencies: + "@jest/console" "^24.3.0" + "@jest/environment" "^24.4.0" + "@jest/test-result" "^24.3.0" + "@jest/types" "^24.3.0" chalk "^2.4.2" exit "^0.1.2" graceful-fs "^4.1.15" - jest-config "^24.1.0" - jest-docblock "^24.0.0" - jest-haste-map "^24.0.0" - jest-jasmine2 "^24.1.0" - jest-leak-detector "^24.0.0" - jest-message-util "^24.0.0" - jest-runtime "^24.1.0" - jest-util "^24.0.0" - jest-worker "^24.0.0" + jest-config "^24.4.0" + jest-docblock "^24.3.0" + jest-haste-map "^24.4.0" + jest-jasmine2 "^24.4.0" + jest-leak-detector "^24.4.0" + jest-message-util "^24.3.0" + jest-resolve "^24.4.0" + jest-runtime "^24.4.0" + jest-util "^24.3.0" + jest-worker "^24.4.0" source-map-support "^0.5.6" throat "^4.0.0" -jest-runtime@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.1.0.tgz#7c157a2e776609e8cf552f956a5a19ec9c985214" - integrity sha512-59/BY6OCuTXxGeDhEMU7+N33dpMQyXq7MLK07cNSIY/QYt2QZgJ7Tjx+rykBI0skAoigFl0A5tmT8UdwX92YuQ== +jest-runtime@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.4.0.tgz#77df2137d1cb78a30f8b7c52cc06427272e06334" + integrity sha512-wmopIA6EqgfSvYmqFvfZViJy5LCyIATUSRRt16HQDNN4ypWUQAaFwZ9fpbPo7e2UnKHTe2CK0dCRB1o/a6JUfQ== dependencies: - "@babel/core" "^7.1.0" - babel-plugin-istanbul "^5.1.0" + "@jest/console" "^24.3.0" + "@jest/environment" "^24.4.0" + "@jest/source-map" "^24.3.0" + "@jest/transform" "^24.4.0" + "@jest/types" "^24.3.0" + "@types/yargs" "^12.0.2" chalk "^2.0.1" - convert-source-map "^1.4.0" exit "^0.1.2" - fast-json-stable-stringify "^2.0.0" glob "^7.1.3" graceful-fs "^4.1.15" - jest-config "^24.1.0" - jest-haste-map "^24.0.0" - jest-message-util "^24.0.0" - jest-regex-util "^24.0.0" - jest-resolve "^24.1.0" - jest-snapshot "^24.1.0" - jest-util "^24.0.0" - jest-validate "^24.0.0" - micromatch "^3.1.10" - realpath-native "^1.0.0" + jest-config "^24.4.0" + jest-haste-map "^24.4.0" + jest-message-util "^24.3.0" + jest-mock "^24.3.0" + jest-regex-util "^24.3.0" + jest-resolve "^24.4.0" + jest-snapshot "^24.4.0" + jest-util "^24.3.0" + jest-validate "^24.4.0" + realpath-native "^1.1.0" slash "^2.0.0" strip-bom "^3.0.0" - write-file-atomic "2.4.1" yargs "^12.0.2" -jest-serializer@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.0.0.tgz#522c44a332cdd194d8c0531eb06a1ee5afb4256b" - integrity sha512-9FKxQyrFgHtx3ozU+1a8v938ILBE7S8Ko3uiAVjT8Yfi2o91j/fj81jacCQZ/Ihjiff/VsUCXVgQ+iF1XdImOw== +jest-serializer@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.4.0.tgz#f70c5918c8ea9235ccb1276d232e459080588db3" + integrity sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q== -jest-snapshot@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.1.0.tgz#85e22f810357aa5994ab61f236617dc2205f2f5b" - integrity sha512-th6TDfFqEmXvuViacU1ikD7xFb7lQsPn2rJl7OEmnfIVpnrx3QNY2t3PE88meeg0u/mQ0nkyvmC05PBqO4USFA== +jest-snapshot@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.4.0.tgz#7e76ff377cf84af65e37b46c48bbda555e7545da" + integrity sha512-h+xO+ZQC+XEcf5wsy6+yducTKw6ku+oS5E2eJZI4YI65AT/lvbMjKgulgQWUOxga4HP0qHnz9uwa67/Zo7jVrw== dependencies: "@babel/types" "^7.0.0" + "@jest/types" "^24.3.0" chalk "^2.0.1" - jest-diff "^24.0.0" - jest-matcher-utils "^24.0.0" - jest-message-util "^24.0.0" - jest-resolve "^24.1.0" + expect "^24.4.0" + jest-diff "^24.4.0" + jest-matcher-utils "^24.4.0" + jest-message-util "^24.3.0" + jest-resolve "^24.4.0" mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^24.0.0" + pretty-format "^24.4.0" semver "^5.5.0" -jest-util@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.0.0.tgz#fd38fcafd6dedbd0af2944d7a227c0d91b68f7d6" - integrity sha512-QxsALc4wguYS7cfjdQSOr5HTkmjzkHgmZvIDkcmPfl1ib8PNV8QUWLwbKefCudWS0PRKioV+VbQ0oCUPC691fQ== +jest-util@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.3.0.tgz#a549ae9910fedbd4c5912b204bb1bcc122ea0057" + integrity sha512-eKIAC+MTKWZthUUVOwZ3Tc5a0cKMnxalQHr6qZ4kPzKn6k09sKvsmjCygqZ1SxVVfUKoa8Sfn6XDv9uTJ1iXTg== dependencies: + "@jest/console" "^24.3.0" + "@jest/fake-timers" "^24.3.0" + "@jest/source-map" "^24.3.0" + "@jest/test-result" "^24.3.0" + "@jest/types" "^24.3.0" + "@types/node" "*" callsites "^3.0.0" chalk "^2.0.1" graceful-fs "^4.1.15" is-ci "^2.0.0" - jest-message-util "^24.0.0" mkdirp "^0.5.1" slash "^2.0.0" source-map "^0.6.0" -jest-validate@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.0.0.tgz#aa8571a46983a6538328fef20406b4a496b6c020" - integrity sha512-vMrKrTOP4BBFIeOWsjpsDgVXATxCspC9S1gqvbJ3Tnn/b9ACsJmteYeVx9830UMV28Cob1RX55x96Qq3Tfad4g== +jest-validate@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.4.0.tgz#4f19c7d738a6bb700620c766428c7738d6985555" + integrity sha512-XESrpRYneLmiN9ayFm9RhBV5dwmhRZ+LbebScuuQ5GsY6ILpX9UeUMUdQ5Iz++YxFsmn5Lyi/Wkw6EV4v7nNTg== dependencies: + "@jest/types" "^24.3.0" camelcase "^5.0.0" chalk "^2.0.1" - jest-get-type "^24.0.0" + jest-get-type "^24.3.0" leven "^2.1.0" - pretty-format "^24.0.0" + pretty-format "^24.4.0" -jest-watcher@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.0.0.tgz#20d44244d10b0b7312410aefd256c1c1eef68890" - integrity sha512-GxkW2QrZ4YxmW1GUWER05McjVDunBlKMFfExu+VsGmXJmpej1saTEKvONdx5RJBlVdpPI5x6E3+EDQSIGgl53g== +jest-watcher@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.3.0.tgz#ee51c6afbe4b35a12fcf1107556db6756d7b9290" + integrity sha512-EpJS/aUG8D3DMuy9XNA4fnkKWy3DQdoWhY92ZUdlETIeEn1xya4Np/96MBSh4II5YvxwKe6JKwbu3Bnzfwa7vA== dependencies: + "@jest/test-result" "^24.3.0" + "@jest/types" "^24.3.0" + "@types/node" "*" + "@types/yargs" "^12.0.9" ansi-escapes "^3.0.0" chalk "^2.0.1" - jest-util "^24.0.0" + jest-util "^24.3.0" string-length "^2.0.0" -jest-worker@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0.tgz#3d3483b077bf04f412f47654a27bba7e947f8b6d" - integrity sha512-s64/OThpfQvoCeHG963MiEZOAAxu8kHsaL/rCMF7lpdzo7vgF0CtPml9hfguOMgykgH/eOm4jFP4ibfHLruytg== +jest-worker@^24.0.0, jest-worker@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.4.0.tgz#fbc452b0120bb5c2a70cdc88fa132b48eeb11dd0" + integrity sha512-BH9X/klG9vxwoO99ZBUbZFfV8qO0XNZ5SIiCyYK2zOuJBl6YJVAeNIQjcoOVNu4HGEHeYEKsUWws8kSlSbZ9YQ== dependencies: + "@types/node" "*" merge-stream "^1.0.1" supports-color "^6.1.0" -jest@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-24.1.0.tgz#b1e1135caefcf2397950ecf7f90e395fde866fd2" - integrity sha512-+q91L65kypqklvlRFfXfdzUKyngQLOcwGhXQaLmVHv+d09LkNXuBuGxlofTFW42XMzu3giIcChchTsCNUjQ78A== +jest@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-24.4.0.tgz#688b71a2dadd41e26d0cfc04e1ddcacf30a1efbb" + integrity sha512-gAGfjvu8hHN0N6/aDyCBpncWWBcpY6wq69Msq/I6Xd763q/ZYBEMh0SKUomrViFoJ/dyistA6b4aJh8e+5QMyw== dependencies: import-local "^2.0.0" - jest-cli "^24.1.0" + jest-cli "^24.4.0" joi@^11.1.1: version "11.4.0" @@ -6352,9 +6631,9 @@ js-base64@^2.1.9: integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw== js-beautify@^1.6.14: - version "1.8.9" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.8.9.tgz#08e3c05ead3ecfbd4f512c3895b1cda76c87d523" - integrity sha512-MwPmLywK9RSX0SPsUJjN7i+RQY9w/yC17Lbrq9ViEefpLRgqAR2BgrMN2AbifkUuhDV8tRauLhLda/9+bE0YQA== + version "1.9.0" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.9.0.tgz#2562fcdee340f9f962ae2ec4a8a40e7aaa6d964f" + integrity sha512-P0skmY4IDjfLiVrx+GLDeme8w5G0R1IGXgccVU5HP2VM3lRblH7qN2LTea5vZAxrDjpZBD0Jv+ahpjwVcbz/rw== dependencies: config-chain "^1.1.12" editorconfig "^0.15.2" @@ -6377,7 +6656,7 @@ js-tokens@^3.0.0, js-tokens@^3.0.2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.11.0, js-yaml@^3.9.0: +js-yaml@^3.11.0, js-yaml@^3.12.0, js-yaml@^3.9.0: version "3.12.2" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.2.tgz#ef1d067c5a9d9cb65bd72f285b5d8105c77f14fc" integrity sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q== @@ -6385,14 +6664,6 @@ js-yaml@^3.11.0, js-yaml@^3.9.0: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^3.12.0: - version "3.12.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600" - integrity sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - js-yaml@~3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" @@ -6406,11 +6677,6 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jsdom-global@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/jsdom-global/-/jsdom-global-3.0.2.tgz#6bd299c13b0c4626b2da2c0393cd4385d606acb9" - integrity sha1-a9KZwTsMRiay2iwDk81DhdYGrLk= - jsdom@^11.5.1: version "11.12.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8" @@ -6443,10 +6709,10 @@ jsdom@^11.5.1: ws "^5.2.0" xml-name-validator "^3.0.0" -jsdom@^13.2.0: - version "13.2.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-13.2.0.tgz#b1a0dbdadc255435262be8ea3723d2dba0d7eb3a" - integrity sha512-cG1NtMWO9hWpqRNRR3dSvEQa8bFI6iLlqU2x4kwX51FQjp0qus8T9aBaAO6iGp3DeBrhdwuKxckknohkmfvsFw== +jsdom@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-14.0.0.tgz#c7f1441ebcc57902d08d5fb2f6ba2baf746da7c6" + integrity sha512-/VkyPmdtbwqpJSkwDx3YyJ3U1oawYNB/h5z8vTUZGAzjtu2OHTeFRfnJqyMHsJ5Cyes23trOmvUpM1GfHH1leA== dependencies: abab "^2.0.0" acorn "^6.0.4" @@ -6837,10 +7103,10 @@ lodash.get@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= +lodash.kebabcase@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" + integrity sha1-hImxyw0p/4gZXM7KRI/21swpXDY= lodash.memoize@^4.1.2: version "4.1.2" @@ -6877,12 +7143,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash.uniqueid@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.uniqueid/-/lodash.uniqueid-4.0.1.tgz#3268f26a7c88e4f4b1758d679271814e31fa5b26" - integrity sha1-MmjyanyI5PSxdY1nknGBTjH6WyY= - -lodash@4.x, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1: +lodash@4.x, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== @@ -6936,7 +7197,7 @@ lowercase-keys@^1.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== -lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2, lru-cache@^4.1.3: +lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2, lru-cache@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== @@ -6951,7 +7212,7 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -magic-string@^0.25.1: +magic-string@^0.25.1, magic-string@^0.25.2: version "0.25.2" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.2.tgz#139c3a729515ec55e96e69e82a11fe890a293ad9" integrity sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg== @@ -6965,6 +7226,14 @@ make-dir@^1.0.0, make-dir@^1.3.0: dependencies: pify "^3.0.0" +make-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" @@ -7042,11 +7311,6 @@ math-expression-evaluator@^1.2.14: resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" integrity sha1-3oGf282E3M2PrlnGrreWFbnSZqw= -math-random@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" - integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== - md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -7155,11 +7419,6 @@ merge2@^1.2.3: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== -merge@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" - integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== - micromatch@^2.3.11: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" @@ -7206,24 +7465,12 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@~1.37.0: - version "1.37.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" - integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg== - mime-db@~1.38.0: version "1.38.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad" integrity sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg== -mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.21" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" - integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg== - dependencies: - mime-db "~1.37.0" - -mime-types@^2.1.18, mime-types@~2.1.18: +mime-types@^2.1.12, mime-types@^2.1.18, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.22" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd" integrity sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog== @@ -7356,7 +7603,7 @@ mkdirp@0.3.0: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" integrity sha1-G79asbqCevI1dRQ0kEJkVfSB/h4= -mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -7640,9 +7887,9 @@ npm-bundled@^1.0.1: integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== npm-packlist@^1.1.6: - version "1.3.0" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.3.0.tgz#7f01e8e44408341379ca98cfd756e7b29bd2626c" - integrity sha512-qPBc6CnxEzpOcc4bjoIBJbYdy0D/LFFPUdxvfwor4/w3vxeE0h6TiOVurCEPpQ6trjN77u/ShyfeJGsbAfB3dA== + version "1.4.1" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.1.tgz#19064cdf988da80ea3cee45533879d90192bbfbc" + integrity sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -7692,9 +7939,9 @@ number-is-nan@^1.0.0: integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= nwsapi@^2.0.7, nwsapi@^2.0.9: - version "2.1.0" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.1.0.tgz#781065940aed90d9bb01ca5d0ce0fcf81c32712f" - integrity sha512-ZG3bLAvdHmhIjaQ/Db1qvBxsGvFMLIRpQszyqbg31VJ53UP++uZX1/gf3Ut96pdwN9AuDwlMqIYLm0UPCdUeHg== + version "2.1.1" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.1.1.tgz#08d6d75e69fd791bdea31507ffafe8c843b67e9c" + integrity sha512-T5GaA1J/d34AC8mkrFD2O0DR17kwJ702ZOtJOsS8RpbsQZVOC2/xYFb1i/cw+xdM54JIlMuojjDOYct8GIWtwg== oauth-sign@~0.9.0: version "0.9.0" @@ -7715,16 +7962,11 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-keys@^1.0.11, object-keys@^1.1.0: +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg== -object-keys@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" - integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== - object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" @@ -7897,9 +8139,9 @@ p-limit@^1.0.0, p-limit@^1.1.0: p-try "^1.0.0" p-limit@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.1.0.tgz#1d5a0d20fb12707c758a655f6bbc4386b5930d68" - integrity sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g== + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" + integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== dependencies: p-try "^2.0.0" @@ -8120,6 +8362,11 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -8135,6 +8382,11 @@ pify@^3.0.0: resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" @@ -8147,10 +8399,10 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= -pirates@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.0.tgz#850b18781b4ac6ec58a43c9ed9ec5fe6796addbd" - integrity sha512-8t5BsXy1LUIjn3WWOlOuFDuKswhQb/tkak641lvBgmPOBUQHXveORtlMCp6OdPV1dtuTaEahKA8VNz6uLfKBtA== +pirates@^4.0.0, pirates@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" + integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== dependencies: node-modules-regexp "^1.0.0" @@ -8535,13 +8787,15 @@ pretty-error@^2.0.2: renderkid "^2.0.1" utila "~0.4" -pretty-format@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.0.0.tgz#cb6599fd73ac088e37ed682f61291e4678f48591" - integrity sha512-LszZaKG665djUcqg5ZQq+XzezHLKrxsA86ZABTozp+oNhkdqa+tG2dX4qa6ERl5c/sRDrAa3lHmwnvKoP+OG/g== +pretty-format@^24.4.0: + version "24.4.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.4.0.tgz#48db91969eb89f272c1bf3514bc5d5b228b3e722" + integrity sha512-SEXFzT01NwO4vaymwhz1/CM+wKCLOT92uqrzxIjmdRQMt7JAEuZ2eInCMvDS+4ZidEB+Rdq+fMs/Vwse8VAh1A== dependencies: + "@jest/types" "^24.3.0" ansi-regex "^4.0.0" ansi-styles "^3.2.0" + react-is "^16.8.4" pretty-time@^1.1.0: version "1.1.0" @@ -8575,7 +8829,7 @@ process@~0.5.1: resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= -progress@^2.0.0: +progress@^2.0.0, progress@^2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -8586,9 +8840,9 @@ promise-inflight@^1.0.1: integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= prompts@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.0.2.tgz#094119b0b0a553ec652908b583205b9867630154" - integrity sha512-Pc/c53d2WZHJWZr78/BhZ5eHsdQtltbyBjHoA4T0cs/4yKJqCcoOHrq2SNKwtspVE0C+ebqAR5u0/mXwrHaADQ== + version "2.0.3" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.0.3.tgz#c5ccb324010b2e8f74752aadceeb57134c1d2522" + integrity sha512-H8oWEoRZpybm6NV4to9/1limhttEo13xK62pNvn2JzY0MA03p7s0OjtmhXyon3uJmxiJJVSuUwEJFFssI3eBiQ== dependencies: kleur "^3.0.2" sisteransi "^1.0.0" @@ -8598,6 +8852,11 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= +proxy-from-env@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" + integrity sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4= + prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -8665,6 +8924,20 @@ punycode@^1.2.4, punycode@^1.4.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= +puppeteer-core@^1.13.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-1.13.0.tgz#f8001851e924e6e9ef6e9fae1778c3ab87c3f307" + integrity sha512-8MypjWVHu2EEdtN2HxhCsTtIYdJgiCcbGpHoosv265fzanfOICC2/DadLZq6/Qc/OKsovQmjkO+2vKMrV3BRfA== + dependencies: + debug "^4.1.0" + extract-zip "^1.6.6" + https-proxy-agent "^2.2.1" + mime "^2.0.3" + progress "^2.0.1" + proxy-from-env "^1.0.0" + rimraf "^2.6.1" + ws "^6.1.0" + q@^1.1.2, q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -8737,6 +9010,11 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-is@^16.8.4: + version "16.8.4" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.4.tgz#90f336a68c3a29a096a3d648ab80e87ec61482a2" + integrity sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA== + read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -8809,15 +9087,6 @@ read-pkg@^3.0.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6: - version "3.1.1" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.1.1.tgz#ed6bbc6c5ba58b090039ff18ce670515795aeb06" - integrity sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - readable-stream@^3.1.1: version "3.2.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.2.0.tgz#de17f229864c120a9f56945756e4f32c4045245d" @@ -8836,10 +9105,10 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" -realpath-native@^1.0.0, realpath-native@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.0.2.tgz#cd51ce089b513b45cf9b1516c82989b51ccc6560" - integrity sha512-+S3zTvVt9yTntFrBpm7TQmQ3tzpCrnA1a/y+3cUHAc9ZR6aIjG0WNLR+Rj79QpJktY+VeW/TQtFlQ1bzsehI8g== +realpath-native@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" + integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA== dependencies: util.promisify "^1.0.0" @@ -8882,13 +9151,6 @@ reduce@^1.0.1: dependencies: object-keys "^1.1.0" -regenerate-unicode-properties@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c" - integrity sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.1.tgz#58a4a74e736380a7ab3c5f7e03f303a941b31289" @@ -8896,6 +9158,13 @@ regenerate-unicode-properties@^8.0.1: dependencies: regenerate "^1.4.0" +regenerate-unicode-properties@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.2.tgz#7b38faa296252376d363558cfbda90c9ce709662" + integrity sha512-SbA/iNrBUf6Pv2zU8Ekv1Qbhv92yxL4hiDa2siuxs4KKn4oOoMDHXjAf7+Nz9qinUQ46B1LcWEi/PhJfPWpZWQ== + dependencies: + regenerate "^1.4.0" + regenerate@^1.2.1, regenerate@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" @@ -8959,17 +9228,17 @@ regexpu-core@^1.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" -regexpu-core@^4.1.3, regexpu-core@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.4.0.tgz#8d43e0d1266883969720345e70c275ee0aec0d32" - integrity sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA== +regexpu-core@^4.1.3, regexpu-core@^4.2.0, regexpu-core@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.5.4.tgz#080d9d02289aa87fe1667a4f5136bc98a6aebaae" + integrity sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ== dependencies: regenerate "^1.4.0" - regenerate-unicode-properties "^7.0.0" + regenerate-unicode-properties "^8.0.2" regjsgen "^0.5.0" regjsparser "^0.6.0" unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.0.2" + unicode-match-property-value-ecmascript "^1.1.0" regexpu-core@^4.1.4: version "4.5.3" @@ -9070,21 +9339,21 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request-promise-core@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" - integrity sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY= +request-promise-core@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346" + integrity sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag== dependencies: - lodash "^4.13.1" + lodash "^4.17.11" request-promise-native@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5" - integrity sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU= + version "1.0.7" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.7.tgz#a49868a624bdea5069f1251d0a836e0d89aa2c59" + integrity sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w== dependencies: - request-promise-core "1.1.1" - stealthy-require "^1.1.0" - tough-cookie ">=2.3.3" + request-promise-core "1.1.2" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" request@^2.87.0, request@^2.88.0: version "2.88.0" @@ -9205,14 +9474,14 @@ rollup-plugin-buble@^0.19.6: buble "^0.19.6" rollup-pluginutils "^2.3.3" -rollup-plugin-commonjs@^9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.2.0.tgz#4604e25069e0c78a09e08faa95dc32dec27f7c89" - integrity sha512-0RM5U4Vd6iHjL6rLvr3lKBwnPsaVml+qxOGaaNUWN1lSq6S33KhITOfHmvxV3z2vy9Mk4t0g4rNlVaJJsNQPWA== +rollup-plugin-commonjs@^9.2.1: + version "9.2.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.2.1.tgz#bb151ca8fa23600c7a03e25f9f0a45b1ee922dac" + integrity sha512-X0A/Cp/t+zbONFinBhiTZrfuUaVwRIp4xsbKq/2ohA2CDULa/7ONSJTelqxon+Vds2R2t2qJTqJQucKUC8GKkw== dependencies: estree-walker "^0.5.2" magic-string "^0.25.1" - resolve "^1.8.1" + resolve "^1.10.0" rollup-pluginutils "^2.3.3" rollup-plugin-json@^3.1.0: @@ -9222,14 +9491,23 @@ rollup-plugin-json@^3.1.0: dependencies: rollup-pluginutils "^2.3.1" -rollup-plugin-node-resolve@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.0.0.tgz#9bc6b8205e9936cc0e26bba2415f1ecf1e64d9b2" - integrity sha512-7Ni+/M5RPSUBfUaP9alwYQiIKnKeXCOHiqBpKUl9kwp3jX5ZJtgXAait1cne6pGEVUUztPD6skIKH9Kq9sNtfw== +rollup-plugin-node-resolve@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.0.1.tgz#f95765d174e5daeef9ea6268566141f53aa9d422" + integrity sha512-fSS7YDuCe0gYqKsr5OvxMloeZYUSgN43Ypi1WeRZzQcWtHgFayV5tUSPYpxuaioIIWaBXl6NrVk0T2/sKwueLg== dependencies: builtin-modules "^3.0.0" is-module "^1.0.0" - resolve "^1.8.1" + resolve "^1.10.0" + +rollup-plugin-replace@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-replace/-/rollup-plugin-replace-2.1.0.tgz#f9c07a4a89a2f8be912ee54b3f0f68d91e9ed0ae" + integrity sha512-SxrAIgpH/B5/W4SeULgreOemxcpEgKs2gcD42zXw50bhqGWmcnlXneVInQpAqzA/cIly4bJrOpeelmB9p4YXSQ== + dependencies: + magic-string "^0.25.1" + minimatch "^3.0.2" + rollup-pluginutils "^2.0.1" rollup-plugin-terser@^4.0.4: version "4.0.4" @@ -9241,22 +9519,22 @@ rollup-plugin-terser@^4.0.4: serialize-javascript "^1.6.1" terser "^3.14.1" -rollup-pluginutils@^2.3.1, rollup-pluginutils@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.3.3.tgz#3aad9b1eb3e7fe8262820818840bf091e5ae6794" - integrity sha512-2XZwja7b6P5q4RZ5FhyX1+f46xi1Z3qBKigLRZ6VTZjwbN0K1IFGMlwm06Uu0Emcre2Z63l77nq/pzn+KxIEoA== +rollup-pluginutils@^2.0.1, rollup-pluginutils@^2.3.1, rollup-pluginutils@^2.3.3: + version "2.4.1" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.4.1.tgz#de43ab54965bbf47843599a7f3adceb723de38db" + integrity sha512-wesMQ9/172IJDIW/lYWm0vW0LiKe5Ekjws481R7z9WTRtmO59cqyM/2uUlxvf6yzm/fElFmHUobeQOYz46dZJw== dependencies: - estree-walker "^0.5.2" - micromatch "^2.3.11" + estree-walker "^0.6.0" + micromatch "^3.1.10" -rollup@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.2.2.tgz#960416d098d3dba44bbe64c8db94510d6e568104" - integrity sha512-fsn5KJcfSuejjrv8GV7kZNciElqxyzZdUq8rA3e528JsR3ccxrWwoptyUY8GGLlgMFAQMB3dZW8nWF2I1/xrZA== +rollup@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.6.0.tgz#4329f4634718197c678d18491724d50d8b7ee76c" + integrity sha512-qu9iWyuiOxAuBM8cAwLuqPclYdarIpayrkfQB7aTGTiyYPbvx+qVF33sIznfq4bxZCiytQux/FvZieUBAXivCw== dependencies: "@types/estree" "0.0.39" - "@types/node" "*" - acorn "^6.1.0" + "@types/node" "^11.9.5" + acorn "^6.1.1" rsvp@^3.3.3: version "3.6.2" @@ -9301,22 +9579,20 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sane@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/sane/-/sane-3.1.0.tgz#995193b7dc1445ef1fe41ddfca2faf9f111854c6" - integrity sha512-G5GClRRxT1cELXfdAq7UKtUsv8q/ZC5k8lQGmjEm4HcAl3HzBy68iglyNCmw4+0tiXPCBZntslHlRhbnsSws+Q== +sane@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/sane/-/sane-4.0.3.tgz#e878c3f19e25cc57fbb734602f48f8a97818b181" + integrity sha512-hSLkC+cPHiBQs7LSyXkotC3UUtyn8C4FMn50TNaacRyvBlI+3ebcxMpqckmTdtXVtel87YS7GXN3UIOj7NiGVQ== dependencies: + "@cnakazawa/watch" "^1.0.3" anymatch "^2.0.0" capture-exit "^1.2.0" - exec-sh "^0.2.0" + exec-sh "^0.3.2" execa "^1.0.0" fb-watchman "^2.0.0" micromatch "^3.1.4" minimist "^1.1.1" walker "~1.0.5" - watch "~0.18.0" - optionalDependencies: - fsevents "^1.2.3" sax@0.5.x: version "0.5.8" @@ -9329,9 +9605,9 @@ sax@^1.2.4, sax@~1.2.1: integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== saxes@^3.1.5: - version "3.1.6" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.6.tgz#2d948a47b54918516c5a64096f08865deb5bd8cd" - integrity sha512-LAYs+lChg1v5uKNzPtsgTxSS5hLo8aIhSMCJt1WMpefAxm3D1RTpMwSpb6ebdL31cubiLTnhokVktBW+cv9Y9w== + version "3.1.9" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.9.tgz#c1c197cd54956d88c09f960254b999e192d7058b" + integrity sha512-FZeKhJglhJHk7eWG5YM0z46VHmI3KJpMBAQm3xa9meDvd+wevB5GuBB0wc0exPInZiBBHqi00DbS8AcvCGCFMw== dependencies: xmlchars "^1.3.1" @@ -9541,7 +9817,7 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.6, source-map-support@^0.5.9, source-map-support@~0.5.9: +source-map-support@^0.5.6, source-map-support@^0.5.9, source-map-support@~0.5.10: version "0.5.10" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" integrity sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ== @@ -9705,7 +9981,7 @@ std-env@^1.1.0, std-env@^1.3.1: dependencies: is-ci "^1.1.0" -stealthy-require@^1.1.0: +stealthy-require@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= @@ -9778,13 +10054,13 @@ string-width@^1.0.1: strip-ansi "^4.0.0" string-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.0.0.tgz#5a1690a57cc78211fffd9bf24bbe24d090604eb1" - integrity sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew== + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== dependencies: emoji-regex "^7.0.1" is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.0.0" + strip-ansi "^5.1.0" string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.2.0" @@ -9828,12 +10104,12 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f" - integrity sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow== +strip-ansi@^5.0.0, strip-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.1.0.tgz#55aaa54e33b4c0649a7338a43437b1887d153ec4" + integrity sha512-TjxrkPONqO2Z8QDCpeE2j6n0M6EwxzyDgzEeGp+FbdvaJAt//ClYi6W5my+3ROlC/hZX2KACUwDfK49Ka5eDvg== dependencies: - ansi-regex "^4.0.0" + ansi-regex "^4.1.0" strip-bom-string@^1.0.0: version "1.0.0" @@ -9929,6 +10205,11 @@ supports-color@^6.0.0, supports-color@^6.1.0: dependencies: has-flag "^3.0.0" +svg-tags@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" + integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= + svgo@^0.7.0: version "0.7.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" @@ -10018,13 +10299,13 @@ terser-webpack-plugin@^1.1.0: worker-farm "^1.5.2" terser@^3.14.1, terser@^3.16.1: - version "3.16.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-3.16.1.tgz#5b0dd4fa1ffd0b0b43c2493b2c364fd179160493" - integrity sha512-JDJjgleBROeek2iBcSNzOHLKsB/MdDf+E/BOAJ0Tk9r7p9/fVobfv7LMJ/g/k3v9SXdmjZnIlFd5nfn/Rt0Xow== + version "3.17.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2" + integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ== dependencies: - commander "~2.17.1" + commander "^2.19.0" source-map "~0.6.1" - source-map-support "~0.5.9" + source-map-support "~0.5.10" test-exclude@^5.0.0: version "5.1.0" @@ -10179,16 +10460,7 @@ toposort@^1.0.0: resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" integrity sha1-LmhELZ9k7HILjMieZEOsbKqVACk= -tough-cookie@>=2.3.3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2" - integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg== - dependencies: - ip-regex "^2.1.0" - psl "^1.1.28" - punycode "^2.1.1" - -tough-cookie@^2.3.4, tough-cookie@^2.5.0: +tough-cookie@^2.3.3, tough-cookie@^2.3.4, tough-cookie@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== @@ -10309,20 +10581,15 @@ unicode-match-property-ecmascript@^1.0.4: unicode-canonical-property-names-ecmascript "^1.0.4" unicode-property-aliases-ecmascript "^1.0.4" -unicode-match-property-value-ecmascript@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz#9f1dc76926d6ccf452310564fd834ace059663d4" - integrity sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ== - unicode-match-property-value-ecmascript@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== unicode-property-aliases-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz#5a533f31b4317ea76f17d807fa0d116546111dd0" - integrity sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg== + version "1.0.5" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" + integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== union-value@^1.0.0: version "1.0.0" @@ -10384,9 +10651,9 @@ unzip-response@^2.0.1: integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= upath@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" - integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== + version "1.1.2" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" + integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== update-notifier@^2.3.0: version "2.5.0" @@ -10536,11 +10803,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vlq@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.0.tgz#8101be90843422954c2b13eb27f2f3122bdcc806" - integrity sha512-o3WmXySo+oI5thgqr7Qy8uBkT/v9Zr+sRyrh1lr8aWPUkgDWdWt4Nae2WKBrLsocgE8BuWWD0jLc+VW8LeU+2g== - vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" @@ -10627,12 +10889,7 @@ vue-template-compiler@^2.5.16, vue-template-compiler@^2.6.8: de-indent "^1.0.2" he "^1.1.0" -vue-template-es2015-compiler@^1.6.0: - version "1.8.2" - resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.8.2.tgz#dd73e80ba58bb65dd7a8aa2aeef6089cf6116f2a" - integrity sha512-cliV19VHLJqFUYbz/XeWXe5CO6guzwd0yrrqqp0bmjlMP3ZZULY7fu8RTC4+3lmHwo6ESVDHFDsvjB15hcR5IA== - -vue-template-es2015-compiler@^1.9.0: +vue-template-es2015-compiler@^1.6.0, vue-template-es2015-compiler@^1.9.0: version "1.9.1" resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== @@ -10745,14 +11002,6 @@ walker@~1.0.5: dependencies: makeerror "1.0.x" -watch@~0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" - integrity sha1-KAlUdsbffJDJYxOJkMClQj60uYY= - dependencies: - exec-sh "^0.2.0" - minimist "^1.2.0" - watchpack@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" @@ -10951,7 +11200,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@^1.2.12, which@^1.2.9, which@^1.3.0: +which@^1.2.9, which@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -11168,10 +11417,10 @@ ws@^5.2.0: dependencies: async-limiter "~1.0.0" -ws@^6.1.2: - version "6.1.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.3.tgz#d2d2e5f0e3c700ef2de89080ebc0ac6e1bf3a72d" - integrity sha512-tbSxiT+qJI223AP4iLfQbkbxkwdFcneYinM2+x46Gx2wgvbaOMO36czfdfVUBRTHvzAMRhDd98sA5d/BuWbQdg== +ws@^6.1.0, ws@^6.1.2: + version "6.2.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.0.tgz#13806d9913b2a5f3cbb9ba47b563c002cbc7c526" + integrity sha512-deZYUNlt2O4buFCa3t5bKLf8A7FPP/TVjwOeVNpw818Ma5nk4MLXls2eoEGS39o8119QIYxTrTDoPQ5B/gTD6w== dependencies: async-limiter "~1.0.0" @@ -11243,6 +11492,13 @@ yargs@^12.0.2: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" +yauzl@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" + integrity sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU= + dependencies: + fd-slicer "~1.0.1" + ylru@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.2.1.tgz#f576b63341547989c1de7ba288760923b27fe84f"