diff options
38 files changed, 840 insertions, 1262 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index 91ea92c..2cd4c02 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,8 +5,8 @@ executors: docker: - image: circleci/node:12.14.0-stretch-browsers environment: - - FIREFOX_VERSION: "68.0esr" - - GECKODRIVER_VERSION: "0.24.0" + - FIREFOX_VERSION: "78.3.0esr" + - GECKODRIVER_VERSION: "0.27.0" working_directory: ~ commands: @@ -15,7 +15,7 @@ For usage and more detailed information, check out our [documentations][document ## Compatibility -- Firefox 68 ESR +- Firefox 78 ESR ## Copyright diff --git a/e2e/lib/FormOptionPage.ts b/e2e/lib/FormOptionPage.ts index 5551684..666bac7 100644 --- a/e2e/lib/FormOptionPage.ts +++ b/e2e/lib/FormOptionPage.ts @@ -1,5 +1,5 @@ import { Lanthan } from "lanthan"; -import { WebDriver, By, until } from "selenium-webdriver"; +import { WebDriver, WebElement, By, error } from "selenium-webdriver"; export default class FormOptionPage { private webdriver: WebDriver; @@ -9,15 +9,15 @@ export default class FormOptionPage { } async setBlacklist(nth: number, url: string): Promise<void> { - const selector = ".form-blacklist-form-row > .column-url"; - const inputs = await this.webdriver.findElements(By.css(selector)); - if (inputs.length <= nth) { + const fieldset = await this.getFieldsetByLegend("Blacklist"); + const rows = await fieldset.findElements(By.css("[role=listitem]")); + if (rows.length <= nth) { throw new RangeError("Index out of range to set a blacklist"); } - await inputs[nth].sendKeys(url); - await this.webdriver.executeScript( - `document.querySelectorAll('${selector}')[${nth}].blur()` - ); + + const input = rows[nth].findElement(By.css("[aria-label=URL]")); + await input.sendKeys(url); + await this.blurActiveElement(); } async setPartialBlacklist( @@ -25,121 +25,122 @@ export default class FormOptionPage { url: string, keys: string ): Promise<void> { - let selector = ".form-partial-blacklist-form-row > .column-url"; - let inputs = await this.webdriver.findElements(By.css(selector)); - if (inputs.length <= nth) { + const fieldset = await this.getFieldsetByLegend("Partial blacklist"); + const rows = await fieldset.findElements(By.css("[role=listitem]")); + if (rows.length <= nth) { throw new RangeError("Index out of range to set a partial blacklist"); } - await inputs[nth].sendKeys(url); - await this.webdriver.executeScript( - `document.querySelectorAll('${selector}')[${nth}].blur()` - ); - selector = ".form-partial-blacklist-form-row > .column-keys"; - inputs = await this.webdriver.findElements(By.css(selector)); - if (inputs.length <= nth) { - throw new RangeError("Index out of range to set a partial blacklist"); - } - await inputs[nth].sendKeys(keys); - await this.webdriver.executeScript( - `document.querySelectorAll('${selector}')[${nth}].blur()` - ); + const urlInput = rows[nth].findElement(By.css("[aria-label=URL]")); + await urlInput.sendKeys(url); + await this.blurActiveElement(); + + const keysInput = rows[nth].findElement(By.css("[aria-label=Keys]")); + await keysInput.sendKeys(keys); + await this.blurActiveElement(); } async setSearchEngine(nth: number, name: string, url: string) { - let selector = ".form-search-form-row > .column-name"; - let inputs = await this.webdriver.findElements(By.css(selector)); - if (inputs.length <= nth) { + const fieldset = await this.getFieldsetByLegend("Search Engines"); + const rows = await fieldset.findElements(By.css("[role=listitem]")); + if (rows.length <= nth) { throw new RangeError("Index out of range to set a search engine"); } - await inputs[nth].sendKeys(name); - await this.webdriver.executeScript( - `document.querySelectorAll('${selector}')[${nth}].blur()` - ); - selector = ".form-search-form-row > .column-url"; - inputs = await this.webdriver.findElements(By.css(selector)); - if (inputs.length <= nth) { - throw new RangeError("Index out of range to set a search engine"); - } - await inputs[nth].sendKeys(url); - await this.webdriver.executeScript( - `document.querySelectorAll('${selector}')[${nth}].blur()` - ); + const nameInput = rows[nth].findElement(By.css("[aria-label=Name")); + await nameInput.sendKeys(name); + await this.blurActiveElement(); + + const urlInput = rows[nth].findElement(By.css("[aria-label=URL]")); + await urlInput.sendKeys(url); + await this.blurActiveElement(); } async addBlacklist(): Promise<void> { - const rows = await this.webdriver.findElements( - By.css(`.form-blacklist-form-row`) - ); - const button = await this.webdriver.findElement( - By.css(".form-blacklist-form .ui-add-button") - ); - await button.click(); - await this.webdriver.wait( - until.elementLocated( - By.css(`.form-blacklist-form-row:nth-child(${rows.length + 1})`) - ) - ); + const fieldset = await this.getFieldsetByLegend("Blacklist"); + const rows = await fieldset.findElements(By.css("[role=listitem]")); + const addButton = await fieldset.findElement(By.css("[aria-label=Add]")); + + await addButton.click(); + await this.webdriver.wait(async () => { + const newRows = await fieldset.findElements(By.css("[role=listitem]")); + return newRows.length == rows.length + 1; + }); } async addPartialBlacklist(): Promise<void> { - const rows = await this.webdriver.findElements( - By.css(`.form-partial-blacklist-form-row`) - ); - const button = await this.webdriver.findElement( - By.css(".form-partial-blacklist-form .ui-add-button") - ); - await button.click(); - await this.webdriver.wait( - until.elementLocated( - By.css(`.form-partial-blacklist-form-row:nth-child(${rows.length + 2})`) - ) - ); + const fieldset = await this.getFieldsetByLegend("Partial blacklist"); + const addButton = await fieldset.findElement(By.css("[aria-label=Add]")); + const rows = await fieldset.findElements(By.css("[role=listitem]")); + + await addButton.click(); + await this.webdriver.wait(async () => { + const newRows = await fieldset.findElements(By.css("[role=listitem]")); + return newRows.length == rows.length + 1; + }); } async removeBlackList(nth: number): Promise<void> { - const buttons = await this.webdriver.findElements( - By.css(".form-blacklist-form-row .ui-delete-button") + const fieldset = await this.getFieldsetByLegend("Blacklist"); + const deleteButtons = await fieldset.findElements( + By.css("[aria-label=Delete]") ); - if (buttons.length <= nth) { + if (deleteButtons.length <= nth) { throw new RangeError("Index out of range to remove blacklist"); } - await buttons[nth].click(); + await deleteButtons[nth].click(); } async removePartialBlackList(nth: number): Promise<void> { - const buttons = await this.webdriver.findElements( - By.css(".form-partial-blacklist-form-row .ui-delete-button") - ); - if (buttons.length <= nth) { - throw new RangeError("Index out of range to remove partial blacklist"); + const fieldset = await this.getFieldsetByLegend("Partial blacklist"); + const deleteButtons = await fieldset.findElements( + By.css("[aria-label=Delete]") + ); + if (deleteButtons.length <= nth) { + throw new RangeError( + `Index out of range ${deleteButtons.length} to remove partial blacklist ${nth}` + ); } - await buttons[nth].click(); + await deleteButtons[nth].click(); } async addSearchEngine(): Promise<void> { - const rows = await this.webdriver.findElements( - By.css(`.form-search-form-row > .column-name`) - ); - const button = await this.webdriver.findElement( - By.css(".form-search-form > .ui-add-button") - ); - await button.click(); - await this.webdriver.wait( - until.elementLocated( - By.css(`.form-search-form-row:nth-child(${rows.length + 1})`) - ) - ); + const fieldset = await this.getFieldsetByLegend("Search Engines"); + const rows = await fieldset.findElements(By.css("[role=listitem]")); + const addButton = await fieldset.findElement(By.css("[aria-label=Add]")); + + await addButton.click(); + await this.webdriver.wait(async () => { + const newRows = await fieldset.findElements(By.css("[role=listitem]")); + return newRows.length == rows.length + 1; + }); } async setDefaultSearchEngine(nth: number): Promise<void> { - const radios = await this.webdriver.findElements( - By.css(".form-search-form-row input[type=radio]") + const fieldset = await this.getFieldsetByLegend("Search Engines"); + const radios = await fieldset.findElements( + By.css("[name=default][type=radio]") ); if (radios.length <= nth) { throw new RangeError("Index out of range to set a default search engine"); } await radios[nth].click(); } + + private async getFieldsetByLegend(legendText: string): Promise<WebElement> { + const fieldsets = await this.webdriver.findElements(By.tagName("fieldset")); + for (const fieldset of fieldsets) { + const legend = await fieldset.findElement(By.tagName("legend")); + if ((await legend.getText()) === legendText) { + return fieldset; + } + } + throw new error.NoSuchElementError( + `Unable to locate fieldset with legend: ` + legendText + ); + } + + private async blurActiveElement(): Promise<void> { + await this.webdriver.executeScript(`document.activeElement.blur()`); + } } diff --git a/e2e/lib/JSONOptionPage.ts b/e2e/lib/JSONOptionPage.ts index 0f2b0a7..2d8147e 100644 --- a/e2e/lib/JSONOptionPage.ts +++ b/e2e/lib/JSONOptionPage.ts @@ -20,9 +20,7 @@ export default class JSONOptionPage { } async getErrorMessage(): Promise<string> { - const error = await this.webdriver.findElement( - By.css(".settings-ui-input-error") - ); + const error = await this.webdriver.findElement(By.css("p[role=alert]")); return error.getText(); } } diff --git a/package.json b/package.json index c31744f..14da1c7 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,6 @@ "karma-webpack": "^4.0.2", "lanthan": "0.0.2", "mocha": "^8.1.1", - "node-sass": "^4.13.1", "prettier": "2.1.2", "prettier-eslint": "11.0.0", "react": "16.13.1", @@ -73,7 +72,6 @@ "redux-promise": "^0.6.0", "reflect-metadata": "^0.1.13", "request-promise-native": "^1.0.8", - "sass-loader": "^9.0.3", "sinon": "^9.0.3", "sinon-chrome": "^3.0.1", "style-loader": "^1.1.3", diff --git a/src/console/components/Console.tsx b/src/console/components/Console.tsx index a23c459..1c673fa 100644 --- a/src/console/components/Console.tsx +++ b/src/console/components/Console.tsx @@ -1,4 +1,3 @@ -import "./console.scss"; import { connect } from "react-redux"; import React from "react"; import Input from "./console/Input"; diff --git a/src/console/components/console.scss b/src/console/index.css index 2d548df..2d548df 100644 --- a/src/console/components/console.scss +++ b/src/console/index.css diff --git a/src/console/index.tsx b/src/console/index.tsx index e1a9dd3..228625e 100644 --- a/src/console/index.tsx +++ b/src/console/index.tsx @@ -5,6 +5,7 @@ import promise from "redux-promise"; import * as consoleActions from "./actions/console"; import { Provider } from "react-redux"; import Console from "./components/Console"; +import "./index.css"; import React from "react"; import ReactDOM from "react-dom"; diff --git a/src/content/presenters/FocusPresenter.ts b/src/content/presenters/FocusPresenter.ts index 4d70a6e..3591039 100644 --- a/src/content/presenters/FocusPresenter.ts +++ b/src/content/presenters/FocusPresenter.ts @@ -11,7 +11,7 @@ export class FocusPresenterImpl implements FocusPresenter { .map((type) => `input[type=${type}]`) .join(","); const targets = window.document.querySelectorAll( - inputSelector + ",textarea" + inputSelector + ",input:not([type]),textarea" ); const target = Array.from(targets).find(doms.isVisible); if (target instanceof HTMLInputElement) { diff --git a/src/settings/components/form/BlacklistForm.scss b/src/settings/components/form/BlacklistForm.scss deleted file mode 100644 index a230d0d..0000000 --- a/src/settings/components/form/BlacklistForm.scss +++ /dev/null @@ -1,9 +0,0 @@ -.form-blacklist-form { - &-row { - display: flex; - - .column-url { - flex: 1; - } - } -} diff --git a/src/settings/components/form/BlacklistForm.tsx b/src/settings/components/form/BlacklistForm.tsx index 859cb9f..6fb9eca 100644 --- a/src/settings/components/form/BlacklistForm.tsx +++ b/src/settings/components/form/BlacklistForm.tsx @@ -1,9 +1,29 @@ -import "./BlacklistForm.scss"; +import styled from "styled-components"; import AddButton from "../ui/AddButton"; import DeleteButton from "../ui/DeleteButton"; import React from "react"; import Blacklist, { BlacklistItem } from "../../../shared/settings/Blacklist"; +const Grid = styled.div``; + +const GridRow = styled.div` + display: flex; +`; + +const GridCell = styled.div<{ grow?: number }>` + &:nth-child(1) { + flex-grow: 1; + } + &:nth-child(2) { + flex-shrink: 1; + } +`; + +const Input = styled.input` + width: 100%; + box-sizing: border-box; +`; + interface Props { value: Blacklist; onChange: (value: Blacklist) => void; @@ -19,37 +39,46 @@ class BlacklistForm extends React.Component<Props> { render() { return ( - <div className="form-blacklist-form"> - {this.props.value.items.map((item, index) => { - if (item.partial) { - return null; - } - return ( - <div key={index} className="form-blacklist-form-row"> - <input - data-index={index} - type="text" - name="url" - className="column-url" - value={item.pattern} - onChange={this.bindValue.bind(this)} - onBlur={this.props.onBlur} - /> - <DeleteButton - data-index={index} - name="delete" - onClick={this.bindValue.bind(this)} - onBlur={this.props.onBlur} - /> - </div> - ); - })} + <> + <Grid role="list"> + {this.props.value.items.map((item, index) => { + if (item.partial) { + return null; + } + return ( + <GridRow role="listitem" key={index}> + <GridCell> + <Input + data-index={index} + type="text" + name="url" + aria-label="URL" + value={item.pattern} + placeholder="example.com/mail/*" + onChange={this.bindValue.bind(this)} + onBlur={this.props.onBlur} + /> + </GridCell> + <GridCell> + <DeleteButton + data-index={index} + name="delete" + onClick={this.bindValue.bind(this)} + onBlur={this.props.onBlur} + aria-label="Delete" + /> + </GridCell> + </GridRow> + ); + })} + </Grid> <AddButton name="add" + aria-label="Add" style={{ float: "right" }} onClick={this.bindValue.bind(this)} /> - </div> + </> ); } diff --git a/src/settings/components/form/KeymapsForm.scss b/src/settings/components/form/KeymapsForm.scss deleted file mode 100644 index 1a4e5cd..0000000 --- a/src/settings/components/form/KeymapsForm.scss +++ /dev/null @@ -1,11 +0,0 @@ -.form-keymaps-form { - column-count: 3; - - &-field-group { - margin-top: 24px; - } - - &-field-group:first-of-type { - margin-top: 24px; - } -} diff --git a/src/settings/components/form/KeymapsForm.tsx b/src/settings/components/form/KeymapsForm.tsx index b9af0df..6582529 100644 --- a/src/settings/components/form/KeymapsForm.tsx +++ b/src/settings/components/form/KeymapsForm.tsx @@ -1,9 +1,21 @@ -import "./KeymapsForm.scss"; import React from "react"; -import Input from "../ui/Input"; +import styled from "styled-components"; +import Text from "../ui/Text"; import keymaps from "../../keymaps"; import { FormKeymaps } from "../../../shared/SettingData"; +const Grid = styled.div` + column-count: 3; +`; + +const FieldGroup = styled.div` + margin-top: 24px; + + &:first-of-type { + margin-top: 24px; + } +`; + interface Props { value: FormKeymaps; onChange: (e: FormKeymaps) => void; @@ -20,15 +32,14 @@ class KeymapsForm extends React.Component<Props> { render() { const values = this.props.value.toJSON(); return ( - <div className="form-keymaps-form"> + <Grid> {keymaps.fields.map((group, index) => { return ( - <div key={index} className="form-keymaps-form-field-group"> + <FieldGroup key={index}> {group.map(([name, label]) => { const value = values[name] || ""; return ( - <Input - type="text" + <Text id={name} name={name} key={name} @@ -39,10 +50,10 @@ class KeymapsForm extends React.Component<Props> { /> ); })} - </div> + </FieldGroup> ); })} - </div> + </Grid> ); } diff --git a/src/settings/components/form/PartialBlacklistForm.scss b/src/settings/components/form/PartialBlacklistForm.scss deleted file mode 100644 index caf6f93..0000000 --- a/src/settings/components/form/PartialBlacklistForm.scss +++ /dev/null @@ -1,28 +0,0 @@ -.form-partial-blacklist-form { - @mixin row-base { - display: flex; - - .column-url { - flex: 5; - min-width: 0; - } - .column-keys { - flex: 1; - min-width: 0; - } - .column-delete { - flex: 1; - min-width: 0; - } - } - - &-header { - @include row-base; - - font-weight: bold; - } - - &-row { - @include row-base; - } -} diff --git a/src/settings/components/form/PartialBlacklistForm.tsx b/src/settings/components/form/PartialBlacklistForm.tsx index 95beee8..b2da2bb 100644 --- a/src/settings/components/form/PartialBlacklistForm.tsx +++ b/src/settings/components/form/PartialBlacklistForm.tsx @@ -1,9 +1,41 @@ -import "./PartialBlacklistForm.scss"; +import React from "react"; +import styled from "styled-components"; import AddButton from "../ui/AddButton"; import DeleteButton from "../ui/DeleteButton"; -import React from "react"; import Blacklist, { BlacklistItem } from "../../../shared/settings/Blacklist"; +const Grid = styled.div``; + +const GridHeader = styled.div` + display: flex; + font-weight: bold; +`; + +const GridRow = styled.div` + display: flex; +`; + +const GridCell = styled.div<{ grow?: number }>` + &:nth-child(1) { + flex-grow: 5; + } + + &:nth-child(2) { + flex-shrink: 1; + min-width: 20%; + max-width: 20%; + } + + &:nth-child(3) { + flex-shrink: 1; + } +`; + +const Input = styled.input` + width: 100%; + box-sizing: border-box; +`; + interface Props { value: Blacklist; onChange: (value: Blacklist) => void; @@ -19,50 +51,62 @@ class PartialBlacklistForm extends React.Component<Props> { render() { return ( - <div className="form-partial-blacklist-form"> - <div className="form-partial-blacklist-form-header"> - <div className="column-url">URL</div> - <div className="column-keys">Keys</div> - </div> - {this.props.value.items.map((item, index) => { - if (!item.partial) { - return null; - } - return ( - <div key={index} className="form-partial-blacklist-form-row"> - <input - data-index={index} - type="text" - name="url" - className="column-url" - value={item.pattern} - onChange={this.bindValue.bind(this)} - onBlur={this.props.onBlur} - /> - <input - data-index={index} - type="text" - name="keys" - className="column-keys" - value={item.keys.join(",")} - onChange={this.bindValue.bind(this)} - onBlur={this.props.onBlur} - /> - <DeleteButton - data-index={index} - name="delete" - onClick={this.bindValue.bind(this)} - onBlur={this.props.onBlur} - /> - </div> - ); - })} + <> + <Grid role="list"> + <GridHeader> + <GridCell>URL</GridCell> + <GridCell>Keys</GridCell> + </GridHeader> + {this.props.value.items.map((item, index) => { + if (!item.partial) { + return null; + } + return ( + <GridRow key={index} role="listitem"> + <GridCell> + <Input + data-index={index} + type="text" + name="url" + aria-label="URL" + value={item.pattern} + placeholder="example.com/mail/*" + onChange={this.bindValue.bind(this)} + onBlur={this.props.onBlur} + /> + </GridCell> + <GridCell> + <Input + data-index={index} + type="text" + name="keys" + aria-label="Keys" + value={item.keys.join(",")} + placeholder="j,k,<C-d>,<C-u>" + onChange={this.bindValue.bind(this)} + onBlur={this.props.onBlur} + /> + </GridCell> + <GridCell> + <DeleteButton + data-index={index} + name="delete" + aria-label="Delete" + onClick={this.bindValue.bind(this)} + onBlur={this.props.onBlur} + /> + </GridCell> + </GridRow> + ); + })} + </Grid> <AddButton name="add" + aria-label="Add" style={{ float: "right" }} onClick={this.bindValue.bind(this)} /> - </div> + </> ); } diff --git a/src/settings/components/form/PropertiesForm.scss b/src/settings/components/form/PropertiesForm.scss deleted file mode 100644 index 7c9e167..0000000 --- a/src/settings/components/form/PropertiesForm.scss +++ /dev/null @@ -1,12 +0,0 @@ -.form-properties-form { - &-row { - .column-name { - display: inline-block; - min-width: 5rem; - font-weight: bold; - } - .column-input { - line-height: 2.2rem; - } - } -} diff --git a/src/settings/components/form/PropertiesForm.tsx b/src/settings/components/form/PropertiesForm.tsx index aebd9b1..53ebf03 100644 --- a/src/settings/components/form/PropertiesForm.tsx +++ b/src/settings/components/form/PropertiesForm.tsx @@ -1,6 +1,20 @@ -import "./PropertiesForm.scss"; +import styled from "styled-components"; import React from "react"; +const Form = styled.div``; + +const Row = styled.div``; + +const Label = styled.label` + display: inline-block; + min-width: 5rem; + font-weight: bold; +`; + +const Input = styled.input` + line-height: 2.2rem; +`; + interface Props { types: { [key: string]: string }; value: { [key: string]: any }; @@ -21,7 +35,7 @@ class PropertiesForm extends React.Component<Props> { const values = this.props.value; return ( - <div className="form-properties-form"> + <Form> {Object.keys(types).map((name) => { const type = types[name]; let inputType = ""; @@ -42,23 +56,22 @@ class PropertiesForm extends React.Component<Props> { return null; } return ( - <div key={name} className="form-properties-form-row"> - <label> - <span className="column-name">{name}</span> - <input + <Row key={name}> + <Label> + <span>{name}</span> + <Input type={inputType} name={name} - className="column-input" value={values[name] ? values[name] : ""} onChange={onChange} onBlur={this.props.onBlur} checked={values[name]} /> - </label> - </div> + </Label> + </Row> ); })} - </div> + </Form> ); } diff --git a/src/settings/components/form/SearchForm.scss b/src/settings/components/form/SearchForm.scss deleted file mode 100644 index 26b2f44..0000000 --- a/src/settings/components/form/SearchForm.scss +++ /dev/null @@ -1,28 +0,0 @@ -.form-search-form { - @mixin row-base { - display: flex; - - .column-name { - flex: 1; - min-width: 0; - } - .column-url { - flex: 5; - min-width: 0; - } - .column-option { - text-align: right; - flex-basis: 5rem; - } - } - - &-header { - @include row-base; - - font-weight: bold; - } - - &-row { - @include row-base; - } -} diff --git a/src/settings/components/form/SearchForm.tsx b/src/settings/components/form/SearchForm.tsx index a4d923d..4bf0e02 100644 --- a/src/settings/components/form/SearchForm.tsx +++ b/src/settings/components/form/SearchForm.tsx @@ -1,9 +1,42 @@ -import "./SearchForm.scss"; import React from "react"; +import styled from "styled-components"; import AddButton from "../ui/AddButton"; import DeleteButton from "../ui/DeleteButton"; import { FormSearch } from "../../../shared/SettingData"; +const Grid = styled.div``; + +const GridHeader = styled.div` + display: flex; + font-weight: bold; +`; + +const GridRow = styled.div` + display: flex; +`; + +const GridCell = styled.div<{ grow?: number }>` + &:nth-child(1) { + flex-grow: 0; + min-width: 10%; + max-width: 10%; + } + + &:nth-child(2) { + flex-grow: 2; + } + + &:nth-child(3) { + flex-grow: 0; + flex-shrink: 1; + } +`; + +const Input = styled.input` + width: 100%; + box-sizing: border-box; +`; + interface Props { value: FormSearch; onChange: (value: FormSearch) => void; @@ -20,57 +53,67 @@ class SearchForm extends React.Component<Props> { render() { const value = this.props.value.toJSON(); return ( - <div className="form-search-form"> - <div className="form-search-form-header"> - <div className="column-name">Name</div> - <div className="column-url">URL</div> - <div className="column-option">Default</div> - </div> - {value.engines.map((engine, index) => { - return ( - <div key={index} className="form-search-form-row"> - <input - data-index={index} - type="text" - name="name" - className="column-name" - value={engine[0]} - onChange={this.bindValue.bind(this)} - onBlur={this.props.onBlur} - /> - <input - data-index={index} - type="text" - name="url" - placeholder="http://example.com/?q={}" - className="column-url" - value={engine[1]} - onChange={this.bindValue.bind(this)} - onBlur={this.props.onBlur} - /> - <div className="column-option"> - <input - data-index={index} - type="radio" - name="default" - checked={value.default === engine[0]} - onChange={this.bindValue.bind(this)} - /> - <DeleteButton - data-index={index} - name="delete" - onClick={this.bindValue.bind(this)} - /> - </div> - </div> - ); - })} + <> + <Grid role="list"> + <GridHeader> + <GridCell>Name</GridCell> + <GridCell>URL</GridCell> + <GridCell>Default</GridCell> + </GridHeader> + {value.engines.map((engine, index) => { + return ( + <GridRow key={index} role="listitem"> + <GridCell> + <Input + data-index={index} + type="text" + name="name" + aria-label="Name" + value={engine[0]} + onChange={this.bindValue.bind(this)} + onBlur={this.props.onBlur} + /> + </GridCell> + <GridCell> + <Input + data-index={index} + type="text" + name="url" + aria-label="URL" + placeholder="http://example.com/?q={}" + value={engine[1]} + onChange={this.bindValue.bind(this)} + onBlur={this.props.onBlur} + /> + </GridCell> + <GridCell> + <input + data-index={index} + type="radio" + name="default" + aria-label="Default" + checked={value.default === engine[0]} + onChange={this.bindValue.bind(this)} + /> + a + <DeleteButton + data-index={index} + aria-label="Delete" + name="delete" + onClick={this.bindValue.bind(this)} + /> + </GridCell> + </GridRow> + ); + })} + </Grid> <AddButton name="add" + aria-label="Add" style={{ float: "right" }} onClick={this.bindValue.bind(this)} /> - </div> + </> ); } diff --git a/src/settings/components/index.tsx b/src/settings/components/index.tsx index 9d71cac..2e2ff52 100644 --- a/src/settings/components/index.tsx +++ b/src/settings/components/index.tsx @@ -1,7 +1,8 @@ -import "./site.scss"; import React from "react"; import { connect } from "react-redux"; -import Input from "./ui/Input"; +import styled from "styled-components"; +import TextArea from "./ui/TextArea"; +import Radio from "./ui/Radio"; import SearchForm from "./form/SearchForm"; import KeymapsForm from "./form/KeymapsForm"; import BlacklistForm from "./form/BlacklistForm"; @@ -18,6 +19,28 @@ import { State as AppState } from "../reducers/setting"; import Properties from "../../shared/settings/Properties"; import Blacklist from "../../shared/settings/Blacklist"; +const Container = styled.form` + padding: 2px; + font-family: system-ui; +`; + +const Fieldset = styled.fieldset` + margin: 0; + padding: 0; + border: none; + margin-top: 1rem; + + &:first-of-type { + margin-top: 1rem; + } +`; + +const Legend = styled.legend` + font-size: 1.5rem; + padding: 0.5rem 0; + font-weight: bold; +`; + const DO_YOU_WANT_TO_CONTINUE = "Some settings in JSON can be lost when migrating. " + "Do you want to continue?"; @@ -40,47 +63,47 @@ class SettingsComponent extends React.Component<Props> { renderFormFields(form: FormSettings) { return ( <div> - <fieldset> - <legend>Keybindings</legend> + <Fieldset> + <Legend>Keybindings</Legend> <KeymapsForm value={form.keymaps} onChange={this.bindKeymapsForm.bind(this)} onBlur={this.save.bind(this)} /> - </fieldset> - <fieldset> - <legend>Search Engines</legend> + </Fieldset> + <Fieldset> + <Legend>Search Engines</Legend> <SearchForm value={form.search} onChange={this.bindSearchForm.bind(this)} onBlur={this.save.bind(this)} /> - </fieldset> - <fieldset> - <legend>Blacklist</legend> + </Fieldset> + <Fieldset> + <Legend>Blacklist</Legend> <BlacklistForm value={form.blacklist} onChange={this.bindBlacklistForm.bind(this)} onBlur={this.save.bind(this)} /> - </fieldset> - <fieldset> - <legend>Partial blacklist</legend> + </Fieldset> + <Fieldset> + <Legend>Partial blacklist</Legend> <PartialBlacklistForm value={form.blacklist} onChange={this.bindBlacklistForm.bind(this)} onBlur={this.save.bind(this)} /> - </fieldset> - <fieldset> - <legend>Properties</legend> + </Fieldset> + <Fieldset> + <Legend>Properties</Legend> <PropertiesForm types={Properties.types()} value={form.properties.toJSON()} onChange={this.bindPropertiesForm.bind(this)} onBlur={this.save.bind(this)} /> - </fieldset> + </Fieldset> </div> ); } @@ -88,8 +111,7 @@ class SettingsComponent extends React.Component<Props> { renderJsonFields(json: JSONTextSettings, error: string) { return ( <div> - <Input - type="textarea" + <TextArea name="json" label="Plain JSON" spellCheck={false} @@ -111,32 +133,28 @@ class SettingsComponent extends React.Component<Props> { fields = this.renderJsonFields(this.props.json!, this.props.error); } return ( - <div> + <Container> <h1>Configure Vim-Vixen</h1> - <form className="vimvixen-settings-form"> - <Input - type="radio" - id="setting-source-form" - name="source" - label="Use form" - checked={this.props.source === "form"} - value="form" - onValueChange={this.bindSource.bind(this)} - disabled={disabled} - /> + <Radio + id="setting-source-form" + name="source" + label="Use form" + checked={this.props.source === "form"} + value="form" + onValueChange={this.bindSource.bind(this)} + disabled={disabled} + /> - <Input - type="radio" - name="source" - label="Use plain JSON" - checked={this.props.source === "json"} - value="json" - onValueChange={this.bindSource.bind(this)} - disabled={disabled} - /> - {fields} - </form> - </div> + <Radio + name="source" + label="Use plain JSON" + checked={this.props.source === "json"} + value="json" + onValueChange={this.bindSource.bind(this)} + disabled={disabled} + /> + {fields} + </Container> ); } diff --git a/src/settings/components/site.scss b/src/settings/components/site.scss deleted file mode 100644 index c0c4f9e..0000000 --- a/src/settings/components/site.scss +++ /dev/null @@ -1,27 +0,0 @@ -.vimvixen-settings-form { - padding: 2px; - - textarea[name=json] { - font-family: monospace; - width: 100%; - min-height: 64ex; - resize: vertical; - } - - fieldset { - margin: 0; - padding: 0; - border: none; - margin-top: 1rem; - - fieldset:first-of-type { - margin-top: 1rem; - } - - legend { - font-size: 1.5rem; - padding: .5rem 0; - font-weight: bold; - } - } -} diff --git a/src/settings/components/ui/AddButton.scss b/src/settings/components/ui/AddButton.scss deleted file mode 100644 index beb5688..0000000 --- a/src/settings/components/ui/AddButton.scss +++ /dev/null @@ -1,13 +0,0 @@ -.ui-add-button { - border: none; - padding: 4; - display: inline; - background: none; - font-weight: bold; - color: green; - cursor: pointer; - - &:hover { - color: darkgreen; - } -} diff --git a/src/settings/components/ui/AddButton.tsx b/src/settings/components/ui/AddButton.tsx index c15a732..8cf4300 100644 --- a/src/settings/components/ui/AddButton.tsx +++ b/src/settings/components/ui/AddButton.tsx @@ -1,19 +1,24 @@ -import "./AddButton.scss"; import React from "react"; +import styled from "styled-components"; -type Props = React.AllHTMLAttributes<HTMLInputElement>; +const Button = styled.input` + border: none; + padding: 4; + display: inline; + background: none; + font-weight: bold; + color: green; + cursor: pointer; -class AddButton extends React.Component<Props> { - render() { - return ( - <input - className="ui-add-button" - type="button" - value="✚" - {...this.props} - /> - ); + &:hover { + color: darkgreen; } -} +`; + +type Props = React.InputHTMLAttributes<HTMLInputElement>; + +const AddButton: React.FC<Props> = (props) => ( + <Button type="button" value="✚" {...props} /> +); export default AddButton; diff --git a/src/settings/components/ui/DeleteButton.scss b/src/settings/components/ui/DeleteButton.scss deleted file mode 100644 index 5932a72..0000000 --- a/src/settings/components/ui/DeleteButton.scss +++ /dev/null @@ -1,13 +0,0 @@ - -.ui-delete-button { - border: none; - padding: 4; - display: inline; - background: none; - color: red; - cursor: pointer; - - &:hover { - color: darkred; - } -} diff --git a/src/settings/components/ui/DeleteButton.tsx b/src/settings/components/ui/DeleteButton.tsx index df8976e..ce0183b 100644 --- a/src/settings/components/ui/DeleteButton.tsx +++ b/src/settings/components/ui/DeleteButton.tsx @@ -1,19 +1,23 @@ -import "./DeleteButton.scss"; import React from "react"; +import styled from "styled-components"; -type Props = React.AllHTMLAttributes<HTMLInputElement>; +const Button = styled.input` + border: none; + padding: 4; + display: inline; + background: none; + color: red; + cursor: pointer; -class DeleteButton extends React.Component<Props> { - render() { - return ( - <input - className="ui-delete-button" - type="button" - value="✖" - {...this.props} - /> - ); + &:hover { + color: darkred; } -} +`; + +type Props = React.InputHTMLAttributes<HTMLInputElement>; + +const DeleteButton: React.FC<Props> = (props) => ( + <Button type="button" value="✖" {...props} /> +); export default DeleteButton; diff --git a/src/settings/components/ui/Input.scss b/src/settings/components/ui/Input.scss deleted file mode 100644 index ad4daf8..0000000 --- a/src/settings/components/ui/Input.scss +++ /dev/null @@ -1,29 +0,0 @@ -.settings-ui-input { - page-break-inside: avoid; - - * { - page-break-inside: avoid; - } - - label { - font-weight: bold; - min-width: 14rem; - display: inline-block; - } - - input[type='text'] { - padding: 4px; - width: 8rem; - } - - input.input-crror, - textarea.input-error { - box-shadow: 0 0 2px red; - } - - &-error { - font-weight: bold; - color: red; - min-height: 1.5em; - } -} diff --git a/src/settings/components/ui/Input.tsx b/src/settings/components/ui/Input.tsx deleted file mode 100644 index 0e24277..0000000 --- a/src/settings/components/ui/Input.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import React from "react"; -import "./Input.scss"; - -interface Props extends React.AllHTMLAttributes<HTMLElement> { - name: string; - type: string; - error?: string; - label: string; - value: string; - onValueChange?: (name: string, value: string) => void; - onBlur?: (e: React.FocusEvent<Element>) => void; -} - -class Input extends React.Component<Props> { - renderText(props: Props) { - const inputClassName = props.error ? "input-error" : ""; - const pp = { ...props }; - delete pp.onValueChange; - return ( - <div className="settings-ui-input"> - <label htmlFor={props.id}>{props.label}</label> - <input - className={inputClassName} - onChange={this.bindOnChange.bind(this)} - {...pp} - /> - </div> - ); - } - - renderRadio(props: Props) { - const inputClassName = props.error ? "input-error" : ""; - const pp = { ...props }; - delete pp.onValueChange; - return ( - <div className="settings-ui-input"> - <label> - <input - className={inputClassName} - onChange={this.bindOnChange.bind(this)} - {...pp} - /> - {props.label} - </label> - </div> - ); - } - - renderTextArea(props: Props) { - const inputClassName = props.error ? "input-error" : ""; - const pp = { ...props }; - delete pp.onValueChange; - return ( - <div className="settings-ui-input"> - <label htmlFor={props.id}>{props.label}</label> - <textarea - className={inputClassName} - onChange={this.bindOnChange.bind(this)} - {...pp} - /> - <p className="settings-ui-input-error">{this.props.error}</p> - </div> - ); - } - - render() { - const { type } = this.props; - - switch (this.props.type) { - case "text": - return this.renderText(this.props); - case "radio": - return this.renderRadio(this.props); - case "textarea": - return this.renderTextArea(this.props); - default: - console.warn(`Unsupported input type ${type}`); - } - return null; - } - - bindOnChange(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) { - if (this.props.onValueChange) { - this.props.onValueChange(e.target.name, e.target.value); - } - } -} - -export default Input; diff --git a/src/settings/components/ui/Radio.tsx b/src/settings/components/ui/Radio.tsx new file mode 100644 index 0000000..c0d4dd9 --- /dev/null +++ b/src/settings/components/ui/Radio.tsx @@ -0,0 +1,33 @@ +import React from "react"; +import styled from "styled-components"; + +const Container = styled.div` + font-family: system-ui; +`; + +interface Props extends React.InputHTMLAttributes<HTMLInputElement> { + label: string; + onValueChange?: (name: string, value: string) => void; +} + +const Radio: React.FC<Props> = (props) => { + const onChange = (e: React.ChangeEvent<HTMLInputElement>) => { + if (props.onValueChange) { + props.onValueChange(e.target.name, e.target.value); + } + }; + + const pp = { ...props }; + delete pp.onValueChange; + + return ( + <Container> + <label htmlFor={props.id}> + <input type="radio" onChange={onChange} {...pp} /> + {props.label} + </label> + </Container> + ); +}; + +export default Radio; diff --git a/src/settings/components/ui/Text.tsx b/src/settings/components/ui/Text.tsx new file mode 100644 index 0000000..700b08a --- /dev/null +++ b/src/settings/components/ui/Text.tsx @@ -0,0 +1,54 @@ +import React from "react"; +import styled from "styled-components"; + +const Container = styled.div` + page-break-inside: avoid; +`; + +const Input = styled.input<{ hasError: boolean }>` + padding: 4px; + width: 8rem; + box-shadow: ${({ hasError }) => (hasError ? "0 0 2px red" : "none")}; +`; + +const Label = styled.label` + font-weight: bold; + min-width: 14rem; + display: inline-block; +`; + +interface Props extends React.HTMLAttributes<HTMLElement> { + name: string; + error?: string; + label: string; + value: string; + onValueChange?: (name: string, value: string) => void; +} + +const Text: React.FC<Props> = (props) => { + const onChange = (e: React.ChangeEvent<HTMLInputElement>) => { + if (props.onValueChange) { + props.onValueChange(e.target.name, e.target.value); + } + }; + + const pp = { ...props }; + delete pp.onValueChange; + + return ( + <Container> + <Label> + {props.label} + <br /> + <Input + type="text" + hasError={props.error !== undefined} + onChange={onChange} + {...pp} + /> + </Label> + </Container> + ); +}; + +export default Text; diff --git a/src/settings/components/ui/TextArea.tsx b/src/settings/components/ui/TextArea.tsx new file mode 100644 index 0000000..9dcd5be --- /dev/null +++ b/src/settings/components/ui/TextArea.tsx @@ -0,0 +1,56 @@ +import React from "react"; +import styled from "styled-components"; + +const Container = styled.div` + page-break-inside: avoid; +`; + +const Label = styled.label` + font-weight: bold; + min-width: 14rem; + display: inline-block; +`; + +const ErrorableTextArea = styled.textarea<{ hasError: boolean }>` + box-shadow: ${({ hasError }) => (hasError ? "0 0 2px red" : "none")}; + font-family: monospace; + font-family: monospace; + width: 100%; + min-height: 64ex; + resize: vertical; +`; + +const ErrorMessage = styled.p` + font-weight: bold; + color: red; + min-height: 1.5em; +`; + +interface Props extends React.TextareaHTMLAttributes<HTMLTextAreaElement> { + error?: string; + label: string; + onValueChange?: (name: string, value: string) => void; +} + +const TextArea: React.FC<Props> = (props) => { + const onChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { + if (props.onValueChange) { + props.onValueChange(e.target.name, e.target.value); + } + }; + + const hasError = typeof props.error !== "undefined" && props.error !== ""; + const pp = { ...props }; + delete pp.onValueChange; + return ( + <Container> + <Label htmlFor={props.id}>{props.label}</Label> + <ErrorableTextArea hasError={hasError} onChange={onChange} {...pp} /> + {hasError ? ( + <ErrorMessage role="alert">{props.error}</ErrorMessage> + ) : null} + </Container> + ); +}; + +export default TextArea; diff --git a/test/settings/components/form/BlacklistForm.test.tsx b/test/settings/components/form/BlacklistForm.test.tsx index e34802a..8727c59 100644 --- a/test/settings/components/form/BlacklistForm.test.tsx +++ b/test/settings/components/form/BlacklistForm.test.tsx @@ -17,16 +17,16 @@ describe("settings/form/BlacklistForm", () => { /> ).root; - const rows = root.findAllByProps({ - className: "form-blacklist-form-row", - }); + const rows = root + .findAllByType("div") + .filter((instance) => instance.props.role === "listitem"); expect(rows).to.have.lengthOf(2); - expect( - rows[0].findByProps({ className: "column-url" }).props.value - ).to.equal("*.slack.com"); - expect( - rows[1].findByProps({ className: "column-url" }).props.value - ).to.equal("www.google.com/maps"); + expect(rows[0].findByProps({ name: "url" }).props.value).to.equal( + "*.slack.com" + ); + expect(rows[1].findByProps({ name: "url" }).props.value).to.equal( + "www.google.com/maps" + ); expect(() => root.findByType(AddButton)).not.throw(); }); @@ -113,7 +113,7 @@ describe("settings/form/BlacklistForm", () => { }); const button = document.querySelector( - "input[type=button].ui-add-button" + "input[type=button][name=add]" ) as HTMLButtonElement; ReactTestUtils.Simulate.click(button); }); diff --git a/test/settings/components/form/SearchEngineForm.test.tsx b/test/settings/components/form/SearchEngineForm.test.tsx index 5f835cc..7b10274 100644 --- a/test/settings/components/form/SearchEngineForm.test.tsx +++ b/test/settings/components/form/SearchEngineForm.test.tsx @@ -21,12 +21,16 @@ describe("settings/form/SearchForm", () => { /> ).root; - const names = root.findAllByProps({ name: "name" }); + const names = root + .findAllByType("input") + .filter((instance) => instance.props.name === "name"); expect(names).to.have.lengthOf(2); expect(names[0].props.value).to.equal("google"); expect(names[1].props.value).to.equal("yahoo"); - const urls = root.findAllByProps({ name: "url" }); + const urls = root + .findAllByType("input") + .filter((instance) => instance.props.name === "url"); expect(urls).to.have.lengthOf(2); expect(urls[0].props.value).to.equal("google.com"); expect(urls[1].props.value).to.equal("yahoo.com"); @@ -139,7 +143,7 @@ describe("settings/form/SearchForm", () => { }); const button = document.querySelector( - "input[type=button].ui-add-button" + "input[type=button][name=add]" ) as HTMLInputElement; ReactTestUtils.Simulate.click(button); }); diff --git a/test/settings/components/ui/Radio.test.tsx b/test/settings/components/ui/Radio.test.tsx new file mode 100644 index 0000000..f929ee3 --- /dev/null +++ b/test/settings/components/ui/Radio.test.tsx @@ -0,0 +1,56 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import ReactTestUtils from "react-dom/test-utils"; +import Radio from "../../../../src/settings/components/ui/Radio"; +import { expect } from "chai"; + +describe("settings/ui/Radio", () => { + let container: HTMLDivElement; + + beforeEach(() => { + container = document.createElement("div"); + document.body.appendChild(container); + }); + + afterEach(() => { + document.body.removeChild(container); + }); + + it("renders radio button", () => { + ReactTestUtils.act(() => { + ReactDOM.render( + <Radio name="myradio" label="myfield" value="myvalue" />, + container + ); + }); + + const label = document.querySelector("label")!; + const input = document.querySelector("input")!; + expect(label.textContent).to.contain("myfield"); + expect(input.type).to.contain("radio"); + expect(input.name).to.contain("myradio"); + expect(input.value).to.contain("myvalue"); + }); + + it("invoke onChange", (done) => { + ReactTestUtils.act(() => { + ReactDOM.render( + <Radio + name="myradio" + type="text" + label="myfield" + value="myvalue" + onChange={(e) => { + expect((e.target as HTMLInputElement).checked).to.be.true; + done(); + }} + />, + container + ); + }); + + const input = document.querySelector("input") as HTMLInputElement; + input.checked = true; + ReactTestUtils.Simulate.change(input); + }); +}); diff --git a/test/settings/components/ui/Text.test.tsx b/test/settings/components/ui/Text.test.tsx new file mode 100644 index 0000000..d5451bb --- /dev/null +++ b/test/settings/components/ui/Text.test.tsx @@ -0,0 +1,55 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import ReactTestUtils from "react-dom/test-utils"; +import Text from "../../../../src/settings/components/ui/Text"; +import { expect } from "chai"; + +describe("settings/ui/Text", () => { + let container: HTMLDivElement; + + beforeEach(() => { + container = document.createElement("div"); + document.body.appendChild(container); + }); + + afterEach(() => { + document.body.removeChild(container); + }); + + it("renders text input", () => { + ReactTestUtils.act(() => { + ReactDOM.render( + <Text name="myname" label="myfield" value="myvalue" />, + container + ); + }); + + const label = document.querySelector("label")!; + const input = document.querySelector("input")!; + expect(label.textContent).to.contain("myfield"); + expect(input.type).to.contain("text"); + expect(input.name).to.contain("myname"); + expect(input.value).to.contain("myvalue"); + }); + + it("invoke onChange", (done) => { + ReactTestUtils.act(() => { + ReactDOM.render( + <Text + name="myname" + label="myfield" + value="myvalue" + onChange={(e) => { + expect((e.target as HTMLInputElement).value).to.equal("newvalue"); + done(); + }} + />, + container + ); + }); + + const input = document.querySelector("input")!; + input.value = "newvalue"; + ReactTestUtils.Simulate.change(input); + }); +}); diff --git a/test/settings/components/ui/TextArea.test.tsx b/test/settings/components/ui/TextArea.test.tsx new file mode 100644 index 0000000..232c7c0 --- /dev/null +++ b/test/settings/components/ui/TextArea.test.tsx @@ -0,0 +1,63 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import ReactTestUtils from "react-dom/test-utils"; +import TextArea from "../../../../src/settings/components/ui/TextArea"; +import { expect } from "chai"; + +describe("settings/ui/TextArea", () => { + let container: HTMLDivElement; + + beforeEach(() => { + container = document.createElement("div"); + document.body.appendChild(container); + }); + + afterEach(() => { + document.body.removeChild(container); + }); + + it("renders textarea", () => { + ReactTestUtils.act(() => { + ReactDOM.render( + <TextArea + type="textarea" + name="myname" + label="myfield" + value="myvalue" + error="myerror" + />, + container + ); + }); + + const label = document.querySelector("label")!; + const textarea = document.querySelector("textarea")!; + const error = document.querySelector("[role=alert]")!; + expect(label.textContent).to.contain("myfield"); + expect(textarea.nodeName).to.contain("TEXTAREA"); + expect(textarea.name).to.contain("myname"); + expect(textarea.value).to.contain("myvalue"); + expect(error.textContent).to.contain("myerror"); + }); + + it("invoke onChange", (done) => { + ReactTestUtils.act(() => { + ReactDOM.render( + <TextArea + name="myname" + label="myfield" + value="myvalue" + onChange={(e) => { + expect((e.target as HTMLInputElement).value).to.equal("newvalue"); + done(); + }} + />, + container + ); + }); + + const input = document.querySelector("textarea")!; + input.value = "newvalue"; + ReactTestUtils.Simulate.change(input); + }); +}); diff --git a/test/settings/components/ui/input.test.tsx b/test/settings/components/ui/input.test.tsx deleted file mode 100644 index d244d8f..0000000 --- a/test/settings/components/ui/input.test.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import React from "react"; -import ReactDOM from "react-dom"; -import ReactTestUtils from "react-dom/test-utils"; -import Input from "../../../../src/settings/components/ui/Input"; -import { expect } from "chai"; - -describe("settings/ui/Input", () => { - let container: HTMLDivElement; - - beforeEach(() => { - container = document.createElement("div"); - document.body.appendChild(container); - }); - - afterEach(() => { - document.body.removeChild(container); - }); - - context("type=text", () => { - it("renders text input", () => { - ReactTestUtils.act(() => { - ReactDOM.render( - <Input type="text" name="myname" label="myfield" value="myvalue" />, - container - ); - }); - - const label = document.querySelector("label")!; - const input = document.querySelector("input")!; - expect(label.textContent).to.contain("myfield"); - expect(input.type).to.contain("text"); - expect(input.name).to.contain("myname"); - expect(input.value).to.contain("myvalue"); - }); - - it("invoke onChange", (done) => { - ReactTestUtils.act(() => { - ReactDOM.render( - <Input - type="text" - name="myname" - label="myfield" - value="myvalue" - onChange={(e) => { - expect((e.target as HTMLInputElement).value).to.equal("newvalue"); - done(); - }} - />, - container - ); - }); - - const input = document.querySelector("input")!; - input.value = "newvalue"; - ReactTestUtils.Simulate.change(input); - }); - }); - - context("type=radio", () => { - it("renders radio button", () => { - ReactTestUtils.act(() => { - ReactDOM.render( - <Input type="radio" name="myname" label="myfield" value="myvalue" />, - container - ); - }); - - const label = document.querySelector("label")!; - const input = document.querySelector("input")!; - expect(label.textContent).to.contain("myfield"); - expect(input.type).to.contain("radio"); - expect(input.name).to.contain("myname"); - expect(input.value).to.contain("myvalue"); - }); - - it("invoke onChange", (done) => { - ReactTestUtils.act(() => { - ReactDOM.render( - <Input - type="text" - name="radio" - label="myfield" - value="myvalue" - onChange={(e) => { - expect((e.target as HTMLInputElement).checked).to.be.true; - done(); - }} - />, - container - ); - }); - - const input = document.querySelector("input") as HTMLInputElement; - input.checked = true; - ReactTestUtils.Simulate.change(input); - }); - }); - - context("type=textarea", () => { - it("renders textarea button", () => { - ReactTestUtils.act(() => { - ReactDOM.render( - <Input - type="textarea" - name="myname" - label="myfield" - value="myvalue" - error="myerror" - />, - container - ); - }); - - const label = document.querySelector("label")!; - const textarea = document.querySelector("textarea")!; - const error = document.querySelector(".settings-ui-input-error")!; - expect(label.textContent).to.contain("myfield"); - expect(textarea.nodeName).to.contain("TEXTAREA"); - expect(textarea.name).to.contain("myname"); - expect(textarea.value).to.contain("myvalue"); - expect(error.textContent).to.contain("myerror"); - }); - - it("invoke onChange", (done) => { - ReactTestUtils.act(() => { - ReactDOM.render( - <Input - type="textarea" - name="myname" - label="myfield" - value="myvalue" - onChange={(e) => { - expect((e.target as HTMLInputElement).value).to.equal("newvalue"); - done(); - }} - />, - container - ); - }); - - const input = document.querySelector("textarea")!; - input.value = "newvalue"; - ReactTestUtils.Simulate.change(input); - }); - }); -}); diff --git a/webpack.config.js b/webpack.config.js index ee252bf..5edee1c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -36,10 +36,6 @@ const config = { test: /\.css$/, loader: 'style-loader!css-loader', }, - { - test: /\.scss$/, - loader: 'style-loader!css-loader!sass-loader?sourceMap=true' - }, ] }, @@ -272,9 +272,9 @@ integrity sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q== "@types/mocha@^8.0.1": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.0.2.tgz#cdd160767c5a445bedef94ea8cfc8ab760fff42b" - integrity sha512-5cv8rmqT3KX9XtWDvSgGYfS4OwrKM2eei90GWLnTYz+AXRiBv5uYcKBjnkQ4katNvfYk3+o2bHGZUsDhdcoUyg== + version "8.0.3" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.0.3.tgz#51b21b6acb6d1b923bbdc7725c38f9f455166402" + integrity sha512-vyxR57nv8NfcU0GZu8EUXZLTbCMupIUwy95LJ6lllN+JRPG25CwMHoB1q5xKh8YKhQnHYRAn4yW2yuHbf/5xgg== "@types/node@*": version "14.0.27" @@ -757,11 +757,6 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.11.0, ajv@^6.12.2, ajv@^6.12.3, ajv json-schema-traverse "^0.4.1" uri-js "^4.2.2" -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= - ansi-colors@4.1.1, ansi-colors@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -835,19 +830,11 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -aproba@^1.0.3, aproba@^1.1.1: +aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -875,11 +862,6 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= - array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -977,11 +959,6 @@ async-each@^1.0.1: resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== -async-foreach@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" - integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= - async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" @@ -1101,13 +1078,6 @@ blob@0.0.5: resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683" integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" - bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -1334,19 +1304,6 @@ camel-case@^4.1.1: pascal-case "^3.1.1" tslib "^1.10.0" -camelcase-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= - dependencies: - camelcase "^2.0.0" - map-obj "^1.0.0" - -camelcase@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= - camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -1379,7 +1336,7 @@ chai@^4.2.0: pathval "^1.1.0" type-detect "^4.0.5" -chalk@^1.1.1, chalk@^1.1.3: +chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= @@ -1547,11 +1504,6 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -1674,11 +1626,6 @@ console-browserify@^1.1.0: resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -1764,14 +1711,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" -cross-spawn@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" - integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI= - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -1867,13 +1806,6 @@ csstype@^3.0.2: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.2.tgz#ee5ff8f208c8cd613b389f7b222c9801ca62b3f7" integrity sha512-ofovWglpqoqbfLNOTBNZLSbMuGrblAf1efvvArGKOZMBrIoJeu5UsAipQolkijtyQx5MtAzT/J9IHj/CEY1mJw== -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= - dependencies: - array-find-index "^1.0.1" - custom-event@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" @@ -1929,7 +1861,7 @@ debug@~3.1.0: dependencies: ms "2.0.0" -decamelize@^1.1.2, decamelize@^1.2.0: +decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= @@ -1985,11 +1917,6 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -2285,13 +2212,6 @@ errno@^0.1.3, errno@~0.1.7: dependencies: prr "~1.0.1" -error-ex@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.4, es-abstract@^1.17.5: version "1.17.6" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" @@ -2794,14 +2714,6 @@ find-up@4.1.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -2941,16 +2853,6 @@ fsevents@~2.1.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== -fstream@^1.0.0, fstream@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" - integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -2961,27 +2863,6 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -gaze@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" - integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== - dependencies: - globule "^1.0.0" - get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -2992,11 +2873,6 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= - get-stdin@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" @@ -3029,7 +2905,7 @@ glob-parent@^5.0.0, glob-parent@~5.1.0: dependencies: is-glob "^4.0.1" -glob@7.1.6, glob@^7.0.0, glob@^7.0.3, glob@^7.1.0, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1: +glob@7.1.6, glob@^7.1.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -3089,15 +2965,6 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -globule@^1.0.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.2.tgz#d8bdd9e9e4eef8f96e245999a5dee7eb5d8529c4" - integrity sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA== - dependencies: - glob "~7.1.1" - lodash "~4.17.10" - minimatch "~3.0.2" - graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" @@ -3155,11 +3022,6 @@ has-symbols@^1.0.0, has-symbols@^1.0.1: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -3243,11 +3105,6 @@ homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" -hosted-git-info@^2.1.4: - version "2.8.8" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" - integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== - html-minifier-terser@^5.0.1: version "5.1.1" resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054" @@ -3388,18 +3245,6 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= -in-publish@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.1.tgz#948b1a535c8030561cea522f73f78f4be357e00c" - integrity sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ== - -indent-string@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= - dependencies: - repeating "^2.0.0" - indent-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" @@ -3428,7 +3273,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3505,11 +3350,6 @@ is-arguments@^1.0.4: resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -3598,18 +3438,6 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-finite@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" - integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" @@ -3697,11 +3525,6 @@ is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -3779,11 +3602,6 @@ iterate-value@^1.0.0: es-get-iterator "^1.0.2" iterate-iterator "^1.0.1" -js-base64@^2.1.8: - version "2.6.4" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" - integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== - js-beautify@^1.6.4: version "1.11.0" resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.11.0.tgz#afb873dc47d58986360093dcb69951e8bcd5ded2" @@ -3984,9 +3802,9 @@ karma-sinon@^1.0.5: integrity sha1-TjRD8oMP3s/2JNN0cWPxIX2qKpo= karma-sourcemap-loader@^0.3.7: - version "0.3.7" - resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz#91322c77f8f13d46fed062b042e1009d4c4505d8" - integrity sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg= + version "0.3.8" + resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.8.tgz#d4bae72fb7a8397328a62b75013d2df937bdcf9c" + integrity sha512-zorxyAakYZuBcHRJE+vbrK2o2JXLFWK8VVjiT/6P+ltLBUGUvqTEkUiQ119MGdOrK7mrmxXHZF1/pfT6GgIZ6g== dependencies: graceful-fs "^4.1.2" @@ -4056,11 +3874,6 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -klona@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/klona/-/klona-1.1.2.tgz#a79e292518a5a5412ec8d097964bff1571a64db0" - integrity sha512-xf88rTeHiXk+XE2Vhi6yj8Wm3gMZrygGdKjJqN8HkV+PwF/t50/LdAKHoHpPcxFAlmQszTZ1CugrK25S7qDRLA== - lanthan@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/lanthan/-/lanthan-0.0.2.tgz#8d2e62e09b68cf3d84bbafc85a56a2c1503dd3ca" @@ -4095,17 +3908,6 @@ lie@~3.3.0: dependencies: immediate "~3.0.5" -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" @@ -4194,7 +3996,7 @@ lodash.once@^4.0.0: resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= -lodash@^4.0.0, lodash@^4.16.3, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.2.1, lodash@~4.17.10: +lodash@^4.16.3, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.2.1: version "4.17.19" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== @@ -4256,14 +4058,6 @@ loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - lower-case@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7" @@ -4271,7 +4065,7 @@ lower-case@^2.0.1: dependencies: tslib "^1.10.0" -lru-cache@^4.0.1, lru-cache@^4.1.5: +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== @@ -4304,11 +4098,6 @@ map-cache@^0.2.2: resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= -map-obj@^1.0.0, map-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= - map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" @@ -4346,22 +4135,6 @@ memory-fs@^0.5.0: errno "^0.1.3" readable-stream "^2.0.1" -meow@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= - dependencies: - camelcase-keys "^2.0.0" - decamelize "^1.1.2" - loud-rejection "^1.0.0" - map-obj "^1.0.1" - minimist "^1.1.3" - normalize-package-data "^2.3.4" - object-assign "^4.0.1" - read-pkg-up "^1.0.1" - redent "^1.0.0" - trim-newlines "^1.0.0" - merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -4444,14 +4217,14 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@3.0.4, minimatch@^3.0.4, minimatch@~3.0.2: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" -minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: +minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -4480,7 +4253,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3: +mkdirp@^0.5.1, mkdirp@^0.5.3: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -4555,7 +4328,7 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.12.1, nan@^2.13.2: +nan@^2.12.1: version "2.14.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== @@ -4587,7 +4360,7 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -neo-async@^2.5.0, neo-async@^2.6.1, neo-async@^2.6.2: +neo-async@^2.5.0, neo-async@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -4627,24 +4400,6 @@ no-case@^3.0.3: lower-case "^2.0.1" tslib "^1.10.0" -node-gyp@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" - integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA== - dependencies: - fstream "^1.0.0" - glob "^7.0.3" - graceful-fs "^4.1.2" - mkdirp "^0.5.0" - nopt "2 || 3" - npmlog "0 || 1 || 2 || 3 || 4" - osenv "0" - request "^2.87.0" - rimraf "2" - semver "~5.3.0" - tar "^2.0.0" - which "1" - node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" @@ -4674,36 +4429,6 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-sass@^4.13.1: - version "4.14.1" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5" - integrity sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g== - dependencies: - async-foreach "^0.1.3" - chalk "^1.1.1" - cross-spawn "^3.0.0" - gaze "^1.0.0" - get-stdin "^4.0.1" - glob "^7.0.3" - in-publish "^2.0.0" - lodash "^4.17.15" - meow "^3.7.0" - mkdirp "^0.5.1" - nan "^2.13.2" - node-gyp "^3.8.0" - npmlog "^4.0.0" - request "^2.88.0" - sass-graph "2.2.5" - stdout-stream "^1.4.0" - "true-case-path" "^1.0.2" - -"nopt@2 || 3": - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= - dependencies: - abbrev "1" - nopt@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" @@ -4712,16 +4437,6 @@ nopt@^4.0.3: abbrev "1" osenv "^0.1.4" -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" @@ -4734,16 +4449,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - nth-check@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" @@ -4751,17 +4456,12 @@ nth-check@~1.0.1: dependencies: boolbase "~1.0.0" -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -4911,7 +4611,7 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@0, osenv@^0.1.4: +osenv@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== @@ -4986,13 +4686,6 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" @@ -5040,13 +4733,6 @@ path-dirname@^1.0.0: resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -5089,15 +4775,6 @@ path-to-regexp@^1.7.0: dependencies: isarray "0.0.1" -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - pathval@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" @@ -5124,28 +4801,11 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7, picomatch@^2.2.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - 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" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" @@ -5490,24 +5150,7 @@ react@16.13.1: object-assign "^4.1.1" prop-types "^15.6.2" -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" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -5552,14 +5195,6 @@ readdirp@~3.4.0: dependencies: picomatch "^2.2.1" -redent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" - integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= - dependencies: - indent-string "^2.1.0" - strip-indent "^1.0.1" - redux-promise@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/redux-promise/-/redux-promise-0.6.0.tgz#c64723b5213bb5603c11b74302883b682e06b319" @@ -5653,13 +5288,6 @@ repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= - dependencies: - is-finite "^1.0.0" - request-promise-core@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" @@ -5676,7 +5304,7 @@ request-promise-native@^1.0.7, request-promise-native@^1.0.8: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.87.0, request@^2.88.0: +request@^2.88.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -5757,7 +5385,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.10.0, resolve@^1.17.0: +resolve@^1.17.0: version "1.17.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== @@ -5782,13 +5410,6 @@ rfdc@^1.1.4: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2" integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug== -rimraf@2, rimraf@^2.5.4, rimraf@^2.6.3, rimraf@^2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -5796,6 +5417,13 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" +rimraf@^2.5.4, rimraf@^2.6.3, rimraf@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -5852,27 +5480,6 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sass-graph@2.2.5: - version "2.2.5" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8" - integrity sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag== - dependencies: - glob "^7.0.0" - lodash "^4.0.0" - scss-tokenizer "^0.2.3" - yargs "^13.3.2" - -sass-loader@^9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-9.0.3.tgz#086adcf0bfdcc9d920413e2cdc3ba3321373d547" - integrity sha512-fOwsP98ac1VMme+V3+o0HaaMHp8Q/C9P+MUazLFVi3Jl7ORGHQXL1XeRZt3zLSGZQQPC8xE42Y2WptItvGjDQg== - dependencies: - klona "^1.1.2" - loader-utils "^2.0.0" - neo-async "^2.6.2" - schema-utils "^2.7.0" - semver "^7.3.2" - scheduler@^0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" @@ -5899,14 +5506,6 @@ schema-utils@^2.6.6, schema-utils@^2.7.0: ajv "^6.12.2" ajv-keywords "^3.4.1" -scss-tokenizer@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" - integrity sha1-jrBtualyMzOCTT9VMGQRSYR85dE= - dependencies: - js-base64 "^2.1.8" - source-map "^0.4.2" - selenium-webdriver@^4.0.0-alpha.5: version "4.0.0-alpha.7" resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.7.tgz#e3879d8457fd7ad8e4424094b7dc0540d99e6797" @@ -5916,7 +5515,7 @@ selenium-webdriver@^4.0.0-alpha.5: rimraf "^2.7.1" tmp "0.0.30" -"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0: +semver@^5.5.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -5931,11 +5530,6 @@ semver@^7.2.1, semver@^7.3.2: resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== -semver@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= - send@0.17.1: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -5979,7 +5573,7 @@ serve-static@1.14.1: parseurl "~1.3.3" send "0.17.1" -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -6066,7 +5660,7 @@ sigmund@^1.0.1: resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= -signal-exit@^3.0.0, signal-exit@^3.0.2: +signal-exit@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== @@ -6229,13 +5823,6 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - integrity sha1-66T12pwNyZneaAMti092FzZSA2s= - dependencies: - amdefine ">=0.0.4" - source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -6251,32 +5838,6 @@ source-map@^0.7.3: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== -spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== - split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" @@ -6324,13 +5885,6 @@ static-extend@^0.1.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= -stdout-stream@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" - integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA== - dependencies: - readable-stream "^2.0.1" - stealthy-require@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" @@ -6377,15 +5931,6 @@ streamroller@^2.2.4: debug "^4.1.1" fs-extra "^8.1.0" -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - "string-width@^1.0.2 || 2": version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -6454,7 +5999,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^3.0.0, strip-ansi@^3.0.1: +strip-ansi@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= @@ -6482,20 +6027,6 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - -strip-indent@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= - dependencies: - get-stdin "^4.0.1" - strip-json-comments@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" @@ -6576,15 +6107,6 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tar@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" - integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== - dependencies: - block-stream "*" - fstream "^1.0.12" - inherits "2" - terser-webpack-plugin@^1.4.3: version "1.4.4" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz#2c63544347324baafa9a56baaddf1634c8abfc2f" @@ -6715,18 +6237,6 @@ tough-cookie@^2.3.3, tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" -trim-newlines@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= - -"true-case-path@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" - integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew== - dependencies: - glob "^7.1.2" - ts-loader@^8.0.2: version "8.0.4" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.4.tgz#02b9c91fbcfdb3114d8b1e98a3829265270eee7a" @@ -6971,14 +6481,6 @@ v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -7123,13 +6625,6 @@ 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, which@^1.2.14, which@^1.2.9, which@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - which@2.0.2, which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -7137,7 +6632,14 @@ which@2.0.2, which@^2.0.1: dependencies: isexe "^2.0.0" -wide-align@1.1.3, wide-align@^1.1.0: +which@^1.2.14, which@^1.2.9, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== |