diff --git a/Makefile b/Makefile index 0827b35d1b3..5371b099936 100644 --- a/Makefile +++ b/Makefile @@ -52,5 +52,8 @@ normalize_yaml: i18n-tasks normalize find ./config/locales -type f | xargs ./scripts/normalize-yaml +check_asset_strings: + find ./app/javascript -name "*.js*" | xargs ./scripts/check-assets + generate_deploy_checklist: ruby lib/release_management/generate_deploy_checklist.rb diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index be141f9340b..d60736db56a 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -1,2 +1,3 @@ //= require i18n-strings +//= require assets //= require local-time diff --git a/app/assets/javascripts/assets.js.erb b/app/assets/javascripts/assets.js.erb new file mode 100644 index 00000000000..f4c170af449 --- /dev/null +++ b/app/assets/javascripts/assets.js.erb @@ -0,0 +1,13 @@ +window.LoginGov = window.LoginGov || {}; +window.LoginGov.assets = {}; + +<% keys = [ + 'state-id-sample-front.jpg', + 'plus.svg', + 'minus.svg', + 'up-carat-thin.svg' +] %> + +<% keys.each do |key| %> + window.LoginGov.assets['<%= ActionController::Base.helpers.j key %>'] = '<%= ActionController::Base.helpers.j ActionController::Base.helpers.asset_path key %>'; +<% end %> diff --git a/app/assets/javascripts/i18n-strings.js.erb b/app/assets/javascripts/i18n-strings.js.erb index 1041c540cec..99743d7eb5f 100644 --- a/app/assets/javascripts/i18n-strings.js.erb +++ b/app/assets/javascripts/i18n-strings.js.erb @@ -46,7 +46,20 @@ window.LoginGov = window.LoginGov || {}; 'zxcvbn.feedback.this_is_similar_to_a_commonly_used_password', 'zxcvbn.feedback.for_a_stronger_password_use_a_few_words_separated_by_spaces_but_avoid_common_phrases', 'zxcvbn.feedback.use_a_longer_keyboard_pattern_with_more_turns', - 'doc_auth.headings.welcome' + 'doc_auth.headings.welcome', + 'image_description.accordian_plus_buttom', + 'image_description.accordian_minus_buttom', + 'users.personal_key.close', + 'doc_auth.tips.title', + 'doc_auth.tips.title_more', + 'doc_auth.tips.header_text', + 'doc_auth.tips.text1', + 'doc_auth.tips.text2', + 'doc_auth.tips.text3', + 'doc_auth.tips.text4', + 'doc_auth.tips.text5', + 'doc_auth.tips.text6', + 'doc_auth.tips.text7' ] %> window.LoginGov.I18n = { diff --git a/app/javascript/app/components/accordion.js b/app/javascript/app/components/accordion.js index 14f5da6239d..186ddd19985 100644 --- a/app/javascript/app/components/accordion.js +++ b/app/javascript/app/components/accordion.js @@ -17,8 +17,10 @@ class Accordion extends Events { } setup() { - this.bindEvents(); - this.onInitialize(); + if (!this.isInitialized()) { + this.bindEvents(); + this.onInitialize(); + } } bindEvents() { @@ -41,6 +43,11 @@ class Accordion extends Events { onInitialize() { this.setExpanded(false); this.collapsedIcon.classList.remove('display-none'); + this.el.setAttribute('data-initialized', ''); + } + + isInitialized() { + return this.el.hasAttribute('data-initialized'); } handleClick() { diff --git a/app/javascript/app/document-capture/components/accordion.jsx b/app/javascript/app/document-capture/components/accordion.jsx new file mode 100644 index 00000000000..76974a1c0ef --- /dev/null +++ b/app/javascript/app/document-capture/components/accordion.jsx @@ -0,0 +1,80 @@ +import React, { useEffect, useRef, useMemo } from 'react'; +import PropTypes from 'prop-types'; +import BaseAccordion from '../../components/accordion'; +import useI18n from '../hooks/use-i18n'; +import Image from './image'; + +function Accordion({ title, children }) { + const elementRef = useRef(null); + const instanceId = useMemo(() => { + Accordion.instances += 1; + return Accordion.instances; + }, []); + const t = useI18n(); + useEffect(() => { + new BaseAccordion(elementRef.current).setup(); + }, []); + + const contentId = `accordion-content-${instanceId}`; + + return ( +
+
+ +
+ +
+ ); +} + +Accordion.instances = 0; + +Accordion.propTypes = { + title: PropTypes.node.isRequired, + children: PropTypes.node.isRequired, +}; + +export default Accordion; diff --git a/app/javascript/app/document-capture/components/document-capture.jsx b/app/javascript/app/document-capture/components/document-capture.jsx index 70c91c459df..e4248849c93 100644 --- a/app/javascript/app/document-capture/components/document-capture.jsx +++ b/app/javascript/app/document-capture/components/document-capture.jsx @@ -1,9 +1,26 @@ +import React from 'react'; +import DocumentTips from './document-tips'; +import Image from './image'; import useI18n from '../hooks/use-i18n'; function DocumentCapture() { const t = useI18n(); - return t('doc_auth.headings.welcome'); + const sample = ( + Sample front of state issued ID + ); + + return ( + <> + + {t('doc_auth.headings.welcome')} + + ); } export default DocumentCapture; diff --git a/app/javascript/app/document-capture/components/document-tips.jsx b/app/javascript/app/document-capture/components/document-tips.jsx new file mode 100644 index 00000000000..07f0fe5c684 --- /dev/null +++ b/app/javascript/app/document-capture/components/document-tips.jsx @@ -0,0 +1,41 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Accordion from './accordion'; +import useI18n from '../hooks/use-i18n'; + +function DocumentTips({ sample }) { + const t = useI18n(); + + const title = ( + <> + {t('doc_auth.tips.title')} + {` ${t('doc_auth.tips.title_more')}`} + + ); + + return ( + + {t('doc_auth.tips.header_text')} + + {!!sample &&
{sample}
} +
+ ); +} + +DocumentTips.propTypes = { + sample: PropTypes.node, +}; + +DocumentTips.defaultProps = { + sample: null, +}; + +export default DocumentTips; diff --git a/app/javascript/app/document-capture/components/image.jsx b/app/javascript/app/document-capture/components/image.jsx new file mode 100644 index 00000000000..26a73bdba3c --- /dev/null +++ b/app/javascript/app/document-capture/components/image.jsx @@ -0,0 +1,27 @@ +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import AssetContext from '../context/asset'; + +function Image({ assetPath, alt, ...imgProps }) { + const assets = useContext(AssetContext); + + const src = Object.prototype.hasOwnProperty.call(assets, assetPath) + ? assets[assetPath] + : assetPath; + + // Disable reason: While props spreading can introduce confusion to what is + // being passed down, in this case the component is intended to represent a + // pass-through to a base `` element, with handling for asset paths. + // + // Seee: https://github.com/airbnb/javascript/tree/master/react#props + + // eslint-disable-next-line react/jsx-props-no-spreading + return {alt}; +} + +Image.propTypes = { + assetPath: PropTypes.string.isRequired, + alt: PropTypes.string.isRequired, +}; + +export default Image; diff --git a/app/javascript/app/document-capture/context/asset.js b/app/javascript/app/document-capture/context/asset.js new file mode 100644 index 00000000000..91173cbe6d9 --- /dev/null +++ b/app/javascript/app/document-capture/context/asset.js @@ -0,0 +1,5 @@ +import { createContext } from 'react'; + +const AssetContext = createContext({}); + +export default AssetContext; diff --git a/app/javascript/packs/document-capture.jsx b/app/javascript/packs/document-capture.jsx index 26e77f3dde9..99ac057e822 100644 --- a/app/javascript/packs/document-capture.jsx +++ b/app/javascript/packs/document-capture.jsx @@ -1,15 +1,18 @@ import React from 'react'; import { render } from 'react-dom'; import DocumentCapture from '../app/document-capture/components/document-capture'; +import AssetContext from '../app/document-capture/context/asset'; import I18nContext from '../app/document-capture/context/i18n'; -const { I18n: i18n } = window.LoginGov; +const { I18n: i18n, assets } = window.LoginGov; const appRoot = document.getElementById('document-capture-form'); appRoot.innerHTML = ''; render( - - - , + + + + + , appRoot, ); diff --git a/config/locales/doc_auth/en.yml b/config/locales/doc_auth/en.yml index 29f25e08c0a..8682fd90f0e 100644 --- a/config/locales/doc_auth/en.yml +++ b/config/locales/doc_auth/en.yml @@ -92,7 +92,9 @@ en: information. text7: Use a high-resolution camera. A good mobile phone or tablet camera will work. + title: Don't take the photo on a white surface! title_html: "Don't take the photo on a white surface!    See more tips..." + title_more: See more tips… titles: doc_auth: Document Authentication diff --git a/config/locales/doc_auth/es.yml b/config/locales/doc_auth/es.yml index fa31b60c9bf..8f4b8363858 100644 --- a/config/locales/doc_auth/es.yml +++ b/config/locales/doc_auth/es.yml @@ -99,6 +99,8 @@ es: la información. text7: Utilice una cámara de alta resolución. La cámara de un buen teléfono móvil o tableta funcionará. + title: "¡No tome la foto en una superficie blanca!" title_html: "¡No tome la foto en una superficie blanca! Ver más..." + title_more: Ver más… titles: doc_auth: Autenticación de documentos diff --git a/config/locales/doc_auth/fr.yml b/config/locales/doc_auth/fr.yml index f4c68e77c47..5f5e92e403b 100644 --- a/config/locales/doc_auth/fr.yml +++ b/config/locales/doc_auth/fr.yml @@ -107,6 +107,8 @@ fr: de lire toutes les informations. text7: Utilisez une caméra haute résolution. La caméra d'un bon téléphone mobile ou d'une tablette fonctionnera. + title: Ne prenez pas la photo sur une surface blanche! title_html: "Ne prenez pas la photo sur une surface blanche! Voir plus..." + title_more: Voir plus… titles: doc_auth: Authentification de document diff --git a/lib/asset_checker.rb b/lib/asset_checker.rb new file mode 100644 index 00000000000..d8a34418fcc --- /dev/null +++ b/lib/asset_checker.rb @@ -0,0 +1,39 @@ +class AssetChecker + def self.run(argv) + assets_file = 'app/assets/javascripts/assets.js.erb' + translations_file = 'app/assets/javascripts/i18n-strings.js.erb' + @asset_strings = load_included_strings(assets_file) + @translation_strings = load_included_strings(translations_file) + argv.map { |f| check_file(f) } + end + + def self.check_file(file) + data = File.open(file).read + missing_translations = find_missing(data, /\Wt\(['"](.*)['"]\)/, @translation_strings) + missing_assets = find_missing(data, /\WassetPath=["'](.*)['"]/, @asset_strings) + if missing_translations.any? || missing_assets.any? # rubocop:disable Style/GuardClause + warn file + missing_translations.each do |t| + warn "Missing translation, #{t}" + end + missing_assets.each do |a| + warn "Missing asset, #{a}" + end + end + end + + def self.find_missing(file_data, pattern, source) + missing = [] + strings = file_data.scan pattern + strings.each do |s| + missing.push(s) unless source.include? s + end + missing + end + + def self.load_included_strings(file) + data = File.open(file).read + key_data = data.split('<% keys = [')[1].split('] %>')[0] + key_data.scan(/['"](.*)['"]/) + end +end diff --git a/package.json b/package.json index f28f4324d2b..71cbb37668e 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "jquery": "^3.5.0", "libphonenumber-js": "^1.7.26", "normalize.css": "^4.2.0", + "prop-types": "^15.7.2", "react": "^16.13.1", "react-dom": "^16.13.1", "sinon": "^1.17.7", @@ -37,7 +38,7 @@ "@babel/preset-react": "^7.10.4", "@babel/register": "^7.4.4", "atob": "^2.1.2", - "babel-eslint": "^7.2.3", + "babel-eslint": "^10.1.0", "btoa": "^1.2.1", "chai": "^3.5.0", "dirty-chai": "^1.2.2", diff --git a/scripts/check-assets b/scripts/check-assets new file mode 100755 index 00000000000..0308e9cefd9 --- /dev/null +++ b/scripts/check-assets @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +$LOAD_PATH.unshift(File.expand_path('../lib', File.dirname(__FILE__))) +require 'asset_checker' + +AssetChecker.run(ARGV) + diff --git a/spec/javascripts/app/document-capture/components/accordion-spec.jsx b/spec/javascripts/app/document-capture/components/accordion-spec.jsx new file mode 100644 index 00000000000..258c2e75805 --- /dev/null +++ b/spec/javascripts/app/document-capture/components/accordion-spec.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import Accordion from '../../../../../app/javascript/app/document-capture/components/accordion'; +import { useDOM } from '../../../support/dom'; + +describe('document-capture/components/accordion', () => { + useDOM(); + + it('renders with a unique ID', () => { + const { container } = render( + <> + Content + Content + , + ); + + const contents = container.querySelectorAll('[id^="accordion-content-"]'); + + expect(contents).to.have.lengthOf(2); + expect(contents[0].id).to.be.ok(); + expect(contents[1].id).to.be.ok(); + expect(contents[0].id).not.to.equal(contents[1].id); + }); +}); diff --git a/spec/javascripts/app/document-capture/components/image-spec.jsx b/spec/javascripts/app/document-capture/components/image-spec.jsx new file mode 100644 index 00000000000..6854f8ecc77 --- /dev/null +++ b/spec/javascripts/app/document-capture/components/image-spec.jsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import Image from '../../../../../app/javascript/app/document-capture/components/image'; +import { useDOM } from '../../../support/dom'; +import AssetContext from '../../../../../app/javascript/app/document-capture/context/asset'; + +describe('document-capture/components/image', () => { + useDOM(); + + it('renders the given assetPath as src if the asset is not known', () => { + const { getByAltText } = render( + unknown, + ); + + const img = getByAltText('unknown'); + + expect(img.src).to.equal('unknown.png'); + }); + + it('renders an img at mapped src if known by context', () => { + const { getByAltText } = render( + + icon + , + ); + + const img = getByAltText('icon'); + + expect(img.src).to.equal('icon-12345.png'); + }); + + it('renders with given props', () => { + const { getByAltText } = render( + icon, + ); + + const img = getByAltText('icon'); + + expect(img.width).to.equal(50); + }); +}); diff --git a/spec/javascripts/app/document-capture/context/asset-spec.jsx b/spec/javascripts/app/document-capture/context/asset-spec.jsx new file mode 100644 index 00000000000..670c5696d03 --- /dev/null +++ b/spec/javascripts/app/document-capture/context/asset-spec.jsx @@ -0,0 +1,16 @@ +import React, { useContext } from 'react'; +import { render } from '@testing-library/react'; +import AssetContext from '../../../../../app/javascript/app/document-capture/context/asset'; +import { useDOM } from '../../../support/dom'; + +describe('document-capture/context/asset', () => { + useDOM(); + + const ContextValue = () => JSON.stringify(useContext(AssetContext)); + + it('defaults to empty object', () => { + const { container } = render(); + + expect(container.textContent).to.equal('{}'); + }); +}); diff --git a/spec/javascripts/spec_helper.js b/spec/javascripts/spec_helper.js index 6b37c24633a..df575b7c2ec 100644 --- a/spec/javascripts/spec_helper.js +++ b/spec/javascripts/spec_helper.js @@ -3,3 +3,12 @@ const dirtyChai = require('dirty-chai'); chai.use(dirtyChai); global.expect = chai.expect; + +// classList.js will throw an error when loaded into the test environment, since +// it assumes the presence of a `self` global. This shim is enough only to skip +// the polyfill. It's expected where a DOM is used that JSDOM will provide the +// Element#classList implementation. +// +// See: https://github.com/eligrey/classList.js/issues/48 +// See: https://github.com/eligrey/classList.js/blob/ecb3305/classList.js#L14 +global.self = global; diff --git a/yarn.lock b/yarn.lock index d2abc1980ff..dc53ab2ca76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,6 +9,13 @@ dependencies: "@babel/highlight" "^7.8.3" +"@babel/code-frame@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== + dependencies: + "@babel/highlight" "^7.10.4" + "@babel/compat-data@^7.8.6", "@babel/compat-data@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.0.tgz#04815556fc90b0c174abd2c0c1bb966faa036a6c" @@ -40,6 +47,15 @@ semver "^5.4.1" source-map "^0.5.0" +"@babel/generator@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.5.tgz#1b903554bc8c583ee8d25f1e8969732e6b829a69" + integrity sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig== + dependencies: + "@babel/types" "^7.10.5" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/generator@^7.9.0": version "7.9.3" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.3.tgz#7c8b2956c6f68b3ab732bd16305916fbba521d94" @@ -138,6 +154,15 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== + dependencies: + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helper-function-name@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" @@ -147,6 +172,13 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.8.3" +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== + dependencies: + "@babel/types" "^7.10.4" + "@babel/helper-get-function-arity@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" @@ -248,6 +280,13 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.8.3" +"@babel/helper-split-export-declaration@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz#2c70576eaa3b5609b24cb99db2888cc3fc4251d1" + integrity sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg== + dependencies: + "@babel/types" "^7.10.4" + "@babel/helper-split-export-declaration@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" @@ -284,6 +323,15 @@ "@babel/traverse" "^7.9.0" "@babel/types" "^7.9.0" +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@babel/highlight@^7.8.3": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" @@ -293,6 +341,11 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/parser@^7.10.4", "@babel/parser@^7.10.5", "@babel/parser@^7.7.0": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.5.tgz#e7c6bf5a7deff957cec9f04b551e2762909d826b" + integrity sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ== + "@babel/parser@^7.8.6", "@babel/parser@^7.9.0": version "7.9.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.3.tgz#043a5fc2ad8b7ea9facddc4e802a1f0f25da7255" @@ -876,6 +929,15 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/template@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/template@^7.8.3", "@babel/template@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" @@ -885,6 +947,21 @@ "@babel/parser" "^7.8.6" "@babel/types" "^7.8.6" +"@babel/traverse@^7.7.0": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.5.tgz#77ce464f5b258be265af618d8fddf0536f20b564" + integrity sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.10.5" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/parser" "^7.10.5" + "@babel/types" "^7.10.5" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.0.tgz#d3882c2830e513f4fe4cec9fe76ea1cc78747892" @@ -909,6 +986,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.10.5", "@babel/types@^7.7.0": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.5.tgz#d88ae7e2fde86bfbfe851d4d81afa70a997b5d15" + integrity sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.0.tgz#00b064c3df83ad32b2dbf5ff07312b15c7f1efb5" @@ -1616,24 +1702,17 @@ axobject-query@^2.1.2: resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== -babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= +babel-eslint@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" + integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-eslint@^7.2.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.3.tgz#b2fe2d80126470f5c19442dc757253a897710827" - integrity sha1-sv4tgBJkcPXBlELcdXJTqJdxCCc= - dependencies: - babel-code-frame "^6.22.0" - babel-traverse "^6.23.1" - babel-types "^6.23.0" - babylon "^6.17.0" + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" babel-loader@^8.0.6: version "8.1.0" @@ -1646,13 +1725,6 @@ babel-loader@^8.0.6: pify "^4.0.1" schema-utils "^2.6.5" -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= - dependencies: - babel-runtime "^6.22.0" - babel-plugin-dynamic-import-node@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" @@ -1669,44 +1741,6 @@ babel-plugin-macros@^2.6.1: cosmiconfig "^6.0.0" resolve "^1.12.0" -babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-traverse@^6.23.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.23.0, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon@^6.17.0, babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -2316,7 +2350,7 @@ chalk@2.4.2, chalk@^2.0, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^1.1.1, chalk@^1.1.3: +chalk@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= @@ -2678,11 +2712,6 @@ core-js-pure@^3.0.0: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== -core-js@^2.4.0: - version "2.6.11" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" - integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== - core-js@^3.4.0: version "3.6.4" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.4.tgz#440a83536b458114b9cb2ac1580ba377dc470647" @@ -3011,7 +3040,7 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, 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== @@ -4268,11 +4297,6 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== - globby@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" @@ -5089,11 +5113,6 @@ js-base64@^2.1.8: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= - js-yaml@3.13.1, js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" @@ -5427,11 +5446,12 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.12: +lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.5, lodash@~4.17.12: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + log-symbols@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" @@ -7593,11 +7613,6 @@ regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4: version "0.13.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" @@ -8723,11 +8738,6 @@ to-arraybuffer@^1.0.0: resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"