aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.eslintrc10
-rw-r--r--e2e/completion.test.ts51
-rw-r--r--e2e/completion_buffers.test.ts100
-rw-r--r--e2e/completion_open.test.ts82
-rw-r--r--e2e/completion_set.test.ts23
-rw-r--r--e2e/lib/Console.ts68
-rw-r--r--e2e/lib/Page.ts4
-rw-r--r--package.json6
-rw-r--r--src/console/components/Console.tsx47
-rw-r--r--src/console/components/Theme.ts53
-rw-r--r--src/console/components/console.scss135
-rw-r--r--src/console/components/console/Completion.tsx49
-rw-r--r--src/console/components/console/CompletionItem.tsx75
-rw-r--r--src/console/components/console/CompletionTitle.tsx17
-rw-r--r--src/console/components/console/Input.tsx27
-rw-r--r--src/console/components/console/Message.tsx31
-rw-r--r--src/content/site-style.ts4
-rw-r--r--test/console/components/console/Completion.test.tsx259
-rw-r--r--test/console/components/console/CompletionItem.test.tsx21
-rw-r--r--test/console/components/console/CompletionTitle.test.tsx15
-rw-r--r--test/console/components/console/Message.test.tsx27
-rw-r--r--tsconfig.json2
-rw-r--r--yarn.lock298
23 files changed, 895 insertions, 509 deletions
diff --git a/.eslintrc b/.eslintrc
index 5eb19bb..9ae5f88 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -36,5 +36,13 @@
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }]
- }
+ },
+ "overrides": [
+ {
+ "files": ["**/*.tsx"],
+ "rules": {
+ "react/prop-types": "off"
+ }
+ }
+ ]
}
diff --git a/e2e/completion.test.ts b/e2e/completion.test.ts
index bc065d3..c0e7052 100644
--- a/e2e/completion.test.ts
+++ b/e2e/completion.test.ts
@@ -28,33 +28,24 @@ describe("general completion test", () => {
page = await Page.navigateTo(webdriver, "about:blank");
});
- it("should all commands on empty line", async () => {
+ it("should shows all commands on empty line", async () => {
const console = await page.showConsole();
- const items = await console.getCompletions();
- assert.strictEqual(items.length, 12);
- assert.deepStrictEqual(items[0], {
- type: "title",
- text: "Console Command",
- });
- assert.ok(items[1].text.startsWith("set"));
- assert.ok(items[2].text.startsWith("open"));
- assert.ok(items[3].text.startsWith("tabopen"));
+ const groups = await console.getCompletions();
+ assert.strictEqual(groups.length, 1);
+ assert.strictEqual(groups[0].title, "Console Command");
+ assert.strictEqual(groups[0].items.length, 11);
});
- it("should only commands filtered by prefix", async () => {
+ it("should shows commands filtered by prefix", async () => {
const console = await page.showConsole();
await console.inputKeys("b");
- const items = await console.getCompletions();
- assert.strictEqual(items.length, 4);
- assert.deepStrictEqual(items[0], {
- type: "title",
- text: "Console Command",
- });
- assert.ok(items[1].text.startsWith("buffer"));
- assert.ok(items[2].text.startsWith("bdelete"));
- assert.ok(items[3].text.startsWith("bdeletes"));
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+ assert.ok(items[0].text.startsWith("buffer"));
+ assert.ok(items[1].text.startsWith("bdelete"));
+ assert.ok(items[2].text.startsWith("bdeletes"));
});
// > byffer
@@ -65,21 +56,24 @@ describe("general completion test", () => {
const console = await page.showConsole();
await console.inputKeys("b");
await eventually(async () => {
- const items = await console.getCompletions();
- assert.strictEqual(items.length, 4);
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+ assert.strictEqual(items.length, 3);
});
await console.sendKeys(Key.TAB);
await eventually(async () => {
- const items = await console.getCompletions();
- assert.ok(items[1].highlight);
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+ assert.ok(items[0].highlight);
assert.strictEqual(await console.currentValue(), "buffer");
});
await console.sendKeys(Key.TAB, Key.TAB);
await eventually(async () => {
- const items = await console.getCompletions();
- assert.ok(items[3].highlight);
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+ assert.ok(items[2].highlight);
assert.strictEqual(await console.currentValue(), "bdeletes");
});
@@ -90,8 +84,9 @@ describe("general completion test", () => {
await console.sendKeys(Key.SHIFT, Key.TAB);
await eventually(async () => {
- const items = await console.getCompletions();
- assert.ok(items[3].highlight);
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+ assert.ok(items[2].highlight);
assert.strictEqual(await console.currentValue(), "bdeletes");
});
});
diff --git a/e2e/completion_buffers.test.ts b/e2e/completion_buffers.test.ts
index 57603f6..13d07ea 100644
--- a/e2e/completion_buffers.test.ts
+++ b/e2e/completion_buffers.test.ts
@@ -72,17 +72,19 @@ describe("completion on buffer/bdelete/bdeletes", () => {
await console.inputKeys("buffer ");
await eventually(async () => {
- const items = await console.getCompletions();
- assert.strictEqual(items.length, 6);
- assert.deepStrictEqual(items[0], { type: "title", text: "Buffers" });
- assert.ok(items[1].text.startsWith("1:"));
- assert.ok(items[2].text.startsWith("2:"));
- assert.ok(items[3].text.startsWith("3:"));
- assert.ok(items[4].text.startsWith("4:"));
- assert.ok(items[5].text.startsWith("5:"));
-
- assert.ok(items[3].text.includes("%"));
- assert.ok(items[5].text.includes("#"));
+ const groups = await console.getCompletions();
+ assert.strictEqual(groups.length, 1);
+ assert.strictEqual(groups[0].title, "Buffers");
+
+ const items = groups[0].items;
+ assert.ok(items[0].text.startsWith("1:"));
+ assert.ok(items[1].text.startsWith("2:"));
+ assert.ok(items[2].text.startsWith("3:"));
+ assert.ok(items[3].text.startsWith("4:"));
+ assert.ok(items[4].text.startsWith("5:"));
+
+ assert.ok(items[2].text.includes("%"));
+ assert.ok(items[4].text.includes("#"));
});
});
@@ -91,11 +93,10 @@ describe("completion on buffer/bdelete/bdeletes", () => {
await console.inputKeys("buffer title_site2");
await eventually(async () => {
- const items = await console.getCompletions();
- assert.deepStrictEqual(items[0], { type: "title", text: "Buffers" });
- assert.ok(items[1].text.startsWith("2:"));
- assert.ok(items[1].text.includes("title_site2"));
- assert.ok(items[1].text.includes(server.url("/site2")));
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+ assert.ok(items[0].text.startsWith("2:"));
+ assert.ok(items[0].text.includes("title_site2"));
});
});
@@ -104,9 +105,9 @@ describe("completion on buffer/bdelete/bdeletes", () => {
await console.inputKeys("buffer /site2");
await eventually(async () => {
- const items = await console.getCompletions();
- assert.deepStrictEqual(items[0], { type: "title", text: "Buffers" });
- assert.ok(items[1].text.startsWith("2:"));
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+ assert.ok(items[0].text.startsWith("2:"));
});
});
@@ -115,10 +116,11 @@ describe("completion on buffer/bdelete/bdeletes", () => {
await console.inputKeys("buffer 2");
await eventually(async () => {
- const items = await console.getCompletions();
- assert.strictEqual(items.length, 2);
- assert.deepStrictEqual(items[0], { type: "title", text: "Buffers" });
- assert.ok(items[1].text.startsWith("2:"));
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+
+ assert.strictEqual(items.length, 1);
+ assert.ok(items[0].text.startsWith("2:"));
});
});
@@ -127,11 +129,12 @@ describe("completion on buffer/bdelete/bdeletes", () => {
await console.inputKeys("bdelete site");
await eventually(async () => {
- const items = await console.getCompletions();
- assert.strictEqual(items.length, 4);
- assert.ok(items[1].text.includes("site3"));
- assert.ok(items[2].text.includes("site4"));
- assert.ok(items[3].text.includes("site5"));
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+ assert.strictEqual(items.length, 3);
+ assert.ok(items[0].text.includes("site3"));
+ assert.ok(items[1].text.includes("site4"));
+ assert.ok(items[2].text.includes("site5"));
});
});
@@ -140,11 +143,12 @@ describe("completion on buffer/bdelete/bdeletes", () => {
await console.inputKeys("bdeletes site");
await eventually(async () => {
- const items = await console.getCompletions();
- assert.strictEqual(items.length, 4);
- assert.ok(items[1].text.includes("site3"));
- assert.ok(items[2].text.includes("site4"));
- assert.ok(items[3].text.includes("site5"));
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+ assert.strictEqual(items.length, 3);
+ assert.ok(items[0].text.includes("site3"));
+ assert.ok(items[1].text.includes("site4"));
+ assert.ok(items[2].text.includes("site5"));
});
});
@@ -153,13 +157,14 @@ describe("completion on buffer/bdelete/bdeletes", () => {
await console.inputKeys("bdelete! site");
await eventually(async () => {
- const items = await console.getCompletions();
- assert.strictEqual(items.length, 6);
- assert.ok(items[1].text.includes("site1"));
- assert.ok(items[2].text.includes("site2"));
- assert.ok(items[3].text.includes("site3"));
- assert.ok(items[4].text.includes("site4"));
- assert.ok(items[5].text.includes("site5"));
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+ assert.strictEqual(items.length, 5);
+ assert.ok(items[0].text.includes("site1"));
+ assert.ok(items[1].text.includes("site2"));
+ assert.ok(items[2].text.includes("site3"));
+ assert.ok(items[3].text.includes("site4"));
+ assert.ok(items[4].text.includes("site5"));
});
});
@@ -168,13 +173,14 @@ describe("completion on buffer/bdelete/bdeletes", () => {
await console.inputKeys("bdeletes! site");
await eventually(async () => {
- const items = await console.getCompletions();
- assert.strictEqual(items.length, 6);
- assert.ok(items[1].text.includes("site1"));
- assert.ok(items[2].text.includes("site2"));
- assert.ok(items[3].text.includes("site3"));
- assert.ok(items[4].text.includes("site4"));
- assert.ok(items[5].text.includes("site5"));
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+ assert.strictEqual(items.length, 5);
+ assert.ok(items[0].text.includes("site1"));
+ assert.ok(items[1].text.includes("site2"));
+ assert.ok(items[2].text.includes("site3"));
+ assert.ok(items[3].text.includes("site4"));
+ assert.ok(items[4].text.includes("site5"));
});
});
});
diff --git a/e2e/completion_open.test.ts b/e2e/completion_open.test.ts
index cefb44f..7eef4c2 100644
--- a/e2e/completion_open.test.ts
+++ b/e2e/completion_open.test.ts
@@ -45,31 +45,13 @@ describe("completion on open/tabopen/winopen commands", () => {
await console.inputKeys("open ");
await eventually(async () => {
- const completions = await console.getCompletions();
- assert.ok(
- completions.find(
- (x) => x.type === "title" && x.text === "Search Engines"
- )
- );
- assert.ok(
- completions.find((x) => x.type === "title" && x.text === "Bookmarks")
- );
- assert.ok(
- completions.find((x) => x.type === "title" && x.text === "History")
- );
- });
- });
-
- it('should filter items with URLs by keywords on "open" command', async () => {
- const console = await page.showConsole();
- await console.inputKeys("open https://");
-
- await eventually(async () => {
- const completions = await console.getCompletions();
- const items = completions
- .filter((x) => x.type === "item")
- .map((x) => x.text);
- assert.ok(items.every((x) => x.includes("https://")));
+ const groups = await console.getCompletions();
+ const titles = groups.map((group) => group.title);
+ assert.deepStrictEqual(titles, [
+ "Search Engines",
+ "Bookmarks",
+ "History",
+ ]);
});
});
@@ -78,11 +60,9 @@ describe("completion on open/tabopen/winopen commands", () => {
await console.inputKeys("open getting");
await eventually(async () => {
- const completions = await console.getCompletions();
- const items = completions
- .filter((x) => x.type === "item")
- .map((x) => x.text);
- assert.ok(items.every((x) => x.toLowerCase().includes("getting")));
+ const groups = await console.getCompletions();
+ const items = groups.map((group) => group.items).flat();
+ assert.ok(items.every((x) => x.text.toLowerCase().includes("getting")));
});
});
@@ -91,24 +71,20 @@ describe("completion on open/tabopen/winopen commands", () => {
await console.inputKeys("tabopen getting");
await eventually(async () => {
- const completions = await console.getCompletions();
- const items = completions
- .filter((x) => x.type === "item")
- .map((x) => x.text);
- assert.ok(items.every((x) => x.includes("https://")));
+ const groups = await console.getCompletions();
+ const items = groups.map((group) => group.items).flat();
+ assert.ok(items.every((x) => x.text.toLowerCase().includes("getting")));
});
});
it('should filter items with titles by keywords on "winopen" command', async () => {
const console = await page.showConsole();
- await console.inputKeys("winopen https://");
+ await console.inputKeys("winopen getting");
await eventually(async () => {
- const completions = await console.getCompletions();
- const items = completions
- .filter((x) => x.type === "item")
- .map((x) => x.text);
- assert.ok(items.every((x) => x.includes("https://")));
+ const groups = await console.getCompletions();
+ const items = groups.map((group) => group.items).flat();
+ assert.ok(items.every((x) => x.text.toLowerCase().includes("getting")));
});
});
@@ -121,10 +97,8 @@ describe("completion on open/tabopen/winopen commands", () => {
await console.inputKeys("open ");
await eventually(async () => {
- const completions = await console.getCompletions();
- const titles = completions
- .filter((x) => x.type === "title")
- .map((x) => x.text);
+ const groups = await console.getCompletions();
+ const titles = groups.map((group) => group.title);
assert.deepStrictEqual(titles, [
"Search Engines",
"Bookmarks",
@@ -141,10 +115,8 @@ describe("completion on open/tabopen/winopen commands", () => {
await console.inputKeys("open ");
await eventually(async () => {
- const completions = await console.getCompletions();
- const titles = completions
- .filter((x) => x.type === "title")
- .map((x) => x.text);
+ const groups = await console.getCompletions();
+ const titles = groups.map((group) => group.title);
assert.deepStrictEqual(titles, [
"Bookmarks",
"Search Engines",
@@ -164,10 +136,8 @@ describe("completion on open/tabopen/winopen commands", () => {
await console.inputKeys("open ");
await eventually(async () => {
- const completions = await console.getCompletions();
- const titles = completions
- .filter((x) => x.type === "title")
- .map((x) => x.text);
+ const groups = await console.getCompletions();
+ const titles = groups.map((group) => group.title);
assert.deepStrictEqual(titles, [
"Search Engines",
"Bookmarks",
@@ -188,10 +158,8 @@ describe("completion on open/tabopen/winopen commands", () => {
await console.inputKeys("open ");
await eventually(async () => {
- const completions = await console.getCompletions();
- const titles = completions
- .filter((x) => x.type === "title")
- .map((x) => x.text);
+ const groups = await console.getCompletions();
+ const titles = groups.map((group) => group.title);
assert.deepStrictEqual(titles, [
"Bookmarks",
"Search Engines",
diff --git a/e2e/completion_set.test.ts b/e2e/completion_set.test.ts
index 0a45ed3..929f649 100644
--- a/e2e/completion_set.test.ts
+++ b/e2e/completion_set.test.ts
@@ -33,14 +33,14 @@ describe("completion on set commands", () => {
await console.inputKeys("set ");
await eventually(async () => {
- const items = await console.getCompletions();
- assert.strictEqual(items.length, 6);
- assert.deepStrictEqual(items[0], { type: "title", text: "Properties" });
- assert.ok(items[1].text.startsWith("hintchars"));
- assert.ok(items[2].text.startsWith("smoothscroll"));
- assert.ok(items[3].text.startsWith("nosmoothscroll"));
- assert.ok(items[4].text.startsWith("complete"));
- assert.ok(items[5].text.startsWith("colorscheme"));
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+ assert.strictEqual(items.length, 5);
+ assert.ok(items[0].text.startsWith("hintchars"));
+ assert.ok(items[1].text.startsWith("smoothscroll"));
+ assert.ok(items[2].text.startsWith("nosmoothscroll"));
+ assert.ok(items[3].text.startsWith("complete"));
+ assert.ok(items[4].text.startsWith("colorscheme"));
});
});
@@ -49,9 +49,10 @@ describe("completion on set commands", () => {
await console.inputKeys("set no");
await eventually(async () => {
- const items = await console.getCompletions();
- assert.strictEqual(items.length, 2);
- assert.ok(items[1].text.includes("nosmoothscroll"));
+ const groups = await console.getCompletions();
+ const items = groups[0].items;
+ assert.strictEqual(items.length, 1);
+ assert.ok(items[0].text.includes("nosmoothscroll"));
});
});
});
diff --git a/e2e/lib/Console.ts b/e2e/lib/Console.ts
index 2c128d1..4d017cc 100644
--- a/e2e/lib/Console.ts
+++ b/e2e/lib/Console.ts
@@ -1,7 +1,11 @@
import { WebDriver, By, Key } from "selenium-webdriver";
+export type CompletionGroups = {
+ title: string;
+ items: Array<CompletionItem>;
+};
+
export type CompletionItem = {
- type: string;
text: string;
highlight: boolean;
};
@@ -25,23 +29,17 @@ export class Console {
}
async execCommand(command: string): Promise<void> {
- const input = await this.webdriver.findElement(
- By.css("input.vimvixen-console-command-input")
- );
+ const input = await this.webdriver.findElement(By.css("input"));
await input.sendKeys(command, Key.ENTER);
}
async getErrorMessage(): Promise<string> {
- const p = await this.webdriver.findElement(
- By.css(".vimvixen-console-error")
- );
+ const p = await this.webdriver.findElement(By.css("[role=alert]"));
return p.getText();
}
async getInformationMessage(): Promise<string> {
- const p = await this.webdriver.findElement(
- By.css(".vimvixen-console-info")
- );
+ const p = await this.webdriver.findElement(By.css("[role=status]"));
return p.getText();
}
@@ -50,36 +48,42 @@ export class Console {
await input.sendKeys(...keys);
}
- getCompletions(): Promise<CompletionItem[]> {
+ getCompletions(): Promise<CompletionGroups[]> {
return this.webdriver.executeScript(() => {
- const items = document.querySelectorAll(
- ".vimvixen-console-completion > li"
- );
- if (items.length === 0) {
+ const groups = document.querySelectorAll("[role=group]");
+ if (groups.length === 0) {
throw new Error("completion items not found");
}
- const objs = [];
- for (const li of Array.from(items)) {
- if (li.classList.contains("vimvixen-console-completion-title")) {
- objs.push({ type: "title", text: li.textContent!.trim() });
- } else if (li.classList.contains("vimvixen-console-completion-item")) {
- const highlight = li.classList.contains(
- "vimvixen-completion-selected"
- );
- objs.push({ type: "item", text: li.textContent!.trim(), highlight });
- } else {
- throw new Error(`unexpected class: ${li.className}`);
- }
- }
- return objs;
+ return Array.from(groups).map((group) => {
+ const describedby = group.getAttribute("aria-describedby") as string;
+ const title = document.getElementById(describedby)!;
+ const items = group.querySelectorAll("[role=menuitem]");
+
+ return {
+ title: title.textContent!.trim(),
+ items: Array.from(items).map((item) => ({
+ text: document.getElementById(
+ item.getAttribute("aria-labelledby")!
+ )!.textContent,
+ highlight: item.getAttribute("aria-selected") === "true",
+ })),
+ };
+ });
});
}
async getTheme(): Promise<string> {
- const wrapper = await this.webdriver.findElement(By.css("div[data-theme]"));
- const theme = await wrapper.getAttribute("data-theme");
- return theme;
+ const color = (await this.webdriver.executeScript(() => {
+ const input = document.querySelector("input")!;
+ return window.getComputedStyle(input).backgroundColor;
+ })) as string;
+ if (color === "rgb(5, 32, 39)") {
+ return "dark";
+ } else if (color === "rgb(255, 255, 255)") {
+ return "light";
+ }
+ throw new Error(`unknown input color: ${color}`);
}
async close(): Promise<void> {
diff --git a/e2e/lib/Page.ts b/e2e/lib/Page.ts
index 85bda8d..6531f19 100644
--- a/e2e/lib/Page.ts
+++ b/e2e/lib/Page.ts
@@ -46,9 +46,7 @@ export default class Page {
await this.sendKeys(":");
await this.webdriver.wait(until.elementIsVisible(iframe));
await this.webdriver.switchTo().frame(0);
- await this.webdriver.wait(
- until.elementLocated(By.css("input.vimvixen-console-command-input"))
- );
+ await this.webdriver.wait(until.elementLocated(By.css("input")));
return new Console(this.webdriver);
}
diff --git a/package.json b/package.json
index 6121a1a..a5d9389 100644
--- a/package.json
+++ b/package.json
@@ -36,8 +36,9 @@
"@types/redux-promise": "^0.5.28",
"@types/selenium-webdriver": "^4.0.6",
"@types/sinon": "^9.0.0",
+ "@types/styled-components": "^5.1.2",
"@typescript-eslint/eslint-plugin": "3.9.0",
- "@typescript-eslint/parser": "3.9.0",
+ "@typescript-eslint/parser": "3.10.1",
"ajv": "^6.11.0",
"ajv-cli": "^3.0.0",
"chai": "^4.2.0",
@@ -62,7 +63,7 @@
"lanthan": "0.0.2",
"mocha": "^8.1.1",
"node-sass": "^4.13.1",
- "prettier": "2.0.5",
+ "prettier": "2.1.2",
"prettier-eslint": "11.0.0",
"react": "16.13.1",
"react-dom": "16.13.1",
@@ -76,6 +77,7 @@
"sinon": "^9.0.3",
"sinon-chrome": "^3.0.1",
"style-loader": "^1.1.3",
+ "styled-components": "^5.1.1",
"ts-loader": "^8.0.2",
"ts-node": "^9.0.0",
"tsyringe": "4.3.0",
diff --git a/src/console/components/Console.tsx b/src/console/components/Console.tsx
index a0e22e4..a23c459 100644
--- a/src/console/components/Console.tsx
+++ b/src/console/components/Console.tsx
@@ -11,6 +11,13 @@ import CommandLineParser, {
} from "../commandline/CommandLineParser";
import { Command } from "../../shared/Command";
import ColorScheme from "../../shared/ColorScheme";
+import { LightTheme, DarkTheme } from "./Theme";
+import styled from "./Theme";
+import { ThemeProvider } from "styled-components";
+
+const ConsoleWrapper = styled.div`
+ border-top: 1px solid gray;
+`;
const COMPLETION_MAX_ITEMS = 33;
@@ -143,28 +150,34 @@ class Console extends React.Component<Props> {
case "command":
case "find":
return (
- <div data-theme={theme} className="vimvixen-console-command-wrapper">
- <Completion
- size={COMPLETION_MAX_ITEMS}
- completions={this.props.completions}
- select={this.props.select}
- />
- <Input
- ref={this.input}
- mode={this.props.mode}
- onBlur={this.onBlur.bind(this)}
- onKeyDown={this.onKeyDown.bind(this)}
- onChange={this.onChange.bind(this)}
- value={this.props.consoleText}
- />
- </div>
+ <ThemeProvider
+ theme={theme === ColorScheme.Dark ? DarkTheme : LightTheme}
+ >
+ <ConsoleWrapper>
+ <Completion
+ size={COMPLETION_MAX_ITEMS}
+ completions={this.props.completions}
+ select={this.props.select}
+ />
+ <Input
+ ref={this.input}
+ mode={this.props.mode}
+ onBlur={this.onBlur.bind(this)}
+ onKeyDown={this.onKeyDown.bind(this)}
+ onChange={this.onChange.bind(this)}
+ value={this.props.consoleText}
+ />
+ </ConsoleWrapper>
+ </ThemeProvider>
);
case "info":
case "error":
return (
- <div data-theme={theme}>
+ <ThemeProvider
+ theme={theme === ColorScheme.Dark ? DarkTheme : LightTheme}
+ >
<Message mode={this.props.mode}>{this.props.messageText}</Message>
- </div>
+ </ThemeProvider>
);
default:
return null;
diff --git a/src/console/components/Theme.ts b/src/console/components/Theme.ts
new file mode 100644
index 0000000..dd7baa5
--- /dev/null
+++ b/src/console/components/Theme.ts
@@ -0,0 +1,53 @@
+import baseStyled, { ThemedStyledInterface } from "styled-components";
+
+type Theme = {
+ completionTitleBackground: string;
+ completionTitleForeground: string;
+ completionItemBackground: string;
+ completionItemForeground: string;
+ completionItemDescriptionForeground: string;
+ completionSelectedBackground: string;
+ completionSelectedForeground: string;
+ commandBackground: string;
+ commandForeground: string;
+ consoleErrorBackground: string;
+ consoleErrorForeground: string;
+ consoleInfoBackground: string;
+ consoleInfoForeground: string;
+};
+
+export const LightTheme: Theme = {
+ completionTitleBackground: "lightgray",
+ completionTitleForeground: "#000000",
+ completionItemBackground: "#ffffff",
+ completionItemForeground: "#000000",
+ completionItemDescriptionForeground: "#008000",
+ completionSelectedBackground: "#ffff00",
+ completionSelectedForeground: "#000000",
+ commandBackground: "#ffffff",
+ commandForeground: "#000000",
+ consoleErrorBackground: "#ff0000",
+ consoleErrorForeground: "#ffffff",
+ consoleInfoBackground: "#ffffff",
+ consoleInfoForeground: "#018786",
+};
+
+export const DarkTheme: Theme = {
+ completionTitleBackground: "#052027",
+ completionTitleForeground: "white",
+ completionItemBackground: "#2f474f",
+ completionItemForeground: "white",
+ completionItemDescriptionForeground: "#86fab0",
+ completionSelectedBackground: "#eeff41",
+ completionSelectedForeground: "#000000",
+ commandBackground: "#052027",
+ commandForeground: "white",
+ consoleErrorBackground: "red",
+ consoleErrorForeground: "white",
+ consoleInfoBackground: "#052027",
+ consoleInfoForeground: "#ffffff",
+};
+
+const styled = baseStyled as ThemedStyledInterface<Theme>;
+
+export default styled;
diff --git a/src/console/components/console.scss b/src/console/components/console.scss
index ccb769b..2d548df 100644
--- a/src/console/components/console.scss
+++ b/src/console/components/console.scss
@@ -1,38 +1,18 @@
-[data-theme="light"] {
- --completion-title-background: lightgray;
- --completion-title-foreground: #000000;
- --completion-item-background: #ffffff;
- --completion-item-foreground: #000000;
- --completion-item-description-foreground: #008000;
- --completion-selected-background: #ffff00;
- --completion-selected-foreground: #000000;
- --command-background: #ffffff;
- --command-foreground: #000000;
- --console-error-background: #ff0000;
- --console-error-foreground: #ffffff;
- --console-info-background: #ffffff;
- --console-info-foreground: #018786;
-}
-
-[data-theme="dark"] {
- --completion-title-background: #052027;
- --completion-title-foreground: white;
- --completion-item-background: #2f474f;
- --completion-item-foreground: white;
- --completion-item-description-foreground: #86fab0;
- --completion-selected-background: #eeff41;
- --completion-selected-foreground: #000000;
- --command-background: #052027;
- --command-foreground: white;
- --console-error-background: red;
- --console-error-foreground: white;
- --console-info-background: #052027;
- --console-info-foreground: #ffffff;
-}
-
html, body, * {
margin: 0;
padding: 0;
+
+ font-style: normal;
+ font-family: monospace;
+ font-size: 12px;
+ line-height: 16px;
+}
+
+input {
+ font-style: normal;
+ font-family: monospace;
+ font-size: 12px;
+ line-height: 16px;
}
body {
@@ -47,95 +27,4 @@ body {
bottom: 0;
margin: 0;
padding: 0;
-
- @mixin console-font {
- font-style: normal;
- font-family: monospace;
- font-size: 12px;
- line-height: 16px;
- }
-
- &-command-wrapper {
- border-top: 1px solid gray;
- }
-
- &-completion {
- @include console-font;
-
- &-title {
- background-color: var(--completion-title-background);
- color: var(--completion-title-foreground);
- font-weight: bold;
- margin: 0;
- padding: 0;
- }
-
- &-item {
- background-color: var(--completion-item-background);
- color: var(--completion-item-foreground);
-
- padding-left: 1.5rem;
- background-position: 0 center;
- background-size: contain;
- background-repeat: no-repeat;
- white-space: pre;
-
- &.vimvixen-completion-selected {
- background-color: var(--completion-selected-background);
- color: var(--completion-selected-foreground);
- }
-
- &-caption {
- display: inline-block;
- width: 40%;
- text-overflow: ellipsis;
- overflow: hidden;
- }
-
- &-url {
- display: inline-block;
- color: var(--completion-item-description-foreground);
- width: 60%;
- text-overflow: ellipsis;
- overflow: hidden;
- }
- }
- }
-
- &-message {
- @include console-font;
-
- border-top: 1px solid gray;
- }
-
- &-error {
- background-color: var(--console-error-background);
- color: var(--console-error-foreground);
- font-weight: bold;
- }
-
- &-info {
- background-color: var(--console-info-background);
- color: var(--console-info-foreground);
- font-weight: normal;
- }
-
- &-command {
- background-color: var(--command-background);
- color: var(--command-foreground);
- display: flex;
-
- &-prompt {
- @include console-font;
- }
-
- &-input {
- border: none;
- flex-grow: 1;
- background-color: var(--command-background);
- color: var(--command-foreground);
-
- @include console-font;
- }
- }
}
diff --git a/src/console/components/console/Completion.tsx b/src/console/components/console/Completion.tsx
index 9b4cf15..09ae278 100644
--- a/src/console/components/console/Completion.tsx
+++ b/src/console/components/console/Completion.tsx
@@ -63,29 +63,52 @@ class Completion extends React.Component<Props, State> {
}
render() {
- let eles = [];
- let index = 0;
+ let itemIndex = 0;
+ let viewIndex = 0;
+ const groups: Array<JSX.Element> = [];
+ const viewOffset = this.state.viewOffset;
+ const viewSize = this.props.size;
- for (const group of this.props.completions) {
- eles.push(<CompletionTitle key={`group-${index}`} title={group.name} />);
+ this.props.completions.forEach((group, groupIndex) => {
+ const items = [];
+ const title = (
+ <CompletionTitle
+ id={`title-${groupIndex}`}
+ key={`group-${groupIndex}`}
+ shown={viewOffset <= viewIndex && viewIndex < viewOffset + viewSize}
+ title={group.name}
+ />
+ );
+ ++viewIndex;
for (const item of group.items) {
- eles.push(
+ items.push(
<CompletionItem
- key={`item-${index}`}
+ shown={viewOffset <= viewIndex && viewIndex < viewOffset + viewSize}
+ key={`item-${itemIndex}`}
icon={item.icon}
caption={item.caption}
url={item.url}
- highlight={index === this.props.select}
+ highlight={itemIndex === this.props.select}
+ aria-selected={itemIndex === this.props.select}
+ role="menuitem"
/>
);
- ++index;
+ ++viewIndex;
+ ++itemIndex;
}
- }
-
- const viewOffset = this.state.viewOffset;
- eles = eles.slice(viewOffset, viewOffset + this.props.size);
+ groups.push(
+ <div
+ key={`group-${groupIndex}`}
+ role="group"
+ aria-describedby={`title-${groupIndex}`}
+ >
+ {title}
+ <ul>{items}</ul>
+ </div>
+ );
+ });
- return <ul className="vimvixen-console-completion">{eles}</ul>;
+ return <div role="menu">{groups}</div>;
}
}
diff --git a/src/console/components/console/CompletionItem.tsx b/src/console/components/console/CompletionItem.tsx
index 657f360..5f2f9f6 100644
--- a/src/console/components/console/CompletionItem.tsx
+++ b/src/console/components/console/CompletionItem.tsx
@@ -1,35 +1,62 @@
import React from "react";
-import PropTypes from "prop-types";
+import styled from "../Theme";
+
+const Container = styled.li<{
+ shown: boolean;
+ icon: string;
+ highlight: boolean;
+}>`
+ background-image: ${({ icon }) => "url(" + icon + ")"};
+ background-color: ${({ highlight, theme }) =>
+ highlight
+ ? theme.completionSelectedBackground
+ : theme.completionItemBackground};
+ color: ${({ highlight, theme }) =>
+ highlight
+ ? theme.completionSelectedForeground
+ : theme.completionItemForeground};
+ display: ${({ shown }) => (shown ? "display" : "none")};
+ padding-left: 1.8rem;
+ background-position: 0 center;
+ background-size: contain;
+ background-repeat: no-repeat;
+ white-space: pre;
+`;
+
+const Caption = styled.span`
+ display: inline-block;
+ width: 40%;
+ text-overflow: ellipsis;
+ overflow: hidden;
+`;
+
+const Description = styled.span`
+ display: inline-block;
+ color: ${({ theme }) => theme.completionItemDescriptionForeground};
+ width: 60%;
+ text-overflow: ellipsis;
+ overflow: hidden;
+`;
interface Props {
+ shown: boolean;
highlight: boolean;
caption?: string;
url?: string;
icon?: string;
}
-const CompletionItem = (props: Props) => {
- let className = "vimvixen-console-completion-item";
- if (props.highlight) {
- className += " vimvixen-completion-selected";
- }
- return (
- <li
- className={className}
- style={{ backgroundImage: "url(" + props.icon + ")" }}
- >
- <span className="vimvixen-console-completion-item-caption">
- {props.caption}
- </span>
- <span className="vimvixen-console-completion-item-url">{props.url}</span>
- </li>
- );
-};
-
-CompletionItem.propTypes = {
- highlight: PropTypes.bool,
- caption: PropTypes.string,
- url: PropTypes.string,
-};
+const CompletionItem: React.FC<React.HTMLAttributes<HTMLElement> & Props> = (
+ props
+) => (
+ <Container
+ icon={props.icon || ""}
+ aria-labelledby={`completion-item-${props.caption}`}
+ {...props}
+ >
+ <Caption id={`completion-item-${props.caption}`}>{props.caption}</Caption>
+ <Description>{props.url}</Description>
+ </Container>
+);
export default CompletionItem;
diff --git a/src/console/components/console/CompletionTitle.tsx b/src/console/components/console/CompletionTitle.tsx
index 7257006..ec2fc8b 100644
--- a/src/console/components/console/CompletionTitle.tsx
+++ b/src/console/components/console/CompletionTitle.tsx
@@ -1,11 +1,22 @@
import React from "react";
+import styled from "../Theme";
+
+const Li = styled.li<{ shown: boolean }>`
+ display: ${({ shown }) => (shown ? "display" : "none")};
+ background-color: ${({ theme }) => theme.completionTitleBackground};
+ color: ${({ theme }) => theme.completionTitleForeground};
+ font-weight: bold;
+ margin: 0;
+ padding: 0;
+`;
interface Props {
+ shown: boolean;
title: string;
}
-const CompletionTitle = (props: Props) => {
- return <li className="vimvixen-console-completion-title">{props.title}</li>;
-};
+const CompletionTitle: React.FC<React.HTMLAttributes<HTMLElement> & Props> = (
+ props
+) => <Li {...props}>{props.title}</Li>;
export default CompletionTitle;
diff --git a/src/console/components/console/Input.tsx b/src/console/components/console/Input.tsx
index e412a0c..448b096 100644
--- a/src/console/components/console/Input.tsx
+++ b/src/console/components/console/Input.tsx
@@ -1,4 +1,22 @@
import React from "react";
+import styled from "../Theme";
+
+const Container = styled.div`
+ background-color: ${({ theme }) => theme.commandBackground};
+ color: ${({ theme }) => theme.commandForeground};
+ display: flex;
+`;
+
+const Prompt = styled.i`
+ font-style: normal;
+`;
+
+const InputInner = styled.input`
+ border: none;
+ flex-grow: 1;
+ background-color: ${({ theme }) => theme.commandBackground};
+ color: ${({ theme }) => theme.commandForeground};
+`;
interface Props {
mode: string;
@@ -32,17 +50,16 @@ class Input extends React.Component<Props> {
}
return (
- <div className="vimvixen-console-command">
- <i className="vimvixen-console-command-prompt">{prompt}</i>
- <input
- className="vimvixen-console-command-input"
+ <Container>
+ <Prompt>{prompt}</Prompt>
+ <InputInner
ref={this.input}
onBlur={this.props.onBlur}
onKeyDown={this.props.onKeyDown}
onChange={this.props.onChange}
value={this.props.value}
/>
- </div>
+ </Container>
);
}
}
diff --git a/src/console/components/console/Message.tsx b/src/console/components/console/Message.tsx
index fd1c9d7..73498fd 100644
--- a/src/console/components/console/Message.tsx
+++ b/src/console/components/console/Message.tsx
@@ -1,24 +1,31 @@
import React from "react";
+import styled from "../Theme";
+
+const Error = styled.p`
+ border-top: 1px solid gray;
+ background-color: ${({ theme }) => theme.consoleErrorBackground};
+ color: ${({ theme }) => theme.consoleErrorForeground};
+ font-weight: bold;
+`;
+
+const Info = styled.p`
+ border-top: 1px solid gray;
+ background-color: ${({ theme }) => theme.consoleInfoBackground};
+ color: ${({ theme }) => theme.consoleInfoForeground};
+ font-weight: normal;
+`;
interface Props {
mode: string;
children: string;
}
-const Message = (props: Props) => {
- switch (props.mode) {
+const Message: React.FC<Props> = ({ mode, children }) => {
+ switch (mode) {
case "error":
- return (
- <p className="vimvixen-console-message vimvixen-console-error">
- {props.children}
- </p>
- );
+ return <Error role="alert">{children}</Error>;
case "info":
- return (
- <p className="vimvixen-console-message vimvixen-console-info">
- {props.children}
- </p>
- );
+ return <Info role="status">{children}</Info>;
}
return null;
};
diff --git a/src/content/site-style.ts b/src/content/site-style.ts
index 0c335fc..3748c6b 100644
--- a/src/content/site-style.ts
+++ b/src/content/site-style.ts
@@ -8,8 +8,8 @@ export default `
height: 100%;
position: fixed;
z-index: 2147483647;
- border: none;
- background-color: unset;
+ border: none !important;
+ background-color: unset !important;
pointer-events:none;
}
diff --git a/test/console/components/console/Completion.test.tsx b/test/console/components/console/Completion.test.tsx
index 921720b..0e4e21f 100644
--- a/test/console/components/console/Completion.test.tsx
+++ b/test/console/components/console/Completion.test.tsx
@@ -1,11 +1,11 @@
import React from "react";
import Completion from "../../../../src/console/components/console/Completion";
-import ReactTestRenderer, { ReactTestInstance } from "react-test-renderer";
+import ReactTestRenderer from "react-test-renderer";
import { expect } from "chai";
import CompletionTitle from "../../../../src/console/components/console/CompletionTitle";
import CompletionItem from "../../../../src/console/components/console/CompletionItem";
-describe("console/components/console/completion", () => {
+describe("console/components/console/completion/Completion", () => {
const completions = [
{
name: "Fruit",
@@ -30,27 +30,19 @@ describe("console/components/console/completion", () => {
<Completion completions={completions} size={30} select={-1} />
).root;
- // const children = root.findByType('ul').children as Array<ReactTestInstance>;
- const children = root.findByType("ul").children as Array<ReactTestInstance>;
- expect(children).to.have.lengthOf(8);
- expect(children.map((e) => e.type)).to.deep.equal([
- CompletionTitle,
- CompletionItem,
- CompletionItem,
- CompletionItem,
- CompletionTitle,
- CompletionItem,
- CompletionItem,
- CompletionItem,
- ]);
- expect(children[0].props.title).to.equal("Fruit");
- expect(children[1].props.caption).to.equal("apple");
- expect(children[2].props.caption).to.equal("banana");
- expect(children[3].props.caption).to.equal("cherry");
- expect(children[4].props.title).to.equal("Element");
- expect(children[5].props.caption).to.equal("argon");
- expect(children[6].props.caption).to.equal("boron");
- expect(children[7].props.caption).to.equal("carbon");
+ const groups = root.findAllByProps({ role: "group" });
+ expect(groups).to.have.lengthOf(2);
+
+ groups.forEach((group, i) => {
+ const title = group.findByType(CompletionTitle);
+ expect(title.props.title).to.equal(completions[i].name);
+
+ const items = group.findAllByType(CompletionItem);
+ expect(items).to.have.lengthOf(completions[i].items.length);
+ items.forEach((item, j) => {
+ expect(item.props.caption).to.equal(completions[i].items[j].caption);
+ });
+ });
});
it("highlight current item", () => {
@@ -58,8 +50,8 @@ describe("console/components/console/completion", () => {
<Completion completions={completions} size={30} select={3} />
).root;
- const children = root.findByType("ul").children as Array<ReactTestInstance>;
- expect(children[5].props.highlight).to.be.true;
+ const items = root.findAllByType(CompletionItem);
+ expect(items[3].props.highlight).to.be.true;
});
it("does not highlight any items", () => {
@@ -67,8 +59,8 @@ describe("console/components/console/completion", () => {
<Completion completions={completions} size={30} select={-1} />
).root;
- const children = root.findByType("ul").findAllByType(CompletionItem);
- expect(children.every((e) => e.props.highlight === false)).to.be.true;
+ const items = root.findAllByType(CompletionItem);
+ expect(items.every((item) => item.props.highlight === false)).to.be.true;
});
it("limits completion items", () => {
@@ -76,19 +68,35 @@ describe("console/components/console/completion", () => {
<Completion completions={completions} size={3} select={-1} />
).root;
- let children = root.findByType("ul").children as Array<ReactTestInstance>;
- expect(children).to.have.lengthOf(3);
+ const showns = root
+ .findAllByProps({ role: "group" })
+ .map((group) =>
+ [
+ group.findByType(CompletionTitle).props.shown,
+ group.findAllByType(CompletionItem).map((item) => item.props.shown),
+ ].flat()
+ )
+ .flat();
- expect(children[0].props.title).to.equal("Fruit");
- expect(children[1].props.caption).to.equal("apple");
- expect(children[2].props.caption).to.equal("banana");
+ expect(showns).to.deep.equal([
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ ]);
root = ReactTestRenderer.create(
<Completion completions={completions} size={3} select={0} />
).root;
- children = root.findByType("ul").children as Array<ReactTestInstance>;
- expect(children[1].props.highlight).to.be.true;
+ const items = root
+ .findAllByType(CompletionItem)
+ .map((item) => item.props.shown);
+ expect(items[1]).to.be.true;
});
it("scrolls up to down with select", () => {
@@ -97,33 +105,76 @@ describe("console/components/console/completion", () => {
);
const root = component.root;
- let children = root.findByType("ul").children as Array<ReactTestInstance>;
- expect(children).to.have.lengthOf(3);
- expect(children[0].props.title).to.equal("Fruit");
- expect(children[1].props.caption).to.equal("apple");
- expect(children[2].props.caption).to.equal("banana");
+ let items = root.findAllByType(CompletionItem);
+ let showns = root
+ .findAllByProps({ role: "group" })
+ .map((group) =>
+ [
+ group.findByType(CompletionTitle).props.shown,
+ group.findAllByType(CompletionItem).map((item) => item.props.shown),
+ ].flat()
+ )
+ .flat();
+ expect(showns).to.deep.equal([
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ ]);
component.update(
<Completion completions={completions} size={3} select={2} />
);
-
- children = root.findByType("ul").children as Array<ReactTestInstance>;
- expect(children).to.have.lengthOf(3);
- expect(children[0].props.caption).to.equal("apple");
- expect(children[1].props.caption).to.equal("banana");
- expect(children[2].props.caption).to.equal("cherry");
- expect(children[2].props.highlight).to.be.true;
+ items = root.findAllByType(CompletionItem);
+ showns = root
+ .findAllByProps({ role: "group" })
+ .map((group) =>
+ [
+ group.findByType(CompletionTitle).props.shown,
+ group.findAllByType(CompletionItem).map((item) => item.props.shown),
+ ].flat()
+ )
+ .flat();
+ expect(showns).to.deep.equal([
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ ]);
+ expect(items[2].props.highlight).to.be.true;
component.update(
<Completion completions={completions} size={3} select={3} />
);
-
- children = root.findByType("ul").children as Array<ReactTestInstance>;
- expect(children).to.have.lengthOf(3);
- expect(children[0].props.caption).to.equal("cherry");
- expect(children[1].props.title).to.equal("Element");
- expect(children[2].props.caption).to.equal("argon");
- expect(children[2].props.highlight).to.be.true;
+ items = root.findAllByType(CompletionItem);
+ showns = root
+ .findAllByProps({ role: "group" })
+ .map((group) =>
+ [
+ group.findByType(CompletionTitle).props.shown,
+ group.findAllByType(CompletionItem).map((item) => item.props.shown),
+ ].flat()
+ )
+ .flat();
+ expect(showns).to.deep.equal([
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ ]);
+ expect(items[3].props.highlight).to.be.true;
});
it("scrolls down to up with select", () => {
@@ -132,34 +183,102 @@ describe("console/components/console/completion", () => {
);
const root = component.root;
- let children = root.findByType("ul").children as Array<ReactTestInstance>;
- expect(children).to.have.lengthOf(3);
- expect(children[0].props.caption).to.equal("argon");
- expect(children[1].props.caption).to.equal("boron");
- expect(children[2].props.caption).to.equal("carbon");
+ let items = root.findAllByType(CompletionItem);
+ let showns = root
+ .findAllByProps({ role: "group" })
+ .map((group) =>
+ [
+ group.findByType(CompletionTitle).props.shown,
+ group.findAllByType(CompletionItem).map((item) => item.props.shown),
+ ].flat()
+ )
+ .flat();
+
+ expect(showns).to.deep.equal([
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ ]);
+ expect(items[5].props.highlight).to.be.true;
component.update(
<Completion completions={completions} size={3} select={4} />
);
-
- children = root.findByType("ul").children as Array<ReactTestInstance>;
- expect(children[1].props.highlight).to.be.true;
+ items = root.findAllByType(CompletionItem);
+ showns = root
+ .findAllByProps({ role: "group" })
+ .map((group) =>
+ [
+ group.findByType(CompletionTitle).props.shown,
+ group.findAllByType(CompletionItem).map((item) => item.props.shown),
+ ].flat()
+ )
+ .flat();
+ expect(showns).to.deep.equal([
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ ]);
+ expect(items[4].props.highlight).to.be.true;
component.update(
<Completion completions={completions} size={3} select={3} />
);
-
- children = root.findByType("ul").children as Array<ReactTestInstance>;
- expect(children[0].props.highlight).to.be.true;
+ items = root.findAllByType(CompletionItem);
+ showns = root
+ .findAllByProps({ role: "group" })
+ .map((group) =>
+ [
+ group.findByType(CompletionTitle).props.shown,
+ group.findAllByType(CompletionItem).map((item) => item.props.shown),
+ ].flat()
+ )
+ .flat();
+ expect(showns).to.deep.equal([
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ ]);
+ expect(items[3].props.highlight).to.be.true;
component.update(
<Completion completions={completions} size={3} select={2} />
);
-
- children = root.findByType("ul").children as Array<ReactTestInstance>;
- expect(children[0].props.caption).to.equal("cherry");
- expect(children[1].props.title).to.equal("Element");
- expect(children[2].props.caption).to.equal("argon");
- expect(children[0].props.highlight).to.be.true;
+ items = root.findAllByType(CompletionItem);
+ showns = root
+ .findAllByProps({ role: "group" })
+ .map((group) =>
+ [
+ group.findByType(CompletionTitle).props.shown,
+ group.findAllByType(CompletionItem).map((item) => item.props.shown),
+ ].flat()
+ )
+ .flat();
+ expect(showns).to.deep.equal([
+ false,
+ false,
+ false,
+ true,
+ true,
+ true,
+ false,
+ false,
+ ]);
+ expect(items[2].props.highlight).to.be.true;
});
});
diff --git a/test/console/components/console/CompletionItem.test.tsx b/test/console/components/console/CompletionItem.test.tsx
new file mode 100644
index 0000000..3a4b1f2
--- /dev/null
+++ b/test/console/components/console/CompletionItem.test.tsx
@@ -0,0 +1,21 @@
+import React from "react";
+import ReactTestRenderer from "react-test-renderer";
+import { expect } from "chai";
+import CompletionItem from "../../../../src/console/components/console/CompletionItem";
+
+describe("console/components/console/completion/CompletionItem", () => {
+ it("renders a CompletionItem", () => {
+ const root = ReactTestRenderer.create(
+ <CompletionItem
+ shown={true}
+ highlight={false}
+ caption="twitter"
+ url="https://twitter.com/"
+ />
+ ).root;
+ const spans = root.findAllByType("span");
+ expect(spans).to.have.lengthOf(2);
+ expect(spans[0].children).to.deep.equal(["twitter"]);
+ expect(spans[1].children).to.deep.equal(["https://twitter.com/"]);
+ });
+});
diff --git a/test/console/components/console/CompletionTitle.test.tsx b/test/console/components/console/CompletionTitle.test.tsx
new file mode 100644
index 0000000..d8cc411
--- /dev/null
+++ b/test/console/components/console/CompletionTitle.test.tsx
@@ -0,0 +1,15 @@
+import React from "react";
+import ReactTestRenderer from "react-test-renderer";
+import { expect } from "chai";
+import CompletionTitle from "../../../../src/console/components/console/CompletionTitle";
+
+describe("console/components/console/completion/CompletionTitle", () => {
+ it("renders a CompletionTitle", () => {
+ const root = ReactTestRenderer.create(
+ <CompletionTitle title="Fruits" shown={true} />
+ ).root;
+
+ const li = root.findByType("li");
+ expect(li.children).to.deep.equal(["Fruits"]);
+ });
+});
diff --git a/test/console/components/console/Message.test.tsx b/test/console/components/console/Message.test.tsx
new file mode 100644
index 0000000..f8f950a
--- /dev/null
+++ b/test/console/components/console/Message.test.tsx
@@ -0,0 +1,27 @@
+import React from "react";
+import ReactTestRenderer from "react-test-renderer";
+import { expect } from "chai";
+import Message from "../../../../src/console/components/console/Message";
+
+describe("console/components/console/completion/Message", () => {
+ it("renders an information message", () => {
+ const root = ReactTestRenderer.create(<Message mode="info">Hello!</Message>)
+ .root;
+
+ const p = root.findByType("p");
+
+ expect(p.props["role"]).to.equal("status");
+ expect(p.children).to.deep.equal(["Hello!"]);
+ });
+
+ it("renders an error message", () => {
+ const root = ReactTestRenderer.create(
+ <Message mode="error">Hello!</Message>
+ ).root;
+
+ const p = root.findByType("p");
+
+ expect(p.props["role"]).to.equal("alert");
+ expect(p.children).to.deep.equal(["Hello!"]);
+ });
+});
diff --git a/tsconfig.json b/tsconfig.json
index f3a6a33..9d56c01 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -2,7 +2,7 @@
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
- "lib": ["es6", "dom", "es2017"],
+ "lib": ["es6", "dom", "esnext"],
"allowJs": true,
"checkJs": false,
"jsx": "react",
diff --git a/yarn.lock b/yarn.lock
index e66e354..cdecbc1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,13 +2,59 @@
# yarn lockfile v1
-"@babel/code-frame@^7.0.0":
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==
dependencies:
"@babel/highlight" "^7.10.4"
+"@babel/generator@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c"
+ integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==
+ dependencies:
+ "@babel/types" "^7.11.0"
+ jsesc "^2.5.1"
+ source-map "^0.5.0"
+
+"@babel/helper-annotate-as-pure@^7.0.0":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3"
+ integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==
+ dependencies:
+ "@babel/types" "^7.10.4"
+
+"@babel/helper-function-name@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a"
+ integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==
+ dependencies:
+ "@babel/helper-get-function-arity" "^7.10.4"
+ "@babel/template" "^7.10.4"
+ "@babel/types" "^7.10.4"
+
+"@babel/helper-get-function-arity@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2"
+ integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==
+ dependencies:
+ "@babel/types" "^7.10.4"
+
+"@babel/helper-module-imports@^7.0.0":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620"
+ integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==
+ dependencies:
+ "@babel/types" "^7.10.4"
+
+"@babel/helper-split-export-declaration@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f"
+ integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==
+ dependencies:
+ "@babel/types" "^7.11.0"
+
"@babel/helper-validator-identifier@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2"
@@ -23,6 +69,11 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
+"@babel/parser@^7.10.4", "@babel/parser@^7.11.0":
+ version "7.11.3"
+ 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"
@@ -30,6 +81,61 @@
dependencies:
regenerator-runtime "^0.13.4"
+"@babel/template@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278"
+ integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ "@babel/parser" "^7.10.4"
+ "@babel/types" "^7.10.4"
+
+"@babel/traverse@^7.4.5":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24"
+ integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ "@babel/generator" "^7.11.0"
+ "@babel/helper-function-name" "^7.10.4"
+ "@babel/helper-split-export-declaration" "^7.11.0"
+ "@babel/parser" "^7.11.0"
+ "@babel/types" "^7.11.0"
+ debug "^4.1.0"
+ globals "^11.1.0"
+ lodash "^4.17.19"
+
+"@babel/types@^7.10.4", "@babel/types@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d"
+ integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.10.4"
+ lodash "^4.17.19"
+ to-fast-properties "^2.0.0"
+
+"@emotion/is-prop-valid@^0.8.8":
+ version "0.8.8"
+ resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
+ integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==
+ dependencies:
+ "@emotion/memoize" "0.7.4"
+
+"@emotion/memoize@0.7.4":
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
+ integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==
+
+"@emotion/stylis@^0.8.4":
+ version "0.8.5"
+ resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04"
+ integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==
+
+"@emotion/unitless@^0.7.4":
+ version "0.7.5"
+ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed"
+ integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
+
"@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":
version "1.8.1"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217"
@@ -133,16 +239,16 @@
"@types/range-parser" "*"
"@types/express@^4.17.2":
- version "4.17.7"
- resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.7.tgz#42045be6475636d9801369cd4418ef65cdb0dd59"
- integrity sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==
+ version "4.17.8"
+ resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.8.tgz#3df4293293317e61c60137d273a2e96cd8d5f27a"
+ integrity sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==
dependencies:
"@types/body-parser" "*"
"@types/express-serve-static-core" "*"
"@types/qs" "*"
"@types/serve-static" "*"
-"@types/hoist-non-react-statics@^3.3.0":
+"@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.0":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
@@ -202,6 +308,13 @@
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==
+ 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"
@@ -248,9 +361,9 @@
"@types/mime" "*"
"@types/sinon@^9.0.0":
- version "9.0.4"
- resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-9.0.4.tgz#e934f904606632287a6e7f7ab0ce3f08a0dad4b1"
- integrity sha512-sJmb32asJZY6Z2u09bl0G2wglSxDlROlAejCjsnor+LzBMz17gu8IU7vKC/vWDnv9zEq2wqADHVXFjf4eE8Gdw==
+ version "9.0.5"
+ resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-9.0.5.tgz#56b2a12662dd8c7d081cdc511af5f872cb37377f"
+ integrity sha512-4CnkGdM/5/FXDGqL32JQ1ttVrGvhOoesLLF7VnTh4KdjK5N5VQOtxaylFqqTjnHx55MnD9O02Nbk5c1ELC8wlQ==
dependencies:
"@types/sinonjs__fake-timers" "*"
@@ -264,6 +377,16 @@
resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==
+"@types/styled-components@^5.1.2":
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.2.tgz#652af475b4af917b355ea1c3068acae63d46455f"
+ integrity sha512-HNocYLfrsnNNm8NTS/W53OERSjRA8dx5Bn6wBd2rXXwt4Z3s+oqvY6/PbVt3e6sgtzI63GX//WiWiRhWur08qQ==
+ dependencies:
+ "@types/hoist-non-react-statics" "*"
+ "@types/react" "*"
+ "@types/react-native" "*"
+ csstype "^3.0.2"
+
"@types/tapable@*", "@types/tapable@^1.0.5":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74"
@@ -309,14 +432,14 @@
semver "^7.3.2"
tsutils "^3.17.1"
-"@typescript-eslint/experimental-utils@3.8.0":
- version "3.8.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.8.0.tgz#ac1f7c88322dcfb7635ece6f0441516dd951099a"
- integrity sha512-o8T1blo1lAJE0QDsW7nSyvZHbiDzQDjINJKyB44Z3sSL39qBy5L10ScI/XwDtaiunoyKGLiY9bzRk4YjsUZl8w==
+"@typescript-eslint/experimental-utils@3.10.1":
+ version "3.10.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686"
+ integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==
dependencies:
"@types/json-schema" "^7.0.3"
- "@typescript-eslint/types" "3.8.0"
- "@typescript-eslint/typescript-estree" "3.8.0"
+ "@typescript-eslint/types" "3.10.1"
+ "@typescript-eslint/typescript-estree" "3.10.1"
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
@@ -331,45 +454,34 @@
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
-"@typescript-eslint/parser@3.9.0":
- version "3.9.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.9.0.tgz#344978a265d9a5c7c8f13e62c78172a4374dabea"
- integrity sha512-rDHOKb6uW2jZkHQniUQVZkixQrfsZGUCNWWbKWep4A5hGhN5dLHMUCNAWnC4tXRlHedXkTDptIpxs6e4Pz8UfA==
- dependencies:
- "@types/eslint-visitor-keys" "^1.0.0"
- "@typescript-eslint/experimental-utils" "3.9.0"
- "@typescript-eslint/types" "3.9.0"
- "@typescript-eslint/typescript-estree" "3.9.0"
- eslint-visitor-keys "^1.1.0"
-
-"@typescript-eslint/parser@^3.0.0":
- version "3.8.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.8.0.tgz#8e1dcd404299bf79492409c81c415fa95a7c622b"
- integrity sha512-u5vjOBaCsnMVQOvkKCXAmmOhyyMmFFf5dbkM3TIbg3MZ2pyv5peE4gj81UAbTHwTOXEwf7eCQTUMKrDl/+qGnA==
+"@typescript-eslint/parser@3.10.1", "@typescript-eslint/parser@^3.0.0":
+ version "3.10.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467"
+ integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==
dependencies:
"@types/eslint-visitor-keys" "^1.0.0"
- "@typescript-eslint/experimental-utils" "3.8.0"
- "@typescript-eslint/types" "3.8.0"
- "@typescript-eslint/typescript-estree" "3.8.0"
+ "@typescript-eslint/experimental-utils" "3.10.1"
+ "@typescript-eslint/types" "3.10.1"
+ "@typescript-eslint/typescript-estree" "3.10.1"
eslint-visitor-keys "^1.1.0"
-"@typescript-eslint/types@3.8.0":
- version "3.8.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.8.0.tgz#58581dd863f86e0cd23353d94362bb90b4bea796"
- integrity sha512-8kROmEQkv6ss9kdQ44vCN1dTrgu4Qxrd2kXr10kz2NP5T8/7JnEfYNxCpPkArbLIhhkGLZV3aVMplH1RXQRF7Q==
+"@typescript-eslint/types@3.10.1":
+ version "3.10.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727"
+ integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==
"@typescript-eslint/types@3.9.0":
version "3.9.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.9.0.tgz#be9d0aa451e1bf3ce99f2e6920659e5b2e6bfe18"
integrity sha512-rb6LDr+dk9RVVXO/NJE8dT1pGlso3voNdEIN8ugm4CWM5w5GimbThCMiMl4da1t5u3YwPWEwOnKAULCZgBtBHg==
-"@typescript-eslint/typescript-estree@3.8.0":
- version "3.8.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.8.0.tgz#0606d19f629f813dbdd5a34c7a1e895d6191cac6"
- integrity sha512-MTv9nPDhlKfclwnplRNDL44mP2SY96YmPGxmMbMy6x12I+pERcxpIUht7DXZaj4mOKKtet53wYYXU0ABaiXrLw==
+"@typescript-eslint/typescript-estree@3.10.1":
+ version "3.10.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853"
+ integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==
dependencies:
- "@typescript-eslint/types" "3.8.0"
- "@typescript-eslint/visitor-keys" "3.8.0"
+ "@typescript-eslint/types" "3.10.1"
+ "@typescript-eslint/visitor-keys" "3.10.1"
debug "^4.1.1"
glob "^7.1.6"
is-glob "^4.0.1"
@@ -391,10 +503,10 @@
semver "^7.3.2"
tsutils "^3.17.1"
-"@typescript-eslint/visitor-keys@3.8.0":
- version "3.8.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.8.0.tgz#ad35110249fb3fc30a36bfcbfeea93e710cfaab1"
- integrity sha512-gfqQWyVPpT9NpLREXNR820AYwgz+Kr1GuF3nf1wxpHD6hdxI62tq03ToomFnDxY0m3pUB39IF7sil7D5TQexLA==
+"@typescript-eslint/visitor-keys@3.10.1":
+ version "3.10.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931"
+ integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==
dependencies:
eslint-visitor-keys "^1.1.0"
@@ -895,6 +1007,21 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2"
integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==
+"babel-plugin-styled-components@>= 1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.11.1.tgz#5296a9e557d736c3186be079fff27c6665d63d76"
+ integrity sha512-YwrInHyKUk1PU3avIRdiLyCpM++18Rs1NgyMXEAQC33rIXs/vro0A+stf4sT0Gf22Got+xRWB8Cm0tw+qkRzBA==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.0.0"
+ "@babel/helper-module-imports" "^7.0.0"
+ babel-plugin-syntax-jsx "^6.18.0"
+ lodash "^4.17.11"
+
+babel-plugin-syntax-jsx@^6.18.0:
+ version "6.18.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
+ integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=
+
backo2@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
@@ -1230,6 +1357,11 @@ camelcase@^6.0.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e"
integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==
+camelize@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b"
+ integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=
+
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@@ -1677,6 +1809,11 @@ crypto-browserify@^3.11.0:
randombytes "^2.0.0"
randomfill "^1.0.3"
+css-color-keywords@^1.0.0:
+ version "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.2.1"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.2.1.tgz#9f48fd7eae1219d629a3f085ba9a9102ca1141a7"
@@ -1706,6 +1843,15 @@ css-select@^1.1.0:
domutils "1.5.1"
nth-check "~1.0.1"
+css-to-react-native@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.0.0.tgz#62dbe678072a824a689bcfee011fc96e02a7d756"
+ integrity sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==
+ dependencies:
+ camelize "^1.0.0"
+ css-color-keywords "^1.0.0"
+ postcss-value-parser "^4.0.2"
+
css-what@2.1:
version "2.1.3"
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
@@ -1769,7 +1915,7 @@ debug@3.2.6:
dependencies:
ms "^2.1.1"
-debug@^4.0.1, debug@^4.1.1, debug@~4.1.0:
+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==
@@ -2931,6 +3077,11 @@ global-prefix@^3.0.0:
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"
+ integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+
globals@^12.1.0:
version "12.4.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8"
@@ -3078,7 +3229,7 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
-hoist-non-react-statics@^3.3.0:
+hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0:
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==
@@ -3670,6 +3821,11 @@ jsbn@~0.1.0:
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
+jsesc@^2.5.1:
+ version "2.5.2"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
+ integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+
json-parse-better-errors@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
@@ -4038,7 +4194,7 @@ lodash.once@^4.0.0:
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
-lodash@^4.0.0, lodash@^4.16.3, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.2.1, lodash@~4.17.10:
+lodash@^4.0.0, lodash@^4.16.3, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.2.1, lodash@~4.17.10:
version "4.17.19"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
@@ -5044,7 +5200,7 @@ postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2:
indexes-of "^1.0.1"
uniq "^1.0.1"
-postcss-value-parser@^4.1.0:
+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==
@@ -5093,10 +5249,10 @@ prettier-linter-helpers@^1.0.0:
dependencies:
fast-diff "^1.1.2"
-prettier@2.0.5, prettier@^2.0.0:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
- integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==
+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==
pretty-error@^2.1.1:
version "2.1.1"
@@ -5868,6 +6024,11 @@ shallow-clone@^3.0.0:
dependencies:
kind-of "^6.0.2"
+shallowequal@^1.1.0:
+ version "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"
@@ -6075,7 +6236,7 @@ source-map@^0.4.2:
dependencies:
amdefine ">=0.0.4"
-source-map@^0.5.6:
+source-map@^0.5.0, source-map@^0.5.6:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -6353,6 +6514,22 @@ style-loader@^1.1.3:
loader-utils "^2.0.0"
schema-utils "^2.6.6"
+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==
+ dependencies:
+ "@babel/helper-module-imports" "^7.0.0"
+ "@babel/traverse" "^7.4.5"
+ "@emotion/is-prop-valid" "^0.8.8"
+ "@emotion/stylis" "^0.8.4"
+ "@emotion/unitless" "^0.7.4"
+ babel-plugin-styled-components ">= 1"
+ css-to-react-native "^3.0.0"
+ hoist-non-react-statics "^3.0.0"
+ 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"
@@ -6488,6 +6665,11 @@ to-arraybuffer@^1.0.0:
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
+to-fast-properties@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+ integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
+
to-object-path@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
@@ -6546,9 +6728,9 @@ trim-newlines@^1.0.0:
glob "^7.1.2"
ts-loader@^8.0.2:
- version "8.0.2"
- resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.2.tgz#ee73ca9350f745799396fff8578ba29b1e95616b"
- integrity sha512-oYT7wOTUawYXQ8XIDsRhziyW0KUEV38jISYlE+9adP6tDtG+O5GkRe4QKQXrHVH4mJJ88DysvEtvGP65wMLlhg==
+ 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==
dependencies:
chalk "^2.3.0"
enhanced-resolve "^4.0.0"