aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.circleci/config.yml2
-rw-r--r--README.md2
-rw-r--r--e2e/tab.test.ts6
-rw-r--r--package.json40
-rw-r--r--src/background/clients/NavigateClient.ts14
-rw-r--r--src/background/controllers/OperationController.ts116
-rw-r--r--src/background/di.ts18
-rw-r--r--src/background/infrastructures/ConsoleClient.ts14
-rw-r--r--src/background/operators/Operator.ts5
-rw-r--r--src/background/operators/OperatorFactory.ts6
-rw-r--r--src/background/operators/OperatorFactoryChain.ts6
-rw-r--r--src/background/operators/impls/CancelOperator.ts15
-rw-r--r--src/background/operators/impls/CloseTabOperator.ts22
-rw-r--r--src/background/operators/impls/CloseTabRightOperator.ts21
-rw-r--r--src/background/operators/impls/CommandOperatorFactoryChain.ts63
-rw-r--r--src/background/operators/impls/DuplicateTabOperator.ts11
-rw-r--r--src/background/operators/impls/InternalOpenURLOperator.ts24
-rw-r--r--src/background/operators/impls/InternalOperatorFactoryChain.ts38
-rw-r--r--src/background/operators/impls/NavigateHistoryNextOperator.ts15
-rw-r--r--src/background/operators/impls/NavigateHistoryPrevOperator.ts15
-rw-r--r--src/background/operators/impls/NavigateLinkNextOperator.ts15
-rw-r--r--src/background/operators/impls/NavigateLinkPrevOperator.ts15
-rw-r--r--src/background/operators/impls/NavigateOperatorFactoryChain.ts66
-rw-r--r--src/background/operators/impls/NavigateParentOperator.ts25
-rw-r--r--src/background/operators/impls/NavigateRootOperator.ts12
-rw-r--r--src/background/operators/impls/OpenHomeOperator.ts29
-rw-r--r--src/background/operators/impls/OpenSourceOperator.ts12
-rw-r--r--src/background/operators/impls/OperatorFactoryImpl.ts45
-rw-r--r--src/background/operators/impls/PinTabOperator.ts11
-rw-r--r--src/background/operators/impls/ReloadTabOperator.ts14
-rw-r--r--src/background/operators/impls/ReopenTabOperator.ts10
-rw-r--r--src/background/operators/impls/RepeatLastOperator.ts18
-rw-r--r--src/background/operators/impls/RepeatOperatorFactoryChain.ts29
-rw-r--r--src/background/operators/impls/ResetZoomOperator.ts10
-rw-r--r--src/background/operators/impls/SelectFirstTabOperator.ts11
-rw-r--r--src/background/operators/impls/SelectLastTabOperator.ts11
-rw-r--r--src/background/operators/impls/SelectPreviousSelectedTabOperator.ts14
-rw-r--r--src/background/operators/impls/SelectTabNextOperator.ts19
-rw-r--r--src/background/operators/impls/SelectTabPrevOperator.ts19
-rw-r--r--src/background/operators/impls/ShowAddBookmarkOperator.ts20
-rw-r--r--src/background/operators/impls/ShowBufferCommandOperator.ts16
-rw-r--r--src/background/operators/impls/ShowCommandOperator.ts15
-rw-r--r--src/background/operators/impls/ShowOpenCommandOperator.ts20
-rw-r--r--src/background/operators/impls/ShowTabOpenCommandOperator.ts20
-rw-r--r--src/background/operators/impls/ShowWinOpenCommandOperator.ts20
-rw-r--r--src/background/operators/impls/StartFindOperator.ts15
-rw-r--r--src/background/operators/impls/TabOperatorFactoryChain.ts64
-rw-r--r--src/background/operators/impls/TogglePinnedTabOperator.ts11
-rw-r--r--src/background/operators/impls/UnpinTabOperator.ts11
-rw-r--r--src/background/operators/impls/ZoomInOperator.ts10
-rw-r--r--src/background/operators/impls/ZoomOperatorFactoryChain.ts28
-rw-r--r--src/background/operators/impls/ZoomOutOperator.ts10
-rw-r--r--src/background/presenters/Notifier.ts4
-rw-r--r--src/background/presenters/WindowPresenter.ts11
-rw-r--r--src/background/presenters/ZoomPresenter.ts60
-rw-r--r--src/background/repositories/BrowserSettingRepository.ts6
-rw-r--r--src/background/repositories/RepeatRepository.ts8
-rw-r--r--src/background/usecases/AddonEnabledUseCase.ts2
-rw-r--r--src/background/usecases/CommandUseCase.ts23
-rw-r--r--src/background/usecases/ConsoleUseCase.ts63
-rw-r--r--src/background/usecases/FindUseCase.ts15
-rw-r--r--src/background/usecases/MarkUseCase.ts12
-rw-r--r--src/background/usecases/NavigateUseCase.ts56
-rw-r--r--src/background/usecases/RepeatUseCase.ts7
-rw-r--r--src/background/usecases/TabSelectUseCase.ts51
-rw-r--r--src/background/usecases/TabUseCase.ts102
-rw-r--r--src/background/usecases/ZoomUseCase.ts51
-rw-r--r--src/content/controllers/KeymapController.ts88
-rw-r--r--src/content/di.ts8
-rw-r--r--src/content/hint-key-producer.ts37
-rw-r--r--src/content/operators/Operator.ts5
-rw-r--r--src/content/operators/OperatorFactory.ts6
-rw-r--r--src/content/operators/OperatorFactoryChain.ts6
-rw-r--r--src/content/operators/impls/AbstractScrollOperator.ts10
-rw-r--r--src/content/operators/impls/AddonOperatorFactoryChain.ts40
-rw-r--r--src/content/operators/impls/BackgroundOperationOperator.ts15
-rw-r--r--src/content/operators/impls/ClipboardOperatorFactoryChain.ts47
-rw-r--r--src/content/operators/impls/DisableAddonOperator.ts15
-rw-r--r--src/content/operators/impls/EnableAddonOperator.ts15
-rw-r--r--src/content/operators/impls/EnableJumpMarkOperator.ts10
-rw-r--r--src/content/operators/impls/EnableSetMarkOperator.ts10
-rw-r--r--src/content/operators/impls/FindNextOperator.ts15
-rw-r--r--src/content/operators/impls/FindOperatorFactoryChain.ts25
-rw-r--r--src/content/operators/impls/FindPrevOperator.ts15
-rw-r--r--src/content/operators/impls/FocusOperator.ts10
-rw-r--r--src/content/operators/impls/FocusOperatorFactoryChain.ts22
-rw-r--r--src/content/operators/impls/FollowOperatorFactoryChain.ts27
-rw-r--r--src/content/operators/impls/HorizontalScrollOperator.ts21
-rw-r--r--src/content/operators/impls/MarkOperatorFactoryChain.ts25
-rw-r--r--src/content/operators/impls/OperatorFactoryImpl.ts51
-rw-r--r--src/content/operators/impls/PageScrollOperator.ts21
-rw-r--r--src/content/operators/impls/PasteOperator.ts25
-rw-r--r--src/content/operators/impls/ScrollOperatorFactoryChain.ts68
-rw-r--r--src/content/operators/impls/ScrollToBottomOperator.ts20
-rw-r--r--src/content/operators/impls/ScrollToEndOperator.ts20
-rw-r--r--src/content/operators/impls/ScrollToHomeOperator.ts20
-rw-r--r--src/content/operators/impls/ScrollToTopOperator.ts20
-rw-r--r--src/content/operators/impls/StartFollowOperator.ts14
-rw-r--r--src/content/operators/impls/ToggleAddonOperator.ts16
-rw-r--r--src/content/operators/impls/URLRepository.ts9
-rw-r--r--src/content/operators/impls/VerticalScrollOperator.ts21
-rw-r--r--src/content/operators/impls/YankURLOperator.ts18
-rw-r--r--src/content/presenters/ScrollPresenter.ts2
-rw-r--r--src/content/repositories/HintKeyRepository.ts49
-rw-r--r--src/content/usecases/ClipboardUseCase.ts34
-rw-r--r--src/content/usecases/FindSlaveUseCase.ts17
-rw-r--r--src/content/usecases/FocusUseCase.ts11
-rw-r--r--src/content/usecases/FollowMasterUseCase.ts18
-rw-r--r--src/content/usecases/HintKeyProducer.ts37
-rw-r--r--src/content/usecases/MarkKeyUseCase.ts8
-rw-r--r--src/content/usecases/ScrollUseCase.ts51
-rw-r--r--test/background/mock/MockBrowserSettingRepository.ts10
-rw-r--r--test/background/mock/MockConsoleClient.ts23
-rw-r--r--test/background/mock/MockNavigateClient.ts19
-rw-r--r--test/background/mock/MockRepeatRepository.ts14
-rw-r--r--test/background/mock/MockTabPresenter.ts179
-rw-r--r--test/background/mock/MockWindowPresenter.ts7
-rw-r--r--test/background/mock/MockZoomPresenter.ts15
-rw-r--r--test/background/operators/impls/CancelOperator.test.ts24
-rw-r--r--test/background/operators/impls/CloseTabOperator.test.ts61
-rw-r--r--test/background/operators/impls/CloseTabRightOperator.test.ts24
-rw-r--r--test/background/operators/impls/CommandOperatorFactoryChain.test.ts42
-rw-r--r--test/background/operators/impls/DuplicateTabOperator.test.ts25
-rw-r--r--test/background/operators/impls/InternalOpenURLOperator.test.ts0
-rw-r--r--test/background/operators/impls/InternalOperatorFactoryChain.test.ts37
-rw-r--r--test/background/operators/impls/NavigateHistoryNextOperator.test.ts25
-rw-r--r--test/background/operators/impls/NavigateHistoryPrevOperator.test.ts25
-rw-r--r--test/background/operators/impls/NavigateLinkNextOperator.test.ts22
-rw-r--r--test/background/operators/impls/NavigateLinkPrevOperator.test.ts22
-rw-r--r--test/background/operators/impls/NavigateOperatorFactoryChain.test.ts56
-rw-r--r--test/background/operators/impls/NavigateParentOperator.test.ts53
-rw-r--r--test/background/operators/impls/NavigateRootOperator.test.ts18
-rw-r--r--test/background/operators/impls/OpenHomeOperator.test.ts70
-rw-r--r--test/background/operators/impls/OpenSourceOperator.test.ts21
-rw-r--r--test/background/operators/impls/PinTabOperator.test.ts25
-rw-r--r--test/background/operators/impls/ReloadTabOperator.test.ts34
-rw-r--r--test/background/operators/impls/ReopenTabOperator.test.ts17
-rw-r--r--test/background/operators/impls/RepeatLastOperator.test.ts56
-rw-r--r--test/background/operators/impls/RepeatOperatorFactoryChain.test.ts32
-rw-r--r--test/background/operators/impls/ResetZoomOperator.test.ts17
-rw-r--r--test/background/operators/impls/SelectFirstTabOperator.test.ts20
-rw-r--r--test/background/operators/impls/SelectLastTabOperator.test.ts20
-rw-r--r--test/background/operators/impls/SelectPreviousSelectedTabOperator.test.ts38
-rw-r--r--test/background/operators/impls/SelectTabNextOperator.test.ts35
-rw-r--r--test/background/operators/impls/SelectTabPrevOperator.test.ts35
-rw-r--r--test/background/operators/impls/ShowAddBookmarkOperator.test.ts50
-rw-r--r--test/background/operators/impls/ShowBufferCommandOperator.test.ts25
-rw-r--r--test/background/operators/impls/ShowCommandOperator.test.ts25
-rw-r--r--test/background/operators/impls/ShowOpenCommandOperator.test.ts50
-rw-r--r--test/background/operators/impls/ShowTabOpenCommandOperator.test.ts50
-rw-r--r--test/background/operators/impls/ShowWinOpenCommandOperator.test.ts50
-rw-r--r--test/background/operators/impls/StartFindOperator.test.ts22
-rw-r--r--test/background/operators/impls/TabOperatorFactoryChain.test.ts71
-rw-r--r--test/background/operators/impls/TogglePinnedTabOperator.test.ts32
-rw-r--r--test/background/operators/impls/UnpinTabOperator.test.ts25
-rw-r--r--test/background/operators/impls/ZoomInOperator.test.ts17
-rw-r--r--test/background/operators/impls/ZoomOperatorFactoryChain.test.ts28
-rw-r--r--test/background/operators/impls/ZoomOutOperator.test.ts17
-rw-r--r--test/background/usecases/NavigateUseCase.test.ts183
-rw-r--r--test/content/mock/MockAddonEnabledRepository.ts18
-rw-r--r--test/content/mock/MockAddonIndicatorClient.ts13
-rw-r--r--test/content/mock/MockClipboardRepository.ts16
-rw-r--r--test/content/mock/MockFindMasterClient.ts11
-rw-r--r--test/content/mock/MockFocusPresenter.ts7
-rw-r--r--test/content/mock/MockFollowMasterClient.ts16
-rw-r--r--test/content/mock/MockMarkKeyRepository.ts43
-rw-r--r--test/content/mock/MockOperationClient.ts16
-rw-r--r--test/content/mock/MockScrollPresenter.ts6
-rw-r--r--test/content/mock/MockSettingRepository.ts20
-rw-r--r--test/content/mock/MockURLRepository.ts9
-rw-r--r--test/content/operators/impls/AddonOperatorFactoryChain.test.ts29
-rw-r--r--test/content/operators/impls/BackgroundOperationOperator.test.ts38
-rw-r--r--test/content/operators/impls/ClipboardOperatorFactoryChain.test.ts31
-rw-r--r--test/content/operators/impls/DisableAddonOperator.test.ts19
-rw-r--r--test/content/operators/impls/EnableAddonOperator.test.ts19
-rw-r--r--test/content/operators/impls/EnableJumpMarkOperator.test.ts19
-rw-r--r--test/content/operators/impls/EnableSetMarkOperator.test.ts19
-rw-r--r--test/content/operators/impls/FindNextOperator.test.ts17
-rw-r--r--test/content/operators/impls/FindOperatorFactoryChain.test.ts21
-rw-r--r--test/content/operators/impls/FindPrevOperator.test.ts17
-rw-r--r--test/content/operators/impls/FocusOperator.test.ts17
-rw-r--r--test/content/operators/impls/FocusOperatorFactoryChain.test.ts17
-rw-r--r--test/content/operators/impls/FollowOperatorFactoryChain.test.ts20
-rw-r--r--test/content/operators/impls/HorizontalScrollOperator.test.ts28
-rw-r--r--test/content/operators/impls/MarkOperatorFactoryChain.test.ts21
-rw-r--r--test/content/operators/impls/PageScrollOperator.test.ts28
-rw-r--r--test/content/operators/impls/PasteOperator.test.ts51
-rw-r--r--test/content/operators/impls/ScrollOperatorFactoryChain.test.ts46
-rw-r--r--test/content/operators/impls/ScrollToBottomOperator.test.ts18
-rw-r--r--test/content/operators/impls/ScrollToEndOperator.test.ts18
-rw-r--r--test/content/operators/impls/ScrollToHomeOperator.test.ts18
-rw-r--r--test/content/operators/impls/ScrollToTopOperator.test.ts18
-rw-r--r--test/content/operators/impls/StartFollowOperator.test.ts20
-rw-r--r--test/content/operators/impls/ToggleAddonOperator.test.ts24
-rw-r--r--test/content/operators/impls/VerticalScrollOperator.test.ts28
-rw-r--r--test/content/operators/impls/YankURLOperator.test.ts26
-rw-r--r--test/content/presenters/NavigationPresenter.test.ts4
-rw-r--r--test/content/usecases/ClipboardUseCase.test.ts95
-rw-r--r--test/content/usecases/HintKeyProducer.test.ts33
-rw-r--r--yarn.lock1584
200 files changed, 4887 insertions, 1988 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 2cd4c02..22dbcfc 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -3,7 +3,7 @@ version: 2.1
executors:
default:
docker:
- - image: circleci/node:12.14.0-stretch-browsers
+ - image: circleci/node:14.15.1-stretch-browsers
environment:
- FIREFOX_VERSION: "78.3.0esr"
- GECKODRIVER_VERSION: "0.27.0"
diff --git a/README.md b/README.md
index 117ece3..c8a75df 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ For usage and more detailed information, check out our [documentations][document
## Copyright
-Copyright © 2017-2019 by Shin'ya Ueoka
+Copyright © 2017-2020 by Shin'ya Ueoka
## Licence
diff --git a/e2e/tab.test.ts b/e2e/tab.test.ts
index 98ec9f8..49d1c03 100644
--- a/e2e/tab.test.ts
+++ b/e2e/tab.test.ts
@@ -79,8 +79,10 @@ describe("tab test", () => {
const page = await Page.currentContext(webdriver);
await page.sendKeys("x", "$");
- const current = await browser.tabs.query({ windowId: win.id });
- assert.strictEqual(current.length, 2);
+ await eventually(async () => {
+ const current = await browser.tabs.query({ windowId: win.id });
+ assert.strictEqual(current.length, 2);
+ });
});
it("duplicates tab by zd", async () => {
diff --git a/package.json b/package.json
index 67ae266..d4fcfb1 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"scripts": {
"schema": "ajv compile -s src/shared/settings/schema.json -o src/shared/settings/validate.js",
"start": "webpack --mode development -w --debug --devtool inline-source-map",
- "build": "NODE_ENV=production webpack --mode production --progress --display-error-details --devtool inline-source-map",
+ "build": "NODE_ENV=production webpack --mode production --progress --devtool inline-source-map",
"package": "yarn build && script/package",
"lint": "eslint --ext .ts,.tsx .",
"lint:fix": "eslint --ext .ts,.tsx . --fix",
@@ -27,12 +27,12 @@
"@types/chai": "^4.2.8",
"@types/express": "^4.17.2",
"@types/mocha": "^8.0.1",
- "@types/node": "^12.12.21",
+ "@types/node": "^14.14.13",
"@types/prop-types": "^15.7.3",
- "@types/react": "^16.9.46",
- "@types/react-dom": "^16.9.5",
+ "@types/react": "^17.0.0",
+ "@types/react-dom": "^17.0.0",
"@types/react-redux": "^7.1.7",
- "@types/react-test-renderer": "^16.9.2",
+ "@types/react-test-renderer": "^17.0.0",
"@types/redux-promise": "^0.5.28",
"@types/selenium-webdriver": "^4.0.6",
"@types/sinon": "^9.0.0",
@@ -40,20 +40,20 @@
"@typescript-eslint/eslint-plugin": "3.9.0",
"@typescript-eslint/parser": "3.10.1",
"ajv": "^6.11.0",
- "ajv-cli": "^3.0.0",
+ "ajv-cli": "^4.0.1",
"chai": "^4.2.0",
- "css-loader": "^4.2.1",
- "eslint": "7.10.0",
- "eslint-config-prettier": "6.11.0",
+ "css-loader": "^5.0.1",
+ "eslint": "7.15.0",
+ "eslint-config-prettier": "7.0.0",
"eslint-plugin-prettier": "3.1.4",
- "eslint-plugin-react": "7.21.2",
- "eslint-plugin-standard": "^4.0.1",
+ "eslint-plugin-react": "7.21.5",
+ "eslint-plugin-standard": "^5.0.0",
"express": "^4.17.1",
- "html-webpack-plugin": "4.3.0",
+ "html-webpack-plugin": "4.5.0",
"jsonwebtoken": "^8.5.1",
"jszip": "^3.2.2",
"karma": "^5.0.0",
- "karma-firefox-launcher": "^1.3.0",
+ "karma-firefox-launcher": "^2.1.0",
"karma-html2js-preprocessor": "^1.1.0",
"karma-mocha": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
@@ -62,9 +62,9 @@
"karma-webpack": "^4.0.2",
"lanthan": "0.0.2",
"mocha": "^8.1.1",
- "prettier": "2.1.2",
- "prettier-eslint": "11.0.0",
- "react": "16.13.1",
+ "prettier": "2.2.1",
+ "prettier-eslint": "12.0.0",
+ "react": "16.14.0",
"react-dom": "16.13.1",
"react-redux": "^7.1.3",
"react-test-renderer": "16.13.1",
@@ -74,15 +74,15 @@
"request-promise-native": "^1.0.8",
"sinon": "^9.0.3",
"sinon-chrome": "^3.0.1",
- "style-loader": "^1.1.3",
+ "style-loader": "^2.0.0",
"styled-components": "^5.1.1",
"ts-loader": "^8.0.2",
"ts-node": "^9.0.0",
- "tsyringe": "4.3.0",
+ "tsyringe": "4.4.0",
"typescript": "4.0.3",
"web-ext-types": "^3.2.1",
"webextensions-api-fake": "^0.9.1",
- "webpack": "4.44.1",
- "webpack-cli": "3.3.12"
+ "webpack": "4.44.2",
+ "webpack-cli": "4.2.0"
}
}
diff --git a/src/background/clients/NavigateClient.ts b/src/background/clients/NavigateClient.ts
index 40ceb45..af8688e 100644
--- a/src/background/clients/NavigateClient.ts
+++ b/src/background/clients/NavigateClient.ts
@@ -1,8 +1,16 @@
-import { injectable } from "tsyringe";
import * as messages from "../../shared/messages";
-@injectable()
-export default class NavigateClient {
+export default interface NavigateClient {
+ historyNext(tabId: number): Promise<void>;
+
+ historyPrev(tabId: number): Promise<void>;
+
+ linkNext(tabId: number): Promise<void>;
+
+ linkPrev(tabId: number): Promise<void>;
+}
+
+export class NavigateClientImpl implements NavigateClient {
async historyNext(tabId: number): Promise<void> {
await browser.tabs.sendMessage(tabId, {
type: messages.NAVIGATE_HISTORY_NEXT,
diff --git a/src/background/controllers/OperationController.ts b/src/background/controllers/OperationController.ts
index 5a7047d..d606ac0 100644
--- a/src/background/controllers/OperationController.ts
+++ b/src/background/controllers/OperationController.ts
@@ -1,23 +1,14 @@
-import { injectable } from "tsyringe";
+import { inject, injectable } from "tsyringe";
import * as operations from "../../shared/operations";
-import FindUseCase from "../usecases/FindUseCase";
-import ConsoleUseCase from "../usecases/ConsoleUseCase";
-import TabUseCase from "../usecases/TabUseCase";
-import TabSelectUseCase from "../usecases/TabSelectUseCase";
-import ZoomUseCase from "../usecases/ZoomUseCase";
-import NavigateUseCase from "../usecases/NavigateUseCase";
+import OperatorFactory from "../operators/OperatorFactory";
import RepeatUseCase from "../usecases/RepeatUseCase";
@injectable()
export default class OperationController {
constructor(
- private findUseCase: FindUseCase,
- private consoleUseCase: ConsoleUseCase,
- private tabUseCase: TabUseCase,
- private tabSelectUseCase: TabSelectUseCase,
- private zoomUseCase: ZoomUseCase,
- private navigateUseCase: NavigateUseCase,
- private repeatUseCase: RepeatUseCase
+ private readonly repeatUseCase: RepeatUseCase,
+ @inject("OperatorFactory")
+ private readonly operatorFactory: OperatorFactory
) {}
async exec(repeat: number, op: operations.Operation): Promise<any> {
@@ -27,105 +18,14 @@ export default class OperationController {
}
}
- // eslint-disable-next-line complexity, max-lines-per-function
- async doOperation(
+ private async doOperation(
repeat: number,
operation: operations.Operation
): Promise<any> {
- // eslint-disable-next-line complexity, max-lines-per-function
- const opFunc = (() => {
- switch (operation.type) {
- case operations.TAB_CLOSE:
- return () =>
- this.tabUseCase.close(false, operation.select === "left");
- case operations.TAB_CLOSE_RIGHT:
- return () => this.tabUseCase.closeRight();
- case operations.TAB_CLOSE_FORCE:
- return () => this.tabUseCase.close(true);
- case operations.TAB_REOPEN:
- return () => this.tabUseCase.reopen();
- case operations.TAB_PREV:
- return () => this.tabSelectUseCase.selectPrev(1);
- case operations.TAB_NEXT:
- return () => this.tabSelectUseCase.selectNext(1);
- case operations.TAB_FIRST:
- return () => this.tabSelectUseCase.selectFirst();
- case operations.TAB_LAST:
- return () => this.tabSelectUseCase.selectLast();
- case operations.TAB_PREV_SEL:
- return () => this.tabSelectUseCase.selectPrevSelected();
- case operations.TAB_RELOAD:
- return () => this.tabUseCase.reload(operation.cache);
- case operations.TAB_PIN:
- return () => this.tabUseCase.setPinned(true);
- case operations.TAB_UNPIN:
- return () => this.tabUseCase.setPinned(false);
- case operations.TAB_TOGGLE_PINNED:
- return () => this.tabUseCase.togglePinned();
- case operations.TAB_DUPLICATE:
- return () => this.tabUseCase.duplicate();
- case operations.PAGE_SOURCE:
- return () => this.tabUseCase.openPageSource();
- case operations.PAGE_HOME:
- return () => this.tabUseCase.openHome(operation.newTab);
- case operations.ZOOM_IN:
- return () => this.zoomUseCase.zoomIn();
- case operations.ZOOM_OUT:
- return () => this.zoomUseCase.zoomOut();
- case operations.ZOOM_NEUTRAL:
- return () => this.zoomUseCase.zoomNutoral();
- case operations.COMMAND_SHOW:
- return () => this.consoleUseCase.showCommand();
- case operations.COMMAND_SHOW_OPEN:
- return () => this.consoleUseCase.showOpenCommand(operation.alter);
- case operations.COMMAND_SHOW_TABOPEN:
- return () => this.consoleUseCase.showTabopenCommand(operation.alter);
- case operations.COMMAND_SHOW_WINOPEN:
- return () => this.consoleUseCase.showWinopenCommand(operation.alter);
- case operations.COMMAND_SHOW_BUFFER:
- return () => this.consoleUseCase.showBufferCommand();
- case operations.COMMAND_SHOW_ADDBOOKMARK:
- return () =>
- this.consoleUseCase.showAddbookmarkCommand(operation.alter);
- case operations.FIND_START:
- return () => this.findUseCase.findStart();
- case operations.CANCEL:
- return () => this.consoleUseCase.hideConsole();
- case operations.NAVIGATE_HISTORY_PREV:
- return () => this.navigateUseCase.openHistoryPrev();
- case operations.NAVIGATE_HISTORY_NEXT:
- return () => this.navigateUseCase.openHistoryNext();
- case operations.NAVIGATE_LINK_PREV:
- return () => this.navigateUseCase.openLinkPrev();
- case operations.NAVIGATE_LINK_NEXT:
- return () => this.navigateUseCase.openLinkNext();
- case operations.NAVIGATE_PARENT:
- return () => this.navigateUseCase.openParent();
- case operations.NAVIGATE_ROOT:
- return () => this.navigateUseCase.openRoot();
- case operations.REPEAT_LAST:
- return () => {
- const last = this.repeatUseCase.getLastOperation();
- if (typeof last !== "undefined") {
- return this.doOperation(1, last);
- }
- return Promise.resolve();
- };
- case operations.INTERNAL_OPEN_URL:
- return () =>
- this.tabUseCase.openURL(
- operation.url,
- operation.newTab,
- operation.newWindow
- );
- default:
- throw new Error("unknown operation: " + operation.type);
- }
- })();
-
+ const operator = this.operatorFactory.create(operation);
for (let i = 0; i < repeat; ++i) {
// eslint-disable-next-line no-await-in-loop
- await opFunc();
+ await operator.run();
}
}
}
diff --git a/src/background/di.ts b/src/background/di.ts
index 5e6ad03..358ff1e 100644
--- a/src/background/di.ts
+++ b/src/background/di.ts
@@ -11,9 +11,16 @@ import HistoryRepositoryImpl from "./completion/impl/HistoryRepositoryImpl";
import BookmarkRepositoryImpl from "./completion/impl/BookmarkRepositoryImpl";
import TabRepositoryImpl from "./completion/impl/TabRepositoryImpl";
import { TabPresenterImpl } from "./presenters/TabPresenter";
+import { OperatorFactoryImpl } from "./operators/impls/OperatorFactoryImpl";
+import { NavigateClientImpl } from "./clients/NavigateClient";
+import { ConsoleClientImpl } from "./infrastructures/ConsoleClient";
+import { BrowserSettingRepositoryImpl } from "./repositories/BrowserSettingRepository";
+import { RepeatRepositoryImpl } from "./repositories/RepeatRepository";
+import { ZoomPresenterImpl } from "./presenters/ZoomPresenter";
+import { WindowPresenterImpl } from "./presenters/WindowPresenter";
container.register("LocalSettingRepository", {
- useValue: LocalSettingRepository,
+ useClass: LocalSettingRepository,
});
container.register("SyncSettingRepository", {
useClass: SyncSettingRepository,
@@ -24,5 +31,14 @@ container.register("CachedSettingRepository", {
container.register("Notifier", { useClass: NotifierImpl });
container.register("HistoryRepository", { useClass: HistoryRepositoryImpl });
container.register("BookmarkRepository", { useClass: BookmarkRepositoryImpl });
+container.register("BrowserSettingRepository", {
+ useClass: BrowserSettingRepositoryImpl,
+});
+container.register("RepeatRepository", { useClass: RepeatRepositoryImpl });
container.register("TabRepository", { useClass: TabRepositoryImpl });
+container.register("ZoomPresenter", { useClass: ZoomPresenterImpl });
container.register("TabPresenter", { useClass: TabPresenterImpl });
+container.register("WindowPresenter", { useClass: WindowPresenterImpl });
+container.register("NavigateClient", { useClass: NavigateClientImpl });
+container.register("ConsoleClient", { useClass: ConsoleClientImpl });
+container.register("OperatorFactory", { useClass: OperatorFactoryImpl });
diff --git a/src/background/infrastructures/ConsoleClient.ts b/src/background/infrastructures/ConsoleClient.ts
index 8d0af89..2a1df5b 100644
--- a/src/background/infrastructures/ConsoleClient.ts
+++ b/src/background/infrastructures/ConsoleClient.ts
@@ -1,8 +1,20 @@
import { injectable } from "tsyringe";
import * as messages from "../../shared/messages";
+export default interface ConsoleClient {
+ showCommand(tabId: number, command: string): Promise<any>;
+
+ showFind(tabId: number): Promise<any>;
+
+ showInfo(tabId: number, message: string): Promise<any>;
+
+ showError(tabId: number, message: string): Promise<any>;
+
+ hide(tabId: number): Promise<any>;
+}
+
@injectable()
-export default class ConsoleClient {
+export class ConsoleClientImpl implements ConsoleClient {
showCommand(tabId: number, command: string): Promise<any> {
return browser.tabs.sendMessage(tabId, {
type: messages.CONSOLE_SHOW_COMMAND,
diff --git a/src/background/operators/Operator.ts b/src/background/operators/Operator.ts
new file mode 100644
index 0000000..3b1fe03
--- /dev/null
+++ b/src/background/operators/Operator.ts
@@ -0,0 +1,5 @@
+interface Operator {
+ run(): Promise<void>;
+}
+
+export default Operator;
diff --git a/src/background/operators/OperatorFactory.ts b/src/background/operators/OperatorFactory.ts
new file mode 100644
index 0000000..9a5234c
--- /dev/null
+++ b/src/background/operators/OperatorFactory.ts
@@ -0,0 +1,6 @@
+import Operator from "./Operator";
+import { Operation } from "../../shared/operations";
+
+export default interface OperatorFactory {
+ create(op: Operation): Operator;
+}
diff --git a/src/background/operators/OperatorFactoryChain.ts b/src/background/operators/OperatorFactoryChain.ts
new file mode 100644
index 0000000..046ed42
--- /dev/null
+++ b/src/background/operators/OperatorFactoryChain.ts
@@ -0,0 +1,6 @@
+import Operator from "./Operator";
+import { Operation } from "../../shared/operations";
+
+export default interface OperatorFactoryChain {
+ create(op: Operation): Operator | null;
+}
diff --git a/src/background/operators/impls/CancelOperator.ts b/src/background/operators/impls/CancelOperator.ts
new file mode 100644
index 0000000..7ab09fb
--- /dev/null
+++ b/src/background/operators/impls/CancelOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class CancelOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.consoleClient.hide(tab.id as number);
+ }
+}
diff --git a/src/background/operators/impls/CloseTabOperator.ts b/src/background/operators/impls/CloseTabOperator.ts
new file mode 100644
index 0000000..5d8e80b
--- /dev/null
+++ b/src/background/operators/impls/CloseTabOperator.ts
@@ -0,0 +1,22 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class CloseTabOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly force: boolean = false,
+ private readonly selectLeft: boolean = false
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ if (!this.force && tab.pinned) {
+ return Promise.resolve();
+ }
+ if (this.selectLeft && tab.index > 0) {
+ const tabs = await this.tabPresenter.getAll();
+ await this.tabPresenter.select(tabs[tab.index - 1].id as number);
+ }
+ return this.tabPresenter.remove([tab.id as number]);
+ }
+}
diff --git a/src/background/operators/impls/CloseTabRightOperator.ts b/src/background/operators/impls/CloseTabRightOperator.ts
new file mode 100644
index 0000000..f36930e
--- /dev/null
+++ b/src/background/operators/impls/CloseTabRightOperator.ts
@@ -0,0 +1,21 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class CloseTabRightOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tabs = await this.tabPresenter.getAll();
+ tabs.sort((t1, t2) => t1.index - t2.index);
+ const index = tabs.findIndex((t) => t.active);
+ if (index < 0) {
+ return;
+ }
+ for (let i = index + 1; i < tabs.length; ++i) {
+ const tab = tabs[i];
+ if (!tab.pinned) {
+ await this.tabPresenter.remove([tab.id as number]);
+ }
+ }
+ }
+}
diff --git a/src/background/operators/impls/CommandOperatorFactoryChain.ts b/src/background/operators/impls/CommandOperatorFactoryChain.ts
new file mode 100644
index 0000000..680a384
--- /dev/null
+++ b/src/background/operators/impls/CommandOperatorFactoryChain.ts
@@ -0,0 +1,63 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import ShowCommandOperator from "./ShowCommandOperator";
+import ShowOpenCommandOperator from "./ShowOpenCommandOperator";
+import ShowTabOpenCommandOperator from "./ShowTabOpenCommandOperator";
+import ShowWinOpenCommandOperator from "./ShowWinOpenCommandOperator";
+import ShowBufferCommandOperator from "./ShowBufferCommandOperator";
+import ShowAddBookmarkOperator from "./ShowAddBookmarkOperator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+import * as operations from "../../../shared/operations";
+import StartFindOperator from "./StartFindOperator";
+
+@injectable()
+export default class CommandOperatorFactoryChain
+ implements OperatorFactoryChain {
+ constructor(
+ @inject("TabPresenter")
+ private readonly tabPresenter: TabPresenter,
+ @inject("ConsoleClient")
+ private readonly consoleClient: ConsoleClient
+ ) {}
+
+ create(op: operations.Operation): Operator | null {
+ switch (op.type) {
+ case operations.COMMAND_SHOW:
+ return new ShowCommandOperator(this.tabPresenter, this.consoleClient);
+ case operations.COMMAND_SHOW_OPEN:
+ return new ShowOpenCommandOperator(
+ this.tabPresenter,
+ this.consoleClient,
+ op.alter
+ );
+ case operations.COMMAND_SHOW_TABOPEN:
+ return new ShowTabOpenCommandOperator(
+ this.tabPresenter,
+ this.consoleClient,
+ op.alter
+ );
+ case operations.COMMAND_SHOW_WINOPEN:
+ return new ShowWinOpenCommandOperator(
+ this.tabPresenter,
+ this.consoleClient,
+ op.alter
+ );
+ case operations.COMMAND_SHOW_BUFFER:
+ return new ShowBufferCommandOperator(
+ this.tabPresenter,
+ this.consoleClient
+ );
+ case operations.COMMAND_SHOW_ADDBOOKMARK:
+ return new ShowAddBookmarkOperator(
+ this.tabPresenter,
+ this.consoleClient,
+ op.alter
+ );
+ case operations.FIND_START:
+ return new StartFindOperator(this.tabPresenter, this.consoleClient);
+ }
+ return null;
+ }
+}
diff --git a/src/background/operators/impls/DuplicateTabOperator.ts b/src/background/operators/impls/DuplicateTabOperator.ts
new file mode 100644
index 0000000..7737cfa
--- /dev/null
+++ b/src/background/operators/impls/DuplicateTabOperator.ts
@@ -0,0 +1,11 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class DuplicateTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ await this.tabPresenter.duplicate(tab.id as number);
+ }
+}
diff --git a/src/background/operators/impls/InternalOpenURLOperator.ts b/src/background/operators/impls/InternalOpenURLOperator.ts
new file mode 100644
index 0000000..6bf513b
--- /dev/null
+++ b/src/background/operators/impls/InternalOpenURLOperator.ts
@@ -0,0 +1,24 @@
+import Operator from "../Operator";
+import WindowPresenter from "../../presenters/WindowPresenter";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class InternalOpenURLOperator implements Operator {
+ constructor(
+ private readonly windowPresenter: WindowPresenter,
+ private readonly tabPresenter: TabPresenter,
+ private readonly url: string,
+ private readonly newTab?: boolean,
+ private readonly newWindow?: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ if (this.newWindow) {
+ await this.windowPresenter.create(this.url);
+ } else if (this.newTab) {
+ await this.tabPresenter.create(this.url);
+ } else {
+ const tab = await this.tabPresenter.getCurrent();
+ await this.tabPresenter.open(this.url, tab.id);
+ }
+ }
+}
diff --git a/src/background/operators/impls/InternalOperatorFactoryChain.ts b/src/background/operators/impls/InternalOperatorFactoryChain.ts
new file mode 100644
index 0000000..05615f6
--- /dev/null
+++ b/src/background/operators/impls/InternalOperatorFactoryChain.ts
@@ -0,0 +1,38 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import CancelOperator from "./CancelOperator";
+import InternalOpenURLOperator from "./InternalOpenURLOperator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+import WindowPresenter from "../../presenters/WindowPresenter";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export default class InternalOperatorFactoryChain
+ implements OperatorFactoryChain {
+ constructor(
+ @inject("WindowPresenter")
+ private readonly windowPresenter: WindowPresenter,
+ @inject("TabPresenter")
+ private readonly tabPresenter: TabPresenter,
+ @inject("ConsoleClient")
+ private readonly consoleClient: ConsoleClient
+ ) {}
+
+ create(op: operations.Operation): Operator | null {
+ switch (op.type) {
+ case operations.CANCEL:
+ return new CancelOperator(this.tabPresenter, this.consoleClient);
+ case operations.INTERNAL_OPEN_URL:
+ return new InternalOpenURLOperator(
+ this.windowPresenter,
+ this.tabPresenter,
+ op.url,
+ op.newTab,
+ op.newWindow
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/background/operators/impls/NavigateHistoryNextOperator.ts b/src/background/operators/impls/NavigateHistoryNextOperator.ts
new file mode 100644
index 0000000..b092c48
--- /dev/null
+++ b/src/background/operators/impls/NavigateHistoryNextOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import NavigateClient from "../../clients/NavigateClient";
+
+export default class NavigateHistoryNextOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly navigateClient: NavigateClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ await this.navigateClient.historyNext(tab.id!);
+ }
+}
diff --git a/src/background/operators/impls/NavigateHistoryPrevOperator.ts b/src/background/operators/impls/NavigateHistoryPrevOperator.ts
new file mode 100644
index 0000000..27d4ee9
--- /dev/null
+++ b/src/background/operators/impls/NavigateHistoryPrevOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import NavigateClient from "../../clients/NavigateClient";
+
+export default class NavigateHistoryPrevOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly navigateClient: NavigateClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ await this.navigateClient.historyPrev(tab.id!);
+ }
+}
diff --git a/src/background/operators/impls/NavigateLinkNextOperator.ts b/src/background/operators/impls/NavigateLinkNextOperator.ts
new file mode 100644
index 0000000..dbbcc45
--- /dev/null
+++ b/src/background/operators/impls/NavigateLinkNextOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import NavigateClient from "../../clients/NavigateClient";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class NavigateLinkNextOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly navigateClient: NavigateClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ await this.navigateClient.linkNext(tab.id!);
+ }
+}
diff --git a/src/background/operators/impls/NavigateLinkPrevOperator.ts b/src/background/operators/impls/NavigateLinkPrevOperator.ts
new file mode 100644
index 0000000..fe41ee6
--- /dev/null
+++ b/src/background/operators/impls/NavigateLinkPrevOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import NavigateClient from "../../clients/NavigateClient";
+
+export default class NavigateLinkPrevOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly navigateClient: NavigateClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ await this.navigateClient.linkPrev(tab.id!);
+ }
+}
diff --git a/src/background/operators/impls/NavigateOperatorFactoryChain.ts b/src/background/operators/impls/NavigateOperatorFactoryChain.ts
new file mode 100644
index 0000000..618db45
--- /dev/null
+++ b/src/background/operators/impls/NavigateOperatorFactoryChain.ts
@@ -0,0 +1,66 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import NavigateHistoryPrevOperator from "./NavigateHistoryPrevOperator";
+import NavigateHistoryNextOperator from "./NavigateHistoryNextOperator";
+import NavigateLinkPrevOperator from "./NavigateLinkPrevOperator";
+import NavigateLinkNextOperator from "./NavigateLinkNextOperator";
+import NavigateParentOperator from "./NavigateParentOperator";
+import NavigateRootOperator from "./NavigateRootOperator";
+import OpenSourceOperator from "./OpenSourceOperator";
+import OpenHomeOperator from "./OpenHomeOperator";
+import TabPresenter from "../../presenters/TabPresenter";
+import NavigateClient from "../../clients/NavigateClient";
+import BrowserSettingRepository from "../../repositories/BrowserSettingRepository";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export default class NavigateOperatorFactoryChain
+ implements OperatorFactoryChain {
+ constructor(
+ @inject("TabPresenter")
+ private readonly tabPresenter: TabPresenter,
+ @inject("NavigateClient")
+ private readonly navigateClient: NavigateClient,
+ @inject("BrowserSettingRepository")
+ private readonly browserSettingRepository: BrowserSettingRepository
+ ) {}
+
+ create(op: operations.Operation): Operator | null {
+ switch (op.type) {
+ case operations.NAVIGATE_HISTORY_PREV:
+ return new NavigateHistoryPrevOperator(
+ this.tabPresenter,
+ this.navigateClient
+ );
+ case operations.NAVIGATE_HISTORY_NEXT:
+ return new NavigateHistoryNextOperator(
+ this.tabPresenter,
+ this.navigateClient
+ );
+ case operations.NAVIGATE_LINK_PREV:
+ return new NavigateLinkPrevOperator(
+ this.tabPresenter,
+ this.navigateClient
+ );
+ case operations.NAVIGATE_LINK_NEXT:
+ return new NavigateLinkNextOperator(
+ this.tabPresenter,
+ this.navigateClient
+ );
+ case operations.NAVIGATE_PARENT:
+ return new NavigateParentOperator(this.tabPresenter);
+ case operations.NAVIGATE_ROOT:
+ return new NavigateRootOperator(this.tabPresenter);
+ case operations.PAGE_SOURCE:
+ return new OpenSourceOperator(this.tabPresenter);
+ case operations.PAGE_HOME:
+ return new OpenHomeOperator(
+ this.tabPresenter,
+ this.browserSettingRepository,
+ op.newTab
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/background/operators/impls/NavigateParentOperator.ts b/src/background/operators/impls/NavigateParentOperator.ts
new file mode 100644
index 0000000..652cfb8
--- /dev/null
+++ b/src/background/operators/impls/NavigateParentOperator.ts
@@ -0,0 +1,25 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class NavigateParentOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ const url = new URL(tab.url!);
+ if (url.hash.length > 0) {
+ url.hash = "";
+ } else if (url.search.length > 0) {
+ url.search = "";
+ } else {
+ const basenamePattern = /\/[^/]+$/;
+ const lastDirPattern = /\/[^/]+\/$/;
+ if (basenamePattern.test(url.pathname)) {
+ url.pathname = url.pathname.replace(basenamePattern, "/");
+ } else if (lastDirPattern.test(url.pathname)) {
+ url.pathname = url.pathname.replace(lastDirPattern, "/");
+ }
+ }
+ await this.tabPresenter.open(url.href);
+ }
+}
diff --git a/src/background/operators/impls/NavigateRootOperator.ts b/src/background/operators/impls/NavigateRootOperator.ts
new file mode 100644
index 0000000..b140156
--- /dev/null
+++ b/src/background/operators/impls/NavigateRootOperator.ts
@@ -0,0 +1,12 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class NavigateRootOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ const url = new URL(tab.url!);
+ await this.tabPresenter.open(url.origin);
+ }
+}
diff --git a/src/background/operators/impls/OpenHomeOperator.ts b/src/background/operators/impls/OpenHomeOperator.ts
new file mode 100644
index 0000000..4773be6
--- /dev/null
+++ b/src/background/operators/impls/OpenHomeOperator.ts
@@ -0,0 +1,29 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import BrowserSettingRepository from "../../repositories/BrowserSettingRepository";
+
+export default class OpenHomeOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly browserSettingRepository: BrowserSettingRepository,
+ private readonly newTab: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ const urls = await this.browserSettingRepository.getHomepageUrls();
+ if (urls.length === 1 && urls[0] === "about:home") {
+ // eslint-disable-next-line max-len
+ throw new Error(
+ "Cannot open Firefox Home (about:home) by WebExtensions, set your custom URLs"
+ );
+ }
+ if (urls.length === 1 && !this.newTab) {
+ await this.tabPresenter.open(urls[0], tab.id);
+ return;
+ }
+ for (const url of urls) {
+ await this.tabPresenter.create(url);
+ }
+ }
+}
diff --git a/src/background/operators/impls/OpenSourceOperator.ts b/src/background/operators/impls/OpenSourceOperator.ts
new file mode 100644
index 0000000..9185ba5
--- /dev/null
+++ b/src/background/operators/impls/OpenSourceOperator.ts
@@ -0,0 +1,12 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class OpenSourceOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ const url = "view-source:" + tab.url;
+ await this.tabPresenter.create(url);
+ }
+}
diff --git a/src/background/operators/impls/OperatorFactoryImpl.ts b/src/background/operators/impls/OperatorFactoryImpl.ts
new file mode 100644
index 0000000..34e7bb5
--- /dev/null
+++ b/src/background/operators/impls/OperatorFactoryImpl.ts
@@ -0,0 +1,45 @@
+import { inject, delay, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactory from "../OperatorFactory";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import CommandOperatorFactoryChain from "./CommandOperatorFactoryChain";
+import InternalOperatorFactoryChain from "./InternalOperatorFactoryChain";
+import NavigateOperatorFactoryChain from "./NavigateOperatorFactoryChain";
+import RepeatOperatorFactoryChain from "./RepeatOperatorFactoryChain";
+import TabOperatorFactoryChain from "./TabOperatorFactoryChain";
+import ZoomOperatorFactoryChain from "./ZoomOperatorFactoryChain";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export class OperatorFactoryImpl implements OperatorFactory {
+ private readonly factoryChains: OperatorFactoryChain[];
+
+ constructor(
+ commandOperatorFactoryChain: CommandOperatorFactoryChain,
+ internalOperatorFactoryChain: InternalOperatorFactoryChain,
+ navigateOperatorFactoryChain: NavigateOperatorFactoryChain,
+ tabOperatorFactoryChain: TabOperatorFactoryChain,
+ zoomOperatorFactoryChain: ZoomOperatorFactoryChain,
+ @inject(delay(() => RepeatOperatorFactoryChain))
+ repeatOperatorFactoryChain: RepeatOperatorFactoryChain
+ ) {
+ this.factoryChains = [
+ commandOperatorFactoryChain,
+ internalOperatorFactoryChain,
+ navigateOperatorFactoryChain,
+ repeatOperatorFactoryChain,
+ tabOperatorFactoryChain,
+ zoomOperatorFactoryChain,
+ ];
+ }
+
+ create(op: operations.Operation): Operator {
+ for (const chain of this.factoryChains) {
+ const operator = chain.create(op);
+ if (operator !== null) {
+ return operator;
+ }
+ }
+ throw new Error("unknown operation: " + op.type);
+ }
+}
diff --git a/src/background/operators/impls/PinTabOperator.ts b/src/background/operators/impls/PinTabOperator.ts
new file mode 100644
index 0000000..8121725
--- /dev/null
+++ b/src/background/operators/impls/PinTabOperator.ts
@@ -0,0 +1,11 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class PinTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.tabPresenter.setPinned(tab.id as number, true);
+ }
+}
diff --git a/src/background/operators/impls/ReloadTabOperator.ts b/src/background/operators/impls/ReloadTabOperator.ts
new file mode 100644
index 0000000..db3389e
--- /dev/null
+++ b/src/background/operators/impls/ReloadTabOperator.ts
@@ -0,0 +1,14 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class ReloadTabOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly cache: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.tabPresenter.reload(tab.id as number, this.cache);
+ }
+}
diff --git a/src/background/operators/impls/ReopenTabOperator.ts b/src/background/operators/impls/ReopenTabOperator.ts
new file mode 100644
index 0000000..507b4a8
--- /dev/null
+++ b/src/background/operators/impls/ReopenTabOperator.ts
@@ -0,0 +1,10 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class ReopenTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ run(): Promise<void> {
+ return this.tabPresenter.reopen();
+ }
+}
diff --git a/src/background/operators/impls/RepeatLastOperator.ts b/src/background/operators/impls/RepeatLastOperator.ts
new file mode 100644
index 0000000..d46daab
--- /dev/null
+++ b/src/background/operators/impls/RepeatLastOperator.ts
@@ -0,0 +1,18 @@
+import Operator from "../Operator";
+import RepeatRepository from "../../repositories/RepeatRepository";
+import OperatorFactory from "../OperatorFactory";
+
+export default class RepeatLastOperator implements Operator {
+ constructor(
+ private readonly repeatRepository: RepeatRepository,
+ private readonly operatorFactory: OperatorFactory
+ ) {}
+
+ run(): Promise<void> {
+ const op = this.repeatRepository.getLastOperation();
+ if (typeof op === "undefined") {
+ return Promise.resolve();
+ }
+ return this.operatorFactory.create(op).run();
+ }
+}
diff --git a/src/background/operators/impls/RepeatOperatorFactoryChain.ts b/src/background/operators/impls/RepeatOperatorFactoryChain.ts
new file mode 100644
index 0000000..5038d48
--- /dev/null
+++ b/src/background/operators/impls/RepeatOperatorFactoryChain.ts
@@ -0,0 +1,29 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import RepeatLastOperator from "./RepeatLastOperator";
+import RepeatRepository from "../../repositories/RepeatRepository";
+import OperatorFactory from "../OperatorFactory";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export default class RepeatOperatorFactoryChain
+ implements OperatorFactoryChain {
+ constructor(
+ @inject("RepeatRepository")
+ private readonly repeatRepository: RepeatRepository,
+ @inject("OperatorFactory")
+ private readonly operatorFactory: OperatorFactory
+ ) {}
+
+ create(op: operations.Operation): Operator | null {
+ switch (op.type) {
+ case operations.REPEAT_LAST:
+ return new RepeatLastOperator(
+ this.repeatRepository,
+ this.operatorFactory
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/background/operators/impls/ResetZoomOperator.ts b/src/background/operators/impls/ResetZoomOperator.ts
new file mode 100644
index 0000000..96af733
--- /dev/null
+++ b/src/background/operators/impls/ResetZoomOperator.ts
@@ -0,0 +1,10 @@
+import Operator from "../Operator";
+import ZoomPresenter from "../../presenters/ZoomPresenter";
+
+export default class ResetZoomOperator implements Operator {
+ constructor(private readonly zoomPresenter: ZoomPresenter) {}
+
+ run(): Promise<void> {
+ return this.zoomPresenter.resetZoom();
+ }
+}
diff --git a/src/background/operators/impls/SelectFirstTabOperator.ts b/src/background/operators/impls/SelectFirstTabOperator.ts
new file mode 100644
index 0000000..c04b8a9
--- /dev/null
+++ b/src/background/operators/impls/SelectFirstTabOperator.ts
@@ -0,0 +1,11 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class SelectFirstTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tabs = await this.tabPresenter.getAll();
+ return this.tabPresenter.select(tabs[0].id as number);
+ }
+}
diff --git a/src/background/operators/impls/SelectLastTabOperator.ts b/src/background/operators/impls/SelectLastTabOperator.ts
new file mode 100644
index 0000000..e16d406
--- /dev/null
+++ b/src/background/operators/impls/SelectLastTabOperator.ts
@@ -0,0 +1,11 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class SelectLastTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tabs = await this.tabPresenter.getAll();
+ return this.tabPresenter.select(tabs[tabs.length - 1].id as number);
+ }
+}
diff --git a/src/background/operators/impls/SelectPreviousSelectedTabOperator.ts b/src/background/operators/impls/SelectPreviousSelectedTabOperator.ts
new file mode 100644
index 0000000..03a778d
--- /dev/null
+++ b/src/background/operators/impls/SelectPreviousSelectedTabOperator.ts
@@ -0,0 +1,14 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class SelectPreviousSelectedTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tabId = await this.tabPresenter.getLastSelectedId();
+ if (tabId === null || typeof tabId === "undefined") {
+ return Promise.resolve();
+ }
+ return this.tabPresenter.select(tabId);
+ }
+}
diff --git a/src/background/operators/impls/SelectTabNextOperator.ts b/src/background/operators/impls/SelectTabNextOperator.ts
new file mode 100644
index 0000000..34d37ff
--- /dev/null
+++ b/src/background/operators/impls/SelectTabNextOperator.ts
@@ -0,0 +1,19 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class SelectTabNextOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tabs = await this.tabPresenter.getAll();
+ if (tabs.length < 2) {
+ return;
+ }
+ const tab = tabs.find((t) => t.active);
+ if (!tab) {
+ return;
+ }
+ const select = (tab.index + 1) % tabs.length;
+ return this.tabPresenter.select(tabs[select].id as number);
+ }
+}
diff --git a/src/background/operators/impls/SelectTabPrevOperator.ts b/src/background/operators/impls/SelectTabPrevOperator.ts
new file mode 100644
index 0000000..3776c1a
--- /dev/null
+++ b/src/background/operators/impls/SelectTabPrevOperator.ts
@@ -0,0 +1,19 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class SelectTabPrevOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tabs = await this.tabPresenter.getAll();
+ if (tabs.length < 2) {
+ return;
+ }
+ const tab = tabs.find((t) => t.active);
+ if (!tab) {
+ return;
+ }
+ const select = (tab.index - 1 + tabs.length) % tabs.length;
+ return this.tabPresenter.select(tabs[select].id as number);
+ }
+}
diff --git a/src/background/operators/impls/ShowAddBookmarkOperator.ts b/src/background/operators/impls/ShowAddBookmarkOperator.ts
new file mode 100644
index 0000000..cce4879
--- /dev/null
+++ b/src/background/operators/impls/ShowAddBookmarkOperator.ts
@@ -0,0 +1,20 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class ShowAddBookmarkOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient,
+ private readonly alter: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ let command = "addbookmark ";
+ if (this.alter) {
+ command += tab.title || "";
+ }
+ return this.consoleClient.showCommand(tab.id as number, command);
+ }
+}
diff --git a/src/background/operators/impls/ShowBufferCommandOperator.ts b/src/background/operators/impls/ShowBufferCommandOperator.ts
new file mode 100644
index 0000000..e1246e4
--- /dev/null
+++ b/src/background/operators/impls/ShowBufferCommandOperator.ts
@@ -0,0 +1,16 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class ShowBufferCommandOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ const command = "buffer ";
+ return this.consoleClient.showCommand(tab.id as number, command);
+ }
+}
diff --git a/src/background/operators/impls/ShowCommandOperator.ts b/src/background/operators/impls/ShowCommandOperator.ts
new file mode 100644
index 0000000..a5e1765
--- /dev/null
+++ b/src/background/operators/impls/ShowCommandOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class ShowCommandOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.consoleClient.showCommand(tab.id as number, "");
+ }
+}
diff --git a/src/background/operators/impls/ShowOpenCommandOperator.ts b/src/background/operators/impls/ShowOpenCommandOperator.ts
new file mode 100644
index 0000000..1e78e5f
--- /dev/null
+++ b/src/background/operators/impls/ShowOpenCommandOperator.ts
@@ -0,0 +1,20 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class ShowOpenCommandOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient,
+ private readonly alter: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ let command = "open ";
+ if (this.alter) {
+ command += tab.url || "";
+ }
+ return this.consoleClient.showCommand(tab.id as number, command);
+ }
+}
diff --git a/src/background/operators/impls/ShowTabOpenCommandOperator.ts b/src/background/operators/impls/ShowTabOpenCommandOperator.ts
new file mode 100644
index 0000000..d734da1
--- /dev/null
+++ b/src/background/operators/impls/ShowTabOpenCommandOperator.ts
@@ -0,0 +1,20 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class ShowTabOpenCommandOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient,
+ private readonly alter: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ let command = "tabopen ";
+ if (this.alter) {
+ command += tab.url || "";
+ }
+ return this.consoleClient.showCommand(tab.id as number, command);
+ }
+}
diff --git a/src/background/operators/impls/ShowWinOpenCommandOperator.ts b/src/background/operators/impls/ShowWinOpenCommandOperator.ts
new file mode 100644
index 0000000..3c5e639
--- /dev/null
+++ b/src/background/operators/impls/ShowWinOpenCommandOperator.ts
@@ -0,0 +1,20 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class ShowWinOpenCommandOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient,
+ private readonly alter: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ let command = "winopen ";
+ if (this.alter) {
+ command += tab.url || "";
+ }
+ return this.consoleClient.showCommand(tab.id as number, command);
+ }
+}
diff --git a/src/background/operators/impls/StartFindOperator.ts b/src/background/operators/impls/StartFindOperator.ts
new file mode 100644
index 0000000..284ac9b
--- /dev/null
+++ b/src/background/operators/impls/StartFindOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class StartFindOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.consoleClient.showFind(tab.id as number);
+ }
+}
diff --git a/src/background/operators/impls/TabOperatorFactoryChain.ts b/src/background/operators/impls/TabOperatorFactoryChain.ts
new file mode 100644
index 0000000..edd3eaf
--- /dev/null
+++ b/src/background/operators/impls/TabOperatorFactoryChain.ts
@@ -0,0 +1,64 @@
+import { inject, injectable } from "tsyringe";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import * as operations from "../../../shared/operations";
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import CloseTabOperator from "./CloseTabOperator";
+import CloseTabRightOperator from "./CloseTabRightOperator";
+import ReopenTabOperator from "./ReopenTabOperator";
+import SelectTabPrevOperator from "./SelectTabPrevOperator";
+import SelectTabNextOperator from "./SelectTabNextOperator";
+import SelectFirstTabOperator from "./SelectFirstTabOperator";
+import SelectLastTabOperator from "./SelectLastTabOperator";
+import SelectPreviousSelectedTabOperator from "./SelectPreviousSelectedTabOperator";
+import ReloadTabOperator from "./ReloadTabOperator";
+import PinTabOperator from "./PinTabOperator";
+import UnpinTabOperator from "./UnpinTabOperator";
+import TogglePinnedTabOperator from "./TogglePinnedTabOperator";
+import DuplicateTabOperator from "./DuplicateTabOperator";
+
+@injectable()
+export default class TabOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("TabPresenter")
+ private readonly tabPresenter: TabPresenter
+ ) {}
+
+ create(op: operations.Operation): Operator | null {
+ switch (op.type) {
+ case operations.TAB_CLOSE:
+ return new CloseTabOperator(
+ this.tabPresenter,
+ false,
+ op.select === "left"
+ );
+ case operations.TAB_CLOSE_RIGHT:
+ return new CloseTabRightOperator(this.tabPresenter);
+ case operations.TAB_CLOSE_FORCE:
+ return new CloseTabOperator(this.tabPresenter, true, false);
+ case operations.TAB_REOPEN:
+ return new ReopenTabOperator(this.tabPresenter);
+ case operations.TAB_PREV:
+ return new SelectTabPrevOperator(this.tabPresenter);
+ case operations.TAB_NEXT:
+ return new SelectTabNextOperator(this.tabPresenter);
+ case operations.TAB_FIRST:
+ return new SelectFirstTabOperator(this.tabPresenter);
+ case operations.TAB_LAST:
+ return new SelectLastTabOperator(this.tabPresenter);
+ case operations.TAB_PREV_SEL:
+ return new SelectPreviousSelectedTabOperator(this.tabPresenter);
+ case operations.TAB_RELOAD:
+ return new ReloadTabOperator(this.tabPresenter, op.cache);
+ case operations.TAB_PIN:
+ return new PinTabOperator(this.tabPresenter);
+ case operations.TAB_UNPIN:
+ return new UnpinTabOperator(this.tabPresenter);
+ case operations.TAB_TOGGLE_PINNED:
+ return new TogglePinnedTabOperator(this.tabPresenter);
+ case operations.TAB_DUPLICATE:
+ return new DuplicateTabOperator(this.tabPresenter);
+ }
+ return null;
+ }
+}
diff --git a/src/background/operators/impls/TogglePinnedTabOperator.ts b/src/background/operators/impls/TogglePinnedTabOperator.ts
new file mode 100644
index 0000000..c4fd4ba
--- /dev/null
+++ b/src/background/operators/impls/TogglePinnedTabOperator.ts
@@ -0,0 +1,11 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class TogglePinnedTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.tabPresenter.setPinned(tab.id as number, !tab.pinned);
+ }
+}
diff --git a/src/background/operators/impls/UnpinTabOperator.ts b/src/background/operators/impls/UnpinTabOperator.ts
new file mode 100644
index 0000000..fa50145
--- /dev/null
+++ b/src/background/operators/impls/UnpinTabOperator.ts
@@ -0,0 +1,11 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class UnpinTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.tabPresenter.setPinned(tab.id as number, false);
+ }
+}
diff --git a/src/background/operators/impls/ZoomInOperator.ts b/src/background/operators/impls/ZoomInOperator.ts
new file mode 100644
index 0000000..e900f0d
--- /dev/null
+++ b/src/background/operators/impls/ZoomInOperator.ts
@@ -0,0 +1,10 @@
+import Operator from "../Operator";
+import ZoomPresenter from "../../presenters/ZoomPresenter";
+
+export default class ZoomInOperator implements Operator {
+ constructor(private readonly zoomPresenter: ZoomPresenter) {}
+
+ run(): Promise<void> {
+ return this.zoomPresenter.zoomIn();
+ }
+}
diff --git a/src/background/operators/impls/ZoomOperatorFactoryChain.ts b/src/background/operators/impls/ZoomOperatorFactoryChain.ts
new file mode 100644
index 0000000..bf930a7
--- /dev/null
+++ b/src/background/operators/impls/ZoomOperatorFactoryChain.ts
@@ -0,0 +1,28 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import ZoomInOperator from "./ZoomInOperator";
+import ZoomOutOperator from "./ZoomOutOperator";
+import ResetZoomOperator from "./ResetZoomOperator";
+import ZoomPresenter from "../../presenters/ZoomPresenter";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export default class ZoomOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("ZoomPresenter")
+ private readonly zoomPresenter: ZoomPresenter
+ ) {}
+
+ create(op: operations.Operation): Operator | null {
+ switch (op.type) {
+ case operations.ZOOM_IN:
+ return new ZoomInOperator(this.zoomPresenter);
+ case operations.ZOOM_OUT:
+ return new ZoomOutOperator(this.zoomPresenter);
+ case operations.ZOOM_NEUTRAL:
+ return new ResetZoomOperator(this.zoomPresenter);
+ }
+ return null;
+ }
+}
diff --git a/src/background/operators/impls/ZoomOutOperator.ts b/src/background/operators/impls/ZoomOutOperator.ts
new file mode 100644
index 0000000..0c0389e
--- /dev/null
+++ b/src/background/operators/impls/ZoomOutOperator.ts
@@ -0,0 +1,10 @@
+import Operator from "../Operator";
+import ZoomPresenter from "../../presenters/ZoomPresenter";
+
+export default class ZoomOutOperator implements Operator {
+ constructor(private readonly zoomPresenter: ZoomPresenter) {}
+
+ run(): Promise<void> {
+ return this.zoomPresenter.zoomOut();
+ }
+}
diff --git a/src/background/presenters/Notifier.ts b/src/background/presenters/Notifier.ts
index 2cd3225..957572d 100644
--- a/src/background/presenters/Notifier.ts
+++ b/src/background/presenters/Notifier.ts
@@ -30,10 +30,10 @@ export class NotifierImpl implements NotifierImpl {
}
async notifyInvalidSettings(onclick: () => void): Promise<void> {
- const title = `Loaded settings is invalid`;
+ const title = `Loading settings failed`;
// eslint-disable-next-line max-len
const message =
- "The default settings is used due to the last saved settings is invalid. Check your current settings from the add-on preference";
+ "The default settings are used due to the last saved settings is invalid. Check your current settings from the add-on preference";
const listener = (id: string) => {
if (id !== NOTIFICATION_ID_INVALID_SETTINGS) {
diff --git a/src/background/presenters/WindowPresenter.ts b/src/background/presenters/WindowPresenter.ts
index 4f37f5d..5eb0f22 100644
--- a/src/background/presenters/WindowPresenter.ts
+++ b/src/background/presenters/WindowPresenter.ts
@@ -1,8 +1,9 @@
-import { injectable } from "tsyringe";
+export default interface WindowPresenter {
+ create(url: string): Promise<void>;
+}
-@injectable()
-export default class WindowPresenter {
- create(url: string): Promise<browser.windows.Window> {
- return browser.windows.create({ url });
+export class WindowPresenterImpl implements WindowPresenter {
+ async create(url: string): Promise<void> {
+ await browser.windows.create({ url });
}
}
diff --git a/src/background/presenters/ZoomPresenter.ts b/src/background/presenters/ZoomPresenter.ts
new file mode 100644
index 0000000..5a3c64d
--- /dev/null
+++ b/src/background/presenters/ZoomPresenter.ts
@@ -0,0 +1,60 @@
+const ZOOM_SETTINGS = [
+ 0.33,
+ 0.5,
+ 0.66,
+ 0.75,
+ 0.8,
+ 0.9,
+ 1.0,
+ 1.1,
+ 1.25,
+ 1.5,
+ 1.75,
+ 2.0,
+ 2.5,
+ 3.0,
+] as const;
+
+export default interface ZoomPresenter {
+ zoomIn(): Promise<void>;
+ zoomOut(): Promise<void>;
+ resetZoom(): Promise<void>;
+}
+
+export class ZoomPresenterImpl implements ZoomPresenter {
+ async zoomIn(): Promise<void> {
+ const tab = await browser.tabs.query({
+ active: true,
+ currentWindow: true,
+ });
+ const tabId = tab[0].id as number;
+ const current = await browser.tabs.getZoom(tabId);
+ const factor = ZOOM_SETTINGS.find((f) => f > current);
+ if (factor) {
+ return browser.tabs.setZoom(tabId, factor);
+ }
+ }
+
+ async zoomOut(): Promise<void> {
+ const tab = await browser.tabs.query({
+ active: true,
+ currentWindow: true,
+ });
+ const tabId = tab[0].id as number;
+ const current = await browser.tabs.getZoom(tabId);
+ const factor = ZOOM_SETTINGS.slice(0)
+ .reverse()
+ .find((f) => f < current);
+ if (factor) {
+ return browser.tabs.setZoom(tabId, factor);
+ }
+ }
+
+ async resetZoom(): Promise<void> {
+ const tab = await browser.tabs.query({
+ active: true,
+ currentWindow: true,
+ });
+ return browser.tabs.setZoom(tab[0].id, 1);
+ }
+}
diff --git a/src/background/repositories/BrowserSettingRepository.ts b/src/background/repositories/BrowserSettingRepository.ts
index e24874b..1dde190 100644
--- a/src/background/repositories/BrowserSettingRepository.ts
+++ b/src/background/repositories/BrowserSettingRepository.ts
@@ -1,8 +1,12 @@
import { injectable } from "tsyringe";
import * as urls from "../../shared/urls";
+export default interface BrowserSettingRepository {
+ getHomepageUrls(): Promise<string[]>;
+}
+
@injectable()
-export default class BrowserSettingRepository {
+export class BrowserSettingRepositoryImpl implements BrowserSettingRepository {
async getHomepageUrls(): Promise<string[]> {
const { value } = await browser.browserSettings.homepageOverride.get({});
return value.split("|").map(urls.normalizeUrl);
diff --git a/src/background/repositories/RepeatRepository.ts b/src/background/repositories/RepeatRepository.ts
index e3ab43d..00098d3 100644
--- a/src/background/repositories/RepeatRepository.ts
+++ b/src/background/repositories/RepeatRepository.ts
@@ -4,8 +4,14 @@ import MemoryStorage from "../infrastructures/MemoryStorage";
const REPEAT_KEY = "repeat";
+export default interface RepeatRepository {
+ getLastOperation(): Operation | undefined;
+
+ setLastOperation(op: Operation): void;
+}
+
@injectable()
-export default class RepeatRepository {
+export class RepeatRepositoryImpl implements RepeatRepository {
private cache: MemoryStorage;
constructor() {
diff --git a/src/background/usecases/AddonEnabledUseCase.ts b/src/background/usecases/AddonEnabledUseCase.ts
index f563ab0..f9bafde 100644
--- a/src/background/usecases/AddonEnabledUseCase.ts
+++ b/src/background/usecases/AddonEnabledUseCase.ts
@@ -22,7 +22,7 @@ export default class AddonEnabledUseCase {
return this.indicatorPresentor.indicate(enabled);
}
- onIndicatorClick(tabId: number): Promise<void> {
+ private onIndicatorClick(tabId: number): Promise<void> {
return this.contentMessageClient.toggleAddonEnabled(tabId);
}
diff --git a/src/background/usecases/CommandUseCase.ts b/src/background/usecases/CommandUseCase.ts
index 811ec77..18ddd4d 100644
--- a/src/background/usecases/CommandUseCase.ts
+++ b/src/background/usecases/CommandUseCase.ts
@@ -12,17 +12,20 @@ import ContentMessageClient from "../infrastructures/ContentMessageClient";
import RepeatUseCase from "../usecases/RepeatUseCase";
@injectable()
-export default class CommandIndicator {
+export default class CommandUseCase {
constructor(
- @inject("TabPresenter") private tabPresenter: TabPresenter,
- private windowPresenter: WindowPresenter,
- private helpPresenter: HelpPresenter,
+ @inject("TabPresenter")
+ private readonly tabPresenter: TabPresenter,
+ @inject("WindowPresenter")
+ private readonly windowPresenter: WindowPresenter,
+ private readonly helpPresenter: HelpPresenter,
@inject("CachedSettingRepository")
- private cachedSettingRepository: CachedSettingRepository,
- private bookmarkRepository: BookmarkRepository,
- private consoleClient: ConsoleClient,
- private contentMessageClient: ContentMessageClient,
- private repeatUseCase: RepeatUseCase
+ private readonly cachedSettingRepository: CachedSettingRepository,
+ private readonly bookmarkRepository: BookmarkRepository,
+ @inject("ConsoleClient")
+ private readonly consoleClient: ConsoleClient,
+ private readonly contentMessageClient: ContentMessageClient,
+ private readonly repeatUseCase: RepeatUseCase
) {}
async open(keywords: string): Promise<browser.tabs.Tab> {
@@ -44,7 +47,7 @@ export default class CommandIndicator {
return this.tabPresenter.create(url);
}
- async winopen(keywords: string): Promise<browser.windows.Window> {
+ async winopen(keywords: string): Promise<void> {
const url = await this.urlOrSearch(keywords);
this.repeatUseCase.storeLastOperation({
type: operations.INTERNAL_OPEN_URL,
diff --git a/src/background/usecases/ConsoleUseCase.ts b/src/background/usecases/ConsoleUseCase.ts
deleted file mode 100644
index 195c70f..0000000
--- a/src/background/usecases/ConsoleUseCase.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import { inject, injectable } from "tsyringe";
-import TabPresenter from "../presenters/TabPresenter";
-import ConsoleClient from "../infrastructures/ConsoleClient";
-
-@injectable()
-export default class ConsoleUseCase {
- constructor(
- @inject("TabPresenter") private tabPresenter: TabPresenter,
- private consoleClient: ConsoleClient
- ) {}
-
- async showCommand(): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- return this.consoleClient.showCommand(tab.id as number, "");
- }
-
- async showOpenCommand(alter: boolean): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- let command = "open ";
- if (alter) {
- command += tab.url || "";
- }
- return this.consoleClient.showCommand(tab.id as number, command);
- }
-
- async showTabopenCommand(alter: boolean): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- let command = "tabopen ";
- if (alter) {
- command += tab.url || "";
- }
- return this.consoleClient.showCommand(tab.id as number, command);
- }
-
- async showWinopenCommand(alter: boolean): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- let command = "winopen ";
- if (alter) {
- command += tab.url || "";
- }
- return this.consoleClient.showCommand(tab.id as number, command);
- }
-
- async showBufferCommand(): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- const command = "buffer ";
- return this.consoleClient.showCommand(tab.id as number, command);
- }
-
- async showAddbookmarkCommand(alter: boolean): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- let command = "addbookmark ";
- if (alter) {
- command += tab.title || "";
- }
- return this.consoleClient.showCommand(tab.id as number, command);
- }
-
- async hideConsole(): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- return this.consoleClient.hide(tab.id as number);
- }
-}
diff --git a/src/background/usecases/FindUseCase.ts b/src/background/usecases/FindUseCase.ts
index facc461..ce96e03 100644
--- a/src/background/usecases/FindUseCase.ts
+++ b/src/background/usecases/FindUseCase.ts
@@ -1,15 +1,9 @@
-import { inject, injectable } from "tsyringe";
+import { injectable } from "tsyringe";
import FindRepository from "../repositories/FindRepository";
-import TabPresenter from "../presenters/TabPresenter";
-import ConsoleClient from "../infrastructures/ConsoleClient";
@injectable()
export default class FindUseCase {
- constructor(
- @inject("TabPresenter") private tabPresenter: TabPresenter,
- private findRepository: FindRepository,
- private consoleClient: ConsoleClient
- ) {}
+ constructor(private readonly findRepository: FindRepository) {}
getKeyword(): Promise<string> {
return this.findRepository.getKeyword();
@@ -18,9 +12,4 @@ export default class FindUseCase {
setKeyword(keyword: string): Promise<any> {
return this.findRepository.setKeyword(keyword);
}
-
- async findStart(): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- return this.consoleClient.showFind(tab.id as number);
- }
}
diff --git a/src/background/usecases/MarkUseCase.ts b/src/background/usecases/MarkUseCase.ts
index 9da9a21..57e04b4 100644
--- a/src/background/usecases/MarkUseCase.ts
+++ b/src/background/usecases/MarkUseCase.ts
@@ -1,16 +1,18 @@
import { inject, injectable } from "tsyringe";
import TabPresenter from "../presenters/TabPresenter";
import MarkRepository from "../repositories/MarkRepository";
-import ConsoleClient from "../infrastructures/ConsoleClient";
import ContentMessageClient from "../infrastructures/ContentMessageClient";
+import ConsoleClient from "../infrastructures/ConsoleClient";
@injectable()
export default class MarkUseCase {
constructor(
- @inject("TabPresenter") private tabPresenter: TabPresenter,
- private markRepository: MarkRepository,
- private consoleClient: ConsoleClient,
- private contentMessageClient: ContentMessageClient
+ @inject("TabPresenter")
+ private readonly tabPresenter: TabPresenter,
+ private readonly markRepository: MarkRepository,
+ @inject("ConsoleClient")
+ private readonly consoleClient: ConsoleClient,
+ private readonly contentMessageClient: ContentMessageClient
) {}
async setGlobal(key: string, x: number, y: number): Promise<any> {
diff --git a/src/background/usecases/NavigateUseCase.ts b/src/background/usecases/NavigateUseCase.ts
deleted file mode 100644
index 974606c..0000000
--- a/src/background/usecases/NavigateUseCase.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { inject, injectable } from "tsyringe";
-import NavigateClient from "../clients/NavigateClient";
-import TabPresenter from "../presenters/TabPresenter";
-
-@injectable()
-export default class NavigateUseCase {
- constructor(
- @inject("TabPresenter") private tabPresenter: TabPresenter,
- private navigateClient: NavigateClient
- ) {}
-
- async openHistoryNext(): Promise<void> {
- const tab = await this.tabPresenter.getCurrent();
- await this.navigateClient.historyNext(tab.id!);
- }
-
- async openHistoryPrev(): Promise<void> {
- const tab = await this.tabPresenter.getCurrent();
- await this.navigateClient.historyPrev(tab.id!);
- }
-
- async openLinkNext(): Promise<void> {
- const tab = await this.tabPresenter.getCurrent();
- await this.navigateClient.linkNext(tab.id!);
- }
-
- async openLinkPrev(): Promise<void> {
- const tab = await this.tabPresenter.getCurrent();
- await this.navigateClient.linkPrev(tab.id!);
- }
-
- async openParent(): Promise<void> {
- const tab = await this.tabPresenter.getCurrent();
- const url = new URL(tab.url!);
- if (url.hash.length > 0) {
- url.hash = "";
- } else if (url.search.length > 0) {
- url.search = "";
- } else {
- const basenamePattern = /\/[^/]+$/;
- const lastDirPattern = /\/[^/]+\/$/;
- if (basenamePattern.test(url.pathname)) {
- url.pathname = url.pathname.replace(basenamePattern, "/");
- } else if (lastDirPattern.test(url.pathname)) {
- url.pathname = url.pathname.replace(lastDirPattern, "/");
- }
- }
- await this.tabPresenter.open(url.href);
- }
-
- async openRoot(): Promise<void> {
- const tab = await this.tabPresenter.getCurrent();
- const url = new URL(tab.url!);
- await this.tabPresenter.open(url.origin);
- }
-}
diff --git a/src/background/usecases/RepeatUseCase.ts b/src/background/usecases/RepeatUseCase.ts
index d7235ee..992e76b 100644
--- a/src/background/usecases/RepeatUseCase.ts
+++ b/src/background/usecases/RepeatUseCase.ts
@@ -1,4 +1,4 @@
-import { injectable } from "tsyringe";
+import { inject, injectable } from "tsyringe";
import * as operations from "../../shared/operations";
import RepeatRepository from "../repositories/RepeatRepository";
@@ -6,7 +6,10 @@ type Operation = operations.Operation;
@injectable()
export default class RepeatUseCase {
- constructor(private repeatRepository: RepeatRepository) {}
+ constructor(
+ @inject("RepeatRepository")
+ private readonly repeatRepository: RepeatRepository
+ ) {}
storeLastOperation(op: Operation): void {
this.repeatRepository.setLastOperation(op);
diff --git a/src/background/usecases/TabSelectUseCase.ts b/src/background/usecases/TabSelectUseCase.ts
deleted file mode 100644
index 663ceb8..0000000
--- a/src/background/usecases/TabSelectUseCase.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import { inject, injectable } from "tsyringe";
-import TabPresenter from "../presenters/TabPresenter";
-
-@injectable()
-export default class TabSelectUseCase {
- constructor(@inject("TabPresenter") private tabPresenter: TabPresenter) {}
-
- async selectPrev(count: number): Promise<any> {
- const tabs = await this.tabPresenter.getAll();
- if (tabs.length < 2) {
- return;
- }
- const tab = tabs.find((t) => t.active);
- if (!tab) {
- return;
- }
- const select = (tab.index - count + tabs.length) % tabs.length;
- return this.tabPresenter.select(tabs[select].id as number);
- }
-
- async selectNext(count: number): Promise<any> {
- const tabs = await this.tabPresenter.getAll();
- if (tabs.length < 2) {
- return;
- }
- const tab = tabs.find((t) => t.active);
- if (!tab) {
- return;
- }
- const select = (tab.index + count) % tabs.length;
- return this.tabPresenter.select(tabs[select].id as number);
- }
-
- async selectFirst(): Promise<any> {
- const tabs = await this.tabPresenter.getAll();
- return this.tabPresenter.select(tabs[0].id as number);
- }
-
- async selectLast(): Promise<any> {
- const tabs = await this.tabPresenter.getAll();
- return this.tabPresenter.select(tabs[tabs.length - 1].id as number);
- }
-
- async selectPrevSelected(): Promise<any> {
- const tabId = await this.tabPresenter.getLastSelectedId();
- if (tabId === null || typeof tabId === "undefined") {
- return Promise.resolve();
- }
- return this.tabPresenter.select(tabId);
- }
-}
diff --git a/src/background/usecases/TabUseCase.ts b/src/background/usecases/TabUseCase.ts
deleted file mode 100644
index 1439107..0000000
--- a/src/background/usecases/TabUseCase.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-import { inject, injectable } from "tsyringe";
-import TabPresenter from "../presenters/TabPresenter";
-import WindowPresenter from "../presenters/WindowPresenter";
-import BrowserSettingRepository from "../repositories/BrowserSettingRepository";
-
-@injectable()
-export default class TabUseCase {
- constructor(
- @inject("TabPresenter") private tabPresenter: TabPresenter,
- private windowPresenter: WindowPresenter,
- private browserSettingRepository: BrowserSettingRepository
- ) {}
-
- async close(force: boolean, selectLeft = false): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- if (!force && tab.pinned) {
- return Promise.resolve();
- }
- if (selectLeft && tab.index > 0) {
- const tabs = await this.tabPresenter.getAll();
- await this.tabPresenter.select(tabs[tab.index - 1].id as number);
- }
- return this.tabPresenter.remove([tab.id as number]);
- }
-
- async closeRight(): Promise<any> {
- const tabs = await this.tabPresenter.getAll();
- tabs.sort((t1, t2) => t1.index - t2.index);
- const index = tabs.findIndex((t) => t.active);
- if (index < 0) {
- return;
- }
- for (let i = index + 1; i < tabs.length; ++i) {
- const tab = tabs[i];
- if (!tab.pinned) {
- this.tabPresenter.remove([tab.id as number]);
- }
- }
- }
-
- reopen(): Promise<any> {
- return this.tabPresenter.reopen();
- }
-
- async reload(cache: boolean): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- return this.tabPresenter.reload(tab.id as number, cache);
- }
-
- async setPinned(pinned: boolean): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- return this.tabPresenter.setPinned(tab.id as number, pinned);
- }
-
- async togglePinned(): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- return this.tabPresenter.setPinned(tab.id as number, !tab.pinned);
- }
-
- async duplicate(): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- return this.tabPresenter.duplicate(tab.id as number);
- }
-
- async openPageSource(): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- const url = "view-source:" + tab.url;
- return this.tabPresenter.create(url);
- }
-
- async openHome(newTab: boolean): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- const urls = await this.browserSettingRepository.getHomepageUrls();
- if (urls.length === 1 && urls[0] === "about:home") {
- // eslint-disable-next-line max-len
- throw new Error(
- "Cannot open Firefox Home (about:home) by WebExtensions, set your custom URLs"
- );
- }
- if (urls.length === 1 && !newTab) {
- return this.tabPresenter.open(urls[0], tab.id);
- }
- for (const url of urls) {
- this.tabPresenter.create(url);
- }
- }
-
- async openURL(
- url: string,
- newTab?: boolean,
- newWindow?: boolean
- ): Promise<void> {
- if (newWindow) {
- await this.windowPresenter.create(url);
- } else if (newTab) {
- await this.tabPresenter.create(url);
- } else {
- const tab = await this.tabPresenter.getCurrent();
- await this.tabPresenter.open(url, tab.id);
- }
- }
-}
diff --git a/src/background/usecases/ZoomUseCase.ts b/src/background/usecases/ZoomUseCase.ts
deleted file mode 100644
index 173e4d7..0000000
--- a/src/background/usecases/ZoomUseCase.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import { inject, injectable } from "tsyringe";
-import TabPresenter from "../presenters/TabPresenter";
-
-const ZOOM_SETTINGS: number[] = [
- 0.33,
- 0.5,
- 0.66,
- 0.75,
- 0.8,
- 0.9,
- 1.0,
- 1.1,
- 1.25,
- 1.5,
- 1.75,
- 2.0,
- 2.5,
- 3.0,
-];
-
-@injectable()
-export default class ZoomUseCase {
- constructor(@inject("TabPresenter") private tabPresenter: TabPresenter) {}
-
- async zoomIn(): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- const tabId = tab.id as number;
- const current = await this.tabPresenter.getZoom(tabId);
- const factor = ZOOM_SETTINGS.find((f) => f > current);
- if (factor) {
- return this.tabPresenter.setZoom(tabId as number, factor);
- }
- }
-
- async zoomOut(): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- const tabId = tab.id as number;
- const current = await this.tabPresenter.getZoom(tabId);
- const factor = ZOOM_SETTINGS.slice(0)
- .reverse()
- .find((f) => f < current);
- if (factor) {
- return this.tabPresenter.setZoom(tabId as number, factor);
- }
- }
-
- async zoomNutoral(): Promise<any> {
- const tab = await this.tabPresenter.getCurrent();
- return this.tabPresenter.setZoom(tab.id as number, 1);
- }
-}
diff --git a/src/content/controllers/KeymapController.ts b/src/content/controllers/KeymapController.ts
index 092e55c..01ac8b5 100644
--- a/src/content/controllers/KeymapController.ts
+++ b/src/content/controllers/KeymapController.ts
@@ -1,32 +1,15 @@
import { injectable, inject } from "tsyringe";
-import * as operations from "../../shared/operations";
import KeymapUseCase from "../usecases/KeymapUseCase";
-import AddonEnabledUseCase from "../usecases/AddonEnabledUseCase";
-import FindSlaveUseCase from "../usecases/FindSlaveUseCase";
-import ScrollUseCase from "../usecases/ScrollUseCase";
-import FocusUseCase from "../usecases/FocusUseCase";
-import ClipboardUseCase from "../usecases/ClipboardUseCase";
-import OperationClient from "../client/OperationClient";
-import MarkKeyyUseCase from "../usecases/MarkKeyUseCase";
-import FollowMasterClient from "../client/FollowMasterClient";
import Key from "../../shared/settings/Key";
+import OperatorFactory from "../operators/OperatorFactory";
@injectable()
export default class KeymapController {
constructor(
private keymapUseCase: KeymapUseCase,
- private addonEnabledUseCase: AddonEnabledUseCase,
- private findSlaveUseCase: FindSlaveUseCase,
- private scrollUseCase: ScrollUseCase,
- private focusUseCase: FocusUseCase,
- private clipbaordUseCase: ClipboardUseCase,
- private markKeyUseCase: MarkKeyyUseCase,
- @inject("OperationClient")
- private operationClient: OperationClient,
-
- @inject("FollowMasterClient")
- private followMasterClient: FollowMasterClient
+ @inject("OperatorFactory")
+ private readonly operatorFactory: OperatorFactory
) {}
// eslint-disable-next-line complexity, max-lines-per-function
@@ -36,65 +19,14 @@ export default class KeymapController {
return false;
}
- if (!operations.isNRepeatable(nextOp.op.type)) {
- nextOp.repeat = 1;
- }
-
- const doFunc = ((op: operations.Operation) => {
- switch (op.type) {
- case operations.ADDON_ENABLE:
- return () => this.addonEnabledUseCase.enable();
- case operations.ADDON_DISABLE:
- return () => this.addonEnabledUseCase.disable();
- case operations.ADDON_TOGGLE_ENABLED:
- return () => this.addonEnabledUseCase.toggle();
- case operations.FIND_NEXT:
- return () => this.findSlaveUseCase.findNext();
- case operations.FIND_PREV:
- return () => this.findSlaveUseCase.findPrev();
- case operations.SCROLL_VERTICALLY:
- return () => this.scrollUseCase.scrollVertically(op.count);
- case operations.SCROLL_HORIZONALLY:
- return () => this.scrollUseCase.scrollHorizonally(op.count);
- case operations.SCROLL_PAGES:
- return () => this.scrollUseCase.scrollPages(op.count);
- case operations.SCROLL_TOP:
- return () => this.scrollUseCase.scrollToTop();
- case operations.SCROLL_BOTTOM:
- return () => this.scrollUseCase.scrollToBottom();
- case operations.SCROLL_HOME:
- return () => this.scrollUseCase.scrollToHome();
- case operations.SCROLL_END:
- return () => this.scrollUseCase.scrollToEnd();
- case operations.FOLLOW_START:
- return () =>
- this.followMasterClient.startFollow(op.newTab, op.background);
- case operations.MARK_SET_PREFIX:
- return () => this.markKeyUseCase.enableSetMode();
- case operations.MARK_JUMP_PREFIX:
- return () => this.markKeyUseCase.enableJumpMode();
- case operations.FOCUS_INPUT:
- return () => this.focusUseCase.focusFirstInput();
- case operations.URLS_YANK:
- return () => this.clipbaordUseCase.yankCurrentURL();
- case operations.URLS_PASTE:
- return () =>
- this.clipbaordUseCase.openOrSearch(op.newTab ? op.newTab : false);
- default:
- return null;
- }
- })(nextOp.op);
+ // Do not await asynchronous methods to return a boolean immidiately. The
+ // caller requires the synchronous response from the callback to identify
+ // to continue of abandon the event propagation.
+ this.operatorFactory
+ .create(nextOp.op, nextOp.repeat)
+ .run()
+ .catch(console.error);
- if (doFunc === null) {
- // Do not await asynchronous methods to return a boolean immidiately. The
- // caller requires the synchronous response from the callback to identify
- // to continue of abandon the event propagations.
- this.operationClient.execBackgroundOp(nextOp.repeat, nextOp.op);
- } else {
- for (let i = 0; i < nextOp.repeat; ++i) {
- doFunc();
- }
- }
return true;
}
diff --git a/src/content/di.ts b/src/content/di.ts
index cc10c78..e74d7ac 100644
--- a/src/content/di.ts
+++ b/src/content/di.ts
@@ -17,6 +17,7 @@ import { FollowMasterRepositoryImpl } from "./repositories/FollowMasterRepositor
import { FollowPresenterImpl } from "./presenters/FollowPresenter";
import { FollowSlaveClientFactoryImpl } from "./client/FollowSlaveClientFactory";
import { FollowSlaveRepositoryImpl } from "./repositories/FollowSlaveRepository";
+import { HintKeyRepositoryImpl } from "./repositories/HintKeyRepository";
import { KeymapRepositoryImpl } from "./repositories/KeymapRepository";
import { MarkClientImpl } from "./client/MarkClient";
import { MarkKeyRepositoryImpl } from "./repositories/MarkKeyRepository";
@@ -28,6 +29,8 @@ import { SettingClientImpl } from "./client/SettingClient";
import { SettingRepositoryImpl } from "./repositories/SettingRepository";
import { TabsClientImpl } from "./client/TabsClient";
import { container } from "tsyringe";
+import OperatorFactoryImpl from "./operators/impls/OperatorFactoryImpl";
+import { URLRepositoryImpl } from "./operators/impls/URLRepository";
container.register("FollowMasterClient", {
useValue: new FollowMasterClientImpl(window.top),
@@ -64,6 +67,9 @@ container.register("FollowSlaveClientFactory", {
container.register("FollowSlaveRepository", {
useClass: FollowSlaveRepositoryImpl,
});
+container.register("HintKeyRepository", {
+ useClass: HintKeyRepositoryImpl,
+});
container.register("KeymapRepository", { useClass: KeymapRepositoryImpl });
container.register("MarkClient", { useClass: MarkClientImpl });
container.register("MarkKeyRepository", { useClass: MarkKeyRepositoryImpl });
@@ -75,4 +81,6 @@ container.register("OperationClient", { useClass: OperationClientImpl });
container.register("ScrollPresenter", { useClass: ScrollPresenterImpl });
container.register("SettingClient", { useClass: SettingClientImpl });
container.register("SettingRepository", { useClass: SettingRepositoryImpl });
+container.register("URLRepository", { useClass: URLRepositoryImpl });
container.register("TabsClient", { useClass: TabsClientImpl });
+container.register("OperatorFactory", { useClass: OperatorFactoryImpl });
diff --git a/src/content/hint-key-producer.ts b/src/content/hint-key-producer.ts
deleted file mode 100644
index a5e2877..0000000
--- a/src/content/hint-key-producer.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-export default class HintKeyProducer {
- private charset: string;
-
- private counter: number[];
-
- constructor(charset: string) {
- if (charset.length === 0) {
- throw new TypeError("charset is empty");
- }
-
- this.charset = charset;
- this.counter = [];
- }
-
- produce(): string {
- this.increment();
-
- return this.counter.map((x) => this.charset[x]).join("");
- }
-
- private increment(): void {
- const max = this.charset.length - 1;
- if (this.counter.every((x) => x === max)) {
- this.counter = new Array(this.counter.length + 1).fill(0);
- return;
- }
-
- this.counter.reverse();
- const len = this.charset.length;
- let num = this.counter.reduce((x, y, index) => x + y * len ** index) + 1;
- for (let i = 0; i < this.counter.length; ++i) {
- this.counter[i] = num % len;
- num = ~~(num / len);
- }
- this.counter.reverse();
- }
-}
diff --git a/src/content/operators/Operator.ts b/src/content/operators/Operator.ts
new file mode 100644
index 0000000..3b1fe03
--- /dev/null
+++ b/src/content/operators/Operator.ts
@@ -0,0 +1,5 @@
+interface Operator {
+ run(): Promise<void>;
+}
+
+export default Operator;
diff --git a/src/content/operators/OperatorFactory.ts b/src/content/operators/OperatorFactory.ts
new file mode 100644
index 0000000..f45973b
--- /dev/null
+++ b/src/content/operators/OperatorFactory.ts
@@ -0,0 +1,6 @@
+import * as operations from "../../shared/operations";
+import Operator from "./Operator";
+
+export default interface OperatorFactory {
+ create(op: operations.Operation, repeat: number): Operator;
+}
diff --git a/src/content/operators/OperatorFactoryChain.ts b/src/content/operators/OperatorFactoryChain.ts
new file mode 100644
index 0000000..98dedb5
--- /dev/null
+++ b/src/content/operators/OperatorFactoryChain.ts
@@ -0,0 +1,6 @@
+import * as operations from "../../shared/operations";
+import Operator from "./Operator";
+
+export default interface OperatorFactoryChain {
+ create(op: operations.Operation, repeat: number): Operator | null;
+}
diff --git a/src/content/operators/impls/AbstractScrollOperator.ts b/src/content/operators/impls/AbstractScrollOperator.ts
new file mode 100644
index 0000000..f8d9f70
--- /dev/null
+++ b/src/content/operators/impls/AbstractScrollOperator.ts
@@ -0,0 +1,10 @@
+import SettingRepository from "../../repositories/SettingRepository";
+
+export default class AbstractScrollOperator {
+ constructor(private readonly settingRepository: SettingRepository) {}
+
+ protected getSmoothScroll(): boolean {
+ const settings = this.settingRepository.get();
+ return settings.properties.smoothscroll;
+ }
+}
diff --git a/src/content/operators/impls/AddonOperatorFactoryChain.ts b/src/content/operators/impls/AddonOperatorFactoryChain.ts
new file mode 100644
index 0000000..54880c4
--- /dev/null
+++ b/src/content/operators/impls/AddonOperatorFactoryChain.ts
@@ -0,0 +1,40 @@
+import { inject, injectable } from "tsyringe";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import AddonIndicatorClient from "../../client/AddonIndicatorClient";
+import AddonEnabledRepository from "../../repositories/AddonEnabledRepository";
+import * as operations from "../../../shared/operations";
+import Operator from "../Operator";
+import EnableAddonOperator from "./EnableAddonOperator";
+import DisableAddonOperator from "./DisableAddonOperator";
+import ToggleAddonOperator from "./ToggleAddonOperator";
+
+@injectable()
+export default class AddonOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("AddonIndicatorClient")
+ private readonly addonIndicatorClient: AddonIndicatorClient,
+ @inject("AddonEnabledRepository")
+ private readonly addonEnabledRepository: AddonEnabledRepository
+ ) {}
+
+ create(op: operations.Operation, _repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.ADDON_ENABLE:
+ return new EnableAddonOperator(
+ this.addonIndicatorClient,
+ this.addonEnabledRepository
+ );
+ case operations.ADDON_DISABLE:
+ return new DisableAddonOperator(
+ this.addonIndicatorClient,
+ this.addonEnabledRepository
+ );
+ case operations.ADDON_TOGGLE_ENABLED:
+ return new ToggleAddonOperator(
+ this.addonIndicatorClient,
+ this.addonEnabledRepository
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/content/operators/impls/BackgroundOperationOperator.ts b/src/content/operators/impls/BackgroundOperationOperator.ts
new file mode 100644
index 0000000..dd86559
--- /dev/null
+++ b/src/content/operators/impls/BackgroundOperationOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import OperationClient from "../../client/OperationClient";
+import * as operations from "../../../shared/operations";
+
+export default class BackgroundOperationOperator implements Operator {
+ constructor(
+ private readonly operationClient: OperationClient,
+ private readonly repeat: number,
+ private readonly op: operations.Operation
+ ) {}
+
+ async run(): Promise<void> {
+ await this.operationClient.execBackgroundOp(this.repeat, this.op);
+ }
+}
diff --git a/src/content/operators/impls/ClipboardOperatorFactoryChain.ts b/src/content/operators/impls/ClipboardOperatorFactoryChain.ts
new file mode 100644
index 0000000..454aea1
--- /dev/null
+++ b/src/content/operators/impls/ClipboardOperatorFactoryChain.ts
@@ -0,0 +1,47 @@
+import { inject, injectable } from "tsyringe";
+import YankURLOperator from "./YankURLOperator";
+import PasteOperator from "./PasteOperator";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import ClipboardRepository from "../../repositories/ClipboardRepository";
+import ConsoleClient from "../../client/ConsoleClient";
+import OperationClient from "../../client/OperationClient";
+import SettingRepository from "../../repositories/SettingRepository";
+import * as operations from "../../../shared/operations";
+import URLRepository from "./URLRepository";
+
+@injectable()
+export default class ClipboardOperatorFactoryChain
+ implements OperatorFactoryChain {
+ constructor(
+ @inject("ClipboardRepository")
+ private readonly clipboardRepository: ClipboardRepository,
+ @inject("ConsoleClient")
+ private readonly consoleClient: ConsoleClient,
+ @inject("OperationClient")
+ private readonly operationClinet: OperationClient,
+ @inject("SettingRepository")
+ private readonly settingRepository: SettingRepository,
+ @inject("URLRepository")
+ private readonly urlRepository: URLRepository
+ ) {}
+
+ create(op: operations.Operation, _repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.URLS_YANK:
+ return new YankURLOperator(
+ this.clipboardRepository,
+ this.consoleClient,
+ this.urlRepository
+ );
+ case operations.URLS_PASTE:
+ return new PasteOperator(
+ this.clipboardRepository,
+ this.settingRepository,
+ this.operationClinet,
+ op.newTab
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/content/operators/impls/DisableAddonOperator.ts b/src/content/operators/impls/DisableAddonOperator.ts
new file mode 100644
index 0000000..28811fe
--- /dev/null
+++ b/src/content/operators/impls/DisableAddonOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import AddonIndicatorClient from "../../client/AddonIndicatorClient";
+import AddonEnabledRepository from "../../repositories/AddonEnabledRepository";
+
+export default class DisableAddonOperator implements Operator {
+ constructor(
+ private readonly indicator: AddonIndicatorClient,
+ private readonly repository: AddonEnabledRepository
+ ) {}
+
+ async run(): Promise<void> {
+ this.repository.set(false);
+ await this.indicator.setEnabled(false);
+ }
+}
diff --git a/src/content/operators/impls/EnableAddonOperator.ts b/src/content/operators/impls/EnableAddonOperator.ts
new file mode 100644
index 0000000..b5b1d79
--- /dev/null
+++ b/src/content/operators/impls/EnableAddonOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import AddonIndicatorClient from "../../client/AddonIndicatorClient";
+import AddonEnabledRepository from "../../repositories/AddonEnabledRepository";
+
+export default class EnableAddonOperator implements Operator {
+ constructor(
+ private readonly indicator: AddonIndicatorClient,
+ private readonly repository: AddonEnabledRepository
+ ) {}
+
+ async run(): Promise<void> {
+ this.repository.set(true);
+ await this.indicator.setEnabled(true);
+ }
+}
diff --git a/src/content/operators/impls/EnableJumpMarkOperator.ts b/src/content/operators/impls/EnableJumpMarkOperator.ts
new file mode 100644
index 0000000..42ca8ee
--- /dev/null
+++ b/src/content/operators/impls/EnableJumpMarkOperator.ts
@@ -0,0 +1,10 @@
+import Operator from "../Operator";
+import MarkKeyRepository from "../../repositories/MarkKeyRepository";
+
+export default class EnableJumpMarkOperator implements Operator {
+ constructor(private readonly repository: MarkKeyRepository) {}
+
+ async run(): Promise<void> {
+ this.repository.enableJumpMode();
+ }
+}
diff --git a/src/content/operators/impls/EnableSetMarkOperator.ts b/src/content/operators/impls/EnableSetMarkOperator.ts
new file mode 100644
index 0000000..3d0daf4
--- /dev/null
+++ b/src/content/operators/impls/EnableSetMarkOperator.ts
@@ -0,0 +1,10 @@
+import Operator from "../Operator";
+import MarkKeyRepository from "../../repositories/MarkKeyRepository";
+
+export default class EnableSetMarkOperator implements Operator {
+ constructor(private readonly repository: MarkKeyRepository) {}
+
+ async run(): Promise<void> {
+ this.repository.enableSetMode();
+ }
+}
diff --git a/src/content/operators/impls/FindNextOperator.ts b/src/content/operators/impls/FindNextOperator.ts
new file mode 100644
index 0000000..c67f6d9
--- /dev/null
+++ b/src/content/operators/impls/FindNextOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import FindMasterClient from "../../client/FindMasterClient";
+
+export default class FindNextOperator implements Operator {
+ constructor(
+ private readonly findMasterClient: FindMasterClient,
+ private readonly repeat: number
+ ) {}
+
+ async run(): Promise<void> {
+ for (let i = 0; i < this.repeat; ++i) {
+ this.findMasterClient.findNext();
+ }
+ }
+}
diff --git a/src/content/operators/impls/FindOperatorFactoryChain.ts b/src/content/operators/impls/FindOperatorFactoryChain.ts
new file mode 100644
index 0000000..b3524c1
--- /dev/null
+++ b/src/content/operators/impls/FindOperatorFactoryChain.ts
@@ -0,0 +1,25 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import FindNextOperator from "./FindNextOperator";
+import FindPrevOperator from "./FindPrevOperator";
+import FindMasterClient from "../../client/FindMasterClient";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export default class FindOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("FindMasterClient")
+ private readonly findMasterClient: FindMasterClient
+ ) {}
+
+ create(op: operations.Operation, repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.FIND_NEXT:
+ return new FindNextOperator(this.findMasterClient, repeat);
+ case operations.FIND_PREV:
+ return new FindPrevOperator(this.findMasterClient, repeat);
+ }
+ return null;
+ }
+}
diff --git a/src/content/operators/impls/FindPrevOperator.ts b/src/content/operators/impls/FindPrevOperator.ts
new file mode 100644
index 0000000..f73e605
--- /dev/null
+++ b/src/content/operators/impls/FindPrevOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import FindMasterClient from "../../client/FindMasterClient";
+
+export default class FindPrevOperator implements Operator {
+ constructor(
+ private readonly findMasterClient: FindMasterClient,
+ private readonly repeat: number
+ ) {}
+
+ async run(): Promise<void> {
+ for (let i = 0; i < this.repeat; ++i) {
+ this.findMasterClient.findPrev();
+ }
+ }
+}
diff --git a/src/content/operators/impls/FocusOperator.ts b/src/content/operators/impls/FocusOperator.ts
new file mode 100644
index 0000000..51d6fec
--- /dev/null
+++ b/src/content/operators/impls/FocusOperator.ts
@@ -0,0 +1,10 @@
+import Operator from "../Operator";
+import FocusPresenter from "../../presenters/FocusPresenter";
+
+export default class FocusOperator implements Operator {
+ constructor(private readonly presenter: FocusPresenter) {}
+
+ async run(): Promise<void> {
+ this.presenter.focusFirstElement();
+ }
+}
diff --git a/src/content/operators/impls/FocusOperatorFactoryChain.ts b/src/content/operators/impls/FocusOperatorFactoryChain.ts
new file mode 100644
index 0000000..c89c1e5
--- /dev/null
+++ b/src/content/operators/impls/FocusOperatorFactoryChain.ts
@@ -0,0 +1,22 @@
+import { inject, injectable } from "tsyringe";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import Operator from "../Operator";
+import FocusOperator from "./FocusOperator";
+import FocusPresenter from "../../presenters/FocusPresenter";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export default class FocusOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("FocusPresenter")
+ private readonly focusPresenter: FocusPresenter
+ ) {}
+
+ create(op: operations.Operation, _repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.FOCUS_INPUT:
+ return new FocusOperator(this.focusPresenter);
+ }
+ return null;
+ }
+}
diff --git a/src/content/operators/impls/FollowOperatorFactoryChain.ts b/src/content/operators/impls/FollowOperatorFactoryChain.ts
new file mode 100644
index 0000000..588e1a4
--- /dev/null
+++ b/src/content/operators/impls/FollowOperatorFactoryChain.ts
@@ -0,0 +1,27 @@
+import { inject, injectable } from "tsyringe";
+import StartFollowOperator from "./StartFollowOperator";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import FollowMasterClient from "../../client/FollowMasterClient";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export default class FollowOperatorFactoryChain
+ implements OperatorFactoryChain {
+ constructor(
+ @inject("FollowMasterClient")
+ private followMasterClient: FollowMasterClient
+ ) {}
+
+ create(op: operations.Operation, _repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.FOLLOW_START:
+ return new StartFollowOperator(
+ this.followMasterClient,
+ op.newTab,
+ op.background
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/content/operators/impls/HorizontalScrollOperator.ts b/src/content/operators/impls/HorizontalScrollOperator.ts
new file mode 100644
index 0000000..f813f85
--- /dev/null
+++ b/src/content/operators/impls/HorizontalScrollOperator.ts
@@ -0,0 +1,21 @@
+import AbstractScrollOperator from "./AbstractScrollOperator";
+import Operator from "../Operator";
+import ScrollPresenter from "../../presenters/ScrollPresenter";
+import SettingRepository from "../../repositories/SettingRepository";
+
+export default class HorizontalScrollOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository,
+ private readonly count: number
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollHorizonally(this.count, smooth);
+ }
+}
diff --git a/src/content/operators/impls/MarkOperatorFactoryChain.ts b/src/content/operators/impls/MarkOperatorFactoryChain.ts
new file mode 100644
index 0000000..7e6c513
--- /dev/null
+++ b/src/content/operators/impls/MarkOperatorFactoryChain.ts
@@ -0,0 +1,25 @@
+import { inject, injectable } from "tsyringe";
+import EnableSetMarkOperator from "./EnableSetMarkOperator";
+import EnableJumpMarkOperator from "./EnableJumpMarkOperator";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import MarkKeyRepository from "../../repositories/MarkKeyRepository";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export default class MarkOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("MarkKeyRepository")
+ private readonly markKeyRepository: MarkKeyRepository
+ ) {}
+
+ create(op: operations.Operation, _repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.MARK_SET_PREFIX:
+ return new EnableSetMarkOperator(this.markKeyRepository);
+ case operations.MARK_JUMP_PREFIX:
+ return new EnableJumpMarkOperator(this.markKeyRepository);
+ }
+ return null;
+ }
+}
diff --git a/src/content/operators/impls/OperatorFactoryImpl.ts b/src/content/operators/impls/OperatorFactoryImpl.ts
new file mode 100644
index 0000000..22b35c8
--- /dev/null
+++ b/src/content/operators/impls/OperatorFactoryImpl.ts
@@ -0,0 +1,51 @@
+import { inject, injectable } from "tsyringe";
+import OperatorFactory from "../OperatorFactory";
+import BackgroundOperationOperator from "./BackgroundOperationOperator";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import { Operation } from "../../../shared/operations";
+import OperationClient from "../../client/OperationClient";
+import AddonOperatorFactoryChain from "./AddonOperatorFactoryChain";
+import ClipboardOperatorFactoryChain from "./ClipboardOperatorFactoryChain";
+import FindOperatorFactoryChain from "./FindOperatorFactoryChain";
+import FocusOperatorFactoryChain from "./FocusOperatorFactoryChain";
+import FollowOperatorFactoryChain from "./FollowOperatorFactoryChain";
+import MarkOperatorFactoryChain from "./MarkOperatorFactoryChain";
+import ScrollOperatorFactoryChain from "./ScrollOperatorFactoryChain";
+
+@injectable()
+export default class OperatorFactoryImpl implements OperatorFactory {
+ private readonly factoryChains: OperatorFactoryChain[];
+
+ constructor(
+ addonOperatorFactoryChain: AddonOperatorFactoryChain,
+ clipboardOperatorFactoryChain: ClipboardOperatorFactoryChain,
+ findOperatorFactoryChain: FindOperatorFactoryChain,
+ focusOperatorFactoryChain: FocusOperatorFactoryChain,
+ followOperatorFactoryChain: FollowOperatorFactoryChain,
+ markOperatorFactoryChain: MarkOperatorFactoryChain,
+ scrollOperatorFactoryChain: ScrollOperatorFactoryChain,
+ @inject("OperationClient")
+ private readonly operationClient: OperationClient
+ ) {
+ this.factoryChains = [
+ addonOperatorFactoryChain,
+ clipboardOperatorFactoryChain,
+ findOperatorFactoryChain,
+ focusOperatorFactoryChain,
+ followOperatorFactoryChain,
+ markOperatorFactoryChain,
+ scrollOperatorFactoryChain,
+ ];
+ }
+
+ create(op: Operation, repeat: number): Operator {
+ for (const chain of this.factoryChains) {
+ const operator = chain.create(op, repeat);
+ if (operator != null) {
+ return operator;
+ }
+ }
+ return new BackgroundOperationOperator(this.operationClient, repeat, op);
+ }
+}
diff --git a/src/content/operators/impls/PageScrollOperator.ts b/src/content/operators/impls/PageScrollOperator.ts
new file mode 100644
index 0000000..377bf92
--- /dev/null
+++ b/src/content/operators/impls/PageScrollOperator.ts
@@ -0,0 +1,21 @@
+import AbstractScrollOperator from "./AbstractScrollOperator";
+import Operator from "../Operator";
+import ScrollPresenter from "../../presenters/ScrollPresenter";
+import SettingRepository from "../../repositories/SettingRepository";
+
+export default class PageScrollOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository,
+ private readonly count: number
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollPages(this.count, smooth);
+ }
+}
diff --git a/src/content/operators/impls/PasteOperator.ts b/src/content/operators/impls/PasteOperator.ts
new file mode 100644
index 0000000..592da66
--- /dev/null
+++ b/src/content/operators/impls/PasteOperator.ts
@@ -0,0 +1,25 @@
+import Operator from "../Operator";
+import ClipboardRepository from "../../repositories/ClipboardRepository";
+import SettingRepository from "../../repositories/SettingRepository";
+import OperationClient from "../../client/OperationClient";
+import * as urls from "../../../shared/urls";
+
+export default class PasteOperator implements Operator {
+ constructor(
+ private readonly repository: ClipboardRepository,
+ private readonly settingRepository: SettingRepository,
+ private readonly operationClient: OperationClient,
+ private readonly newTab: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const search = this.settingRepository.get().search;
+ const text = this.repository.read();
+ const url = urls.searchUrl(text, search);
+
+ // NOTE: Repeat pasting from clipboard instead of opening a certain url.
+ // 'Repeat last' command is implemented in the background script and cannot
+ // access to clipboard until Firefox 63.
+ await this.operationClient.internalOpenUrl(url, this.newTab);
+ }
+}
diff --git a/src/content/operators/impls/ScrollOperatorFactoryChain.ts b/src/content/operators/impls/ScrollOperatorFactoryChain.ts
new file mode 100644
index 0000000..6847aea
--- /dev/null
+++ b/src/content/operators/impls/ScrollOperatorFactoryChain.ts
@@ -0,0 +1,68 @@
+import { inject, injectable } from "tsyringe";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import ScrollPresenter from "../../presenters/ScrollPresenter";
+import SettingRepository from "../../repositories/SettingRepository";
+import * as operations from "../../../shared/operations";
+import Operator from "../Operator";
+import VerticalScrollOperator from "./VerticalScrollOperator";
+import HorizontalScrollOperator from "./HorizontalScrollOperator";
+import PageScrollOperator from "./PageScrollOperator";
+import ScrollToTopOperator from "./ScrollToTopOperator";
+import ScrollToBottomOperator from "./ScrollToBottomOperator";
+import ScrollToHomeOperator from "./ScrollToHomeOperator";
+import ScrollToEndOperator from "./ScrollToEndOperator";
+
+@injectable()
+export default class ScrollOperatorFactoryChain
+ implements OperatorFactoryChain {
+ constructor(
+ @inject("ScrollPresenter")
+ private readonly scrollPresenter: ScrollPresenter,
+ @inject("SettingRepository")
+ private readonly settingRepository: SettingRepository
+ ) {}
+
+ create(op: operations.Operation, repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.SCROLL_VERTICALLY:
+ return new VerticalScrollOperator(
+ this.scrollPresenter,
+ this.settingRepository,
+ op.count * repeat
+ );
+ case operations.SCROLL_HORIZONALLY:
+ return new HorizontalScrollOperator(
+ this.scrollPresenter,
+ this.settingRepository,
+ op.count * repeat
+ );
+ case operations.SCROLL_PAGES:
+ return new PageScrollOperator(
+ this.scrollPresenter,
+ this.settingRepository,
+ op.count * repeat
+ );
+ case operations.SCROLL_TOP:
+ return new ScrollToTopOperator(
+ this.scrollPresenter,
+ this.settingRepository
+ );
+ case operations.SCROLL_BOTTOM:
+ return new ScrollToBottomOperator(
+ this.scrollPresenter,
+ this.settingRepository
+ );
+ case operations.SCROLL_HOME:
+ return new ScrollToHomeOperator(
+ this.scrollPresenter,
+ this.settingRepository
+ );
+ case operations.SCROLL_END:
+ return new ScrollToEndOperator(
+ this.scrollPresenter,
+ this.settingRepository
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/content/operators/impls/ScrollToBottomOperator.ts b/src/content/operators/impls/ScrollToBottomOperator.ts
new file mode 100644
index 0000000..4db521b
--- /dev/null
+++ b/src/content/operators/impls/ScrollToBottomOperator.ts
@@ -0,0 +1,20 @@
+import AbstractScrollOperator from "./AbstractScrollOperator";
+import Operator from "../Operator";
+import ScrollPresenter from "../../presenters/ScrollPresenter";
+import SettingRepository from "../../repositories/SettingRepository";
+
+export default class ScrollToBottomOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollToBottom(smooth);
+ }
+}
diff --git a/src/content/operators/impls/ScrollToEndOperator.ts b/src/content/operators/impls/ScrollToEndOperator.ts
new file mode 100644
index 0000000..8217e15
--- /dev/null
+++ b/src/content/operators/impls/ScrollToEndOperator.ts
@@ -0,0 +1,20 @@
+import AbstractScrollOperator from "./AbstractScrollOperator";
+import Operator from "../Operator";
+import ScrollPresenter from "../../presenters/ScrollPresenter";
+import SettingRepository from "../../repositories/SettingRepository";
+
+export default class ScrollToEndOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollToEnd(smooth);
+ }
+}
diff --git a/src/content/operators/impls/ScrollToHomeOperator.ts b/src/content/operators/impls/ScrollToHomeOperator.ts
new file mode 100644
index 0000000..a0d7701
--- /dev/null
+++ b/src/content/operators/impls/ScrollToHomeOperator.ts
@@ -0,0 +1,20 @@
+import AbstractScrollOperator from "./AbstractScrollOperator";
+import Operator from "../Operator";
+import ScrollPresenter from "../../presenters/ScrollPresenter";
+import SettingRepository from "../../repositories/SettingRepository";
+
+export default class ScrollToHomeOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollToHome(smooth);
+ }
+}
diff --git a/src/content/operators/impls/ScrollToTopOperator.ts b/src/content/operators/impls/ScrollToTopOperator.ts
new file mode 100644
index 0000000..6075758
--- /dev/null
+++ b/src/content/operators/impls/ScrollToTopOperator.ts
@@ -0,0 +1,20 @@
+import AbstractScrollOperator from "./AbstractScrollOperator";
+import Operator from "../Operator";
+import ScrollPresenter from "../../presenters/ScrollPresenter";
+import SettingRepository from "../../repositories/SettingRepository";
+
+export default class ScrollToTopOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollToTop(smooth);
+ }
+}
diff --git a/src/content/operators/impls/StartFollowOperator.ts b/src/content/operators/impls/StartFollowOperator.ts
new file mode 100644
index 0000000..6f30058
--- /dev/null
+++ b/src/content/operators/impls/StartFollowOperator.ts
@@ -0,0 +1,14 @@
+import Operator from "../Operator";
+import FollowMasterClient from "../../client/FollowMasterClient";
+
+export default class StartFollowOperator implements Operator {
+ constructor(
+ private readonly followMasterClient: FollowMasterClient,
+ private readonly newTab: boolean,
+ private readonly background: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ this.followMasterClient.startFollow(this.newTab, this.background);
+ }
+}
diff --git a/src/content/operators/impls/ToggleAddonOperator.ts b/src/content/operators/impls/ToggleAddonOperator.ts
new file mode 100644
index 0000000..2a249d6
--- /dev/null
+++ b/src/content/operators/impls/ToggleAddonOperator.ts
@@ -0,0 +1,16 @@
+import Operator from "../Operator";
+import AddonIndicatorClient from "../../client/AddonIndicatorClient";
+import AddonEnabledRepository from "../../repositories/AddonEnabledRepository";
+
+export default class ToggleAddonOperator implements Operator {
+ constructor(
+ private readonly indicator: AddonIndicatorClient,
+ private readonly repository: AddonEnabledRepository
+ ) {}
+
+ async run(): Promise<void> {
+ const current = this.repository.get();
+ this.repository.set(!current);
+ await this.indicator.setEnabled(!current);
+ }
+}
diff --git a/src/content/operators/impls/URLRepository.ts b/src/content/operators/impls/URLRepository.ts
new file mode 100644
index 0000000..a1efc2e
--- /dev/null
+++ b/src/content/operators/impls/URLRepository.ts
@@ -0,0 +1,9 @@
+export default interface URLRepository {
+ getCurrentURL(): string;
+}
+
+export class URLRepositoryImpl implements URLRepository {
+ getCurrentURL(): string {
+ return window.location.href;
+ }
+}
diff --git a/src/content/operators/impls/VerticalScrollOperator.ts b/src/content/operators/impls/VerticalScrollOperator.ts
new file mode 100644
index 0000000..4ab336c
--- /dev/null
+++ b/src/content/operators/impls/VerticalScrollOperator.ts
@@ -0,0 +1,21 @@
+import AbstractScrollOperator from "./AbstractScrollOperator";
+import Operator from "../Operator";
+import ScrollPresenter from "../../presenters/ScrollPresenter";
+import SettingRepository from "../../repositories/SettingRepository";
+
+export default class VerticalScrollOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository,
+ private readonly count: number
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollVertically(this.count, smooth);
+ }
+}
diff --git a/src/content/operators/impls/YankURLOperator.ts b/src/content/operators/impls/YankURLOperator.ts
new file mode 100644
index 0000000..2e774eb
--- /dev/null
+++ b/src/content/operators/impls/YankURLOperator.ts
@@ -0,0 +1,18 @@
+import Operator from "../Operator";
+import ClipboardRepository from "../../repositories/ClipboardRepository";
+import ConsoleClient from "../../client/ConsoleClient";
+import URLRepository from "./URLRepository";
+
+export default class YankURLOperator implements Operator {
+ constructor(
+ private readonly repository: ClipboardRepository,
+ private readonly consoleClient: ConsoleClient,
+ private readonly urlRepository: URLRepository
+ ) {}
+
+ async run(): Promise<void> {
+ const url = this.urlRepository.getCurrentURL();
+ this.repository.write(url);
+ await this.consoleClient.info("Yanked " + url);
+ }
+}
diff --git a/src/content/presenters/ScrollPresenter.ts b/src/content/presenters/ScrollPresenter.ts
index a8b2034..508532c 100644
--- a/src/content/presenters/ScrollPresenter.ts
+++ b/src/content/presenters/ScrollPresenter.ts
@@ -31,7 +31,7 @@ const isScrollableStyle = (element: Element): boolean => {
return canBeScrolled(element);
};
-// Find a visiable and scrollable element by depth-first search. Currently
+// Find a visible and scrollable element by depth-first search. Currently
// this method is called by each scrolling, and the returned value of this
// method is not cached. That does not cause performance issue because in the
// most pages, the window is root element i,e, documentElement.
diff --git a/src/content/repositories/HintKeyRepository.ts b/src/content/repositories/HintKeyRepository.ts
new file mode 100644
index 0000000..342b003
--- /dev/null
+++ b/src/content/repositories/HintKeyRepository.ts
@@ -0,0 +1,49 @@
+export default interface HintKeyRepository {
+ reset(charset: string): void;
+
+ produce(): string;
+}
+
+const current: {
+ charset: string;
+ counter: number[];
+} = {
+ charset: "",
+ counter: [],
+};
+
+export class HintKeyRepositoryImpl implements HintKeyRepository {
+ reset(charset: string): void {
+ if (charset.length === 0) {
+ throw new TypeError("charset is empty");
+ }
+ current.charset = charset;
+ current.counter = [];
+ }
+
+ produce(): string {
+ if (current.charset === "") {
+ throw new Error("charset is not set");
+ }
+ this.increment();
+
+ return current.counter.map((x) => current.charset[x]).join("");
+ }
+
+ private increment(): void {
+ const max = current.charset.length - 1;
+ if (current.counter.every((x) => x === max)) {
+ current.counter = new Array(current.counter.length + 1).fill(0);
+ return;
+ }
+
+ current.counter.reverse();
+ const len = current.charset.length;
+ let num = current.counter.reduce((x, y, index) => x + y * len ** index) + 1;
+ for (let i = 0; i < current.counter.length; ++i) {
+ current.counter[i] = num % len;
+ num = ~~(num / len);
+ }
+ current.counter.reverse();
+ }
+}
diff --git a/src/content/usecases/ClipboardUseCase.ts b/src/content/usecases/ClipboardUseCase.ts
deleted file mode 100644
index 875fc11..0000000
--- a/src/content/usecases/ClipboardUseCase.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { injectable, inject } from "tsyringe";
-import * as urls from "../../shared/urls";
-import ClipboardRepository from "../repositories/ClipboardRepository";
-import SettingRepository from "../repositories/SettingRepository";
-import ConsoleClient from "../client/ConsoleClient";
-import OperationClient from "../client/OperationClient";
-
-@injectable()
-export default class ClipboardUseCase {
- constructor(
- @inject("ClipboardRepository") private repository: ClipboardRepository,
- @inject("SettingRepository") private settingRepository: SettingRepository,
- @inject("ConsoleClient") private consoleClient: ConsoleClient,
- @inject("OperationClient") private operationClinet: OperationClient
- ) {}
-
- async yankCurrentURL(): Promise<string> {
- const url = window.location.href;
- this.repository.write(url);
- await this.consoleClient.info("Yanked " + url);
- return Promise.resolve(url);
- }
-
- async openOrSearch(newTab: boolean): Promise<void> {
- const search = this.settingRepository.get().search;
- const text = this.repository.read();
- const url = urls.searchUrl(text, search);
-
- // TODO: Repeat pasting from clipboard instead of opening a certain url.
- // 'Repeat last' command is implemented in the background script and cannot
- // access to clipboard until Firefox 63.
- await this.operationClinet.internalOpenUrl(url, newTab);
- }
-}
diff --git a/src/content/usecases/FindSlaveUseCase.ts b/src/content/usecases/FindSlaveUseCase.ts
deleted file mode 100644
index 3b8c4b4..0000000
--- a/src/content/usecases/FindSlaveUseCase.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { injectable, inject } from "tsyringe";
-import FindMasterClient from "../client/FindMasterClient";
-
-@injectable()
-export default class FindSlaveUseCase {
- constructor(
- @inject("FindMasterClient") private findMasterClient: FindMasterClient
- ) {}
-
- findNext() {
- this.findMasterClient.findNext();
- }
-
- findPrev() {
- this.findMasterClient.findPrev();
- }
-}
diff --git a/src/content/usecases/FocusUseCase.ts b/src/content/usecases/FocusUseCase.ts
deleted file mode 100644
index 8c62003..0000000
--- a/src/content/usecases/FocusUseCase.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { injectable, inject } from "tsyringe";
-import FocusPresenter from "../presenters/FocusPresenter";
-
-@injectable()
-export default class FocusUseCases {
- constructor(@inject("FocusPresenter") private presenter: FocusPresenter) {}
-
- focusFirstInput() {
- this.presenter.focusFirstElement();
- }
-}
diff --git a/src/content/usecases/FollowMasterUseCase.ts b/src/content/usecases/FollowMasterUseCase.ts
index 88c682e..f4705e1 100644
--- a/src/content/usecases/FollowMasterUseCase.ts
+++ b/src/content/usecases/FollowMasterUseCase.ts
@@ -4,13 +4,10 @@ import FollowMasterRepository from "../repositories/FollowMasterRepository";
import FollowSlaveClient from "../client/FollowSlaveClient";
import FollowSlaveClientFactory from "../client/FollowSlaveClientFactory";
import SettingRepository from "../repositories/SettingRepository";
-import HintKeyProducer from "./HintKeyProducer";
+import HintKeyRepository from "../repositories/HintKeyRepository";
@injectable()
export default class FollowMasterUseCase {
- // TODO Make repository
- private producer: HintKeyProducer | null;
-
constructor(
@inject("FollowKeyRepository")
private followKeyRepository: FollowKeyRepository,
@@ -22,14 +19,15 @@ export default class FollowMasterUseCase {
private settingRepository: SettingRepository,
@inject("FollowSlaveClientFactory")
- private followSlaveClientFactory: FollowSlaveClientFactory
- ) {
- this.producer = null;
- }
+ private followSlaveClientFactory: FollowSlaveClientFactory,
+
+ @inject("HintKeyRepository")
+ private hintKeyRepository: HintKeyRepository
+ ) {}
startFollow(newTab: boolean, background: boolean): void {
const hintchars = this.settingRepository.get().properties.hintchars;
- this.producer = new HintKeyProducer(hintchars);
+ this.hintKeyRepository.reset(hintchars);
this.followKeyRepository.clearKeys();
this.followMasterRepository.setCurrentFollowMode(newTab, background);
@@ -59,7 +57,7 @@ export default class FollowMasterUseCase {
createSlaveHints(count: number, sender: Window): void {
const produced = [];
for (let i = 0; i < count; ++i) {
- const tag = this.producer!.produce();
+ const tag = this.hintKeyRepository.produce();
produced.push(tag);
this.followMasterRepository.addTag(tag);
}
diff --git a/src/content/usecases/HintKeyProducer.ts b/src/content/usecases/HintKeyProducer.ts
deleted file mode 100644
index a5e2877..0000000
--- a/src/content/usecases/HintKeyProducer.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-export default class HintKeyProducer {
- private charset: string;
-
- private counter: number[];
-
- constructor(charset: string) {
- if (charset.length === 0) {
- throw new TypeError("charset is empty");
- }
-
- this.charset = charset;
- this.counter = [];
- }
-
- produce(): string {
- this.increment();
-
- return this.counter.map((x) => this.charset[x]).join("");
- }
-
- private increment(): void {
- const max = this.charset.length - 1;
- if (this.counter.every((x) => x === max)) {
- this.counter = new Array(this.counter.length + 1).fill(0);
- return;
- }
-
- this.counter.reverse();
- const len = this.charset.length;
- let num = this.counter.reduce((x, y, index) => x + y * len ** index) + 1;
- for (let i = 0; i < this.counter.length; ++i) {
- this.counter[i] = num % len;
- num = ~~(num / len);
- }
- this.counter.reverse();
- }
-}
diff --git a/src/content/usecases/MarkKeyUseCase.ts b/src/content/usecases/MarkKeyUseCase.ts
index b807c74..61ed135 100644
--- a/src/content/usecases/MarkKeyUseCase.ts
+++ b/src/content/usecases/MarkKeyUseCase.ts
@@ -15,18 +15,10 @@ export default class MarkKeyUseCase {
return this.repository.isJumpMode();
}
- enableSetMode(): void {
- this.repository.enableSetMode();
- }
-
disableSetMode(): void {
this.repository.disabeSetMode();
}
- enableJumpMode(): void {
- this.repository.enableJumpMode();
- }
-
disableJumpMode(): void {
this.repository.disabeJumpMode();
}
diff --git a/src/content/usecases/ScrollUseCase.ts b/src/content/usecases/ScrollUseCase.ts
deleted file mode 100644
index 319c8b4..0000000
--- a/src/content/usecases/ScrollUseCase.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import { injectable, inject } from "tsyringe";
-import ScrollPresenter from "../presenters/ScrollPresenter";
-import SettingRepository from "../repositories/SettingRepository";
-
-@injectable()
-export default class ScrollUseCase {
- constructor(
- @inject("ScrollPresenter") private presenter: ScrollPresenter,
- @inject("SettingRepository") private settingRepository: SettingRepository
- ) {}
-
- scrollVertically(count: number): void {
- const smooth = this.getSmoothScroll();
- this.presenter.scrollVertically(count, smooth);
- }
-
- scrollHorizonally(count: number): void {
- const smooth = this.getSmoothScroll();
- this.presenter.scrollHorizonally(count, smooth);
- }
-
- scrollPages(count: number): void {
- const smooth = this.getSmoothScroll();
- this.presenter.scrollPages(count, smooth);
- }
-
- scrollToTop(): void {
- const smooth = this.getSmoothScroll();
- this.presenter.scrollToTop(smooth);
- }
-
- scrollToBottom(): void {
- const smooth = this.getSmoothScroll();
- this.presenter.scrollToBottom(smooth);
- }
-
- scrollToHome(): void {
- const smooth = this.getSmoothScroll();
- this.presenter.scrollToHome(smooth);
- }
-
- scrollToEnd(): void {
- const smooth = this.getSmoothScroll();
- this.presenter.scrollToEnd(smooth);
- }
-
- private getSmoothScroll(): boolean {
- const settings = this.settingRepository.get();
- return settings.properties.smoothscroll;
- }
-}
diff --git a/test/background/mock/MockBrowserSettingRepository.ts b/test/background/mock/MockBrowserSettingRepository.ts
new file mode 100644
index 0000000..22e7084
--- /dev/null
+++ b/test/background/mock/MockBrowserSettingRepository.ts
@@ -0,0 +1,10 @@
+import BrowserSettingRepository from "../../../src/background/repositories/BrowserSettingRepository";
+
+export default class MockBrowserSettingRepository
+ implements BrowserSettingRepository {
+ constructor(private readonly homepageUrls: string[]) {}
+
+ getHomepageUrls(): Promise<string[]> {
+ return Promise.resolve(this.homepageUrls);
+ }
+}
diff --git a/test/background/mock/MockConsoleClient.ts b/test/background/mock/MockConsoleClient.ts
new file mode 100644
index 0000000..d1f8fc3
--- /dev/null
+++ b/test/background/mock/MockConsoleClient.ts
@@ -0,0 +1,23 @@
+import ConsoleClient from "../../../src/background/infrastructures/ConsoleClient";
+
+export default class MockConsoleClient implements ConsoleClient {
+ hide(_tabId: number): Promise<any> {
+ throw new Error("not implemented");
+ }
+
+ showCommand(_tabId: number, _command: string): Promise<any> {
+ throw new Error("not implemented");
+ }
+
+ showError(_tabId: number, _message: string): Promise<any> {
+ throw new Error("not implemented");
+ }
+
+ showFind(_tabId: number): Promise<any> {
+ throw new Error("not implemented");
+ }
+
+ showInfo(_tabId: number, _message: string): Promise<any> {
+ throw new Error("not implemented");
+ }
+}
diff --git a/test/background/mock/MockNavigateClient.ts b/test/background/mock/MockNavigateClient.ts
new file mode 100644
index 0000000..d9442a4
--- /dev/null
+++ b/test/background/mock/MockNavigateClient.ts
@@ -0,0 +1,19 @@
+import NavigateClient from "../../../src/background/clients/NavigateClient";
+
+export default class MockNavigateClient implements NavigateClient {
+ historyNext(_tabId: number): Promise<void> {
+ throw new Error("not implemented");
+ }
+
+ historyPrev(_tabId: number): Promise<void> {
+ throw new Error("not implemented");
+ }
+
+ linkNext(_tabId: number): Promise<void> {
+ throw new Error("not implemented");
+ }
+
+ linkPrev(_tabId: number): Promise<void> {
+ throw new Error("not implemented");
+ }
+}
diff --git a/test/background/mock/MockRepeatRepository.ts b/test/background/mock/MockRepeatRepository.ts
new file mode 100644
index 0000000..1a686c8
--- /dev/null
+++ b/test/background/mock/MockRepeatRepository.ts
@@ -0,0 +1,14 @@
+import RepeatRepository from "../../../src/background/repositories/RepeatRepository";
+import { Operation } from "../../../src/shared/operations";
+
+export default class MockRepeatRepository implements RepeatRepository {
+ private op: Operation | undefined = undefined;
+
+ getLastOperation(): Operation | undefined {
+ return this.op;
+ }
+
+ setLastOperation(op: Operation): void {
+ this.op = op;
+ }
+}
diff --git a/test/background/mock/MockTabPresenter.ts b/test/background/mock/MockTabPresenter.ts
new file mode 100644
index 0000000..22fb947
--- /dev/null
+++ b/test/background/mock/MockTabPresenter.ts
@@ -0,0 +1,179 @@
+import TabPresenter from "../../../src/background/presenters/TabPresenter";
+
+export default class MockTabPresenter implements TabPresenter {
+ private readonly tabs: browser.tabs.Tab[] = [];
+ private readonly zooms: number[] = [];
+ private nextid = 0;
+
+ private readonly lastSelectedId: number | undefined;
+
+ private static defaultTabOptions = {
+ hidden: false,
+ highlighted: false,
+ incognito: false,
+ isArticle: false,
+ isInReaderMode: false,
+ lastAccessed: 0,
+ pinned: false,
+ selected: false,
+ windowId: 0,
+ };
+
+ create(
+ url: string,
+ opts?: {
+ active?: boolean;
+ cookieStoreId?: string;
+ index?: number;
+ openerTabId?: number;
+ pinned?: boolean;
+ windowId?: number;
+ }
+ ): Promise<browser.tabs.Tab> {
+ const tab = {
+ ...MockTabPresenter.defaultTabOptions,
+ ...opts,
+ id: this.nextid++,
+ active: false,
+ title: "welcome, world",
+ url,
+ index: this.tabs.length,
+ };
+ if (opts?.active || this.tabs.length === 0) {
+ this.tabs.forEach((t) => (t.active = false));
+ tab.active = true;
+ }
+ this.tabs.push(tab);
+ this.zooms.push(1);
+ return Promise.resolve(tab);
+ }
+
+ duplicate(id: number): Promise<browser.tabs.Tab> {
+ const src = this.tabs.find((t) => t.id === id);
+ if (!src) {
+ throw new Error(`tab ${id} not found`);
+ }
+ this.tabs.forEach((t) => (t.active = false));
+ const tab = { ...src, id: this.nextid++, active: true };
+ this.tabs.push(tab);
+ this.zooms.push(1);
+
+ return Promise.resolve(tab);
+ }
+
+ getAll(): Promise<browser.tabs.Tab[]> {
+ return Promise.resolve([...this.tabs]);
+ }
+
+ getByKeyword(
+ keyword: string,
+ excludePinned: boolean
+ ): Promise<browser.tabs.Tab[]> {
+ const tabs = this.tabs
+
+ .filter((t) => {
+ return (
+ (t.url && t.url.toLowerCase().includes(keyword.toLowerCase())) ||
+ (t.title && t.title.toLowerCase().includes(keyword.toLowerCase()))
+ );
+ })
+ .filter((t) => {
+ return !(excludePinned && t.pinned);
+ });
+ return Promise.resolve(tabs);
+ }
+
+ getCurrent(): Promise<browser.tabs.Tab> {
+ const tab = this.tabs.find((t) => t.active);
+ if (!tab) {
+ throw new Error("active tab not found");
+ }
+ return Promise.resolve(tab);
+ }
+
+ getLastSelectedId(): Promise<number | undefined> {
+ return Promise.resolve(this.lastSelectedId);
+ }
+
+ getZoom(tabId: number): Promise<number> {
+ const index = this.tabs.findIndex((t) => t.id === tabId);
+ if (index === -1) {
+ throw new Error(`tab ${tabId} not found`);
+ }
+ return Promise.resolve(this.zooms[index]);
+ }
+
+ onSelected(
+ _listener: (arg: { tabId: number; windowId: number }) => void
+ ): void {
+ throw new Error("not implemented");
+ }
+
+ open(url: string, tabId?: number): Promise<browser.tabs.Tab> {
+ let tab = this.tabs.find((t) => t.active);
+ if (!tab) {
+ throw new Error(`active tab not found`);
+ }
+ if (tabId !== undefined) {
+ tab = this.tabs.find((t) => t.id === tabId);
+ }
+ if (!tab) {
+ throw new Error(`tab ${tabId} not found`);
+ }
+ tab.url = url;
+ return Promise.resolve(tab);
+ }
+
+ reload(_tabId: number, _cache: boolean): Promise<void> {
+ throw new Error("not implemented");
+ }
+
+ remove(ids: number[]): Promise<void> {
+ for (const id of ids) {
+ const index = this.tabs.findIndex((t) => t.id === id);
+ if (index === -1) {
+ throw new Error(`tab ${id} not found`);
+ }
+ const tab = this.tabs[index];
+ this.tabs.splice(index, 1);
+ this.zooms.splice(index, 1);
+ if (tab.active) {
+ this.tabs[Math.min(index, this.tabs.length - 1)].active = true;
+ }
+ }
+
+ return Promise.resolve(undefined);
+ }
+
+ reopen(): Promise<void> {
+ throw new Error("not implemented");
+ }
+
+ select(tabId: number): Promise<void> {
+ const tab = this.tabs.find((t) => t.id === tabId);
+ if (!tab) {
+ throw new Error(`tab ${tabId} not found`);
+ }
+ this.tabs.forEach((t) => (t.active = false));
+ tab.active = true;
+ return Promise.resolve(undefined);
+ }
+
+ setPinned(tabId: number, pinned: boolean): Promise<void> {
+ const tab = this.tabs.find((t) => t.id === tabId);
+ if (!tab) {
+ throw new Error(`tab ${tabId} not found`);
+ }
+ tab.pinned = pinned;
+ return Promise.resolve();
+ }
+
+ setZoom(tabId: number, factor: number): Promise<void> {
+ const index = this.tabs.findIndex((t) => t.id === tabId);
+ if (index === -1) {
+ throw new Error(`tab ${tabId} not found`);
+ }
+ this.zooms[index] = factor;
+ return Promise.resolve();
+ }
+}
diff --git a/test/background/mock/MockWindowPresenter.ts b/test/background/mock/MockWindowPresenter.ts
new file mode 100644
index 0000000..420ae8b
--- /dev/null
+++ b/test/background/mock/MockWindowPresenter.ts
@@ -0,0 +1,7 @@
+import WindowPresenter from "../../../src/background/presenters/WindowPresenter";
+
+export default class MockWindowPresenter implements WindowPresenter {
+ create(_url: string): Promise<void> {
+ throw new Error("not implemented");
+ }
+}
diff --git a/test/background/mock/MockZoomPresenter.ts b/test/background/mock/MockZoomPresenter.ts
new file mode 100644
index 0000000..53d1980
--- /dev/null
+++ b/test/background/mock/MockZoomPresenter.ts
@@ -0,0 +1,15 @@
+import ZoomPresenter from "../../../src/background/presenters/ZoomPresenter";
+
+export default class MockZoomPresenter implements ZoomPresenter {
+ resetZoom(): Promise<void> {
+ throw new Error("not implemented");
+ }
+
+ zoomIn(): Promise<void> {
+ throw new Error("not implemented");
+ }
+
+ zoomOut(): Promise<void> {
+ throw new Error("not implemented");
+ }
+}
diff --git a/test/background/operators/impls/CancelOperator.test.ts b/test/background/operators/impls/CancelOperator.test.ts
new file mode 100644
index 0000000..915becf
--- /dev/null
+++ b/test/background/operators/impls/CancelOperator.test.ts
@@ -0,0 +1,24 @@
+import sinon from "sinon";
+import CancelOperator from "../../../../src/background/operators/impls/CancelOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockConsoleClient from "../../mock/MockConsoleClient";
+
+describe("CancelOperator", () => {
+ describe("#run", () => {
+ it("hides console", async () => {
+ const tabPresenter = new MockTabPresenter();
+ const currenTab = await tabPresenter.create("https://example.com/");
+
+ const consoleClient = new MockConsoleClient();
+ const mock = sinon
+ .mock(consoleClient)
+ .expects("hide")
+ .withArgs(currenTab?.id);
+ const sut = new CancelOperator(tabPresenter, consoleClient);
+
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/CloseTabOperator.test.ts b/test/background/operators/impls/CloseTabOperator.test.ts
new file mode 100644
index 0000000..ba9cbfe
--- /dev/null
+++ b/test/background/operators/impls/CloseTabOperator.test.ts
@@ -0,0 +1,61 @@
+import { expect } from "chai";
+import CloseTabOperator from "../../../../src/background/operators/impls/CloseTabOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+
+describe("CloseTabOperator", () => {
+ describe("#run", () => {
+ it("close a current tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const sut = new CloseTabOperator(tabPresenter);
+
+ await sut.run();
+
+ const tabs = await tabPresenter.getAll();
+ expect(tabs.map((t) => t.url)).to.deep.equal([
+ "https://example.com/1",
+ "https://example.com/3",
+ ]);
+ });
+
+ it("close a current tab forcely", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", {
+ pinned: true,
+ active: false,
+ });
+ await tabPresenter.create("https://example.com/2", {
+ pinned: true,
+ active: true,
+ });
+ await tabPresenter.create("https://example.com/3", {
+ pinned: true,
+ active: false,
+ });
+ const sut = new CloseTabOperator(tabPresenter, true);
+
+ await sut.run();
+
+ const tabs = await tabPresenter.getAll();
+ expect(tabs.map((t) => t.url)).to.deep.equal([
+ "https://example.com/1",
+ "https://example.com/3",
+ ]);
+ });
+
+ it("close a current tab and select left of the closed tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const sut = new CloseTabOperator(tabPresenter, false, true);
+
+ await sut.run();
+
+ const tab = await tabPresenter.getCurrent();
+ expect(tab.url).to.equal("https://example.com/1");
+ });
+ });
+});
diff --git a/test/background/operators/impls/CloseTabRightOperator.test.ts b/test/background/operators/impls/CloseTabRightOperator.test.ts
new file mode 100644
index 0000000..c2a106c
--- /dev/null
+++ b/test/background/operators/impls/CloseTabRightOperator.test.ts
@@ -0,0 +1,24 @@
+import { expect } from "chai";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import CloseTabRightOperator from "../../../../src/background/operators/impls/CloseTabRightOperator";
+
+describe("CloseTabRightOperator", () => {
+ describe("#run", () => {
+ it("close the right of the current tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ await tabPresenter.create("https://example.com/4", { active: false });
+ const sut = new CloseTabRightOperator(tabPresenter);
+
+ await sut.run();
+
+ const tabs = await tabPresenter.getAll();
+ expect(tabs.map((t) => t.url)).to.deep.equal([
+ "https://example.com/1",
+ "https://example.com/2",
+ ]);
+ });
+ });
+});
diff --git a/test/background/operators/impls/CommandOperatorFactoryChain.test.ts b/test/background/operators/impls/CommandOperatorFactoryChain.test.ts
new file mode 100644
index 0000000..e481c5a
--- /dev/null
+++ b/test/background/operators/impls/CommandOperatorFactoryChain.test.ts
@@ -0,0 +1,42 @@
+import "reflect-metadata";
+import { expect } from "chai";
+import CommandOperatorFactoryChain from "../../../../src/background/operators/impls/CommandOperatorFactoryChain";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockConsoleClient from "../../mock/MockConsoleClient";
+import * as operations from "../../../../src/shared/operations";
+import ShowCommandOperator from "../../../../src/background/operators/impls/ShowCommandOperator";
+import ShowTabOpenCommandOperator from "../../../../src/background/operators/impls/ShowTabOpenCommandOperator";
+import ShowWinOpenCommandOperator from "../../../../src/background/operators/impls/ShowWinOpenCommandOperator";
+import ShowBufferCommandOperator from "../../../../src/background/operators/impls/ShowBufferCommandOperator";
+import ShowAddBookmarkOperator from "../../../../src/background/operators/impls/ShowAddBookmarkOperator";
+import StartFindOperator from "../../../../src/background/operators/impls/StartFindOperator";
+
+describe("CommandOperatorFactoryChain", () => {
+ describe("#create", () => {
+ it("returns a operator for the operation", async () => {
+ const tabPresenter = new MockTabPresenter();
+ const consoleClient = new MockConsoleClient();
+ const sut = new CommandOperatorFactoryChain(tabPresenter, consoleClient);
+
+ expect(sut.create({ type: operations.COMMAND_SHOW })).to.be.instanceOf(
+ ShowCommandOperator
+ );
+ expect(
+ sut.create({ type: operations.COMMAND_SHOW_TABOPEN, alter: true })
+ ).to.be.instanceOf(ShowTabOpenCommandOperator);
+ expect(
+ sut.create({ type: operations.COMMAND_SHOW_WINOPEN, alter: true })
+ ).to.be.instanceOf(ShowWinOpenCommandOperator);
+ expect(
+ sut.create({ type: operations.COMMAND_SHOW_BUFFER })
+ ).to.be.instanceOf(ShowBufferCommandOperator);
+ expect(
+ sut.create({ type: operations.COMMAND_SHOW_ADDBOOKMARK, alter: true })
+ ).to.be.instanceOf(ShowAddBookmarkOperator);
+ expect(sut.create({ type: operations.FIND_START })).to.be.instanceOf(
+ StartFindOperator
+ );
+ expect(sut.create({ type: operations.CANCEL })).to.be.null;
+ });
+ });
+});
diff --git a/test/background/operators/impls/DuplicateTabOperator.test.ts b/test/background/operators/impls/DuplicateTabOperator.test.ts
new file mode 100644
index 0000000..ce2c19d
--- /dev/null
+++ b/test/background/operators/impls/DuplicateTabOperator.test.ts
@@ -0,0 +1,25 @@
+import { expect } from "chai";
+import DuplicateTabOperator from "../../../../src/background/operators/impls/DuplicateTabOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+
+describe("DuplicateTabOperator", () => {
+ describe("#run", () => {
+ it("duplicate a tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const sut = new DuplicateTabOperator(tabPresenter);
+
+ await sut.run();
+
+ const tabs = await tabPresenter.getAll();
+ expect(tabs.map((t) => t.url)).to.deep.equal([
+ "https://example.com/1",
+ "https://example.com/2",
+ "https://example.com/3",
+ "https://example.com/2",
+ ]);
+ });
+ });
+});
diff --git a/test/background/operators/impls/InternalOpenURLOperator.test.ts b/test/background/operators/impls/InternalOpenURLOperator.test.ts
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/background/operators/impls/InternalOpenURLOperator.test.ts
diff --git a/test/background/operators/impls/InternalOperatorFactoryChain.test.ts b/test/background/operators/impls/InternalOperatorFactoryChain.test.ts
new file mode 100644
index 0000000..09029db
--- /dev/null
+++ b/test/background/operators/impls/InternalOperatorFactoryChain.test.ts
@@ -0,0 +1,37 @@
+import "reflect-metadata";
+import { expect } from "chai";
+import InternalOperatorFactoryChain from "../../../../src/background/operators/impls/InternalOperatorFactoryChain";
+import MockWindowPresenter from "../../mock/MockWindowPresenter";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockConsoleClient from "../../mock/MockConsoleClient";
+import CancelOperator from "../../../../src/background/operators/impls/CancelOperator";
+import InternalOpenURLOperator from "../../../../src/background/operators/impls/InternalOpenURLOperator";
+import * as operations from "../../../../src/shared/operations";
+
+describe("InternalOperatorFactoryChain", () => {
+ describe("#create", () => {
+ it("returns a operator for the operation", async () => {
+ const windowPresenter = new MockWindowPresenter();
+ const tabPresenter = new MockTabPresenter();
+ const consoleClient = new MockConsoleClient();
+ const sut = new InternalOperatorFactoryChain(
+ windowPresenter,
+ tabPresenter,
+ consoleClient
+ );
+
+ expect(sut.create({ type: operations.CANCEL })).to.be.instanceOf(
+ CancelOperator
+ );
+ expect(
+ sut.create({
+ type: operations.INTERNAL_OPEN_URL,
+ url: "https://example.com",
+ newTab: false,
+ newWindow: false,
+ })
+ ).to.be.instanceOf(InternalOpenURLOperator);
+ expect(sut.create({ type: operations.COMMAND_SHOW })).to.be.null;
+ });
+ });
+});
diff --git a/test/background/operators/impls/NavigateHistoryNextOperator.test.ts b/test/background/operators/impls/NavigateHistoryNextOperator.test.ts
new file mode 100644
index 0000000..de8f597
--- /dev/null
+++ b/test/background/operators/impls/NavigateHistoryNextOperator.test.ts
@@ -0,0 +1,25 @@
+import sinon from "sinon";
+import NavigateHistoryNextOperator from "../../../../src/background/operators/impls/NavigateHistoryNextOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockNavigateClient from "../../mock/MockNavigateClient";
+
+describe("NavigateHistoryNextOperator", () => {
+ describe("#run", () => {
+ it("send a message to navigate next in the history", async () => {
+ const navigateClient = new MockNavigateClient();
+ const mock = sinon
+ .mock(navigateClient)
+ .expects("historyNext")
+ .withArgs(1);
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const sut = new NavigateHistoryNextOperator(tabPresenter, navigateClient);
+
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/NavigateHistoryPrevOperator.test.ts b/test/background/operators/impls/NavigateHistoryPrevOperator.test.ts
new file mode 100644
index 0000000..6ebe71e
--- /dev/null
+++ b/test/background/operators/impls/NavigateHistoryPrevOperator.test.ts
@@ -0,0 +1,25 @@
+import sinon from "sinon";
+import NavigateHistoryPrevOperator from "../../../../src/background/operators/impls/NavigateHistoryPrevOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockNavigateClient from "../../mock/MockNavigateClient";
+
+describe("NavigateHistoryPrevOperator", () => {
+ describe("#run", () => {
+ it("send a message to navigate previous in the history", async () => {
+ const navigateClient = new MockNavigateClient();
+ const mock = sinon
+ .mock(navigateClient)
+ .expects("historyPrev")
+ .withArgs(1);
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const sut = new NavigateHistoryPrevOperator(tabPresenter, navigateClient);
+
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/NavigateLinkNextOperator.test.ts b/test/background/operators/impls/NavigateLinkNextOperator.test.ts
new file mode 100644
index 0000000..09c4907
--- /dev/null
+++ b/test/background/operators/impls/NavigateLinkNextOperator.test.ts
@@ -0,0 +1,22 @@
+import sinon from "sinon";
+import NavigateLinkNextOperator from "../../../../src/background/operators/impls/NavigateLinkNextOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockNavigateClient from "../../mock/MockNavigateClient";
+
+describe("NavigateLinkNextOperator", () => {
+ describe("#run", () => {
+ it("send a message to navigate next page", async () => {
+ const navigateClient = new MockNavigateClient();
+ const mock = sinon.mock(navigateClient).expects("linkNext").withArgs(1);
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const sut = new NavigateLinkNextOperator(tabPresenter, navigateClient);
+
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/NavigateLinkPrevOperator.test.ts b/test/background/operators/impls/NavigateLinkPrevOperator.test.ts
new file mode 100644
index 0000000..6b7f791
--- /dev/null
+++ b/test/background/operators/impls/NavigateLinkPrevOperator.test.ts
@@ -0,0 +1,22 @@
+import sinon from "sinon";
+import NavigateLinkPrevOperator from "../../../../src/background/operators/impls/NavigateLinkPrevOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockNavigateClient from "../../mock/MockNavigateClient";
+
+describe("NavigateLinkPrevOperator", () => {
+ describe("#run", () => {
+ it("send a message to navigate next page", async () => {
+ const navigateClient = new MockNavigateClient();
+ const mock = sinon.mock(navigateClient).expects("linkPrev").withArgs(1);
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const sut = new NavigateLinkPrevOperator(tabPresenter, navigateClient);
+
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/NavigateOperatorFactoryChain.test.ts b/test/background/operators/impls/NavigateOperatorFactoryChain.test.ts
new file mode 100644
index 0000000..dfb5654
--- /dev/null
+++ b/test/background/operators/impls/NavigateOperatorFactoryChain.test.ts
@@ -0,0 +1,56 @@
+import "reflect-metadata";
+import { expect } from "chai";
+import NavigateOperatorFactoryChain from "../../../../src/background/operators/impls/NavigateOperatorFactoryChain";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockNavigateClient from "../../mock/MockNavigateClient";
+import MockBrowserSettingRepository from "../../mock/MockBrowserSettingRepository";
+import NavigateHistoryPrevOperator from "../../../../src/background/operators/impls/NavigateHistoryPrevOperator";
+import NavigateHistoryNextOperator from "../../../../src/background/operators/impls/NavigateHistoryNextOperator";
+import NavigateLinkPrevOperator from "../../../../src/background/operators/impls/NavigateLinkPrevOperator";
+import NavigateLinkNextOperator from "../../../../src/background/operators/impls/NavigateLinkNextOperator";
+import NavigateParentOperator from "../../../../src/background/operators/impls/NavigateParentOperator";
+import NavigateRootOperator from "../../../../src/background/operators/impls/NavigateRootOperator";
+import OpenHomeOperator from "../../../../src/background/operators/impls/OpenHomeOperator";
+import OpenSourceOperator from "../../../../src/background/operators/impls/OpenSourceOperator";
+import * as operations from "../../../../src/shared/operations";
+
+describe("NavigateOperatorFactoryChain", () => {
+ describe("#create", () => {
+ it("returns a operator for the operation", async () => {
+ const tabPresenter = new MockTabPresenter();
+ const navigateClient = new MockNavigateClient();
+ const browserSettingRepository = new MockBrowserSettingRepository([]);
+ const sut = new NavigateOperatorFactoryChain(
+ tabPresenter,
+ navigateClient,
+ browserSettingRepository
+ );
+
+ expect(
+ sut.create({ type: operations.NAVIGATE_HISTORY_PREV })
+ ).to.be.instanceOf(NavigateHistoryPrevOperator);
+ expect(
+ sut.create({ type: operations.NAVIGATE_HISTORY_NEXT })
+ ).to.be.instanceOf(NavigateHistoryNextOperator);
+ expect(
+ sut.create({ type: operations.NAVIGATE_LINK_PREV })
+ ).to.be.instanceOf(NavigateLinkPrevOperator);
+ expect(
+ sut.create({ type: operations.NAVIGATE_LINK_NEXT })
+ ).to.be.instanceOf(NavigateLinkNextOperator);
+ expect(sut.create({ type: operations.NAVIGATE_PARENT })).to.be.instanceOf(
+ NavigateParentOperator
+ );
+ expect(sut.create({ type: operations.NAVIGATE_ROOT })).to.be.instanceOf(
+ NavigateRootOperator
+ );
+ expect(sut.create({ type: operations.PAGE_SOURCE })).to.be.instanceOf(
+ OpenSourceOperator
+ );
+ expect(
+ sut.create({ type: operations.PAGE_HOME, newTab: false })
+ ).to.be.instanceOf(OpenHomeOperator);
+ expect(sut.create({ type: operations.CANCEL })).to.be.null;
+ });
+ });
+});
diff --git a/test/background/operators/impls/NavigateParentOperator.test.ts b/test/background/operators/impls/NavigateParentOperator.test.ts
new file mode 100644
index 0000000..cc57f17
--- /dev/null
+++ b/test/background/operators/impls/NavigateParentOperator.test.ts
@@ -0,0 +1,53 @@
+import { expect } from "chai";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import NavigateParentOperator from "../../../../src/background/operators/impls/NavigateParentOperator";
+
+describe("NavigateParentOperator", () => {
+ describe("#run", () => {
+ it("opens a parent directory of the file in the URL", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/fruits/yellow/banana", {
+ active: true,
+ });
+ const sut = new NavigateParentOperator(tabPresenter);
+
+ await sut.run();
+
+ const url = (await tabPresenter.getCurrent()).url;
+ expect(url).to.be.equal("https://example.com/fruits/yellow/");
+ });
+
+ it("opens a parent directory of the directoryin the URL", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/fruits/yellow/");
+ const sut = new NavigateParentOperator(tabPresenter);
+
+ await sut.run();
+
+ const url = (await tabPresenter.getCurrent()).url;
+ expect(url).to.be.equal("https://example.com/fruits/");
+ });
+
+ it("removes a hash in the URL", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/fruits/yellow/#top");
+ const sut = new NavigateParentOperator(tabPresenter);
+
+ await sut.run();
+
+ const url = (await tabPresenter.getCurrent()).url;
+ expect(url).to.be.equal("https://example.com/fruits/yellow/");
+ });
+
+ it("removes query parameters in the URL", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/search?q=apple");
+ const sut = new NavigateParentOperator(tabPresenter);
+
+ await sut.run();
+
+ const url = (await tabPresenter.getCurrent()).url;
+ expect(url).to.be.equal("https://example.com/search");
+ });
+ });
+});
diff --git a/test/background/operators/impls/NavigateRootOperator.test.ts b/test/background/operators/impls/NavigateRootOperator.test.ts
new file mode 100644
index 0000000..bbe574c
--- /dev/null
+++ b/test/background/operators/impls/NavigateRootOperator.test.ts
@@ -0,0 +1,18 @@
+import { expect } from "chai";
+import NavigateRootOperator from "../../../../src/background/operators/impls/NavigateRootOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+
+describe("NavigateRootOperator", () => {
+ describe("#run", () => {
+ it("opens root directory in the URL", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/search?q=apple#top");
+ const sut = new NavigateRootOperator(tabPresenter);
+
+ await sut.run();
+
+ const url = (await tabPresenter.getCurrent()).url;
+ expect(url).to.be.equal("https://example.com");
+ });
+ });
+});
diff --git a/test/background/operators/impls/OpenHomeOperator.test.ts b/test/background/operators/impls/OpenHomeOperator.test.ts
new file mode 100644
index 0000000..3c9288f
--- /dev/null
+++ b/test/background/operators/impls/OpenHomeOperator.test.ts
@@ -0,0 +1,70 @@
+import { expect } from "chai";
+import OpenHomeOperator from "../../../../src/background/operators/impls/OpenHomeOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockBrowserSettingRepository from "../../mock/MockBrowserSettingRepository";
+
+describe("OpenHomeOperator", () => {
+ describe("#run", () => {
+ it("opens a home page of the browser into the current tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/");
+ const browserSettingRepository = new MockBrowserSettingRepository([
+ "https://example.net/",
+ ]);
+ const sut = new OpenHomeOperator(
+ tabPresenter,
+ browserSettingRepository,
+ false
+ );
+
+ await sut.run();
+
+ const url = (await tabPresenter.getCurrent()).url;
+ expect(url).to.be.equal("https://example.net/");
+ });
+
+ it("opens a home page of the browser into a new tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/");
+ const browserSettingRepository = new MockBrowserSettingRepository([
+ "https://example.net/",
+ ]);
+ const sut = new OpenHomeOperator(
+ tabPresenter,
+ browserSettingRepository,
+ true
+ );
+
+ await sut.run();
+
+ const urls = (await tabPresenter.getAll()).map((t) => t.url);
+ expect(urls).to.be.deep.equal([
+ "https://example.com/",
+ "https://example.net/",
+ ]);
+ });
+
+ it("opens home pages of the browser", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/");
+ const browserSettingRepository = new MockBrowserSettingRepository([
+ "https://example.net/",
+ "https://example.org/",
+ ]);
+ const sut = new OpenHomeOperator(
+ tabPresenter,
+ browserSettingRepository,
+ false
+ );
+
+ await sut.run();
+
+ const urls = (await tabPresenter.getAll()).map((t) => t.url);
+ expect(urls).to.be.deep.equal([
+ "https://example.com/",
+ "https://example.net/",
+ "https://example.org/",
+ ]);
+ });
+ });
+});
diff --git a/test/background/operators/impls/OpenSourceOperator.test.ts b/test/background/operators/impls/OpenSourceOperator.test.ts
new file mode 100644
index 0000000..541032b
--- /dev/null
+++ b/test/background/operators/impls/OpenSourceOperator.test.ts
@@ -0,0 +1,21 @@
+import { expect } from "chai";
+import OpenSourceOperator from "../../../../src/background/operators/impls/OpenSourceOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+
+describe("OpenSourceOperator", () => {
+ describe("#run", () => {
+ it("opens view-source URL of the current tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/");
+ const sut = new OpenSourceOperator(tabPresenter);
+
+ await sut.run();
+
+ const urls = (await tabPresenter.getAll()).map((t) => t.url);
+ expect(urls).to.be.deep.equal([
+ "https://example.com/",
+ "view-source:https://example.com/",
+ ]);
+ });
+ });
+});
diff --git a/test/background/operators/impls/PinTabOperator.test.ts b/test/background/operators/impls/PinTabOperator.test.ts
new file mode 100644
index 0000000..0c940b6
--- /dev/null
+++ b/test/background/operators/impls/PinTabOperator.test.ts
@@ -0,0 +1,25 @@
+import { expect } from "chai";
+import PinTabOperator from "../../../../src/background/operators/impls/PinTabOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+
+describe("PinTabOperator", () => {
+ describe("#run", () => {
+ it("make pinned to the current tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/", {
+ active: true,
+ pinned: false,
+ });
+ await tabPresenter.create("https://example.com/", {
+ active: false,
+ pinned: false,
+ });
+ const sut = new PinTabOperator(tabPresenter);
+
+ await sut.run();
+
+ const pins = (await tabPresenter.getAll()).map((t) => t.pinned);
+ expect(pins).to.deep.equal([true, false]);
+ });
+ });
+});
diff --git a/test/background/operators/impls/ReloadTabOperator.test.ts b/test/background/operators/impls/ReloadTabOperator.test.ts
new file mode 100644
index 0000000..e87782b
--- /dev/null
+++ b/test/background/operators/impls/ReloadTabOperator.test.ts
@@ -0,0 +1,34 @@
+import sinon from "sinon";
+import ReloadTabOperator from "../../../../src/background/operators/impls/ReloadTabOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+
+describe("ReloadTabOperator", () => {
+ describe("#run", () => {
+ it("reloads the current tab with cache", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/", { active: true });
+ await tabPresenter.create("https://example.com/", { active: false });
+ const mock = sinon.mock(tabPresenter).expects("reload").withArgs(0, true);
+
+ const sut = new ReloadTabOperator(tabPresenter, true);
+ await sut.run();
+
+ mock.verify();
+ });
+
+ it("reloads the current tab without cache", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/", { active: true });
+ await tabPresenter.create("https://example.com/", { active: false });
+ const mock = sinon
+ .mock(tabPresenter)
+ .expects("reload")
+ .withArgs(0, false);
+
+ const sut = new ReloadTabOperator(tabPresenter, false);
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/ReopenTabOperator.test.ts b/test/background/operators/impls/ReopenTabOperator.test.ts
new file mode 100644
index 0000000..43b1575
--- /dev/null
+++ b/test/background/operators/impls/ReopenTabOperator.test.ts
@@ -0,0 +1,17 @@
+import sinon from "sinon";
+import ReopenTabOperator from "../../../../src/background/operators/impls/ReopenTabOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+
+describe("ReopenTabOperator", () => {
+ describe("#run", () => {
+ it("reopens closed tabs", async () => {
+ const tabPresenter = new MockTabPresenter();
+ const mock = sinon.mock(tabPresenter).expects("reopen");
+
+ const sut = new ReopenTabOperator(tabPresenter);
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/RepeatLastOperator.test.ts b/test/background/operators/impls/RepeatLastOperator.test.ts
new file mode 100644
index 0000000..57f1227
--- /dev/null
+++ b/test/background/operators/impls/RepeatLastOperator.test.ts
@@ -0,0 +1,56 @@
+import RepeatLastOperator from "../../../../src/background/operators/impls/RepeatLastOperator";
+import MockRepeatRepository from "../../mock/MockRepeatRepository";
+import OperatorFactory from "../../../../src/background/operators/OperatorFactory";
+import * as operations from "../../../../src/shared/operations";
+import Operator from "../../../../src/background/operators/Operator";
+import sinon from "sinon";
+
+class MockOperatorFactory implements OperatorFactory {
+ create(_op: operations.Operation): Operator {
+ throw new Error("not implemented");
+ }
+}
+
+class MockOperator implements Operator {
+ run(): Promise<void> {
+ throw new Error("not implemented");
+ }
+}
+
+describe("RepeatLastOperator", () => {
+ describe("#run", () => {
+ it("repeat last operation", async () => {
+ const operator = new MockOperator();
+ const operatorMock = sinon.mock(operator).expects("run").once();
+ const repeatRepository = new MockRepeatRepository();
+ repeatRepository.setLastOperation({ type: operations.CANCEL });
+
+ const operatorFactory = new MockOperatorFactory();
+ const operatorFactoryMock = sinon
+ .mock(operatorFactory)
+ .expects("create")
+ .withArgs({ type: operations.CANCEL });
+ operatorFactoryMock.returns(operator);
+
+ const sut = new RepeatLastOperator(repeatRepository, operatorFactory);
+ await sut.run();
+
+ operatorFactoryMock.verify();
+ operatorMock.verify();
+ });
+
+ it("does nothing if no last operations", async () => {
+ const repeatRepository = new MockRepeatRepository();
+ const operatorFactory = new MockOperatorFactory();
+ const operatorFactoryMock = sinon
+ .mock(operatorFactory)
+ .expects("create")
+ .never();
+
+ const sut = new RepeatLastOperator(repeatRepository, operatorFactory);
+ await sut.run();
+
+ operatorFactoryMock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/RepeatOperatorFactoryChain.test.ts b/test/background/operators/impls/RepeatOperatorFactoryChain.test.ts
new file mode 100644
index 0000000..e12d788
--- /dev/null
+++ b/test/background/operators/impls/RepeatOperatorFactoryChain.test.ts
@@ -0,0 +1,32 @@
+import "reflect-metadata";
+import { expect } from "chai";
+import RepeatOperatorFactoryChain from "../../../../src/background/operators/impls/RepeatOperatorFactoryChain";
+import RepeatLastOperator from "../../../../src/background/operators/impls/RepeatLastOperator";
+import OperatorFactory from "../../../../src/background/operators/OperatorFactory";
+import MockRepeatRepository from "../../mock/MockRepeatRepository";
+import Operator from "../../../../src/content/operators/Operator";
+import * as operations from "../../../../src/shared/operations";
+
+class MockOperatorFactory implements OperatorFactory {
+ create(_op: operations.Operation): Operator {
+ throw new Error("not implemented");
+ }
+}
+
+describe("RepeatOperatorFactoryChain", () => {
+ describe("#create", () => {
+ it("returns a operator for the operation", async () => {
+ const repeatRepository = new MockRepeatRepository();
+ const operatorFactory = new MockOperatorFactory();
+ const sut = new RepeatOperatorFactoryChain(
+ repeatRepository,
+ operatorFactory
+ );
+
+ expect(sut.create({ type: operations.REPEAT_LAST })).to.be.instanceOf(
+ RepeatLastOperator
+ );
+ expect(sut.create({ type: operations.CANCEL })).to.be.null;
+ });
+ });
+});
diff --git a/test/background/operators/impls/ResetZoomOperator.test.ts b/test/background/operators/impls/ResetZoomOperator.test.ts
new file mode 100644
index 0000000..68cda05
--- /dev/null
+++ b/test/background/operators/impls/ResetZoomOperator.test.ts
@@ -0,0 +1,17 @@
+import sinon from "sinon";
+import ResetZoomOperator from "../../../../src/background/operators/impls/ResetZoomOperator";
+import MockZoomPresenter from "../../mock/MockZoomPresenter";
+
+describe("ResetZoomOperator", () => {
+ describe("#run", () => {
+ it("resets zoom on the tab", async () => {
+ const zoomPresenter = new MockZoomPresenter();
+ const mock = sinon.mock(zoomPresenter).expects("resetZoom").once();
+
+ const sut = new ResetZoomOperator(zoomPresenter);
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/SelectFirstTabOperator.test.ts b/test/background/operators/impls/SelectFirstTabOperator.test.ts
new file mode 100644
index 0000000..a3f1d7e
--- /dev/null
+++ b/test/background/operators/impls/SelectFirstTabOperator.test.ts
@@ -0,0 +1,20 @@
+import { expect } from "chai";
+import SelectFirstTabOperator from "../../../../src/background/operators/impls/SelectFirstTabOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+
+describe("SelectFirstTabOperator", () => {
+ describe("#run", () => {
+ it("select the leftmost tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+
+ const sut = new SelectFirstTabOperator(tabPresenter);
+ await sut.run();
+
+ const url = (await tabPresenter.getCurrent()).url;
+ expect(url).to.equal("https://example.com/1");
+ });
+ });
+});
diff --git a/test/background/operators/impls/SelectLastTabOperator.test.ts b/test/background/operators/impls/SelectLastTabOperator.test.ts
new file mode 100644
index 0000000..b8cf5c4
--- /dev/null
+++ b/test/background/operators/impls/SelectLastTabOperator.test.ts
@@ -0,0 +1,20 @@
+import { expect } from "chai";
+import SelectLastTabOperator from "../../../../src/background/operators/impls/SelectLastTabOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+
+describe("SelectLastTabOperator", () => {
+ describe("#run", () => {
+ it("select the rightmost tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+
+ const sut = new SelectLastTabOperator(tabPresenter);
+ await sut.run();
+
+ const url = (await tabPresenter.getCurrent()).url;
+ expect(url).to.equal("https://example.com/3");
+ });
+ });
+});
diff --git a/test/background/operators/impls/SelectPreviousSelectedTabOperator.test.ts b/test/background/operators/impls/SelectPreviousSelectedTabOperator.test.ts
new file mode 100644
index 0000000..5e6cc73
--- /dev/null
+++ b/test/background/operators/impls/SelectPreviousSelectedTabOperator.test.ts
@@ -0,0 +1,38 @@
+import { expect } from "chai";
+import sinon from "sinon";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import SelectPreviousSelectedTabOperator from "../../../../src/background/operators/impls/SelectPreviousSelectedTabOperator";
+
+describe("SelectPreviousSelectedTabOperator", () => {
+ describe("#run", () => {
+ it("select the last-selected tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ sinon.stub(tabPresenter, "getLastSelectedId").returns(Promise.resolve(0));
+
+ const sut = new SelectPreviousSelectedTabOperator(tabPresenter);
+ await sut.run();
+
+ const url = (await tabPresenter.getCurrent()).url;
+ expect(url).to.equal("https://example.com/1");
+ });
+
+ it("do nothing if no last-selected tabs", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ sinon
+ .stub(tabPresenter, "getLastSelectedId")
+ .returns(Promise.resolve(undefined));
+ const mock = sinon.mock(tabPresenter).expects("select").never();
+
+ const sut = new SelectPreviousSelectedTabOperator(tabPresenter);
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/SelectTabNextOperator.test.ts b/test/background/operators/impls/SelectTabNextOperator.test.ts
new file mode 100644
index 0000000..5952d92
--- /dev/null
+++ b/test/background/operators/impls/SelectTabNextOperator.test.ts
@@ -0,0 +1,35 @@
+import { expect } from "chai";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import SelectTabNextOperator from "../../../../src/background/operators/impls/SelectTabNextOperator";
+
+describe("SelectTabNextOperator", () => {
+ describe("#run", () => {
+ it("select a right tab of the current tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+
+ const sut = new SelectTabNextOperator(tabPresenter);
+ await sut.run();
+
+ const url = (await tabPresenter.getCurrent()).url;
+ expect(url).to.equal("https://example.com/3");
+ });
+ });
+
+ describe("#run", () => {
+ it("select a right tab of the current tab in rotation", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: false });
+ await tabPresenter.create("https://example.com/3", { active: true });
+
+ const sut = new SelectTabNextOperator(tabPresenter);
+ await sut.run();
+
+ const url = (await tabPresenter.getCurrent()).url;
+ expect(url).to.equal("https://example.com/1");
+ });
+ });
+});
diff --git a/test/background/operators/impls/SelectTabPrevOperator.test.ts b/test/background/operators/impls/SelectTabPrevOperator.test.ts
new file mode 100644
index 0000000..c9092fa
--- /dev/null
+++ b/test/background/operators/impls/SelectTabPrevOperator.test.ts
@@ -0,0 +1,35 @@
+import { expect } from "chai";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import SelectTabPrevOperator from "../../../../src/background/operators/impls/SelectTabPrevOperator";
+
+describe("SelectTabPrevOperator", () => {
+ describe("#run", () => {
+ it("select a left tab of the current tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+
+ const sut = new SelectTabPrevOperator(tabPresenter);
+ await sut.run();
+
+ const url = (await tabPresenter.getCurrent()).url;
+ expect(url).to.equal("https://example.com/1");
+ });
+ });
+
+ describe("#run", () => {
+ it("select a left tab of the current tab in rotation", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: true });
+ await tabPresenter.create("https://example.com/2", { active: false });
+ await tabPresenter.create("https://example.com/3", { active: false });
+
+ const sut = new SelectTabPrevOperator(tabPresenter);
+ await sut.run();
+
+ const url = (await tabPresenter.getCurrent()).url;
+ expect(url).to.equal("https://example.com/3");
+ });
+ });
+});
diff --git a/test/background/operators/impls/ShowAddBookmarkOperator.test.ts b/test/background/operators/impls/ShowAddBookmarkOperator.test.ts
new file mode 100644
index 0000000..1e083c2
--- /dev/null
+++ b/test/background/operators/impls/ShowAddBookmarkOperator.test.ts
@@ -0,0 +1,50 @@
+import sinon from "sinon";
+import ShowAddBookmarkOperator from "../../../../src/background/operators/impls/ShowAddBookmarkOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockConsoleClient from "../../mock/MockConsoleClient";
+
+describe("ShowAddBookmarkOperator", () => {
+ describe("#run", () => {
+ it("show command with addbookmark command", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const consoleClient = new MockConsoleClient();
+ const mock = sinon
+ .mock(consoleClient)
+ .expects("showCommand")
+ .withArgs(1, "addbookmark ");
+
+ const sut = new ShowAddBookmarkOperator(
+ tabPresenter,
+ consoleClient,
+ false
+ );
+ await sut.run();
+
+ mock.verify();
+ });
+
+ it("show command with addbookmark command and an URL of the current tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const consoleClient = new MockConsoleClient();
+ const mock = sinon
+ .mock(consoleClient)
+ .expects("showCommand")
+ .withArgs(1, "addbookmark welcome, world");
+
+ const sut = new ShowAddBookmarkOperator(
+ tabPresenter,
+ consoleClient,
+ true
+ );
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/ShowBufferCommandOperator.test.ts b/test/background/operators/impls/ShowBufferCommandOperator.test.ts
new file mode 100644
index 0000000..91455b3
--- /dev/null
+++ b/test/background/operators/impls/ShowBufferCommandOperator.test.ts
@@ -0,0 +1,25 @@
+import sinon from "sinon";
+import ShowBufferCommandOperator from "../../../../src/background/operators/impls/ShowBufferCommandOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockConsoleClient from "../../mock/MockConsoleClient";
+
+describe("ShowBufferCommandOperator", () => {
+ describe("#run", () => {
+ it("show command with buffer command", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const consoleClient = new MockConsoleClient();
+ const mock = sinon
+ .mock(consoleClient)
+ .expects("showCommand")
+ .withArgs(1, "buffer ");
+
+ const sut = new ShowBufferCommandOperator(tabPresenter, consoleClient);
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/ShowCommandOperator.test.ts b/test/background/operators/impls/ShowCommandOperator.test.ts
new file mode 100644
index 0000000..83b028c
--- /dev/null
+++ b/test/background/operators/impls/ShowCommandOperator.test.ts
@@ -0,0 +1,25 @@
+import sinon from "sinon";
+import ShowCommandOperator from "../../../../src/background/operators/impls/ShowCommandOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockConsoleClient from "../../mock/MockConsoleClient";
+
+describe("ShowCommandOperator", () => {
+ describe("#run", () => {
+ it("show command with addbookmark command", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const consoleClient = new MockConsoleClient();
+ const mock = sinon
+ .mock(consoleClient)
+ .expects("showCommand")
+ .withArgs(1, "");
+
+ const sut = new ShowCommandOperator(tabPresenter, consoleClient);
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/ShowOpenCommandOperator.test.ts b/test/background/operators/impls/ShowOpenCommandOperator.test.ts
new file mode 100644
index 0000000..2c2105a
--- /dev/null
+++ b/test/background/operators/impls/ShowOpenCommandOperator.test.ts
@@ -0,0 +1,50 @@
+import sinon from "sinon";
+import ShowOpenCommandOperator from "../../../../src/background/operators/impls/ShowOpenCommandOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockConsoleClient from "../../mock/MockConsoleClient";
+
+describe("ShowOpenCommandOperator", () => {
+ describe("#run", () => {
+ it("show command with open command", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const consoleClient = new MockConsoleClient();
+ const mock = sinon
+ .mock(consoleClient)
+ .expects("showCommand")
+ .withArgs(1, "open ");
+
+ const sut = new ShowOpenCommandOperator(
+ tabPresenter,
+ consoleClient,
+ false
+ );
+ await sut.run();
+
+ mock.verify();
+ });
+
+ it("show command with open command and an URL of the current tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const consoleClient = new MockConsoleClient();
+ const mock = sinon
+ .mock(consoleClient)
+ .expects("showCommand")
+ .withArgs(1, "open https://example.com/2");
+
+ const sut = new ShowOpenCommandOperator(
+ tabPresenter,
+ consoleClient,
+ true
+ );
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/ShowTabOpenCommandOperator.test.ts b/test/background/operators/impls/ShowTabOpenCommandOperator.test.ts
new file mode 100644
index 0000000..e291d05
--- /dev/null
+++ b/test/background/operators/impls/ShowTabOpenCommandOperator.test.ts
@@ -0,0 +1,50 @@
+import sinon from "sinon";
+import ShowTabOpenCommandOperator from "../../../../src/background/operators/impls/ShowTabOpenCommandOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockConsoleClient from "../../mock/MockConsoleClient";
+
+describe("ShowTabOpenCommandOperator", () => {
+ describe("#run", () => {
+ it("show command with tabopen command", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const consoleClient = new MockConsoleClient();
+ const mock = sinon
+ .mock(consoleClient)
+ .expects("showCommand")
+ .withArgs(1, "tabopen ");
+
+ const sut = new ShowTabOpenCommandOperator(
+ tabPresenter,
+ consoleClient,
+ false
+ );
+ await sut.run();
+
+ mock.verify();
+ });
+
+ it("show command with tabopen command and an URL of the current tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const consoleClient = new MockConsoleClient();
+ const mock = sinon
+ .mock(consoleClient)
+ .expects("showCommand")
+ .withArgs(1, "tabopen https://example.com/2");
+
+ const sut = new ShowTabOpenCommandOperator(
+ tabPresenter,
+ consoleClient,
+ true
+ );
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/ShowWinOpenCommandOperator.test.ts b/test/background/operators/impls/ShowWinOpenCommandOperator.test.ts
new file mode 100644
index 0000000..c81a2d4
--- /dev/null
+++ b/test/background/operators/impls/ShowWinOpenCommandOperator.test.ts
@@ -0,0 +1,50 @@
+import sinon from "sinon";
+import ShowWinOpenCommandOperator from "../../../../src/background/operators/impls/ShowWinOpenCommandOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockConsoleClient from "../../mock/MockConsoleClient";
+
+describe("ShowWinOpenCommandOperator", () => {
+ describe("#run", () => {
+ it("show command with winopen command", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const consoleClient = new MockConsoleClient();
+ const mock = sinon
+ .mock(consoleClient)
+ .expects("showCommand")
+ .withArgs(1, "winopen ");
+
+ const sut = new ShowWinOpenCommandOperator(
+ tabPresenter,
+ consoleClient,
+ false
+ );
+ await sut.run();
+
+ mock.verify();
+ });
+
+ it("show command with winopen command and an URL of the current tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const consoleClient = new MockConsoleClient();
+ const mock = sinon
+ .mock(consoleClient)
+ .expects("showCommand")
+ .withArgs(1, "winopen https://example.com/2");
+
+ const sut = new ShowWinOpenCommandOperator(
+ tabPresenter,
+ consoleClient,
+ true
+ );
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/StartFindOperator.test.ts b/test/background/operators/impls/StartFindOperator.test.ts
new file mode 100644
index 0000000..7764520
--- /dev/null
+++ b/test/background/operators/impls/StartFindOperator.test.ts
@@ -0,0 +1,22 @@
+import sinon from "sinon";
+import StartFindOperator from "../../../../src/background/operators/impls/StartFindOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import MockConsoleClient from "../../mock/MockConsoleClient";
+
+describe("StartFindOperator", () => {
+ describe("#run", () => {
+ it("show find console", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/1", { active: false });
+ await tabPresenter.create("https://example.com/2", { active: true });
+ await tabPresenter.create("https://example.com/3", { active: false });
+ const consoleClient = new MockConsoleClient();
+ const mock = sinon.mock(consoleClient).expects("showFind").withArgs(1);
+
+ const sut = new StartFindOperator(tabPresenter, consoleClient);
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/TabOperatorFactoryChain.test.ts b/test/background/operators/impls/TabOperatorFactoryChain.test.ts
new file mode 100644
index 0000000..7ab5de0
--- /dev/null
+++ b/test/background/operators/impls/TabOperatorFactoryChain.test.ts
@@ -0,0 +1,71 @@
+import "reflect-metadata";
+import { expect } from "chai";
+import TabOperatorFactoryChain from "../../../../src/background/operators/impls/TabOperatorFactoryChain";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+import DuplicateTabOperator from "../../../../src/background/operators/impls/DuplicateTabOperator";
+import TogglePinnedTabOperator from "../../../../src/background/operators/impls/TogglePinnedTabOperator";
+import UnpinTabOperator from "../../../../src/background/operators/impls/UnpinTabOperator";
+import PinTabOperator from "../../../../src/background/operators/impls/PinTabOperator";
+import ReloadTabOperator from "../../../../src/background/operators/impls/ReloadTabOperator";
+import SelectPreviousSelectedTabOperator from "../../../../src/background/operators/impls/SelectPreviousSelectedTabOperator";
+import SelectLastTabOperator from "../../../../src/background/operators/impls/SelectLastTabOperator";
+import SelectFirstTabOperator from "../../../../src/background/operators/impls/SelectFirstTabOperator";
+import SelectTabNextOperator from "../../../../src/background/operators/impls/SelectTabNextOperator";
+import SelectTabPrevOperator from "../../../../src/background/operators/impls/SelectTabPrevOperator";
+import ReopenTabOperator from "../../../../src/background/operators/impls/ReopenTabOperator";
+import CloseTabOperator from "../../../../src/background/operators/impls/CloseTabOperator";
+import CloseTabRightOperator from "../../../../src/background/operators/impls/CloseTabRightOperator";
+import * as operations from "../../../../src/shared/operations";
+
+describe("TabOperatorFactoryChain", () => {
+ describe("#create", () => {
+ it("returns a operator for the operation", async () => {
+ const tabPresenter = new MockTabPresenter();
+ const sut = new TabOperatorFactoryChain(tabPresenter);
+
+ expect(sut.create({ type: operations.TAB_CLOSE })).to.be.instanceOf(
+ CloseTabOperator
+ );
+ expect(sut.create({ type: operations.TAB_CLOSE_RIGHT })).to.be.instanceOf(
+ CloseTabRightOperator
+ );
+ expect(sut.create({ type: operations.TAB_CLOSE_FORCE })).to.be.instanceOf(
+ CloseTabOperator
+ );
+ expect(sut.create({ type: operations.TAB_REOPEN })).to.be.instanceOf(
+ ReopenTabOperator
+ );
+ expect(sut.create({ type: operations.TAB_PREV })).to.be.instanceOf(
+ SelectTabPrevOperator
+ );
+ expect(sut.create({ type: operations.TAB_NEXT })).to.be.instanceOf(
+ SelectTabNextOperator
+ );
+ expect(sut.create({ type: operations.TAB_FIRST })).to.be.instanceOf(
+ SelectFirstTabOperator
+ );
+ expect(
+ sut.create({ type: operations.TAB_LAST, newTab: false })
+ ).to.be.instanceOf(SelectLastTabOperator);
+ expect(
+ sut.create({ type: operations.TAB_PREV_SEL, newTab: false })
+ ).to.be.instanceOf(SelectPreviousSelectedTabOperator);
+ expect(
+ sut.create({ type: operations.TAB_RELOAD, cache: false })
+ ).to.be.instanceOf(ReloadTabOperator);
+ expect(sut.create({ type: operations.TAB_PIN })).to.be.instanceOf(
+ PinTabOperator
+ );
+ expect(sut.create({ type: operations.TAB_UNPIN })).to.be.instanceOf(
+ UnpinTabOperator
+ );
+ expect(
+ sut.create({ type: operations.TAB_TOGGLE_PINNED })
+ ).to.be.instanceOf(TogglePinnedTabOperator);
+ expect(sut.create({ type: operations.TAB_DUPLICATE })).to.be.instanceOf(
+ DuplicateTabOperator
+ );
+ expect(sut.create({ type: operations.CANCEL })).to.be.null;
+ });
+ });
+});
diff --git a/test/background/operators/impls/TogglePinnedTabOperator.test.ts b/test/background/operators/impls/TogglePinnedTabOperator.test.ts
new file mode 100644
index 0000000..f155f83
--- /dev/null
+++ b/test/background/operators/impls/TogglePinnedTabOperator.test.ts
@@ -0,0 +1,32 @@
+import { expect } from "chai";
+import TogglePinnedTabOperator from "../../../../src/background/operators/impls/TogglePinnedTabOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+
+describe("TogglePinnedTabOperator", () => {
+ describe("#run", () => {
+ it("toggle pinned to the current tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/", {
+ active: true,
+ pinned: false,
+ });
+ await tabPresenter.create("https://example.com/", {
+ active: false,
+ pinned: false,
+ });
+ const sut = new TogglePinnedTabOperator(tabPresenter);
+
+ await sut.run();
+ expect((await tabPresenter.getAll()).map((t) => t.pinned)).to.deep.equal([
+ true,
+ false,
+ ]);
+
+ await sut.run();
+ expect((await tabPresenter.getAll()).map((t) => t.pinned)).to.deep.equal([
+ false,
+ false,
+ ]);
+ });
+ });
+});
diff --git a/test/background/operators/impls/UnpinTabOperator.test.ts b/test/background/operators/impls/UnpinTabOperator.test.ts
new file mode 100644
index 0000000..745f48c
--- /dev/null
+++ b/test/background/operators/impls/UnpinTabOperator.test.ts
@@ -0,0 +1,25 @@
+import { expect } from "chai";
+import UnpinTabOperator from "../../../../src/background/operators/impls/UnpinTabOperator";
+import MockTabPresenter from "../../mock/MockTabPresenter";
+
+describe("UnpinTabOperator", () => {
+ describe("#run", () => {
+ it("make unpinned to the current tab", async () => {
+ const tabPresenter = new MockTabPresenter();
+ await tabPresenter.create("https://example.com/", {
+ active: true,
+ pinned: true,
+ });
+ await tabPresenter.create("https://example.com/", {
+ active: false,
+ pinned: true,
+ });
+ const sut = new UnpinTabOperator(tabPresenter);
+
+ await sut.run();
+
+ const pins = (await tabPresenter.getAll()).map((t) => t.pinned);
+ expect(pins).to.deep.equal([false, true]);
+ });
+ });
+});
diff --git a/test/background/operators/impls/ZoomInOperator.test.ts b/test/background/operators/impls/ZoomInOperator.test.ts
new file mode 100644
index 0000000..097e760
--- /dev/null
+++ b/test/background/operators/impls/ZoomInOperator.test.ts
@@ -0,0 +1,17 @@
+import sinon from "sinon";
+import ZoomInOperator from "../../../../src/background/operators/impls/ZoomInOperator";
+import MockZoomPresenter from "../../mock/MockZoomPresenter";
+
+describe("ZoomInOperator", () => {
+ describe("#run", () => {
+ it("zoom-out the current tab", async () => {
+ const zoomPresenter = new MockZoomPresenter();
+ const mock = sinon.mock(zoomPresenter).expects("zoomIn").once();
+
+ const sut = new ZoomInOperator(zoomPresenter);
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/operators/impls/ZoomOperatorFactoryChain.test.ts b/test/background/operators/impls/ZoomOperatorFactoryChain.test.ts
new file mode 100644
index 0000000..10c1cee
--- /dev/null
+++ b/test/background/operators/impls/ZoomOperatorFactoryChain.test.ts
@@ -0,0 +1,28 @@
+import "reflect-metadata";
+import { expect } from "chai";
+import ZoomOperatorFactoryChain from "../../../../src/background/operators/impls/ZoomOperatorFactoryChain";
+import MockZoomPresenter from "../../mock/MockZoomPresenter";
+import ZoomInOperator from "../../../../src/background/operators/impls/ZoomInOperator";
+import ZoomOutOperator from "../../../../src/background/operators/impls/ZoomOutOperator";
+import ResetZoomOperator from "../../../../src/background/operators/impls/ResetZoomOperator";
+import * as operations from "../../../../src/shared/operations";
+
+describe("ZoomOperatorFactoryChain", () => {
+ describe("#create", () => {
+ it("returns a operator for the operation", async () => {
+ const zoomPresenter = new MockZoomPresenter();
+ const sut = new ZoomOperatorFactoryChain(zoomPresenter);
+
+ expect(sut.create({ type: operations.ZOOM_IN })).to.be.instanceOf(
+ ZoomInOperator
+ );
+ expect(sut.create({ type: operations.ZOOM_OUT })).to.be.instanceOf(
+ ZoomOutOperator
+ );
+ expect(sut.create({ type: operations.ZOOM_NEUTRAL })).to.be.instanceOf(
+ ResetZoomOperator
+ );
+ expect(sut.create({ type: operations.CANCEL })).to.be.null;
+ });
+ });
+});
diff --git a/test/background/operators/impls/ZoomOutOperator.test.ts b/test/background/operators/impls/ZoomOutOperator.test.ts
new file mode 100644
index 0000000..e0bbcd9
--- /dev/null
+++ b/test/background/operators/impls/ZoomOutOperator.test.ts
@@ -0,0 +1,17 @@
+import sinon from "sinon";
+import ZoomOutOperator from "../../../../src/background/operators/impls/ZoomOutOperator";
+import MockZoomPresenter from "../../mock/MockZoomPresenter";
+
+describe("ZoomOutOperator", () => {
+ describe("#run", () => {
+ it("zoom-in the current tab", async () => {
+ const zoomPresenter = new MockZoomPresenter();
+ const mock = sinon.mock(zoomPresenter).expects("zoomOut").once();
+
+ const sut = new ZoomOutOperator(zoomPresenter);
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/background/usecases/NavigateUseCase.test.ts b/test/background/usecases/NavigateUseCase.test.ts
deleted file mode 100644
index 086d6cd..0000000
--- a/test/background/usecases/NavigateUseCase.test.ts
+++ /dev/null
@@ -1,183 +0,0 @@
-import "reflect-metadata";
-import TabPresenter from "../../../src/background/presenters/TabPresenter";
-import NavigateUseCase from "../../../src/background/usecases/NavigateUseCase";
-import NavigateClient from "../../../src/background/clients/NavigateClient";
-import * as sinon from "sinon";
-
-class MockTabPresenter implements TabPresenter {
- create(_url: string, _opts?: unknown): Promise<browser.tabs.Tab> {
- throw new Error("not implemented");
- }
-
- duplicate(_id: number): Promise<browser.tabs.Tab> {
- throw new Error("not implemented");
- }
-
- getAll(): Promise<browser.tabs.Tab[]> {
- throw new Error("not implemented");
- }
-
- getByKeyword(
- _keyword: string,
- _excludePinned: boolean
- ): Promise<browser.tabs.Tab[]> {
- throw new Error("not implemented");
- }
-
- getCurrent(): Promise<browser.tabs.Tab> {
- throw new Error("not implemented");
- }
-
- getLastSelectedId(): Promise<number | undefined> {
- throw new Error("not implemented");
- }
-
- getZoom(_tabId: number): Promise<number> {
- throw new Error("not implemented");
- }
-
- onSelected(
- _listener: (arg: { tabId: number; windowId: number }) => void
- ): void {
- throw new Error("not implemented");
- }
-
- open(_url: string, _tabId?: number): Promise<browser.tabs.Tab> {
- throw new Error("not implemented");
- }
-
- reload(_tabId: number, _cache: boolean): Promise<void> {
- throw new Error("not implemented");
- }
-
- remove(_ids: number[]): Promise<void> {
- throw new Error("not implemented");
- }
-
- reopen(): Promise<void> {
- throw new Error("not implemented");
- }
-
- select(_tabId: number): Promise<void> {
- throw new Error("not implemented");
- }
-
- setPinned(_tabId: number, _pinned: boolean): Promise<void> {
- throw new Error("not implemented");
- }
-
- setZoom(_tabId: number, _factor: number): Promise<void> {
- throw new Error("not implemented");
- }
-}
-
-describe("NavigateUseCase", () => {
- let sut: NavigateUseCase;
- let tabPresenter: TabPresenter;
- let navigateClient: NavigateClient;
-
- beforeEach(() => {
- tabPresenter = new MockTabPresenter();
- navigateClient = new NavigateClient();
- sut = new NavigateUseCase(tabPresenter, navigateClient);
- });
-
- const newTab = (url: string): browser.tabs.Tab => {
- return {
- index: 0,
- title: "dummy title",
- url: url,
- active: true,
- hidden: false,
- highlighted: false,
- incognito: false,
- isArticle: false,
- isInReaderMode: false,
- lastAccessed: 1585446733000,
- pinned: false,
- selected: false,
- windowId: 0,
- };
- };
-
- describe("#openParent()", async () => {
- it("opens parent directory of file", async () => {
- sinon
- .stub(tabPresenter, "getCurrent")
- .returns(
- Promise.resolve(newTab("https://google.com/fruits/yellow/banana"))
- );
-
- const mock = sinon
- .mock(tabPresenter)
- .expects("open")
- .withArgs("https://google.com/fruits/yellow/");
-
- await sut.openParent();
-
- mock.verify();
- });
-
- it("opens parent directory of directory", async () => {
- sinon
- .stub(tabPresenter, "getCurrent")
- .returns(Promise.resolve(newTab("https://google.com/fruits/yellow/")));
-
- const mock = sinon
- .mock(tabPresenter)
- .expects("open")
- .withArgs("https://google.com/fruits/");
-
- await sut.openParent();
-
- mock.verify();
- });
-
- it("removes hash", async () => {
- sinon
- .stub(tabPresenter, "getCurrent")
- .returns(Promise.resolve(newTab("https://google.com/#top")));
-
- const mock = sinon
- .mock(tabPresenter)
- .expects("open")
- .withArgs("https://google.com/");
-
- await sut.openParent();
-
- mock.verify();
- });
-
- it("removes search query", async () => {
- sinon
- .stub(tabPresenter, "getCurrent")
- .returns(Promise.resolve(newTab("https://google.com/search?q=apple")));
-
- const mock = sinon
- .mock(tabPresenter)
- .expects("open")
- .withArgs("https://google.com/search");
-
- await sut.openParent();
-
- mock.verify();
- });
- });
-
- describe("#openRoot()", () => {
- it("opens root direectory", async () => {
- sinon
- .stub(tabPresenter, "getCurrent")
- .returns(Promise.resolve(newTab("https://google.com/seach?q=apple")));
-
- const mock = sinon
- .mock(tabPresenter)
- .expects("open")
- .withArgs("https://google.com");
-
- await sut.openRoot();
-
- mock.verify();
- });
- });
-});
diff --git a/test/content/mock/MockAddonEnabledRepository.ts b/test/content/mock/MockAddonEnabledRepository.ts
new file mode 100644
index 0000000..cbe248b
--- /dev/null
+++ b/test/content/mock/MockAddonEnabledRepository.ts
@@ -0,0 +1,18 @@
+import AddonEnabledRepository from "../../../src/content/repositories/AddonEnabledRepository";
+
+export default class MockAddonEnabledRepository
+ implements AddonEnabledRepository {
+ public enabled: boolean;
+
+ constructor(initialValue = false) {
+ this.enabled = initialValue;
+ }
+
+ get(): boolean {
+ return this.enabled;
+ }
+
+ set(on: boolean): void {
+ this.enabled = on;
+ }
+}
diff --git a/test/content/mock/MockAddonIndicatorClient.ts b/test/content/mock/MockAddonIndicatorClient.ts
new file mode 100644
index 0000000..6ea9798
--- /dev/null
+++ b/test/content/mock/MockAddonIndicatorClient.ts
@@ -0,0 +1,13 @@
+import AddonIndicatorClient from "../../../src/content/client/AddonIndicatorClient";
+
+export default class MockAddonIndicatorClient implements AddonIndicatorClient {
+ public enabled: boolean;
+
+ constructor(initialValue = false) {
+ this.enabled = initialValue;
+ }
+
+ async setEnabled(enabled: boolean): Promise<void> {
+ this.enabled = enabled;
+ }
+}
diff --git a/test/content/mock/MockClipboardRepository.ts b/test/content/mock/MockClipboardRepository.ts
new file mode 100644
index 0000000..c6e53bd
--- /dev/null
+++ b/test/content/mock/MockClipboardRepository.ts
@@ -0,0 +1,16 @@
+import ClipboardRepository from "../../../src/content/repositories/ClipboardRepository";
+
+export default class MockClipboardRepository implements ClipboardRepository {
+ private value: string;
+
+ constructor(initValue = "") {
+ this.value = initValue;
+ }
+ read(): string {
+ return this.value;
+ }
+
+ write(text: string): void {
+ this.value = text;
+ }
+}
diff --git a/test/content/mock/MockFindMasterClient.ts b/test/content/mock/MockFindMasterClient.ts
new file mode 100644
index 0000000..a035cc5
--- /dev/null
+++ b/test/content/mock/MockFindMasterClient.ts
@@ -0,0 +1,11 @@
+import FindMasterClient from "../../../src/content/client/FindMasterClient";
+
+export default class MockFindMasterClient implements FindMasterClient {
+ findNext(): void {
+ throw new Error("not implemented");
+ }
+
+ findPrev(): void {
+ throw new Error("not implemented");
+ }
+}
diff --git a/test/content/mock/MockFocusPresenter.ts b/test/content/mock/MockFocusPresenter.ts
new file mode 100644
index 0000000..43454d0
--- /dev/null
+++ b/test/content/mock/MockFocusPresenter.ts
@@ -0,0 +1,7 @@
+import FocusPresenter from "../../../src/content/presenters/FocusPresenter";
+
+export default class MockFocusPresenter implements FocusPresenter {
+ focusFirstElement(): boolean {
+ throw new Error("not implemented");
+ }
+}
diff --git a/test/content/mock/MockFollowMasterClient.ts b/test/content/mock/MockFollowMasterClient.ts
new file mode 100644
index 0000000..fc660d5
--- /dev/null
+++ b/test/content/mock/MockFollowMasterClient.ts
@@ -0,0 +1,16 @@
+import FollowMasterClient from "../../../src/content/client/FollowMasterClient";
+import Key from "../../../src/shared/settings/Key";
+
+export default class MockFollowMasterClient implements FollowMasterClient {
+ responseHintCount(_count: number): void {
+ throw new Error("not implemented");
+ }
+
+ sendKey(_key: Key): void {
+ throw new Error("not implemented");
+ }
+
+ startFollow(_newTab: boolean, _background: boolean): void {
+ throw new Error("not implemented");
+ }
+}
diff --git a/test/content/mock/MockMarkKeyRepository.ts b/test/content/mock/MockMarkKeyRepository.ts
new file mode 100644
index 0000000..12bc75c
--- /dev/null
+++ b/test/content/mock/MockMarkKeyRepository.ts
@@ -0,0 +1,43 @@
+import MarkKeyRepository from "../../../src/content/repositories/MarkKeyRepository";
+
+export default class MockMarkKeyRepository implements MarkKeyRepository {
+ public jumpMode: boolean;
+ public setMode: boolean;
+
+ constructor(
+ initialValue: {
+ jumpMode: boolean;
+ setMode: boolean;
+ } = {
+ jumpMode: false,
+ setMode: false,
+ }
+ ) {
+ this.jumpMode = initialValue.jumpMode;
+ this.setMode = initialValue.setMode;
+ }
+
+ disabeJumpMode(): void {
+ this.jumpMode = false;
+ }
+
+ disabeSetMode(): void {
+ this.setMode = false;
+ }
+
+ enableJumpMode(): void {
+ this.jumpMode = true;
+ }
+
+ enableSetMode(): void {
+ this.setMode = true;
+ }
+
+ isJumpMode(): boolean {
+ return this.jumpMode;
+ }
+
+ isSetMode(): boolean {
+ return this.setMode;
+ }
+}
diff --git a/test/content/mock/MockOperationClient.ts b/test/content/mock/MockOperationClient.ts
new file mode 100644
index 0000000..2f50f77
--- /dev/null
+++ b/test/content/mock/MockOperationClient.ts
@@ -0,0 +1,16 @@
+import OperationClient from "../../../src/content/client/OperationClient";
+import * as operations from "../../../src/shared/operations";
+
+export default class MockOperationClient implements OperationClient {
+ execBackgroundOp(_repeat: number, _op: operations.Operation): Promise<void> {
+ throw new Error("not implemented");
+ }
+
+ internalOpenUrl(
+ _url: string,
+ _newTab?: boolean,
+ _background?: boolean
+ ): Promise<void> {
+ throw new Error("not implemented");
+ }
+}
diff --git a/test/content/mock/MockScrollPresenter.ts b/test/content/mock/MockScrollPresenter.ts
index c802227..8b4cf2a 100644
--- a/test/content/mock/MockScrollPresenter.ts
+++ b/test/content/mock/MockScrollPresenter.ts
@@ -3,10 +3,10 @@ import ScrollPresenter, {
} from "../../../src/content/presenters/ScrollPresenter";
export default class MockScrollPresenter implements ScrollPresenter {
- private pos: Point;
+ private readonly pos: Point;
- constructor() {
- this.pos = { x: 0, y: 0 };
+ constructor(initX = 0, initY = 0) {
+ this.pos = { x: initX, y: initY };
}
getScroll(): Point {
diff --git a/test/content/mock/MockSettingRepository.ts b/test/content/mock/MockSettingRepository.ts
new file mode 100644
index 0000000..5242713
--- /dev/null
+++ b/test/content/mock/MockSettingRepository.ts
@@ -0,0 +1,20 @@
+import SettingRepository from "../../../src/content/repositories/SettingRepository";
+import Settings, {
+ DefaultSetting,
+} from "../../../src/shared/settings/Settings";
+
+export default class MockSettingRepository implements SettingRepository {
+ private value: Settings;
+
+ constructor(initValue: Settings = DefaultSetting) {
+ this.value = initValue;
+ }
+
+ get(): Settings {
+ return this.value;
+ }
+
+ set(setting: Settings): void {
+ this.value = setting;
+ }
+}
diff --git a/test/content/mock/MockURLRepository.ts b/test/content/mock/MockURLRepository.ts
new file mode 100644
index 0000000..731a7fb
--- /dev/null
+++ b/test/content/mock/MockURLRepository.ts
@@ -0,0 +1,9 @@
+import URLRepository from "../../../src/content/operators/impls/URLRepository";
+
+export default class MockURLRepository implements URLRepository {
+ constructor(private url: string = "https://example.com/") {}
+
+ getCurrentURL(): string {
+ return this.url;
+ }
+}
diff --git a/test/content/operators/impls/AddonOperatorFactoryChain.test.ts b/test/content/operators/impls/AddonOperatorFactoryChain.test.ts
new file mode 100644
index 0000000..c064bb9
--- /dev/null
+++ b/test/content/operators/impls/AddonOperatorFactoryChain.test.ts
@@ -0,0 +1,29 @@
+import AddonOperatorFactoryChain from "../../../../src/content/operators/impls/AddonOperatorFactoryChain";
+import EnableAddonOperator from "../../../../src/content/operators/impls/EnableAddonOperator";
+import DisableAddonOperator from "../../../../src/content/operators/impls/DisableAddonOperator";
+import ToggleAddonOperator from "../../../../src/content/operators/impls/ToggleAddonOperator";
+import * as operations from "../../../../src/shared/operations";
+import { expect } from "chai";
+import MockAddonIndicatorClient from "../../mock/MockAddonIndicatorClient";
+import MockAddonEnabledRepository from "../../mock/MockAddonEnabledRepository";
+
+describe("AddonOperatorFactoryChain", () => {
+ describe("#create", () => {
+ it("returns an operator", () => {
+ const sut = new AddonOperatorFactoryChain(
+ new MockAddonIndicatorClient(),
+ new MockAddonEnabledRepository()
+ );
+ expect(sut.create({ type: operations.ADDON_ENABLE }, 0)).to.be.instanceOf(
+ EnableAddonOperator
+ );
+ expect(
+ sut.create({ type: operations.ADDON_DISABLE }, 0)
+ ).to.be.instanceOf(DisableAddonOperator);
+ expect(
+ sut.create({ type: operations.ADDON_TOGGLE_ENABLED }, 0)
+ ).to.be.instanceOf(ToggleAddonOperator);
+ expect(sut.create({ type: operations.SCROLL_TOP }, 0)).to.be.null;
+ });
+ });
+});
diff --git a/test/content/operators/impls/BackgroundOperationOperator.test.ts b/test/content/operators/impls/BackgroundOperationOperator.test.ts
new file mode 100644
index 0000000..b8b1fbd
--- /dev/null
+++ b/test/content/operators/impls/BackgroundOperationOperator.test.ts
@@ -0,0 +1,38 @@
+import * as operations from "../../../../src/shared/operations";
+import BackgroundOperationOperator from "../../../../src/content/operators/impls/BackgroundOperationOperator";
+import OperationClient from "../../../../src/content/client/OperationClient";
+import { expect } from "chai";
+
+class MockOperationClient implements OperationClient {
+ public readonly executedOps: {
+ op: operations.Operation;
+ repeat: number;
+ }[] = [];
+ async execBackgroundOp(
+ repeat: number,
+ op: operations.Operation
+ ): Promise<void> {
+ this.executedOps.push({ repeat, op });
+ }
+
+ internalOpenUrl(): Promise<void> {
+ throw new Error("not implemented");
+ }
+}
+
+describe("BackgroundOperationOperator", () => {
+ describe("#run", () => {
+ it("returns an operator", async () => {
+ const client = new MockOperationClient();
+ const sut = new BackgroundOperationOperator(client, 2, {
+ type: operations.TAB_CLOSE,
+ });
+
+ await sut.run();
+
+ expect(client.executedOps).to.deep.equal([
+ { op: { type: operations.TAB_CLOSE }, repeat: 2 },
+ ]);
+ });
+ });
+});
diff --git a/test/content/operators/impls/ClipboardOperatorFactoryChain.test.ts b/test/content/operators/impls/ClipboardOperatorFactoryChain.test.ts
new file mode 100644
index 0000000..9ddc229
--- /dev/null
+++ b/test/content/operators/impls/ClipboardOperatorFactoryChain.test.ts
@@ -0,0 +1,31 @@
+import * as operations from "../../../../src/shared/operations";
+import { expect } from "chai";
+import ClipboardOperatorFactoryChain from "../../../../src/content/operators/impls/ClipboardOperatorFactoryChain";
+import YankURLOperator from "../../../../src/content/operators/impls/YankURLOperator";
+import PasteOperator from "../../../../src/content/operators/impls/PasteOperator";
+import MockClipboardRepository from "../../mock/MockClipboardRepository";
+import MockOperationClient from "../../mock/MockOperationClient";
+import MockSettingRepository from "../../mock/MockSettingRepository";
+import MockConsoleClient from "../../mock/MockConsoleClient";
+import MockURLRepository from "../../mock/MockURLRepository";
+
+describe("ClipboardOperatorFactoryChain", () => {
+ describe("#create", () => {
+ it("returns an operator", () => {
+ const sut = new ClipboardOperatorFactoryChain(
+ new MockClipboardRepository(),
+ new MockConsoleClient(),
+ new MockOperationClient(),
+ new MockSettingRepository(),
+ new MockURLRepository()
+ );
+ expect(sut.create({ type: operations.URLS_YANK }, 0)).to.be.instanceOf(
+ YankURLOperator
+ );
+ expect(
+ sut.create({ type: operations.URLS_PASTE, newTab: false }, 0)
+ ).to.be.instanceOf(PasteOperator);
+ expect(sut.create({ type: operations.SCROLL_TOP }, 0)).to.be.null;
+ });
+ });
+});
diff --git a/test/content/operators/impls/DisableAddonOperator.test.ts b/test/content/operators/impls/DisableAddonOperator.test.ts
new file mode 100644
index 0000000..358ae44
--- /dev/null
+++ b/test/content/operators/impls/DisableAddonOperator.test.ts
@@ -0,0 +1,19 @@
+import { expect } from "chai";
+import DisableAddonOperator from "../../../../src/content/operators/impls/DisableAddonOperator";
+import MockAddonIndicatorClient from "../../mock/MockAddonIndicatorClient";
+import MockAddonEnabledRepository from "../../mock/MockAddonEnabledRepository";
+
+describe("DisableAddonOperator", () => {
+ describe("#run", () => {
+ it("disables addon", async () => {
+ const client = new MockAddonIndicatorClient(true);
+ const repository = new MockAddonEnabledRepository(true);
+ const sut = new DisableAddonOperator(client, repository);
+
+ await sut.run();
+
+ expect(client.enabled).to.be.false;
+ expect(repository.enabled).to.be.false;
+ });
+ });
+});
diff --git a/test/content/operators/impls/EnableAddonOperator.test.ts b/test/content/operators/impls/EnableAddonOperator.test.ts
new file mode 100644
index 0000000..a6ca31b
--- /dev/null
+++ b/test/content/operators/impls/EnableAddonOperator.test.ts
@@ -0,0 +1,19 @@
+import { expect } from "chai";
+import EnableAddonOperator from "../../../../src/content/operators/impls/EnableAddonOperator";
+import MockAddonIndicatorClient from "../../mock/MockAddonIndicatorClient";
+import MockAddonEnabledRepository from "../../mock/MockAddonEnabledRepository";
+
+describe("EnableAddonOperator", () => {
+ describe("#run", () => {
+ it("enabled addon", async () => {
+ const client = new MockAddonIndicatorClient(false);
+ const repository = new MockAddonEnabledRepository(false);
+ const sut = new EnableAddonOperator(client, repository);
+
+ await sut.run();
+
+ expect(client.enabled).to.be.true;
+ expect(repository.enabled).to.be.true;
+ });
+ });
+});
diff --git a/test/content/operators/impls/EnableJumpMarkOperator.test.ts b/test/content/operators/impls/EnableJumpMarkOperator.test.ts
new file mode 100644
index 0000000..66b4ecd
--- /dev/null
+++ b/test/content/operators/impls/EnableJumpMarkOperator.test.ts
@@ -0,0 +1,19 @@
+import { expect } from "chai";
+import EnableJumpMarkOperator from "../../../../src/content/operators/impls/EnableJumpMarkOperator";
+import MockMarkKeyRepository from "../../mock/MockMarkKeyRepository";
+
+describe("EnableJumpMarkOperator", () => {
+ describe("#run", () => {
+ it("starts mark jump mode", async () => {
+ const repository = new MockMarkKeyRepository({
+ jumpMode: false,
+ setMode: false,
+ });
+ const sut = new EnableJumpMarkOperator(repository);
+
+ await sut.run();
+
+ expect(repository.jumpMode).to.be.true;
+ });
+ });
+});
diff --git a/test/content/operators/impls/EnableSetMarkOperator.test.ts b/test/content/operators/impls/EnableSetMarkOperator.test.ts
new file mode 100644
index 0000000..b28874d
--- /dev/null
+++ b/test/content/operators/impls/EnableSetMarkOperator.test.ts
@@ -0,0 +1,19 @@
+import { expect } from "chai";
+import EnableSetMarkOperator from "../../../../src/content/operators/impls/EnableSetMarkOperator";
+import MockMarkKeyRepository from "../../mock/MockMarkKeyRepository";
+
+describe("EnableSetMarkOperator", () => {
+ describe("#run", () => {
+ it("starts mark set mode", async () => {
+ const repository = new MockMarkKeyRepository({
+ jumpMode: false,
+ setMode: false,
+ });
+ const sut = new EnableSetMarkOperator(repository);
+
+ await sut.run();
+
+ expect(repository.setMode).to.be.true;
+ });
+ });
+});
diff --git a/test/content/operators/impls/FindNextOperator.test.ts b/test/content/operators/impls/FindNextOperator.test.ts
new file mode 100644
index 0000000..d93d45e
--- /dev/null
+++ b/test/content/operators/impls/FindNextOperator.test.ts
@@ -0,0 +1,17 @@
+import sinon from "sinon";
+import FindNextOperator from "../../../../src/content/operators/impls/FindNextOperator";
+import MockFindMasterClient from "../../mock/MockFindMasterClient";
+
+describe("FindNextOperator", () => {
+ describe("#run", () => {
+ it("find next keyword", async () => {
+ const client = new MockFindMasterClient();
+ const mock = sinon.mock(client).expects("findNext").exactly(3);
+ const sut = new FindNextOperator(client, 3);
+
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/content/operators/impls/FindOperatorFactoryChain.test.ts b/test/content/operators/impls/FindOperatorFactoryChain.test.ts
new file mode 100644
index 0000000..6c599ae
--- /dev/null
+++ b/test/content/operators/impls/FindOperatorFactoryChain.test.ts
@@ -0,0 +1,21 @@
+import * as operations from "../../../../src/shared/operations";
+import { expect } from "chai";
+import FindOperatorFactoryChain from "../../../../src/content/operators/impls/FindOperatorFactoryChain";
+import MockFindMasterClient from "../../mock/MockFindMasterClient";
+import FindNextOperator from "../../../../src/content/operators/impls/FindNextOperator";
+import FindPrevOperator from "../../../../src/content/operators/impls/FindPrevOperator";
+
+describe("FindOperatorFactoryChain", () => {
+ describe("#create", () => {
+ it("returns an operator", () => {
+ const sut = new FindOperatorFactoryChain(new MockFindMasterClient());
+ expect(sut.create({ type: operations.FIND_NEXT }, 0)).to.be.instanceOf(
+ FindNextOperator
+ );
+ expect(sut.create({ type: operations.FIND_PREV }, 0)).to.be.instanceOf(
+ FindPrevOperator
+ );
+ expect(sut.create({ type: operations.SCROLL_TOP }, 0)).to.be.null;
+ });
+ });
+});
diff --git a/test/content/operators/impls/FindPrevOperator.test.ts b/test/content/operators/impls/FindPrevOperator.test.ts
new file mode 100644
index 0000000..1ebde8d
--- /dev/null
+++ b/test/content/operators/impls/FindPrevOperator.test.ts
@@ -0,0 +1,17 @@
+import sinon from "sinon";
+import FindPrevOperator from "../../../../src/content/operators/impls/FindPrevOperator";
+import MockFindMasterClient from "../../mock/MockFindMasterClient";
+
+describe("FindPrevOperator", () => {
+ describe("#run", () => {
+ it("find previous keyword", async () => {
+ const client = new MockFindMasterClient();
+ const mock = sinon.mock(client).expects("findPrev").exactly(3);
+ const sut = new FindPrevOperator(client, 3);
+
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/content/operators/impls/FocusOperator.test.ts b/test/content/operators/impls/FocusOperator.test.ts
new file mode 100644
index 0000000..a0eb53b
--- /dev/null
+++ b/test/content/operators/impls/FocusOperator.test.ts
@@ -0,0 +1,17 @@
+import sinon from "sinon";
+import FocusOperator from "../../../../src/content/operators/impls/FocusOperator";
+import MockFocusPresenter from "../../mock/MockFocusPresenter";
+
+describe("FocusOperator", () => {
+ describe("#run", () => {
+ it("focus a first input", async () => {
+ const presenter = new MockFocusPresenter();
+ const mock = sinon.mock(presenter).expects("focusFirstElement");
+ const sut = new FocusOperator(presenter);
+
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/content/operators/impls/FocusOperatorFactoryChain.test.ts b/test/content/operators/impls/FocusOperatorFactoryChain.test.ts
new file mode 100644
index 0000000..91f734b
--- /dev/null
+++ b/test/content/operators/impls/FocusOperatorFactoryChain.test.ts
@@ -0,0 +1,17 @@
+import * as operations from "../../../../src/shared/operations";
+import { expect } from "chai";
+import FocusOperatorFactoryChain from "../../../../src/content/operators/impls/FocusOperatorFactoryChain";
+import FocusOperator from "../../../../src/content/operators/impls/FocusOperator";
+import MockFocusPresenter from "../../mock/MockFocusPresenter";
+
+describe("FocusOperatorFactoryChain", () => {
+ describe("#create", () => {
+ it("returns an operator", () => {
+ const sut = new FocusOperatorFactoryChain(new MockFocusPresenter());
+ expect(sut.create({ type: operations.FOCUS_INPUT }, 0)).to.be.instanceOf(
+ FocusOperator
+ );
+ expect(sut.create({ type: operations.SCROLL_TOP }, 0)).to.be.null;
+ });
+ });
+});
diff --git a/test/content/operators/impls/FollowOperatorFactoryChain.test.ts b/test/content/operators/impls/FollowOperatorFactoryChain.test.ts
new file mode 100644
index 0000000..526a93c
--- /dev/null
+++ b/test/content/operators/impls/FollowOperatorFactoryChain.test.ts
@@ -0,0 +1,20 @@
+import * as operations from "../../../../src/shared/operations";
+import { expect } from "chai";
+import FocusOperatorFactoryChain from "../../../../src/content/operators/impls/FocusOperatorFactoryChain";
+import FocusOperator from "../../../../src/content/operators/impls/FocusOperator";
+import MockFocusPresenter from "../../mock/MockFocusPresenter";
+
+describe("FocusOperatorFactoryChain", () => {
+ describe("#create", () => {
+ it("returns an operator", () => {
+ const sut = new FocusOperatorFactoryChain(new MockFocusPresenter());
+ expect(
+ sut.create(
+ { type: operations.FOCUS_INPUT, newTab: false, background: false },
+ 0
+ )
+ ).to.be.instanceOf(FocusOperator);
+ expect(sut.create({ type: operations.SCROLL_TOP }, 0)).to.be.null;
+ });
+ });
+});
diff --git a/test/content/operators/impls/HorizontalScrollOperator.test.ts b/test/content/operators/impls/HorizontalScrollOperator.test.ts
new file mode 100644
index 0000000..f77a34e
--- /dev/null
+++ b/test/content/operators/impls/HorizontalScrollOperator.test.ts
@@ -0,0 +1,28 @@
+import { expect } from "chai";
+import HorizontalScrollOperator from "../../../../src/content/operators/impls/HorizontalScrollOperator";
+import MockScrollPresenter from "../../mock/MockScrollPresenter";
+import MockSettingRepository from "../../mock/MockSettingRepository";
+
+describe("HorizontalScrollOperator", () => {
+ describe("#run", () => {
+ it("scroll horizontally", async () => {
+ const presenter = new MockScrollPresenter();
+ const settingRepository = new MockSettingRepository();
+ const sut = new HorizontalScrollOperator(presenter, settingRepository, 1);
+
+ await sut.run();
+
+ expect(presenter.getScroll()).to.deep.equal({ x: 1, y: 0 });
+ });
+
+ it("scroll horizontally with repeats", async () => {
+ const presenter = new MockScrollPresenter();
+ const settingRepository = new MockSettingRepository();
+ const sut = new HorizontalScrollOperator(presenter, settingRepository, 5);
+
+ await sut.run();
+
+ expect(presenter.getScroll()).to.deep.equal({ x: 5, y: 0 });
+ });
+ });
+});
diff --git a/test/content/operators/impls/MarkOperatorFactoryChain.test.ts b/test/content/operators/impls/MarkOperatorFactoryChain.test.ts
new file mode 100644
index 0000000..1f094dd
--- /dev/null
+++ b/test/content/operators/impls/MarkOperatorFactoryChain.test.ts
@@ -0,0 +1,21 @@
+import * as operations from "../../../../src/shared/operations";
+import { expect } from "chai";
+import MarkOperatorFactoryChain from "../../../../src/content/operators/impls/MarkOperatorFactoryChain";
+import MockMarkKeyRepository from "../../mock/MockMarkKeyRepository";
+import EnableSetMarkOperator from "../../../../src/content/operators/impls/EnableSetMarkOperator";
+import EnableJumpMarkOperator from "../../../../src/content/operators/impls/EnableJumpMarkOperator";
+
+describe("MarkOperatorFactoryChain", () => {
+ describe("#create", () => {
+ it("returns an operator", () => {
+ const sut = new MarkOperatorFactoryChain(new MockMarkKeyRepository());
+ expect(
+ sut.create({ type: operations.MARK_SET_PREFIX }, 0)
+ ).to.be.instanceOf(EnableSetMarkOperator);
+ expect(
+ sut.create({ type: operations.MARK_JUMP_PREFIX }, 0)
+ ).to.be.instanceOf(EnableJumpMarkOperator);
+ expect(sut.create({ type: operations.SCROLL_TOP }, 0)).to.be.null;
+ });
+ });
+});
diff --git a/test/content/operators/impls/PageScrollOperator.test.ts b/test/content/operators/impls/PageScrollOperator.test.ts
new file mode 100644
index 0000000..80c9185
--- /dev/null
+++ b/test/content/operators/impls/PageScrollOperator.test.ts
@@ -0,0 +1,28 @@
+import { expect } from "chai";
+import PageScrollOperator from "../../../../src/content/operators/impls/PageScrollOperator";
+import MockScrollPresenter from "../../mock/MockScrollPresenter";
+import MockSettingRepository from "../../mock/MockSettingRepository";
+
+describe("PageScrollOperator", () => {
+ describe("#run", () => {
+ it("scroll by a page", async () => {
+ const presenter = new MockScrollPresenter();
+ const settingRepository = new MockSettingRepository();
+ const sut = new PageScrollOperator(presenter, settingRepository, 1);
+
+ await sut.run();
+
+ expect(presenter.getScroll()).to.deep.equal({ x: 1, y: 0 });
+ });
+
+ it("scroll by a page with repeats", async () => {
+ const presenter = new MockScrollPresenter();
+ const settingRepository = new MockSettingRepository();
+ const sut = new PageScrollOperator(presenter, settingRepository, 5);
+
+ await sut.run();
+
+ expect(presenter.getScroll()).to.deep.equal({ x: 5, y: 0 });
+ });
+ });
+});
diff --git a/test/content/operators/impls/PasteOperator.test.ts b/test/content/operators/impls/PasteOperator.test.ts
new file mode 100644
index 0000000..8a3a374
--- /dev/null
+++ b/test/content/operators/impls/PasteOperator.test.ts
@@ -0,0 +1,51 @@
+import sinon from "sinon";
+import PasteOperator from "../../../../src/content/operators/impls/PasteOperator";
+import MockClipboardRepository from "../../mock/MockClipboardRepository";
+import MockSettingRepository from "../../mock/MockSettingRepository";
+import MockOperationClient from "../../mock/MockOperationClient";
+
+describe("PasteOperator", () => {
+ describe("#run", () => {
+ it("open a search url", async () => {
+ const clipboardRepository = new MockClipboardRepository("apple");
+ const settingRepository = new MockSettingRepository();
+ const operationClient = new MockOperationClient();
+ const mockOperationClient = sinon
+ .mock(operationClient)
+ .expects("internalOpenUrl")
+ .withArgs("https://google.com/search?q=apple");
+ const sut = new PasteOperator(
+ clipboardRepository,
+ settingRepository,
+ operationClient,
+ false
+ );
+
+ await sut.run();
+
+ mockOperationClient.verify();
+ });
+
+ it("open a url", async () => {
+ const clipboardRepository = new MockClipboardRepository(
+ "https://example.com/"
+ );
+ const settingRepository = new MockSettingRepository();
+ const operationClient = new MockOperationClient();
+ const mockOperationClient = sinon
+ .mock(operationClient)
+ .expects("internalOpenUrl")
+ .withArgs("https://example.com/");
+ const sut = new PasteOperator(
+ clipboardRepository,
+ settingRepository,
+ operationClient,
+ false
+ );
+
+ await sut.run();
+
+ mockOperationClient.verify();
+ });
+ });
+});
diff --git a/test/content/operators/impls/ScrollOperatorFactoryChain.test.ts b/test/content/operators/impls/ScrollOperatorFactoryChain.test.ts
new file mode 100644
index 0000000..08034cb
--- /dev/null
+++ b/test/content/operators/impls/ScrollOperatorFactoryChain.test.ts
@@ -0,0 +1,46 @@
+import { expect } from "chai";
+import ScrollOperatorFactoryChain from "../../../../src/content/operators/impls/ScrollOperatorFactoryChain";
+import MockScrollPresenter from "../../mock/MockScrollPresenter";
+import MockSettingRepository from "../../mock/MockSettingRepository";
+import HorizontalScrollOperator from "../../../../src/content/operators/impls/HorizontalScrollOperator";
+import VerticalScrollOperator from "../../../../src/content/operators/impls/VerticalScrollOperator";
+import PageScrollOperator from "../../../../src/content/operators/impls/PageScrollOperator";
+import ScrollToTopOperator from "../../../../src/content/operators/impls/ScrollToTopOperator";
+import ScrollToBottomOperator from "../../../../src/content/operators/impls/ScrollToBottomOperator";
+import ScrollToHomeOperator from "../../../../src/content/operators/impls/ScrollToHomeOperator";
+import ScrollToEndOperator from "../../../../src/content/operators/impls/ScrollToEndOperator";
+import * as operations from "../../../../src/shared/operations";
+
+describe("ScrollOperatorFactoryChain", () => {
+ describe("#create", () => {
+ it("returns an operator", () => {
+ const sut = new ScrollOperatorFactoryChain(
+ new MockScrollPresenter(),
+ new MockSettingRepository()
+ );
+ expect(
+ sut.create({ type: operations.SCROLL_HORIZONALLY, count: 10 }, 0)
+ ).to.be.instanceOf(HorizontalScrollOperator);
+ expect(
+ sut.create({ type: operations.SCROLL_VERTICALLY, count: 10 }, 0)
+ ).to.be.instanceOf(VerticalScrollOperator);
+ expect(
+ sut.create({ type: operations.SCROLL_PAGES, count: 10 }, 0)
+ ).to.be.instanceOf(PageScrollOperator);
+ expect(sut.create({ type: operations.SCROLL_TOP }, 0)).to.be.instanceOf(
+ ScrollToTopOperator
+ );
+ expect(
+ sut.create({ type: operations.SCROLL_BOTTOM }, 0)
+ ).to.be.instanceOf(ScrollToBottomOperator);
+ expect(sut.create({ type: operations.SCROLL_HOME }, 0)).to.be.instanceOf(
+ ScrollToHomeOperator
+ );
+ expect(sut.create({ type: operations.SCROLL_END }, 0)).to.be.instanceOf(
+ ScrollToEndOperator
+ );
+ expect(sut.create({ type: operations.PAGE_HOME, newTab: false }, 0)).to.be
+ .null;
+ });
+ });
+});
diff --git a/test/content/operators/impls/ScrollToBottomOperator.test.ts b/test/content/operators/impls/ScrollToBottomOperator.test.ts
new file mode 100644
index 0000000..500c8f2
--- /dev/null
+++ b/test/content/operators/impls/ScrollToBottomOperator.test.ts
@@ -0,0 +1,18 @@
+import { expect } from "chai";
+import ScrollToBottomOperator from "../../../../src/content/operators/impls/ScrollToBottomOperator";
+import MockScrollPresenter from "../../mock/MockScrollPresenter";
+import MockSettingRepository from "../../mock/MockSettingRepository";
+
+describe("ScrollToBottomOperator", () => {
+ describe("#run", () => {
+ it("scroll to bottom", async () => {
+ const presenter = new MockScrollPresenter();
+ const settingRepository = new MockSettingRepository();
+ const sut = new ScrollToBottomOperator(presenter, settingRepository);
+
+ await sut.run();
+
+ expect(presenter.getScroll()).to.deep.equal({ x: 0, y: Infinity });
+ });
+ });
+});
diff --git a/test/content/operators/impls/ScrollToEndOperator.test.ts b/test/content/operators/impls/ScrollToEndOperator.test.ts
new file mode 100644
index 0000000..0c98c8d
--- /dev/null
+++ b/test/content/operators/impls/ScrollToEndOperator.test.ts
@@ -0,0 +1,18 @@
+import { expect } from "chai";
+import ScrollToEndOperator from "../../../../src/content/operators/impls/ScrollToEndOperator";
+import MockScrollPresenter from "../../mock/MockScrollPresenter";
+import MockSettingRepository from "../../mock/MockSettingRepository";
+
+describe("ScrollToEndOperator", () => {
+ describe("#run", () => {
+ it("scroll to rightmost", async () => {
+ const presenter = new MockScrollPresenter();
+ const settingRepository = new MockSettingRepository();
+ const sut = new ScrollToEndOperator(presenter, settingRepository);
+
+ await sut.run();
+
+ expect(presenter.getScroll()).to.deep.equal({ x: Infinity, y: 0 });
+ });
+ });
+});
diff --git a/test/content/operators/impls/ScrollToHomeOperator.test.ts b/test/content/operators/impls/ScrollToHomeOperator.test.ts
new file mode 100644
index 0000000..f8614d2
--- /dev/null
+++ b/test/content/operators/impls/ScrollToHomeOperator.test.ts
@@ -0,0 +1,18 @@
+import { expect } from "chai";
+import ScrollToHomeOperator from "../../../../src/content/operators/impls/ScrollToHomeOperator";
+import MockScrollPresenter from "../../mock/MockScrollPresenter";
+import MockSettingRepository from "../../mock/MockSettingRepository";
+
+describe("ScrollToHomeOperator", () => {
+ describe("#run", () => {
+ it("scroll to leftmost", async () => {
+ const presenter = new MockScrollPresenter(10, 10);
+ const settingRepository = new MockSettingRepository();
+ const sut = new ScrollToHomeOperator(presenter, settingRepository);
+
+ await sut.run();
+
+ expect(presenter.getScroll()).to.deep.equal({ x: 0, y: 10 });
+ });
+ });
+});
diff --git a/test/content/operators/impls/ScrollToTopOperator.test.ts b/test/content/operators/impls/ScrollToTopOperator.test.ts
new file mode 100644
index 0000000..25a84ba
--- /dev/null
+++ b/test/content/operators/impls/ScrollToTopOperator.test.ts
@@ -0,0 +1,18 @@
+import { expect } from "chai";
+import ScrollToTopOperator from "../../../../src/content/operators/impls/ScrollToTopOperator";
+import MockScrollPresenter from "../../mock/MockScrollPresenter";
+import MockSettingRepository from "../../mock/MockSettingRepository";
+
+describe("ScrollToTopOperator", () => {
+ describe("#run", () => {
+ it("scroll to top", async () => {
+ const presenter = new MockScrollPresenter(10, 10);
+ const settingRepository = new MockSettingRepository();
+ const sut = new ScrollToTopOperator(presenter, settingRepository);
+
+ await sut.run();
+
+ expect(presenter.getScroll()).to.deep.equal({ x: 10, y: 0 });
+ });
+ });
+});
diff --git a/test/content/operators/impls/StartFollowOperator.test.ts b/test/content/operators/impls/StartFollowOperator.test.ts
new file mode 100644
index 0000000..8f9bd2d
--- /dev/null
+++ b/test/content/operators/impls/StartFollowOperator.test.ts
@@ -0,0 +1,20 @@
+import sinon from "sinon";
+import StartFollowOperator from "../../../../src/content/operators/impls/StartFollowOperator";
+import MockFollowMasterClient from "../../mock/MockFollowMasterClient";
+
+describe("StartFollowOperator", () => {
+ describe("#run", () => {
+ it("starts following links", async () => {
+ const client = new MockFollowMasterClient();
+ const mock = sinon
+ .mock(client)
+ .expects("startFollow")
+ .withArgs(true, false);
+ const sut = new StartFollowOperator(client, true, false);
+
+ await sut.run();
+
+ mock.verify();
+ });
+ });
+});
diff --git a/test/content/operators/impls/ToggleAddonOperator.test.ts b/test/content/operators/impls/ToggleAddonOperator.test.ts
new file mode 100644
index 0000000..6026eb1
--- /dev/null
+++ b/test/content/operators/impls/ToggleAddonOperator.test.ts
@@ -0,0 +1,24 @@
+import { expect } from "chai";
+import ToggleAddonOperator from "../../../../src/content/operators/impls/ToggleAddonOperator";
+import MockAddonIndicatorClient from "../../mock/MockAddonIndicatorClient";
+import MockAddonEnabledRepository from "../../mock/MockAddonEnabledRepository";
+
+describe("ToggleAddonOperator", () => {
+ describe("#run", () => {
+ it("toggles addon-enabled state", async () => {
+ const client = new MockAddonIndicatorClient(true);
+ const repository = new MockAddonEnabledRepository(true);
+ const sut = new ToggleAddonOperator(client, repository);
+
+ await sut.run();
+
+ expect(client.enabled).to.be.false;
+ expect(repository.enabled).to.be.false;
+
+ await sut.run();
+
+ expect(client.enabled).to.be.true;
+ expect(repository.enabled).to.be.true;
+ });
+ });
+});
diff --git a/test/content/operators/impls/VerticalScrollOperator.test.ts b/test/content/operators/impls/VerticalScrollOperator.test.ts
new file mode 100644
index 0000000..05b15d2
--- /dev/null
+++ b/test/content/operators/impls/VerticalScrollOperator.test.ts
@@ -0,0 +1,28 @@
+import { expect } from "chai";
+import VerticalScrollOperator from "../../../../src/content/operators/impls/VerticalScrollOperator";
+import MockScrollPresenter from "../../mock/MockScrollPresenter";
+import MockSettingRepository from "../../mock/MockSettingRepository";
+
+describe("VerticalScrollOperator", () => {
+ describe("#run", () => {
+ it("scroll vertically", async () => {
+ const presenter = new MockScrollPresenter();
+ const settingRepository = new MockSettingRepository();
+ const sut = new VerticalScrollOperator(presenter, settingRepository, 1);
+
+ await sut.run();
+
+ expect(presenter.getScroll()).to.deep.equal({ x: 0, y: 1 });
+ });
+
+ it("scroll vertically with repeats", async () => {
+ const presenter = new MockScrollPresenter();
+ const settingRepository = new MockSettingRepository();
+ const sut = new VerticalScrollOperator(presenter, settingRepository, 5);
+
+ await sut.run();
+
+ expect(presenter.getScroll()).to.deep.equal({ x: 0, y: 5 });
+ });
+ });
+});
diff --git a/test/content/operators/impls/YankURLOperator.test.ts b/test/content/operators/impls/YankURLOperator.test.ts
new file mode 100644
index 0000000..46e3d06
--- /dev/null
+++ b/test/content/operators/impls/YankURLOperator.test.ts
@@ -0,0 +1,26 @@
+import { expect } from "chai";
+import MockClipboardRepository from "../../mock/MockClipboardRepository";
+import YankURLOperator from "../../../../src/content/operators/impls/YankURLOperator";
+import MockURLRepository from "../../mock/MockURLRepository";
+import MockConsoleClient from "../../mock/MockConsoleClient";
+
+describe("YankOperation", () => {
+ describe("#run", () => {
+ it("copy current URL", async () => {
+ const clipboardRepository = new MockClipboardRepository();
+ const consoleClient = new MockConsoleClient();
+ const urlRepository = new MockURLRepository("https://example.com/");
+ const sut = new YankURLOperator(
+ clipboardRepository,
+ consoleClient,
+ urlRepository
+ );
+
+ await sut.run();
+
+ expect(clipboardRepository.read()).to.equal("https://example.com/");
+ expect(consoleClient.text).to.equal("Yanked https://example.com/");
+ expect(consoleClient.isError).to.be.false;
+ });
+ });
+});
diff --git a/test/content/presenters/NavigationPresenter.test.ts b/test/content/presenters/NavigationPresenter.test.ts
index af3b487..8d003c4 100644
--- a/test/content/presenters/NavigationPresenter.test.ts
+++ b/test/content/presenters/NavigationPresenter.test.ts
@@ -1,7 +1,9 @@
import { NavigationPresenterImpl } from "../../../src/content/presenters/NavigationPresenter";
import { expect } from "chai";
-describe("NavigationPresenterImpl", () => {
+describe("NavigationPresenterImpl", function () {
+ this.timeout(5000);
+
let sut: NavigationPresenterImpl;
const testRel = (done: () => void, rel: string, html: string) => {
diff --git a/test/content/usecases/ClipboardUseCase.test.ts b/test/content/usecases/ClipboardUseCase.test.ts
deleted file mode 100644
index 5de3e69..0000000
--- a/test/content/usecases/ClipboardUseCase.test.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import ClipboardRepository from "../../../src/content/repositories/ClipboardRepository";
-import { SettingRepositoryImpl } from "../../../src/content/repositories/SettingRepository";
-import ClipboardUseCase from "../../../src/content/usecases/ClipboardUseCase";
-import OperationClient from "../../../src/content/client/OperationClient";
-import ConsoleClient from "../../../src/content/client/ConsoleClient";
-
-import * as sinon from "sinon";
-import { expect } from "chai";
-import { Operation } from "../../../src/shared/operations";
-
-describe("ClipboardUseCase", () => {
- let clipboardRepository: ClipboardRepository;
-
- let operationClient: OperationClient;
-
- let consoleClient: ConsoleClient;
-
- let sut: ClipboardUseCase;
-
- beforeEach(() => {
- clipboardRepository = new (class implements ClipboardRepository {
- read(): string {
- return "";
- }
- write(_text: string) {}
- })();
- operationClient = new (class implements OperationClient {
- execBackgroundOp(_repeat: number, _op: Operation): Promise<void> {
- return Promise.resolve();
- }
- internalOpenUrl(
- _url: string,
- _newTab?: boolean,
- _background?: boolean
- ): Promise<void> {
- return Promise.resolve();
- }
- })();
- consoleClient = new (class implements ConsoleClient {
- error(_text: string): Promise<void> {
- return Promise.resolve();
- }
- info(_text: string): Promise<void> {
- return Promise.resolve();
- }
- })();
-
- sut = new ClipboardUseCase(
- clipboardRepository,
- new SettingRepositoryImpl(),
- consoleClient,
- operationClient
- );
- });
-
- describe("#yankCurrentURL", () => {
- it("yanks current url", async () => {
- const href = window.location.href;
- const mockRepository = sinon.mock(clipboardRepository);
- mockRepository.expects("write").withArgs(href);
- const mockConsoleClient = sinon.mock(consoleClient);
- mockConsoleClient.expects("info").withArgs("Yanked " + href);
-
- const yanked = await sut.yankCurrentURL();
-
- expect(yanked).to.equal(href);
- mockRepository.verify();
- mockConsoleClient.verify();
- });
- });
-
- describe("#openOrSearch", () => {
- it("opens url from the clipboard", async () => {
- const url = "https://github.com/ueokande/vim-vixen";
- sinon.stub(clipboardRepository, "read").returns(url);
- const mockOperationClient = sinon.mock(operationClient);
- mockOperationClient.expects("internalOpenUrl").withArgs(url, true);
-
- await sut.openOrSearch(true);
-
- mockOperationClient.verify();
- });
-
- it("opens search results from the clipboard", async () => {
- const url = "https://google.com/search?q=banana";
- sinon.stub(clipboardRepository, "read").returns("banana");
- const mockOperationClient = sinon.mock(operationClient);
- mockOperationClient.expects("internalOpenUrl").withArgs(url, true);
-
- await sut.openOrSearch(true);
-
- mockOperationClient.verify();
- });
- });
-});
diff --git a/test/content/usecases/HintKeyProducer.test.ts b/test/content/usecases/HintKeyProducer.test.ts
index f7e02ea..9d320b4 100644
--- a/test/content/usecases/HintKeyProducer.test.ts
+++ b/test/content/usecases/HintKeyProducer.test.ts
@@ -1,13 +1,7 @@
-import HintKeyProducer from "../../../src/content/usecases/HintKeyProducer";
+import { HintKeyRepositoryImpl } from "../../../src/content/repositories/HintKeyRepository";
import { expect } from "chai";
-describe("HintKeyProducer class", () => {
- describe("#constructor", () => {
- it("throws an exception on empty charset", () => {
- expect(() => new HintKeyProducer("")).to.throw(TypeError);
- });
- });
-
+describe("HintKeyProducerImpl class", () => {
describe("#produce", () => {
it("produce incremented keys", () => {
const charset = "abc";
@@ -30,10 +24,29 @@ describe("HintKeyProducer class", () => {
"aba",
];
- const producer = new HintKeyProducer(charset);
+ const sut = new HintKeyRepositoryImpl();
+ sut.reset(charset);
for (let i = 0; i < sequences.length; ++i) {
- expect(producer.produce()).to.equal(sequences[i]);
+ expect(sut.produce()).to.equal(sequences[i]);
}
});
});
+
+ describe("#reset", () => {
+ it("resets charset", () => {
+ const sut = new HintKeyRepositoryImpl();
+
+ sut.reset("ab");
+ expect(sut.produce()).to.equal("a");
+ expect(sut.produce()).to.equal("b");
+
+ sut.reset("xy");
+ expect(sut.produce()).to.equal("x");
+ expect(sut.produce()).to.equal("y");
+ });
+ it("throws an exception on empty charset", () => {
+ const sut = new HintKeyRepositoryImpl();
+ expect(() => sut.reset("")).to.throw(TypeError);
+ });
+ });
});
diff --git a/yarn.lock b/yarn.lock
index 5e55226..2b974f7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -74,10 +74,10 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.3.tgz#9e1eae46738bcd08e23e867bab43e7b95299a8f9"
integrity sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA==
-"@babel/runtime@^7.5.5":
- version "7.11.2"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
- integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==
+"@babel/runtime@^7.12.1":
+ version "7.12.5"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e"
+ integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==
dependencies:
regenerator-runtime "^0.13.4"
@@ -136,10 +136,10 @@
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed"
integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
-"@eslint/eslintrc@^0.1.3":
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.1.3.tgz#7d1a2b2358552cc04834c0979bd4275362e37085"
- integrity sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==
+"@eslint/eslintrc@^0.2.2":
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.2.tgz#d01fc791e2fc33e88a29d6f3dc7e93d0cd784b76"
+ integrity sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==
dependencies:
ajv "^6.12.4"
debug "^4.1.1"
@@ -152,7 +152,7 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
-"@sinonjs/commons@^1", "@sinonjs/commons@^1.3.0", "@sinonjs/commons@^1.4.0", "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.7.2":
+"@sinonjs/commons@^1", "@sinonjs/commons@^1.3.0", "@sinonjs/commons@^1.4.0", "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.1":
version "1.8.1"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217"
integrity sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==
@@ -191,10 +191,10 @@
array-from "^2.1.1"
lodash "^4.17.15"
-"@sinonjs/samsam@^5.0.2", "@sinonjs/samsam@^5.1.0":
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-5.1.0.tgz#3afe719232b541bb6cf3411a4c399a188de21ec0"
- integrity sha512-42nyaQOVunX5Pm6GRJobmzbS7iLI+fhERITnETXzzwDZh+TtDr/Au3yAvXVjFmZ4wEUaE4Y3NFZfKv0bV0cbtg==
+"@sinonjs/samsam@^5.0.2", "@sinonjs/samsam@^5.3.0":
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-5.3.0.tgz#1d2f0743dc54bf13fe9d508baefacdffa25d4329"
+ integrity sha512-hXpcfx3aq+ETVBwPlRFICld5EnrkexXuXDwqUNhDdr5L8VjvMeSRwyOa0qL7XFmR+jVWR4rUZtnxlG7RX72sBg==
dependencies:
"@sinonjs/commons" "^1.6.0"
lodash.get "^4.4.2"
@@ -211,9 +211,9 @@
integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==
"@types/assert@^1.4.6":
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/@types/assert/-/assert-1.5.1.tgz#9c4b57935d446ffcfb31d583799c47272161e270"
- integrity sha512-W34OXyUAXEg0IvkMBr6WHTsvxh4veqNVJJGni/6pp13BabT/nuiEtUVkf+EYo8FIT4CQSVYfZ05XtUo5nRSWfQ==
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/@types/assert/-/assert-1.5.2.tgz#dbc440f6bd7a83b03c37c65e81076d07cf8becdc"
+ integrity sha512-DLsoZH9z5DLDi6qMbXKqeqlQLK1h3rfR9dK+KX8UJSGHJylvIZPOCQEKr/d/FClPoZE/eHOa3+e270eUJCUTog==
"@types/body-parser@*":
version "1.19.0"
@@ -224,9 +224,9 @@
"@types/node" "*"
"@types/chai@^4.2.8":
- version "4.2.12"
- resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.12.tgz#6160ae454cd89dae05adc3bb97997f488b608201"
- integrity sha512-aN5IAC8QNtSUdQzxu7lGBgYAOuU1tmRU4c9dIq5OKGf/SBVjXo+ffM2wEjudAWbgpOhy60nLoAGH1xm8fpCKFQ==
+ version "4.2.14"
+ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.14.tgz#44d2dd0b5de6185089375d976b4ec5caf6861193"
+ integrity sha512-G+ITQPXkwTrslfG5L/BksmbLUA0M1iybEsmCWPqzSxsRRhJZimBKJkoMi8fr/CPygPTj4zO5pJH7I2/cm9M7SQ==
"@types/color-name@^1.1.1":
version "1.1.1"
@@ -255,9 +255,9 @@
"@types/range-parser" "*"
"@types/express@^4.17.2":
- version "4.17.8"
- resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.8.tgz#3df4293293317e61c60137d273a2e96cd8d5f27a"
- integrity sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==
+ version "4.17.9"
+ resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.9.tgz#f5f2df6add703ff28428add52bdec8a1091b0a78"
+ integrity sha512-SDzEIZInC4sivGIFY4Sz1GG6J9UObPwCInYJjko2jzOf/Imx/dlpume6Xxwj1ORL82tBbmN4cPDIDkLbWHk9hw==
dependencies:
"@types/body-parser" "*"
"@types/express-serve-static-core" "*"
@@ -282,7 +282,7 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd"
integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==
-"@types/json-schema@^7.0.5":
+"@types/json-schema@^7.0.6":
version "7.0.6"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==
@@ -293,19 +293,14 @@
integrity sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==
"@types/mocha@^8.0.1":
- 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"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.27.tgz#a151873af5a5e851b51b3b065c9e63390a9e0eb1"
- integrity sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==
+ version "8.0.4"
+ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.0.4.tgz#b840c2dce46bacf286e237bfb59a29e843399148"
+ integrity sha512-M4BwiTJjHmLq6kjON7ZoI2JMlBvpY3BYSdiP6s/qCT3jb1s9/DeJF0JELpAxiVSIxXDzfNKe+r7yedMIoLbknQ==
-"@types/node@^12.12.21":
- version "12.12.54"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.54.tgz#a4b58d8df3a4677b6c08bfbc94b7ad7a7a5f82d1"
- integrity sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w==
+"@types/node@*", "@types/node@^14.14.13":
+ version "14.14.13"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.13.tgz#9e425079799322113ae8477297ae6ef51b8e0cdf"
+ integrity sha512-vbxr0VZ8exFMMAjCW8rJwaya0dMCDyYW2ZRdTyjtrCvJoENMpdUHOT/eTzvgyA5ZnqRZ/sI0NwqAxNHKYokLJQ==
"@types/prop-types@*", "@types/prop-types@^15.7.3":
version "15.7.3"
@@ -322,41 +317,34 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
-"@types/react-dom@^16.9.5":
- version "16.9.8"
- resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423"
- integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==
- dependencies:
- "@types/react" "*"
-
-"@types/react-native@*":
- version "0.63.8"
- resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.63.8.tgz#73ec087122c64c309eeaf150b565b8d755f0fb1f"
- integrity sha512-QRwGFRTyGafRVTUS+0GYyJrlpmS3boyBaFI0ULSc+mh/lQNxrzbdQvoL2k5X7+t9hxyqA4dTQAlP6l0ir/fNJQ==
+"@types/react-dom@^17.0.0":
+ version "17.0.0"
+ resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.0.tgz#b3b691eb956c4b3401777ee67b900cb28415d95a"
+ integrity sha512-lUqY7OlkF/RbNtD5nIq7ot8NquXrdFrjSOR6+w9a9RFQevGi1oZO1dcJbXMeONAPKtZ2UrZOEJ5UOCVsxbLk/g==
dependencies:
"@types/react" "*"
"@types/react-redux@^7.1.7":
- version "7.1.9"
- resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.9.tgz#280c13565c9f13ceb727ec21e767abe0e9b4aec3"
- integrity sha512-mpC0jqxhP4mhmOl3P4ipRsgTgbNofMRXJb08Ms6gekViLj61v1hOZEKWDCyWsdONr6EjEA6ZHXC446wdywDe0w==
+ version "7.1.13"
+ resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.13.tgz#8766a0078433621957cd78a6096d316bccbcb3ca"
+ integrity sha512-+Z8C22kL/fkEWFETc+duRyJT6P23G1GbowdLgRsjPyimJdpBv52Uqg4p3vCW6qagBj4EUi5jKhe+by+Uv3+QTQ==
dependencies:
"@types/hoist-non-react-statics" "^3.3.0"
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"
-"@types/react-test-renderer@^16.9.2":
- version "16.9.3"
- resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-16.9.3.tgz#96bab1860904366f4e848b739ba0e2f67bcae87e"
- integrity sha512-wJ7IlN5NI82XMLOyHSa+cNN4Z0I+8/YaLl04uDgcZ+W+ExWCmCiVTLT/7fRNqzy4OhStZcUwIqLNF7q+AdW43Q==
+"@types/react-test-renderer@^17.0.0":
+ version "17.0.0"
+ resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-17.0.0.tgz#9be47b375eeb906fced37049e67284a438d56620"
+ integrity sha512-nvw+F81OmyzpyIE1S0xWpLonLUZCMewslPuA8BtjSKc5XEbn8zEQBXS7KuOLHTNnSOEM2Pum50gHOoZ62tqTRg==
dependencies:
"@types/react" "*"
-"@types/react@*", "@types/react@^16.9.46":
- version "16.9.51"
- resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.51.tgz#f8aa51ffa9996f1387f63686696d9b59713d2b60"
- integrity sha512-lQa12IyO+DMlnSZ3+AGHRUiUcpK47aakMMoBG8f7HGxJT8Yfe+WE128HIXaHOHVPReAW0oDS3KAI0JI2DDe1PQ==
+"@types/react@*", "@types/react@^17.0.0":
+ version "17.0.0"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.0.tgz#5af3eb7fad2807092f0046a1302b7823e27919b8"
+ integrity sha512-aj/L7RIMsRlWML3YB6KZiXB3fV2t41+5RBGYF8z+tAKU43Px8C3cYUZsDvf1/+Bm4FK21QWBrDutu8ZJ/70qOw==
dependencies:
"@types/prop-types" "*"
csstype "^3.0.2"
@@ -382,9 +370,9 @@
"@types/mime" "*"
"@types/sinon@^9.0.0":
- version "9.0.7"
- resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-9.0.7.tgz#c277e19cf9eb0c71106e785650f1e5c299262302"
- integrity sha512-uyFiy2gp4P/FK9pmU3WIbT5ZzH54hCswwRkQFhxX7xl8jzhW3g+xOkVqk5YP4cIO//Few8UDAX0MtzFpqBEqwA==
+ version "9.0.9"
+ resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-9.0.9.tgz#115843b491583f924080f684b6d0d7438344f73c"
+ integrity sha512-z/y8maYOQyYLyqaOB+dYQ6i0pxKLOsfwCmHmn4T7jS/SDHicIslr37oE3Dg8SCqKrKeBy6Lemu7do2yy+unLrw==
dependencies:
"@types/sinonjs__fake-timers" "*"
@@ -399,13 +387,12 @@
integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==
"@types/styled-components@^5.1.2":
- version "5.1.3"
- resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.3.tgz#6fab3d9c8f7d9a15cbb89d379d850c985002f363"
- integrity sha512-HGpirof3WOhiX17lb61Q/tpgqn48jxO8EfZkdJ8ueYqwLbK2AHQe/G08DasdA2IdKnmwOIP1s9X2bopxKXgjRw==
+ version "5.1.7"
+ resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.7.tgz#3cd10b088c1cb1acde2e4b166b3e8275a3083710"
+ integrity sha512-BJzPhFygYspyefAGFZTZ/8lCEY4Tk+Iqktvnko3xmJf9LrLqs3+grxPeU3O0zLl6yjbYBopD0/VikbHgXDbJtA==
dependencies:
"@types/hoist-non-react-statics" "*"
"@types/react" "*"
- "@types/react-native" "*"
csstype "^3.0.2"
"@types/tapable@*", "@types/tapable@^1.0.5":
@@ -538,6 +525,11 @@
dependencies:
eslint-visitor-keys "^1.1.0"
+"@ungap/promise-all-settled@1.1.2":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
+ integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
+
"@webassemblyjs/ast@1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
@@ -683,6 +675,18 @@
"@webassemblyjs/wast-parser" "1.9.0"
"@xtuc/long" "4.2.2"
+"@webpack-cli/info@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.1.0.tgz#c596d5bc48418b39df00c5ed7341bf0f102dbff1"
+ integrity sha512-uNWSdaYHc+f3LdIZNwhdhkjjLDDl3jP2+XBqAq9H8DjrJUvlOKdP8TNruy1yEaDfgpAIgbSAN7pye4FEHg9tYQ==
+ dependencies:
+ envinfo "^7.7.3"
+
+"@webpack-cli/serve@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.1.0.tgz#13ad38f89b6e53d1133bac0006a128217a6ebf92"
+ integrity sha512-7RfnMXCpJ/NThrhq4gYQYILB18xWyoQcBey81oIyVbmgbc6m5ZHHyFK+DyH7pLHJf0p14MxL4mTsoPAgBSTpIg==
+
"@xtuc/ieee754@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
@@ -693,11 +697,6 @@
resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
-abbrev@1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
- integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
-
accepts@~1.3.4, accepts@~1.3.7:
version "1.3.7"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
@@ -711,6 +710,11 @@ acorn-jsx@^5.2.0:
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe"
integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==
+acorn-jsx@^5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
+ integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==
+
acorn@^6.4.1:
version "6.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
@@ -726,17 +730,16 @@ after@0.8.2:
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
-ajv-cli@^3.0.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/ajv-cli/-/ajv-cli-3.3.0.tgz#dd72207f5395051db7d620ab7d4da1cec3d50f06"
- integrity sha512-4eiNNjDlainn5Rm+rU3egxLUUxzevcB+gviBLs9sm6etHNrE7l2JSQ3yoz5hE+eqrth3pTygELOafhSIO8Hiig==
+ajv-cli@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/ajv-cli/-/ajv-cli-4.0.1.tgz#00543699942f8bec8b2e7aadc62909139c788cf8"
+ integrity sha512-vRV3Qrqq9yiKZbjX2uaqjykE2QI08/SlY/fPR7e6hloTTCOGXXcGXghLVgBkqeN7Ts/+Xfc21CjOX0p41Hskcw==
dependencies:
- ajv "^6.7.0"
- ajv-pack "^0.3.0"
+ ajv "^7.0.0"
fast-json-patch "^2.0.0"
glob "^7.1.0"
- js-yaml "^3.13.1"
- json-schema-migrate "^0.2.0"
+ js-yaml "^3.14.0"
+ json-schema-migrate "^1.0.0"
json5 "^2.1.3"
minimist "^1.2.0"
@@ -750,32 +753,24 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
-ajv-pack@^0.3.0:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/ajv-pack/-/ajv-pack-0.3.1.tgz#b72c4d4219e3928e62842d742ded93bf50796560"
- integrity sha1-tyxNQhnjko5ihC10Le2Tv1B5ZWA=
+ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.11.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
+ version "6.12.6"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
dependencies:
- js-beautify "^1.6.4"
- require-from-string "^1.2.0"
-
-ajv@^5.0.0:
- version "5.5.2"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
- integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=
- dependencies:
- co "^4.6.0"
- fast-deep-equal "^1.0.0"
+ fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
- json-schema-traverse "^0.3.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
-ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.11.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.7.0:
- version "6.12.5"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da"
- integrity sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==
+ajv@^7.0.0, ajv@^7.0.0-beta.9:
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.0.2.tgz#04ccc89a93449c64382fe0846d45a7135d986dbc"
+ integrity sha512-qIaxO9RXjaXyO21tJr0EvwPcZa49m64GcXCU8ZrLjCAlFyMuOcPpI560So4A11M1WsKslJYIXn6jSyG5P0xIeg==
dependencies:
fast-deep-equal "^3.1.1"
- fast-json-stable-stringify "^2.0.0"
- json-schema-traverse "^0.4.1"
+ json-schema-traverse "^1.0.0"
+ require-from-string "^2.0.2"
uri-js "^4.2.2"
ansi-colors@4.1.1, ansi-colors@^4.1.1:
@@ -788,13 +783,6 @@ ansi-colors@^3.0.0:
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
-ansi-escapes@^4.2.1:
- version "4.3.1"
- resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61"
- integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==
- dependencies:
- type-fest "^0.11.0"
-
ansi-regex@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
@@ -883,6 +871,11 @@ arr-union@^3.1.0:
resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
+array-back@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.1.tgz#9b80312935a52062e1a233a9c7abeb5481b30e90"
+ integrity sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==
+
array-flatten@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
@@ -916,16 +909,6 @@ array.prototype.flatmap@^1.2.3:
es-abstract "^1.17.0-next.1"
function-bind "^1.1.1"
-array.prototype.map@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/array.prototype.map/-/array.prototype.map-1.0.2.tgz#9a4159f416458a23e9483078de1106b2ef68f8ec"
- integrity sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==
- dependencies:
- define-properties "^1.1.3"
- es-abstract "^1.17.0-next.1"
- es-array-method-boxes-properly "^1.0.0"
- is-string "^1.0.4"
-
arraybuffer.slice@~0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
@@ -975,6 +958,11 @@ astral-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
+astral-regex@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
+ integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
+
async-each@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
@@ -1325,15 +1313,15 @@ camel-case@^4.1.1:
pascal-case "^3.1.1"
tslib "^1.10.0"
-camelcase@^5.0.0, camelcase@^5.3.1:
+camelcase@^5.0.0:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
-camelcase@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e"
- integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==
+camelcase@^6.0.0, camelcase@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809"
+ integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==
camelize@^1.0.0:
version "1.0.0"
@@ -1377,7 +1365,7 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.2:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
-chalk@^4.0.0, chalk@^4.1.0:
+chalk@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
@@ -1385,20 +1373,15 @@ chalk@^4.0.0, chalk@^4.1.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
-chardet@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
- integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
-
check-error@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=
-chokidar@3.4.2, chokidar@^3.4.1, chokidar@^3.4.2:
- version "3.4.2"
- resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d"
- integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==
+chokidar@3.4.3, chokidar@^3.4.1, chokidar@^3.4.2:
+ version "3.4.3"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b"
+ integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==
dependencies:
anymatch "~3.1.1"
braces "~3.0.2"
@@ -1406,7 +1389,7 @@ chokidar@3.4.2, chokidar@^3.4.1, chokidar@^3.4.2:
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
- readdirp "~3.4.0"
+ readdirp "~3.5.0"
optionalDependencies:
fsevents "~2.1.2"
@@ -1466,18 +1449,6 @@ clean-css@^4.2.3:
dependencies:
source-map "~0.6.0"
-cli-cursor@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
- integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
- dependencies:
- restore-cursor "^3.1.0"
-
-cli-width@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
- integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
-
cliui@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
@@ -1505,11 +1476,6 @@ clone-deep@^4.0.1:
kind-of "^6.0.2"
shallow-clone "^3.0.0"
-co@^4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
- integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
-
collection-visit@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
@@ -1542,6 +1508,11 @@ color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+colorette@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
+ integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
+
colors@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
@@ -1554,7 +1525,17 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
-commander@^2.19.0, commander@^2.20.0:
+command-line-usage@^6.1.0:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.1.tgz#c908e28686108917758a49f45efb4f02f76bc03f"
+ integrity sha512-F59pEuAR9o1SF/bD0dQBDluhpT4jJQNWUHEuVBqpDmCUo6gPjCi+m9fCWnWZVR/oG6cMTUms4h+3NPl74wGXvA==
+ dependencies:
+ array-back "^4.0.1"
+ chalk "^2.4.2"
+ table-layout "^1.0.1"
+ typical "^5.2.0"
+
+commander@^2.20.0:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
@@ -1564,6 +1545,11 @@ commander@^4.1.1:
resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
+commander@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75"
+ integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==
+
common-tags@^1.4.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937"
@@ -1609,14 +1595,6 @@ concat-stream@^1.5.0:
readable-stream "^2.2.2"
typedarray "^0.0.6"
-config-chain@^1.1.12:
- version "1.1.12"
- resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
- integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==
- dependencies:
- ini "^1.3.4"
- proto-list "~1.2.1"
-
connect@^3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8"
@@ -1717,18 +1695,12 @@ 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@^6.0.5:
- version "6.0.5"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
- integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
- dependencies:
- nice-try "^1.0.4"
- path-key "^2.0.1"
- semver "^5.5.0"
- shebang-command "^1.2.0"
- which "^1.2.9"
+create-require@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
+ integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
-cross-spawn@^7.0.2:
+cross-spawn@^7.0.0, cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -1759,22 +1731,22 @@ css-color-keywords@^1.0.0:
resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
integrity sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=
-css-loader@^4.2.1:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.3.0.tgz#c888af64b2a5b2e85462c72c0f4a85c7e2e0821e"
- integrity sha512-rdezjCjScIrsL8BSYszgT4s476IcNKt6yX69t0pHjJVnPUTDpn4WfIpDQTN3wCJvUvfsz/mFjuGOekf3PY3NUg==
+css-loader@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.0.1.tgz#9e4de0d6636a6266a585bd0900b422c85539d25f"
+ integrity sha512-cXc2ti9V234cq7rJzFKhirb2L2iPy8ZjALeVJAozXYz9te3r4eqLSixNAbMDJSgJEQywqXzs8gonxaboeKqwiw==
dependencies:
- camelcase "^6.0.0"
+ camelcase "^6.2.0"
cssesc "^3.0.0"
- icss-utils "^4.1.1"
+ icss-utils "^5.0.0"
loader-utils "^2.0.0"
- postcss "^7.0.32"
- postcss-modules-extract-imports "^2.0.0"
- postcss-modules-local-by-default "^3.0.3"
- postcss-modules-scope "^2.2.0"
- postcss-modules-values "^3.0.0"
+ postcss "^8.1.4"
+ postcss-modules-extract-imports "^3.0.0"
+ postcss-modules-local-by-default "^4.0.0"
+ postcss-modules-scope "^3.0.0"
+ postcss-modules-values "^4.0.0"
postcss-value-parser "^4.1.0"
- schema-utils "^2.7.1"
+ schema-utils "^3.0.0"
semver "^7.3.2"
css-select@^1.1.0:
@@ -1845,12 +1817,12 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
dependencies:
ms "2.0.0"
-debug@4.1.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@~4.1.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
- integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
+debug@4.2.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1"
+ integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==
dependencies:
- ms "^2.1.1"
+ ms "2.1.2"
debug@~3.1.0:
version "3.1.0"
@@ -1859,11 +1831,23 @@ debug@~3.1.0:
dependencies:
ms "2.0.0"
+debug@~4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
+ integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
+ dependencies:
+ ms "^2.1.1"
+
decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+decamelize@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837"
+ integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==
+
decode-uri-component@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
@@ -1876,7 +1860,12 @@ deep-eql@^3.0.1:
dependencies:
type-detect "^4.0.0"
-deep-is@^0.1.3, deep-is@~0.1.3:
+deep-extend@~0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
+ integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
+
+deep-is@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
@@ -1933,11 +1922,6 @@ destroy@~1.0.4:
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
-detect-file@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
- integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
-
di@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
@@ -2077,16 +2061,6 @@ ecdsa-sig-formatter@1.0.11:
dependencies:
safe-buffer "^5.0.1"
-editorconfig@^0.15.3:
- version "0.15.3"
- resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5"
- integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==
- dependencies:
- commander "^2.19.0"
- lru-cache "^4.1.5"
- semver "^5.6.0"
- sigmund "^1.0.1"
-
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -2172,7 +2146,7 @@ engine.io@~3.4.0:
engine.io-parser "~2.2.0"
ws "^7.1.2"
-enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.1, enhanced-resolve@^4.3.0:
+enhanced-resolve@^4.0.0, enhanced-resolve@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126"
integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==
@@ -2181,7 +2155,7 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.1, enhanced-resolve@^4.3.0:
memory-fs "^0.5.0"
tapable "^1.0.0"
-enquirer@^2.3.5:
+enquirer@^2.3.5, enquirer@^2.3.6:
version "2.3.6"
resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
@@ -2203,6 +2177,11 @@ entities@^2.0.0:
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f"
integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==
+envinfo@^7.7.3:
+ version "7.7.3"
+ resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.7.3.tgz#4b2d8622e3e7366afb8091b23ed95569ea0208cc"
+ integrity sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA==
+
errno@^0.1.3, errno@~0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
@@ -2210,7 +2189,7 @@ errno@^0.1.3, errno@~0.1.7:
dependencies:
prr "~1.0.1"
-es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.4, es-abstract@^1.17.5:
+es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.5:
version "1.17.6"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a"
integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==
@@ -2227,23 +2206,23 @@ es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.4, es-abstrac
string.prototype.trimend "^1.0.1"
string.prototype.trimstart "^1.0.1"
-es-array-method-boxes-properly@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e"
- integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==
-
-es-get-iterator@^1.0.2:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.0.tgz#bb98ad9d6d63b31aacdc8f89d5d0ee57bcb5b4c8"
- integrity sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==
+es-abstract@^1.18.0-next.0:
+ version "1.18.0-next.1"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68"
+ integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==
dependencies:
- es-abstract "^1.17.4"
+ es-to-primitive "^1.2.1"
+ function-bind "^1.1.1"
+ has "^1.0.3"
has-symbols "^1.0.1"
- is-arguments "^1.0.4"
- is-map "^2.0.1"
- is-set "^2.0.1"
- is-string "^1.0.5"
- isarray "^2.0.5"
+ is-callable "^1.2.2"
+ is-negative-zero "^2.0.0"
+ is-regex "^1.1.1"
+ object-inspect "^1.8.0"
+ object-keys "^1.1.1"
+ object.assign "^4.1.1"
+ string.prototype.trimend "^1.0.1"
+ string.prototype.trimstart "^1.0.1"
es-to-primitive@^1.2.1:
version "1.2.1"
@@ -2269,12 +2248,10 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
-eslint-config-prettier@6.11.0:
- version "6.11.0"
- resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz#f6d2238c1290d01c859a8b5c1f7d352a0b0da8b1"
- integrity sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==
- dependencies:
- get-stdin "^6.0.0"
+eslint-config-prettier@7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-7.0.0.tgz#c1ae4106f74e6c0357f44adb076771d032ac0e97"
+ integrity sha512-8Y8lGLVPPZdaNA7JXqnvETVC7IiVRgAP6afQu9gOQRn90YY3otMNh+x7Vr2vMePQntF+5erdSUBqSzCmU/AxaQ==
eslint-plugin-prettier@3.1.4:
version "3.1.4"
@@ -2283,27 +2260,27 @@ eslint-plugin-prettier@3.1.4:
dependencies:
prettier-linter-helpers "^1.0.0"
-eslint-plugin-react@7.21.2:
- version "7.21.2"
- resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.21.2.tgz#3bd5d2c4c36d5a0428d0d6dda301ac9a84d681b2"
- integrity sha512-j3XKvrK3rpBzveKFbgAeGsWb9uz6iUOrR0jixRfjwdFeGSRsXvVTFtHDQYCjsd1/6Z/xvb8Vy3LiI5Reo7fDrg==
+eslint-plugin-react@7.21.5:
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz#50b21a412b9574bfe05b21db176e8b7b3b15bff3"
+ integrity sha512-8MaEggC2et0wSF6bUeywF7qQ46ER81irOdWS4QWxnnlAEsnzeBevk1sWh7fhpCghPpXb+8Ks7hvaft6L/xsR6g==
dependencies:
array-includes "^3.1.1"
array.prototype.flatmap "^1.2.3"
doctrine "^2.1.0"
has "^1.0.3"
- jsx-ast-utils "^2.4.1"
+ jsx-ast-utils "^2.4.1 || ^3.0.0"
object.entries "^1.1.2"
object.fromentries "^2.0.2"
object.values "^1.1.1"
prop-types "^15.7.2"
- resolve "^1.17.0"
+ resolve "^1.18.1"
string.prototype.matchall "^4.0.2"
-eslint-plugin-standard@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz#ff0519f7ffaff114f76d1bd7c3996eef0f6e20b4"
- integrity sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ==
+eslint-plugin-standard@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-5.0.0.tgz#c43f6925d669f177db46f095ea30be95476b1ee4"
+ integrity sha512-eSIXPc9wBM4BrniMzJRBm2uoVuXz2EPa+NXPk2+itrVt+r5SbKFERx/IgrK/HmfjddyKVz2f+j+7gBRvu19xLg==
eslint-scope@^4.0.3:
version "4.0.3"
@@ -2321,13 +2298,6 @@ eslint-scope@^5.0.0, eslint-scope@^5.1.1:
esrecurse "^4.3.0"
estraverse "^4.1.1"
-eslint-utils@^1.4.3:
- version "1.4.3"
- resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f"
- integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==
- dependencies:
- eslint-visitor-keys "^1.1.0"
-
eslint-utils@^2.0.0, eslint-utils@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
@@ -2340,13 +2310,18 @@ eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
-eslint@7.10.0:
- version "7.10.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.10.0.tgz#494edb3e4750fb791133ca379e786a8f648c72b9"
- integrity sha512-BDVffmqWl7JJXqCjAK6lWtcQThZB/aP1HXSH1JKwGwv0LQEdvpR7qzNrUT487RM39B5goWuboFad5ovMBmD8yA==
+eslint-visitor-keys@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
+ integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
+
+eslint@7.15.0:
+ version "7.15.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.15.0.tgz#eb155fb8ed0865fcf5d903f76be2e5b6cd7e0bc7"
+ integrity sha512-Vr64xFDT8w30wFll643e7cGrIkPEU50yIiI36OdSIDoSGguIeaLzBo0vpGvzo9RECUqq7htURfwEtKqwytkqzA==
dependencies:
"@babel/code-frame" "^7.0.0"
- "@eslint/eslintrc" "^0.1.3"
+ "@eslint/eslintrc" "^0.2.2"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
@@ -2355,11 +2330,11 @@ eslint@7.10.0:
enquirer "^2.3.5"
eslint-scope "^5.1.1"
eslint-utils "^2.1.0"
- eslint-visitor-keys "^1.3.0"
- espree "^7.3.0"
+ eslint-visitor-keys "^2.0.0"
+ espree "^7.3.1"
esquery "^1.2.0"
esutils "^2.0.2"
- file-entry-cache "^5.0.1"
+ file-entry-cache "^6.0.0"
functional-red-black-tree "^1.0.1"
glob-parent "^5.0.0"
globals "^12.1.0"
@@ -2383,50 +2358,50 @@ eslint@7.10.0:
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
-eslint@^6.8.0:
- version "6.8.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb"
- integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==
+eslint@^7.9.0:
+ version "7.16.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.16.0.tgz#a761605bf9a7b32d24bb7cde59aeb0fd76f06092"
+ integrity sha512-iVWPS785RuDA4dWuhhgXTNrGxHHK3a8HLSMBgbbU59ruJDubUraXN8N5rn7kb8tG6sjg74eE0RA3YWT51eusEw==
dependencies:
"@babel/code-frame" "^7.0.0"
+ "@eslint/eslintrc" "^0.2.2"
ajv "^6.10.0"
- chalk "^2.1.0"
- cross-spawn "^6.0.5"
+ chalk "^4.0.0"
+ cross-spawn "^7.0.2"
debug "^4.0.1"
doctrine "^3.0.0"
- eslint-scope "^5.0.0"
- eslint-utils "^1.4.3"
- eslint-visitor-keys "^1.1.0"
- espree "^6.1.2"
- esquery "^1.0.1"
+ enquirer "^2.3.5"
+ eslint-scope "^5.1.1"
+ eslint-utils "^2.1.0"
+ eslint-visitor-keys "^2.0.0"
+ espree "^7.3.1"
+ esquery "^1.2.0"
esutils "^2.0.2"
- file-entry-cache "^5.0.1"
+ file-entry-cache "^6.0.0"
functional-red-black-tree "^1.0.1"
glob-parent "^5.0.0"
globals "^12.1.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
- inquirer "^7.0.0"
is-glob "^4.0.0"
js-yaml "^3.13.1"
json-stable-stringify-without-jsonify "^1.0.1"
- levn "^0.3.0"
- lodash "^4.17.14"
+ levn "^0.4.1"
+ lodash "^4.17.19"
minimatch "^3.0.4"
- mkdirp "^0.5.1"
natural-compare "^1.4.0"
- optionator "^0.8.3"
+ optionator "^0.9.1"
progress "^2.0.0"
- regexpp "^2.0.1"
- semver "^6.1.2"
- strip-ansi "^5.2.0"
- strip-json-comments "^3.0.1"
- table "^5.2.3"
+ regexpp "^3.1.0"
+ semver "^7.2.1"
+ strip-ansi "^6.0.0"
+ strip-json-comments "^3.1.0"
+ table "^6.0.4"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
-espree@^6.1.2, espree@^6.2.1:
+espree@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a"
integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==
@@ -2435,13 +2410,13 @@ espree@^6.1.2, espree@^6.2.1:
acorn-jsx "^5.2.0"
eslint-visitor-keys "^1.1.0"
-espree@^7.3.0:
- version "7.3.0"
- resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348"
- integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==
+espree@^7.3.0, espree@^7.3.1:
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6"
+ integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==
dependencies:
acorn "^7.4.0"
- acorn-jsx "^5.2.0"
+ acorn-jsx "^5.3.1"
eslint-visitor-keys "^1.3.0"
esprima@^4.0.0:
@@ -2508,6 +2483,21 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
md5.js "^1.3.4"
safe-buffer "^5.1.1"
+execa@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a"
+ integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==
+ dependencies:
+ cross-spawn "^7.0.0"
+ get-stream "^5.0.0"
+ human-signals "^1.1.1"
+ is-stream "^2.0.0"
+ merge-stream "^2.0.0"
+ npm-run-path "^4.0.0"
+ onetime "^5.1.0"
+ signal-exit "^3.0.2"
+ strip-final-newline "^2.0.0"
+
expand-brackets@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
@@ -2521,13 +2511,6 @@ expand-brackets@^2.1.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
-expand-tilde@^2.0.0, expand-tilde@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
- integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=
- dependencies:
- homedir-polyfill "^1.0.1"
-
express@^4.17.1:
version "4.17.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
@@ -2584,15 +2567,6 @@ extend@^3.0.0, extend@~3.0.2:
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
-external-editor@^3.0.3:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
- integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
- dependencies:
- chardet "^0.7.0"
- iconv-lite "^0.4.24"
- tmp "^0.0.33"
-
extglob@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
@@ -2617,11 +2591,6 @@ extsprintf@^1.2.0:
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
-fast-deep-equal@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"
- integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=
-
fast-deep-equal@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
@@ -2649,7 +2618,7 @@ fast-json-stable-stringify@^2.0.0:
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
-fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
+fast-levenshtein@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
@@ -2659,19 +2628,12 @@ figgy-pudding@^3.5.1:
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e"
integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==
-figures@^3.0.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
- integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
- dependencies:
- escape-string-regexp "^1.0.5"
-
-file-entry-cache@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c"
- integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==
+file-entry-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a"
+ integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==
dependencies:
- flat-cache "^2.0.1"
+ flat-cache "^3.0.4"
file-uri-to-path@1.0.0:
version "1.0.0"
@@ -2732,7 +2694,7 @@ find-up@^3.0.0:
dependencies:
locate-path "^3.0.0"
-find-up@^4.1.0:
+find-up@^4.0.0, find-up@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
@@ -2740,37 +2702,29 @@ find-up@^4.1.0:
locate-path "^5.0.0"
path-exists "^4.0.0"
-findup-sync@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1"
- integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==
- dependencies:
- detect-file "^1.0.0"
- is-glob "^4.0.0"
- micromatch "^3.0.4"
- resolve-dir "^1.0.1"
-
-flat-cache@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0"
- integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==
+flat-cache@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
+ integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==
dependencies:
- flatted "^2.0.0"
- rimraf "2.6.3"
- write "1.0.3"
+ flatted "^3.1.0"
+ rimraf "^3.0.2"
-flat@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2"
- integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==
- dependencies:
- is-buffer "~2.0.3"
+flat@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
+ integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
-flatted@^2.0.0, flatted@^2.0.1:
+flatted@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==
+flatted@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067"
+ integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==
+
flush-write-stream@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
@@ -2892,10 +2846,12 @@ 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@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b"
- integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==
+get-stream@^5.0.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
+ integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
+ dependencies:
+ pump "^3.0.0"
get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
@@ -2936,42 +2892,6 @@ glob@7.1.6, glob@^7.1.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
once "^1.3.0"
path-is-absolute "^1.0.0"
-global-modules@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea"
- integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==
- dependencies:
- global-prefix "^1.0.1"
- is-windows "^1.0.1"
- resolve-dir "^1.0.0"
-
-global-modules@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
- integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==
- dependencies:
- global-prefix "^3.0.0"
-
-global-prefix@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe"
- integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=
- dependencies:
- expand-tilde "^2.0.2"
- homedir-polyfill "^1.0.1"
- ini "^1.3.4"
- is-windows "^1.0.1"
- which "^1.2.14"
-
-global-prefix@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97"
- integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==
- dependencies:
- ini "^1.3.5"
- kind-of "^6.0.2"
- which "^1.3.1"
-
globals@^11.1.0:
version "11.12.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
@@ -3110,20 +3030,13 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
-hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0:
+hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies:
react-is "^16.7.0"
-homedir-polyfill@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
- integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==
- dependencies:
- parse-passwd "^1.0.0"
-
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"
@@ -3137,10 +3050,10 @@ html-minifier-terser@^5.0.1:
relateurl "^0.2.7"
terser "^4.6.3"
-html-webpack-plugin@4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.3.0.tgz#53bf8f6d696c4637d5b656d3d9863d89ce8174fd"
- integrity sha512-C0fzKN8yQoVLTelcJxZfJCE+aAvQiY2VUf3UuKrR4a9k5UMWYOtpDLsaXwATbcVCnI05hUS7L9ULQHWLZhyi3w==
+html-webpack-plugin@4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.0.tgz#625097650886b97ea5dae331c320e3238f6c121c"
+ integrity sha512-MouoXEYSjTzCrjIxWwg8gxL5fE2X2WZJLmBYXlaJhQUH5K/b5OrqmV7T4dB7iu0xkmJ6JlUuV6fFVtnqbPopZw==
dependencies:
"@types/html-minifier-terser" "^5.0.0"
"@types/tapable" "^1.0.5"
@@ -3209,19 +3122,22 @@ https-browserify@^1.0.0:
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
-iconv-lite@0.4.24, iconv-lite@^0.4.24:
+human-signals@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
+ integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
+
+iconv-lite@0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
dependencies:
safer-buffer ">= 2.1.2 < 3"
-icss-utils@^4.0.0, icss-utils@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467"
- integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==
- dependencies:
- postcss "^7.0.14"
+icss-utils@^5.0.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae"
+ integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==
ieee754@^1.1.4:
version "1.1.13"
@@ -3251,13 +3167,13 @@ import-fresh@^3.0.0, import-fresh@^3.2.1:
parent-module "^1.0.0"
resolve-from "^4.0.0"
-import-local@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d"
- integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==
+import-local@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6"
+ integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==
dependencies:
- pkg-dir "^3.0.0"
- resolve-cwd "^2.0.0"
+ pkg-dir "^4.2.0"
+ resolve-cwd "^3.0.0"
imurmurhash@^0.1.4:
version "0.1.4"
@@ -3307,30 +3223,6 @@ inherits@2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
-ini@^1.3.4, ini@^1.3.5:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
- integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
-
-inquirer@^7.0.0:
- version "7.3.3"
- resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003"
- integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==
- dependencies:
- ansi-escapes "^4.2.1"
- chalk "^4.1.0"
- cli-cursor "^3.1.0"
- cli-width "^3.0.0"
- external-editor "^3.0.3"
- figures "^3.0.0"
- lodash "^4.17.19"
- mute-stream "0.0.8"
- run-async "^2.4.0"
- rxjs "^6.6.0"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
- through "^2.3.6"
-
internal-slot@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3"
@@ -3340,10 +3232,10 @@ internal-slot@^1.0.2:
has "^1.0.3"
side-channel "^1.0.2"
-interpret@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
- integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
+interpret@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9"
+ integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
ipaddr.js@1.9.1:
version "1.9.1"
@@ -3364,11 +3256,6 @@ is-accessor-descriptor@^1.0.0:
dependencies:
kind-of "^6.0.0"
-is-arguments@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3"
- integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==
-
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"
@@ -3388,16 +3275,23 @@ is-buffer@^1.1.5:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
-is-buffer@~2.0.3:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623"
- integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==
-
is-callable@^1.1.4, is-callable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb"
integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==
+is-callable@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9"
+ integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==
+
+is-core-module@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a"
+ integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==
+ dependencies:
+ has "^1.0.3"
+
is-data-descriptor@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
@@ -3481,10 +3375,10 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
dependencies:
is-extglob "^2.1.1"
-is-map@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.1.tgz#520dafc4307bb8ebc33b813de5ce7c9400d644a1"
- integrity sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==
+is-negative-zero@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461"
+ integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=
is-number@^3.0.0:
version "3.0.0"
@@ -3498,10 +3392,10 @@ is-number@^7.0.0:
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
-is-plain-obj@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
- integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
+is-plain-obj@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
+ integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
is-plain-object@^2.0.3, is-plain-object@^2.0.4:
version "2.0.4"
@@ -3515,19 +3409,19 @@ is-promise@^2.1.0:
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
-is-regex@^1.1.0:
+is-regex@^1.1.0, is-regex@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9"
integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==
dependencies:
has-symbols "^1.0.1"
-is-set@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.1.tgz#d1604afdab1724986d30091575f54945da7e5f43"
- integrity sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==
+is-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
+ integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
-is-string@^1.0.4, is-string@^1.0.5:
+is-string@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6"
integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==
@@ -3544,7 +3438,7 @@ is-typedarray@~1.0.0:
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
-is-windows@^1.0.1, is-windows@^1.0.2:
+is-windows@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
@@ -3554,7 +3448,7 @@ is-wsl@^1.1.0:
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
-is-wsl@^2.1.0:
+is-wsl@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
@@ -3576,11 +3470,6 @@ isarray@2.0.1:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"
integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=
-isarray@^2.0.5:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
- integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
-
isbinaryfile@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.6.tgz#edcb62b224e2b4710830b67498c8e4e5a4d2610b"
@@ -3608,36 +3497,12 @@ isstream@~0.1.2:
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
-iterate-iterator@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/iterate-iterator/-/iterate-iterator-1.0.1.tgz#1693a768c1ddd79c969051459453f082fe82e9f6"
- integrity sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==
-
-iterate-value@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/iterate-value/-/iterate-value-1.0.2.tgz#935115bd37d006a52046535ebc8d07e9c9337f57"
- integrity sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==
- dependencies:
- es-get-iterator "^1.0.2"
- iterate-iterator "^1.0.1"
-
-js-beautify@^1.6.4:
- version "1.11.0"
- resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.11.0.tgz#afb873dc47d58986360093dcb69951e8bcd5ded2"
- integrity sha512-a26B+Cx7USQGSWnz9YxgJNMmML/QG2nqIaL7VVYPCXbqiKz8PN0waSNvroMtvAK6tY7g/wPdNWGEP+JTNIBr6A==
- dependencies:
- config-chain "^1.1.12"
- editorconfig "^0.15.3"
- glob "^7.1.3"
- mkdirp "~1.0.3"
- nopt "^4.0.3"
-
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-js-yaml@3.14.0, js-yaml@^3.13.1:
+js-yaml@3.14.0:
version "3.14.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482"
integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==
@@ -3645,6 +3510,14 @@ js-yaml@3.14.0, js-yaml@^3.13.1:
argparse "^1.0.7"
esprima "^4.0.0"
+js-yaml@^3.13.1, js-yaml@^3.14.0:
+ version "3.14.1"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
+ integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^4.0.0"
+
jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
@@ -3660,23 +3533,23 @@ json-parse-better-errors@^1.0.2:
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
-json-schema-migrate@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/json-schema-migrate/-/json-schema-migrate-0.2.0.tgz#ba47a5b0072fc72396460e1bd60b44d52178bbc6"
- integrity sha1-ukelsAcvxyOWRg4b1gtE1SF4u8Y=
+json-schema-migrate@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/json-schema-migrate/-/json-schema-migrate-1.0.0.tgz#9169a3f9c0b0c5dfc749d01bb7c76d31ad081599"
+ integrity sha512-Ze3G4zCBi0ZHKQaK3EEFv7Q0d3/LxZldrH/6rFNNegkGGolMp6Deg6rLWyOaRApPABeZfMyZXbIiAFyRP1bHQA==
dependencies:
- ajv "^5.0.0"
-
-json-schema-traverse@^0.3.0:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
- integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=
+ ajv "^7.0.0-beta.9"
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+json-schema-traverse@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
+ integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+
json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
@@ -3739,13 +3612,13 @@ jsprim@^1.2.2:
json-schema "0.2.3"
verror "1.10.0"
-jsx-ast-utils@^2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e"
- integrity sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==
+"jsx-ast-utils@^2.4.1 || ^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.0.0.tgz#0f49d5093bafa4b45d3fe02147d8b40ffc6c7438"
+ integrity sha512-sPuicm6EPKYI/UnWpOatvg4pI50qaBo4dSOMGUPutmJ26ttedFKXr0It0XXPk4HKnQ/1X0st4eSS2w2jhFk9Ow==
dependencies:
array-includes "^3.1.1"
- object.assign "^4.1.0"
+ object.assign "^4.1.1"
jszip@^3.2.2:
version "3.5.0"
@@ -3779,12 +3652,13 @@ jws@^3.2.2:
jwa "^1.4.1"
safe-buffer "^5.0.1"
-karma-firefox-launcher@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/karma-firefox-launcher/-/karma-firefox-launcher-1.3.0.tgz#ebcbb1d1ddfada6be900eb8fae25bcf2dcdc8171"
- integrity sha512-Fi7xPhwrRgr+94BnHX0F5dCl1miIW4RHnzjIGxF8GaIEp7rNqX7LSi7ok63VXs3PS/5MQaQMhGxw+bvD+pibBQ==
+karma-firefox-launcher@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/karma-firefox-launcher/-/karma-firefox-launcher-2.1.0.tgz#d0d328c93dfcf9b46f1ac83b4bb32f43aadb2050"
+ integrity sha512-dkiyqN2R6fCWt78rciOXJLFDWcQ7QEQi++HgebPJlw1y0ycDjGNDHuSrhdh48QG02fzZKK20WHFWVyBZ6CPngg==
dependencies:
- is-wsl "^2.1.0"
+ is-wsl "^2.2.0"
+ which "^2.0.1"
karma-html2js-preprocessor@^1.1.0:
version "1.1.0"
@@ -3895,13 +3769,10 @@ lanthan@0.0.2:
request-promise-native "^1.0.7"
selenium-webdriver "^4.0.0-alpha.5"
-levn@^0.3.0, levn@~0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
- integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=
- dependencies:
- prelude-ls "~1.1.2"
- type-check "~0.3.2"
+leven@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
+ integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
levn@^0.4.1:
version "0.4.1"
@@ -3923,7 +3794,7 @@ loader-runner@^2.4.0:
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
-loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
+loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
@@ -4018,6 +3889,11 @@ lodash@^4.16.3, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
+lodash@^4.17.20:
+ version "4.17.20"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
+ integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
+
log-symbols@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920"
@@ -4082,14 +3958,6 @@ lower-case@^2.0.1:
dependencies:
tslib "^1.10.0"
-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==
- dependencies:
- pseudomap "^1.0.2"
- yallist "^2.1.2"
-
lru-cache@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
@@ -4157,12 +4025,17 @@ merge-descriptors@1.0.1:
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
+merge-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
+ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+
methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
-micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4:
+micromatch@^3.1.10, micromatch@^3.1.4:
version "3.1.10"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
@@ -4277,20 +4150,16 @@ mkdirp@^0.5.1, mkdirp@^0.5.3:
dependencies:
minimist "^1.2.5"
-mkdirp@~1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
- integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
-
mocha@^8.1.1:
- version "8.1.3"
- resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.1.3.tgz#5e93f873e35dfdd69617ea75f9c68c2ca61c2ac5"
- integrity sha512-ZbaYib4hT4PpF4bdSO2DohooKXIn4lDeiYqB+vTmCdr6l2woW0b6H3pf5x4sM5nwQMru9RvjjHYWVGltR50ZBw==
+ version "8.2.1"
+ resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.2.1.tgz#f2fa68817ed0e53343d989df65ccd358bc3a4b39"
+ integrity sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==
dependencies:
+ "@ungap/promise-all-settled" "1.1.2"
ansi-colors "4.1.1"
browser-stdout "1.3.1"
- chokidar "3.4.2"
- debug "4.1.1"
+ chokidar "3.4.3"
+ debug "4.2.0"
diff "4.0.2"
escape-string-regexp "4.0.0"
find-up "5.0.0"
@@ -4301,17 +4170,16 @@ mocha@^8.1.1:
log-symbols "4.0.0"
minimatch "3.0.4"
ms "2.1.2"
- object.assign "4.1.0"
- promise.allsettled "1.0.2"
- serialize-javascript "4.0.0"
- strip-json-comments "3.0.1"
- supports-color "7.1.0"
+ nanoid "3.1.12"
+ serialize-javascript "5.0.1"
+ strip-json-comments "3.1.1"
+ supports-color "7.2.0"
which "2.0.2"
wide-align "1.1.3"
- workerpool "6.0.0"
+ workerpool "6.0.2"
yargs "13.3.2"
yargs-parser "13.1.2"
- yargs-unparser "1.6.1"
+ yargs-unparser "2.0.0"
move-concurrently@^1.0.1:
version "1.0.1"
@@ -4340,16 +4208,21 @@ ms@2.1.2, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-mute-stream@0.0.8:
- version "0.0.8"
- resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
- integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
-
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==
+nanoid@3.1.12:
+ version "3.1.12"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654"
+ integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==
+
+nanoid@^3.1.20:
+ version "3.1.20"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
+ integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==
+
nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@@ -4382,11 +4255,6 @@ neo-async@^2.5.0, neo-async@^2.6.1:
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
-nice-try@^1.0.4:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
- integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
-
nise@^1.5.2:
version "1.5.3"
resolved "https://registry.yarnpkg.com/nise/-/nise-1.5.3.tgz#9d2cfe37d44f57317766c6e9408a359c5d3ac1f7"
@@ -4446,14 +4314,6 @@ node-libs-browser@^2.2.1:
util "^0.11.0"
vm-browserify "^1.0.1"
-nopt@^4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
- integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==
- dependencies:
- abbrev "1"
- osenv "^0.1.4"
-
normalize-path@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
@@ -4466,6 +4326,13 @@ 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==
+npm-run-path@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
+ integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
+ dependencies:
+ path-key "^3.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"
@@ -4497,7 +4364,7 @@ object-copy@^0.1.0:
define-property "^0.2.5"
kind-of "^3.0.3"
-object-inspect@^1.7.0:
+object-inspect@^1.7.0, object-inspect@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==
@@ -4514,7 +4381,7 @@ object-visit@^1.0.0:
dependencies:
isobject "^3.0.0"
-object.assign@4.1.0, object.assign@^4.1.0:
+object.assign@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
@@ -4524,6 +4391,16 @@ object.assign@4.1.0, object.assign@^4.1.0:
has-symbols "^1.0.0"
object-keys "^1.0.11"
+object.assign@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd"
+ integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==
+ dependencies:
+ define-properties "^1.1.3"
+ es-abstract "^1.18.0-next.0"
+ has-symbols "^1.0.1"
+ object-keys "^1.1.1"
+
object.entries@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add"
@@ -4589,18 +4466,6 @@ onetime@^5.1.0:
dependencies:
mimic-fn "^2.1.0"
-optionator@^0.8.3:
- version "0.8.3"
- resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
- integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
- dependencies:
- deep-is "~0.1.3"
- fast-levenshtein "~2.0.6"
- levn "~0.3.0"
- prelude-ls "~1.1.2"
- type-check "~0.3.2"
- word-wrap "~1.2.3"
-
optionator@^0.9.1:
version "0.9.1"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
@@ -4618,24 +4483,11 @@ os-browserify@^0.3.0:
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=
-os-homedir@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
- integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
-
-os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2:
+os-tmpdir@~1.0.1:
version "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.1.4:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
- integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
- dependencies:
- os-homedir "^1.0.0"
- os-tmpdir "^1.0.0"
-
p-limit@^2.0.0, p-limit@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
@@ -4717,11 +4569,6 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5:
pbkdf2 "^3.0.3"
safe-buffer "^5.1.1"
-parse-passwd@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
- integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
-
parseqs@0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
@@ -4779,12 +4626,7 @@ path-is-absolute@^1.0.0:
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
-path-key@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
- integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
-
-path-key@^3.1.0:
+path-key@^3.0.0, path-key@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
@@ -4844,45 +4686,47 @@ pkg-dir@^3.0.0:
dependencies:
find-up "^3.0.0"
+pkg-dir@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
+ integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
+ dependencies:
+ find-up "^4.0.0"
+
posix-character-classes@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
-postcss-modules-extract-imports@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e"
- integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==
- dependencies:
- postcss "^7.0.5"
+postcss-modules-extract-imports@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d"
+ integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==
-postcss-modules-local-by-default@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0"
- integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==
+postcss-modules-local-by-default@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c"
+ integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==
dependencies:
- icss-utils "^4.1.1"
- postcss "^7.0.32"
+ icss-utils "^5.0.0"
postcss-selector-parser "^6.0.2"
postcss-value-parser "^4.1.0"
-postcss-modules-scope@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee"
- integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==
+postcss-modules-scope@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06"
+ integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==
dependencies:
- postcss "^7.0.6"
- postcss-selector-parser "^6.0.0"
+ postcss-selector-parser "^6.0.4"
-postcss-modules-values@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10"
- integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==
+postcss-modules-values@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c"
+ integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==
dependencies:
- icss-utils "^4.0.0"
- postcss "^7.0.6"
+ icss-utils "^5.0.0"
-postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2:
+postcss-selector-parser@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c"
integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==
@@ -4891,39 +4735,44 @@ postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2:
indexes-of "^1.0.1"
uniq "^1.0.1"
+postcss-selector-parser@^6.0.4:
+ version "6.0.4"
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3"
+ integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==
+ dependencies:
+ cssesc "^3.0.0"
+ indexes-of "^1.0.1"
+ uniq "^1.0.1"
+ util-deprecate "^1.0.2"
+
postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
-postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6:
- version "7.0.32"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d"
- integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==
+postcss@^8.1.4:
+ version "8.2.1"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.1.tgz#eabc5557c4558059b9d9e5b15bce7ffa9089c2a8"
+ integrity sha512-RhsqOOAQzTgh1UB/IZdca7F9WDb7SUCR2Vnv1x7DbvuuggQIpoDwjK+q0rzoPffhYvWNKX5JSwS4so4K3UC6vA==
dependencies:
- chalk "^2.4.2"
+ colorette "^1.2.1"
+ nanoid "^3.1.20"
source-map "^0.6.1"
- supports-color "^6.1.0"
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
-prelude-ls@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
- integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
-
-prettier-eslint@11.0.0:
- version "11.0.0"
- resolved "https://registry.yarnpkg.com/prettier-eslint/-/prettier-eslint-11.0.0.tgz#b19b97c8a1fc4c898b7d1a54b948ef957ceb101d"
- integrity sha512-ACjL7T8m10HCO7DwYdXwhNWuZzQv86JkZAhVpzFV9brTMWi3i6LhqoELFaXf6RetDngujz89tnbDmGyvDl+rzA==
+prettier-eslint@12.0.0:
+ version "12.0.0"
+ resolved "https://registry.yarnpkg.com/prettier-eslint/-/prettier-eslint-12.0.0.tgz#b4dab5111aad1c0dca062eb7f92a69d5fb1ac1d3"
+ integrity sha512-N8SGGQwAosISXTNl1E57sBbtnqUGlyRWjcfIUxyD3HF4ynehA9GZ8IfJgiep/OfYvCof/JEpy9ZqSl250Wia7A==
dependencies:
"@typescript-eslint/parser" "^3.0.0"
common-tags "^1.4.0"
dlv "^1.1.0"
- eslint "^6.8.0"
+ eslint "^7.9.0"
indent-string "^4.0.0"
lodash.merge "^4.6.0"
loglevel-colored-level-prefix "^1.0.0"
@@ -4940,10 +4789,10 @@ prettier-linter-helpers@^1.0.0:
dependencies:
fast-diff "^1.1.2"
-prettier@2.1.2, prettier@^2.0.0:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5"
- integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==
+prettier@2.2.1, prettier@^2.0.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"
+ integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==
pretty-error@^2.1.1:
version "2.1.1"
@@ -4981,17 +4830,6 @@ promise-inflight@^1.0.1:
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
-promise.allsettled@1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/promise.allsettled/-/promise.allsettled-1.0.2.tgz#d66f78fbb600e83e863d893e98b3d4376a9c47c9"
- integrity sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==
- dependencies:
- array.prototype.map "^1.0.1"
- define-properties "^1.1.3"
- es-abstract "^1.17.0-next.1"
- function-bind "^1.1.1"
- iterate-value "^1.0.0"
-
prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
@@ -5001,11 +4839,6 @@ prop-types@^15.6.2, prop-types@^15.7.2:
object-assign "^4.1.1"
react-is "^16.8.1"
-proto-list@~1.2.1:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
- integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
-
proxy-addr@~2.0.5:
version "2.0.6"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
@@ -5019,11 +4852,6 @@ prr@~1.0.1:
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
-pseudomap@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
- integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
-
psl@^1.1.28:
version "1.8.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
@@ -5146,21 +4974,21 @@ react-dom@16.13.1:
prop-types "^15.6.2"
scheduler "^0.19.1"
-react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6, react-is@^16.9.0:
+react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-redux@^7.1.3:
- version "7.2.1"
- resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.1.tgz#8dedf784901014db2feca1ab633864dee68ad985"
- integrity sha512-T+VfD/bvgGTUA74iW9d2i5THrDQWbweXP0AVNI8tNd1Rk5ch1rnMiJkDD67ejw7YBKM4+REvcvqRuWJb7BLuEg==
+ version "7.2.2"
+ resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.2.tgz#03862e803a30b6b9ef8582dadcc810947f74b736"
+ integrity sha512-8+CQ1EvIVFkYL/vu6Olo7JFLWop1qRUeb46sGtIMDCSpgwPQq8fPLpirIB0iTqFe9XYEFPHssdX8/UwN6pAkEA==
dependencies:
- "@babel/runtime" "^7.5.5"
- hoist-non-react-statics "^3.3.0"
+ "@babel/runtime" "^7.12.1"
+ hoist-non-react-statics "^3.3.2"
loose-envify "^1.4.0"
prop-types "^15.7.2"
- react-is "^16.9.0"
+ react-is "^16.13.1"
react-test-renderer@16.13.1:
version "16.13.1"
@@ -5172,10 +5000,10 @@ react-test-renderer@16.13.1:
react-is "^16.8.6"
scheduler "^0.19.1"
-react@16.13.1:
- version "16.13.1"
- resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
- integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==
+react@16.14.0:
+ version "16.14.0"
+ resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d"
+ integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
@@ -5212,13 +5040,25 @@ readdirp@^2.2.1:
micromatch "^3.1.10"
readable-stream "^2.0.2"
-readdirp@~3.4.0:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada"
- integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==
+readdirp@~3.5.0:
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
+ integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==
dependencies:
picomatch "^2.2.1"
+rechoir@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.0.tgz#32650fd52c21ab252aa5d65b19310441c7e03aca"
+ integrity sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==
+ dependencies:
+ resolve "^1.9.0"
+
+reduce-flatten@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27"
+ integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==
+
redux-promise@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/redux-promise/-/redux-promise-0.6.0.tgz#c64723b5213bb5603c11b74302883b682e06b319"
@@ -5271,11 +5111,6 @@ regexp.prototype.flags@^1.3.0:
define-properties "^1.1.3"
es-abstract "^1.17.0-next.1"
-regexpp@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
- integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==
-
regexpp@^3.0.0, regexpp@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
@@ -5359,10 +5194,10 @@ require-directory@^2.1.1:
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
-require-from-string@^1.2.0:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418"
- integrity sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=
+require-from-string@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
+ integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
require-main-filename@^2.0.0:
version "2.0.0"
@@ -5379,51 +5214,36 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
-resolve-cwd@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
- integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=
- dependencies:
- resolve-from "^3.0.0"
-
-resolve-dir@^1.0.0, resolve-dir@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43"
- integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=
- dependencies:
- expand-tilde "^2.0.0"
- global-modules "^1.0.0"
-
-resolve-from@^3.0.0:
+resolve-cwd@^3.0.0:
version "3.0.0"
- resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
- integrity sha1-six699nWiBvItuZTM17rywoYh0g=
+ resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
+ integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==
+ dependencies:
+ resolve-from "^5.0.0"
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+resolve-from@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
+ integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+
resolve-url@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
-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==
+resolve@^1.18.1, resolve@^1.9.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c"
+ integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==
dependencies:
+ is-core-module "^2.1.0"
path-parse "^1.0.6"
-restore-cursor@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
- integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
- dependencies:
- onetime "^5.1.0"
- signal-exit "^3.0.2"
-
ret@~0.1.10:
version "0.1.15"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
@@ -5434,13 +5254,6 @@ rfdc@^1.1.4:
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2"
integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==
-rimraf@2.6.3:
- version "2.6.3"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
- integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
- 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"
@@ -5463,11 +5276,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0"
inherits "^2.0.1"
-run-async@^2.4.0:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
- integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
-
run-queue@^1.0.0, run-queue@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
@@ -5475,13 +5283,6 @@ run-queue@^1.0.0, run-queue@^1.0.3:
dependencies:
aproba "^1.1.1"
-rxjs@^6.6.0:
- version "6.6.2"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2"
- integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==
- dependencies:
- tslib "^1.9.0"
-
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
@@ -5521,13 +5322,13 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
-schema-utils@^2.6.6, schema-utils@^2.7.1:
- version "2.7.1"
- resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
- integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==
+schema-utils@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef"
+ integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==
dependencies:
- "@types/json-schema" "^7.0.5"
- ajv "^6.12.4"
+ "@types/json-schema" "^7.0.6"
+ ajv "^6.12.5"
ajv-keywords "^3.5.2"
selenium-webdriver@^4.0.0-alpha.5:
@@ -5539,12 +5340,12 @@ selenium-webdriver@^4.0.0-alpha.5:
rimraf "^2.7.1"
tmp "0.0.30"
-semver@^5.5.0, semver@^5.6.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==
-semver@^6.0.0, semver@^6.1.2:
+semver@^6.0.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
@@ -5573,10 +5374,10 @@ send@0.17.1:
range-parser "~1.2.1"
statuses "~1.5.0"
-serialize-javascript@4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa"
- integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==
+serialize-javascript@5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4"
+ integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==
dependencies:
randombytes "^2.1.0"
@@ -5647,13 +5448,6 @@ shallowequal@^1.1.0:
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
-shebang-command@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
- integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
- dependencies:
- shebang-regex "^1.0.0"
-
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
@@ -5661,11 +5455,6 @@ shebang-command@^2.0.0:
dependencies:
shebang-regex "^3.0.0"
-shebang-regex@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
- integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
-
shebang-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
@@ -5679,11 +5468,6 @@ side-channel@^1.0.2:
es-abstract "^1.17.0-next.1"
object-inspect "^1.7.0"
-sigmund@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
- integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=
-
signal-exit@^3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
@@ -5712,14 +5496,14 @@ sinon@^7.2.3:
supports-color "^5.5.0"
sinon@^9.0.3:
- version "9.0.3"
- resolved "https://registry.yarnpkg.com/sinon/-/sinon-9.0.3.tgz#bffc3ec28c936332cd2a41833547b9eed201ecff"
- integrity sha512-IKo9MIM111+smz9JGwLmw5U1075n1YXeAq8YeSFlndCLhAL5KGn6bLgu7b/4AYHTV/LcEMcRm2wU2YiL55/6Pg==
+ version "9.2.2"
+ resolved "https://registry.yarnpkg.com/sinon/-/sinon-9.2.2.tgz#b83cf5d43838f99cfa3644453f4c7db23e7bd535"
+ integrity sha512-9Owi+RisvCZpB0bdOVFfL314I6I4YoRlz6Isi4+fr8q8YQsDPoCe5UnmNtKHRThX3negz2bXHWIuiPa42vM8EQ==
dependencies:
- "@sinonjs/commons" "^1.7.2"
+ "@sinonjs/commons" "^1.8.1"
"@sinonjs/fake-timers" "^6.0.1"
"@sinonjs/formatio" "^5.0.1"
- "@sinonjs/samsam" "^5.1.0"
+ "@sinonjs/samsam" "^5.3.0"
diff "^4.0.2"
nise "^4.0.4"
supports-color "^7.1.0"
@@ -5733,6 +5517,15 @@ slice-ansi@^2.1.0:
astral-regex "^1.0.0"
is-fullwidth-code-point "^2.0.0"
+slice-ansi@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
+ integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==
+ dependencies:
+ ansi-styles "^4.0.0"
+ astral-regex "^2.0.0"
+ is-fullwidth-code-point "^3.0.0"
+
snapdragon-node@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
@@ -6051,28 +5844,28 @@ strip-ansi@^6.0.0:
dependencies:
ansi-regex "^5.0.0"
-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"
- integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==
+strip-final-newline@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
+ integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
-strip-json-comments@^3.0.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
+strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
-style-loader@^1.1.3:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.2.1.tgz#c5cbbfbf1170d076cfdd86e0109c5bba114baa1a"
- integrity sha512-ByHSTQvHLkWE9Ir5+lGbVOXhxX10fbprhLvdg96wedFZb4NDekDPxVKv5Fwmio+QcMlkkNfuK+5W1peQ5CUhZg==
+style-loader@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-2.0.0.tgz#9669602fd4690740eaaec137799a03addbbc393c"
+ integrity sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==
dependencies:
loader-utils "^2.0.0"
- schema-utils "^2.6.6"
+ schema-utils "^3.0.0"
styled-components@^5.1.1:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.1.1.tgz#96dfb02a8025794960863b9e8e365e3b6be5518d"
- integrity sha512-1ps8ZAYu2Husx+Vz8D+MvXwEwvMwFv+hqqUwhNlDN5ybg6A+3xyW1ECrAgywhvXapNfXiz79jJyU0x22z0FFTg==
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.2.1.tgz#6ed7fad2dc233825f64c719ffbdedd84ad79101a"
+ integrity sha512-sBdgLWrCFTKtmZm/9x7jkIabjFNVzCUeKfoQsM6R3saImkUnjx0QYdLwJHBjY9ifEcmjDamJDVfknWm1yxZPxQ==
dependencies:
"@babel/helper-module-imports" "^7.0.0"
"@babel/traverse" "^7.4.5"
@@ -6085,10 +5878,10 @@ styled-components@^5.1.1:
shallowequal "^1.1.0"
supports-color "^5.5.0"
-supports-color@7.1.0, supports-color@^7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1"
- integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==
+supports-color@7.2.0, supports-color@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
dependencies:
has-flag "^4.0.0"
@@ -6104,18 +5897,21 @@ supports-color@^5.3.0, supports-color@^5.5.0:
dependencies:
has-flag "^3.0.0"
-supports-color@^6.1.0:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
- integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
- dependencies:
- has-flag "^3.0.0"
-
symbol-observable@^1.0.3, symbol-observable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
+table-layout@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.1.tgz#8411181ee951278ad0638aea2f779a9ce42894f9"
+ integrity sha512-dEquqYNJiGwY7iPfZ3wbXDI944iqanTSchrACLL2nOB+1r+h1Nzu2eH+DuPPvWvm5Ry7iAPeFlgEtP5bIp5U7Q==
+ dependencies:
+ array-back "^4.0.1"
+ deep-extend "~0.6.0"
+ typical "^5.2.0"
+ wordwrapjs "^4.0.0"
+
table@^5.2.3:
version "5.4.6"
resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
@@ -6126,6 +5922,16 @@ table@^5.2.3:
slice-ansi "^2.1.0"
string-width "^3.0.0"
+table@^6.0.4:
+ version "6.0.4"
+ resolved "https://registry.yarnpkg.com/table/-/table-6.0.4.tgz#c523dd182177e926c723eb20e1b341238188aa0d"
+ integrity sha512-sBT4xRLdALd+NFBvwOz8bw4b15htyythha+q+DVZqy2RS08PPC8O2sZFgJYEY7bJvbCFKccs+WIZ/cd+xxTWCw==
+ dependencies:
+ ajv "^6.12.4"
+ lodash "^4.17.20"
+ slice-ansi "^4.0.0"
+ string-width "^4.2.0"
+
tapable@^1.0.0, tapable@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
@@ -6168,11 +5974,6 @@ through2@^2.0.0:
readable-stream "~2.3.6"
xtend "~4.0.1"
-through@^2.3.6:
- version "2.3.8"
- resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
- integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
-
timers-browserify@^2.0.4:
version "2.0.11"
resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f"
@@ -6194,13 +5995,6 @@ tmp@0.2.1:
dependencies:
rimraf "^3.0.0"
-tmp@^0.0.33:
- version "0.0.33"
- resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
- integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
- dependencies:
- os-tmpdir "~1.0.2"
-
to-array@0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
@@ -6262,9 +6056,9 @@ tough-cookie@^2.3.3, tough-cookie@~2.5.0:
punycode "^2.1.1"
ts-loader@^8.0.2:
- version "8.0.4"
- resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.4.tgz#02b9c91fbcfdb3114d8b1e98a3829265270eee7a"
- integrity sha512-5u8KF1SW8eCUb/Ff7At81e3wznPmT/27fvaGRO9CziVy+6NlPVRvrzSox4OwU0/e6OflOUB32Err4VquysCSAQ==
+ version "8.0.12"
+ resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.12.tgz#1de9f1de65176318c1e6d187bfc496182f8dc2a0"
+ integrity sha512-UIivVfGVJDdwwjgSrbtcL9Nf10c1BWnL1mxAQUVcnhNIn/P9W3nP5v60Z0aBMtc7ZrE11lMmU6+5jSgAXmGaYw==
dependencies:
chalk "^2.3.0"
enhanced-resolve "^4.0.0"
@@ -6273,11 +6067,12 @@ ts-loader@^8.0.2:
semver "^6.0.0"
ts-node@^9.0.0:
- version "9.0.0"
- resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.0.0.tgz#e7699d2a110cc8c0d3b831715e417688683460b3"
- integrity sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==
+ version "9.1.1"
+ resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
+ integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==
dependencies:
arg "^4.1.0"
+ create-require "^1.1.0"
diff "^4.0.1"
make-error "^1.1.1"
source-map-support "^0.5.17"
@@ -6295,10 +6090,10 @@ tsutils@^3.17.1:
dependencies:
tslib "^1.8.1"
-tsyringe@4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/tsyringe/-/tsyringe-4.3.0.tgz#50ce2ec56c83569a2dfafb7233a5265a2a10bde4"
- integrity sha512-Vzty1M/EQXSsEE8aoIOLl1l793chcPyQAnFJaS1mFDtFvNPY+jknSPwMIF6yfcjua+2GTgwxWFzuA3cjIx4NZA==
+tsyringe@4.4.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/tsyringe/-/tsyringe-4.4.0.tgz#cd8a6866316b4cf643ee5e72c41c8a221ccea73d"
+ integrity sha512-SlMApe1lhIq546CDp7bF+IdF4RB6d+9C5T7B0AS0P/Bm+Qpizj/gEmZzvw9J/KlXPEt4qHTbi1TRvX3rCPSdTg==
dependencies:
tslib "^1.9.3"
@@ -6326,23 +6121,11 @@ type-check@^0.4.0, type-check@~0.4.0:
dependencies:
prelude-ls "^1.2.1"
-type-check@~0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
- integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=
- dependencies:
- prelude-ls "~1.1.2"
-
type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5, type-detect@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
-type-fest@^0.11.0:
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1"
- integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==
-
type-fest@^0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
@@ -6371,6 +6154,11 @@ typescript@^3.9.3:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
+typical@^5.0.0, typical@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066"
+ integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==
+
ua-parser-js@0.7.22:
version "0.7.22"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.22.tgz#960df60a5f911ea8f1c818f3747b99c6e177eae3"
@@ -6458,7 +6246,7 @@ use@^3.1.0:
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
-util-deprecate@^1.0.1, util-deprecate@~1.0.1:
+util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
@@ -6500,10 +6288,10 @@ uuid@^3.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
-v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1:
- version "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==
+v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132"
+ integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==
vary@~1.1.2:
version "1.1.2"
@@ -6571,22 +6359,24 @@ webextensions-api-fake@^0.9.1:
dependencies:
sinon-chrome "^3.0.0"
-webpack-cli@3.3.12:
- version "3.3.12"
- resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a"
- integrity sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==
- dependencies:
- chalk "^2.4.2"
- cross-spawn "^6.0.5"
- enhanced-resolve "^4.1.1"
- findup-sync "^3.0.0"
- global-modules "^2.0.0"
- import-local "^2.0.0"
- interpret "^1.4.0"
- loader-utils "^1.4.0"
- supports-color "^6.1.0"
- v8-compile-cache "^2.1.1"
- yargs "^13.3.2"
+webpack-cli@4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.2.0.tgz#10a09030ad2bd4d8b0f78322fba6ea43ec56aaaa"
+ integrity sha512-EIl3k88vaF4fSxWSgtAQR+VwicfLMTZ9amQtqS4o+TDPW9HGaEpbFBbAZ4A3ZOT5SOnMxNOzROsSTPiE8tBJPA==
+ dependencies:
+ "@webpack-cli/info" "^1.1.0"
+ "@webpack-cli/serve" "^1.1.0"
+ colorette "^1.2.1"
+ command-line-usage "^6.1.0"
+ commander "^6.2.0"
+ enquirer "^2.3.6"
+ execa "^4.1.0"
+ import-local "^3.0.2"
+ interpret "^2.2.0"
+ leven "^3.1.0"
+ rechoir "^0.7.0"
+ v8-compile-cache "^2.2.0"
+ webpack-merge "^4.2.2"
webpack-dev-middleware@^3.7.0:
version "3.7.2"
@@ -6607,6 +6397,13 @@ webpack-log@^2.0.0:
ansi-colors "^3.0.0"
uuid "^3.3.2"
+webpack-merge@^4.2.2:
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d"
+ integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==
+ dependencies:
+ lodash "^4.17.15"
+
webpack-sources@^1.4.0, webpack-sources@^1.4.1:
version "1.4.3"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
@@ -6615,10 +6412,10 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1:
source-list-map "^2.0.0"
source-map "~0.6.1"
-webpack@4.44.1:
- version "4.44.1"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.1.tgz#17e69fff9f321b8f117d1fda714edfc0b939cc21"
- integrity sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==
+webpack@4.44.2:
+ version "4.44.2"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72"
+ integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==
dependencies:
"@webassemblyjs/ast" "1.9.0"
"@webassemblyjs/helper-module-context" "1.9.0"
@@ -6656,13 +6453,6 @@ which@2.0.2, which@^2.0.1:
dependencies:
isexe "^2.0.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"
@@ -6670,11 +6460,19 @@ wide-align@1.1.3:
dependencies:
string-width "^1.0.2 || 2"
-word-wrap@^1.2.3, word-wrap@~1.2.3:
+word-wrap@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
+wordwrapjs@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.0.tgz#9aa9394155993476e831ba8e59fb5795ebde6800"
+ integrity sha512-Svqw723a3R34KvsMgpjFBYCgNOSdcW3mQFK4wIfhGQhtaFVOJmdYoXgi63ne3dTlWgatVcUc7t4HtQ/+bUVIzQ==
+ dependencies:
+ reduce-flatten "^2.0.0"
+ typical "^5.0.0"
+
worker-farm@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8"
@@ -6682,10 +6480,10 @@ worker-farm@^1.7.0:
dependencies:
errno "~0.1.7"
-workerpool@6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.0.0.tgz#85aad67fa1a2c8ef9386a1b43539900f61d03d58"
- integrity sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==
+workerpool@6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.0.2.tgz#e241b43d8d033f1beb52c7851069456039d1d438"
+ integrity sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==
wrap-ansi@^5.1.0:
version "5.1.0"
@@ -6710,13 +6508,6 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
-write@1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3"
- integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==
- dependencies:
- mkdirp "^0.5.1"
-
ws@^7.1.2:
version "7.3.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8"
@@ -6744,11 +6535,6 @@ y18n@^4.0.0:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
-yallist@^2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
- integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
-
yallist@^3.0.2:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
@@ -6762,14 +6548,6 @@ yargs-parser@13.1.2, yargs-parser@^13.1.2:
camelcase "^5.0.0"
decamelize "^1.2.0"
-yargs-parser@^15.0.1:
- version "15.0.1"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.1.tgz#54786af40b820dcb2fb8025b11b4d659d76323b3"
- integrity sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==
- dependencies:
- camelcase "^5.0.0"
- decamelize "^1.2.0"
-
yargs-parser@^18.1.2:
version "18.1.3"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
@@ -6778,18 +6556,17 @@ yargs-parser@^18.1.2:
camelcase "^5.0.0"
decamelize "^1.2.0"
-yargs-unparser@1.6.1:
- version "1.6.1"
- resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.1.tgz#bd4b0ee05b4c94d058929c32cb09e3fce71d3c5f"
- integrity sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==
+yargs-unparser@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb"
+ integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==
dependencies:
- camelcase "^5.3.1"
- decamelize "^1.2.0"
- flat "^4.1.0"
- is-plain-obj "^1.1.0"
- yargs "^14.2.3"
+ camelcase "^6.0.0"
+ decamelize "^4.0.0"
+ flat "^5.0.2"
+ is-plain-obj "^2.1.0"
-yargs@13.3.2, yargs@^13.3.2:
+yargs@13.3.2:
version "13.3.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
@@ -6805,23 +6582,6 @@ yargs@13.3.2, yargs@^13.3.2:
y18n "^4.0.0"
yargs-parser "^13.1.2"
-yargs@^14.2.3:
- version "14.2.3"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.3.tgz#1a1c3edced1afb2a2fea33604bc6d1d8d688a414"
- integrity sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==
- dependencies:
- cliui "^5.0.0"
- decamelize "^1.2.0"
- find-up "^3.0.0"
- get-caller-file "^2.0.1"
- require-directory "^2.1.1"
- require-main-filename "^2.0.0"
- set-blocking "^2.0.0"
- string-width "^3.0.0"
- which-module "^2.0.0"
- y18n "^4.0.0"
- yargs-parser "^15.0.1"
-
yargs@^15.3.1:
version "15.4.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"