diff --git a/packages/editor-mobile/__e2e__/device-utils.ts b/packages/editor-mobile/__e2e__/device-utils.ts
new file mode 100644
index 000000000..973d9c244
--- /dev/null
+++ b/packages/editor-mobile/__e2e__/device-utils.ts
@@ -0,0 +1,48 @@
+/*
+This file is part of the Notesnook project (https://notesnook.com/)
+
+Copyright (C) 2023 Streetwriters (Private) Limited
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+import { AndroidDevice } from "@playwright/test";
+export type DeviceSize = {
+ width: number;
+ height: number;
+ /**
+ * Convert device independent height to device specific height
+ */
+ h: (percentage: number) => number;
+ /**
+ * Convert device independent width to device specific width
+ */
+ w: (percentage: number) => number;
+};
+export async function getDeviceSize(
+ device: AndroidDevice
+): Promise {
+ const output = (await device.shell(`wm size`)).toString("utf-8");
+ const parsed = /(\d+)x(\d+)/g.exec(output);
+ if (!parsed) throw new Error("Failed to find device size.");
+
+ const width = parseInt(parsed[1]);
+ const height = parseInt(parsed[2]);
+ return {
+ height,
+ width,
+ h: (p) => p * height,
+ w: (p) => p * width
+ };
+}
diff --git a/packages/editor-mobile/__e2e__/editor.mobile.test.ts b/packages/editor-mobile/__e2e__/editor.mobile.test.ts
new file mode 100644
index 000000000..1a5e8db01
--- /dev/null
+++ b/packages/editor-mobile/__e2e__/editor.mobile.test.ts
@@ -0,0 +1,97 @@
+/*
+This file is part of the Notesnook project (https://notesnook.com/)
+
+Copyright (C) 2023 Streetwriters (Private) Limited
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+import { expect, test } from "@playwright/test";
+import { androidTest } from "./test-utils";
+import { getKey, setKeyboard, type } from "./keyboard-utils";
+
+androidTest(
+ "backspacing from new line should not change caret position",
+ async ({ chrome, device, keyboards, baseURL, size }, info) => {
+ info.setTimeout(30000);
+
+ for (const keyboard of keyboards) {
+ await test.step(keyboard.name, async () => {
+ if (!(await setKeyboard(device, keyboard.ime)))
+ throw new Error("Failed to set keyboard.");
+
+ const page = await chrome.newPage();
+
+ await page.goto(baseURL);
+
+ await page.focus(".ProseMirror");
+
+ await page.waitForTimeout(1000);
+
+ await type(page, device, keyboard, size, "HI\nLA");
+
+ await page.waitForTimeout(100);
+
+ await page.keyboard.press("ArrowLeft");
+ await page.keyboard.press("ArrowLeft");
+
+ await device.input.tap(getKey(keyboard, size, "DEL"));
+
+ await page.waitForTimeout(100);
+
+ await type(page, device, keyboard, size, "HO");
+
+ expect((await page.textContent(".ProseMirror"))?.toLowerCase()).toBe(
+ "hihola"
+ );
+
+ await page.close();
+ });
+ }
+ }
+);
+
+androidTest(
+ "pressing enter after entering a word should move the caret to the new line",
+ async ({ chrome, device, keyboards, baseURL, size }, info) => {
+ info.setTimeout(30000);
+
+ for (const keyboard of keyboards) {
+ await test.step(keyboard.name, async () => {
+ if (!(await setKeyboard(device, keyboard.ime)))
+ throw new Error("Failed to set keyboard.");
+
+ const page = await chrome.newPage();
+
+ await page.goto(baseURL);
+
+ await page.focus(".ProseMirror");
+
+ await page.waitForTimeout(1000);
+
+ await type(page, device, keyboard, size, "HELLO");
+
+ await page.waitForTimeout(100);
+
+ await type(page, device, keyboard, size, "\nWORLD");
+
+ expect((await page.innerHTML(".ProseMirror"))?.toLowerCase()).toBe(
+ 'hello
world
'
+ );
+
+ await page.close();
+ });
+ }
+ }
+);
diff --git a/packages/editor-mobile/__e2e__/keyboard-utils.ts b/packages/editor-mobile/__e2e__/keyboard-utils.ts
new file mode 100644
index 000000000..9a663d7f7
--- /dev/null
+++ b/packages/editor-mobile/__e2e__/keyboard-utils.ts
@@ -0,0 +1,213 @@
+/*
+This file is part of the Notesnook project (https://notesnook.com/)
+
+Copyright (C) 2023 Streetwriters (Private) Limited
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+import { AndroidDevice, Page } from "@playwright/test";
+import { DeviceSize } from "./device-utils";
+
+export type Keyboard = {
+ name: string;
+ ime: string;
+ pkg: string;
+ layout: {
+ start: number;
+ end: number;
+ keyHeight: number;
+ keyWidth: number;
+ rowMargin: number;
+ specialKeyWidth: number;
+ spaceBarWidth: number;
+ rows: number;
+ };
+};
+
+const KEYBOARD_ROWS = [
+ "QWERTYUIOP".split(""),
+ ["", ..."ASDFGHJKL".split(""), ""],
+ ["SHIFT", ..."ZXCVBNM".split(""), "DEL"]
+];
+
+const SPECIAL_KEY_MAP = {
+ "\n": "Enter",
+ ".": "Period",
+ " ": "Space"
+} as const;
+
+/**
+ * Pixels to device independent height (percentage based)
+ */
+function h(px: number) {
+ return px / 2460;
+}
+/**
+ * Pixels to device independent width (percentage based)
+ */
+function w(px: number) {
+ return px / 1080;
+}
+
+export const SUPPORTED_KEYBOARDS: Keyboard[] = [
+ {
+ name: "Gboard",
+ ime: "com.google.android.inputmethod.latin/com.android.inputmethod.latin.LatinIME",
+ pkg: "com.google.android.inputmethod.latin",
+
+ layout: {
+ start: h(1700), //,
+ end: h(2300),
+ keyHeight: h(120),
+ keyWidth: w(100),
+ rowMargin: h(30),
+ specialKeyWidth: w(100 + 50),
+ spaceBarWidth: w(100 * 4),
+ rows: 4
+ }
+ },
+ {
+ name: "OpenBoard",
+ ime: "org.dslul.openboard.inputmethod.latin/.LatinIME",
+ pkg: "org.dslul.openboard.inputmethod.latin",
+ layout: {
+ start: h(1650),
+ end: h(2300),
+ keyHeight: h(110),
+ rowMargin: h(40),
+ keyWidth: w(100),
+ specialKeyWidth: w(100 + 50),
+ spaceBarWidth: w(100 * 4),
+ rows: 4
+ }
+ },
+ {
+ name: "SwiftKey",
+ ime: "com.touchtype.swiftkey/com.touchtype.KeyboardService",
+ pkg: "com.touchtype.swiftkey",
+ layout: {
+ start: h(1800),
+ end: h(2300),
+ keyHeight: h(100),
+ rowMargin: h(10),
+ keyWidth: w(100),
+ specialKeyWidth: w(100 + 50),
+ spaceBarWidth: w(100 * 4.5),
+ rows: 4
+ }
+ },
+ {
+ name: "Grammarly Keyboard",
+ ime: "com.grammarly.android.keyboard/.LatinIME",
+ pkg: "com.grammarly.android.keyboard",
+ layout: {
+ start: h(1700),
+ end: h(2300),
+ keyHeight: h(120),
+ rowMargin: h(25),
+ keyWidth: w(100),
+ specialKeyWidth: w(140),
+ spaceBarWidth: w(100 * 4),
+ rows: 4
+ }
+ }
+];
+
+export async function getKeyboards(device: AndroidDevice) {
+ const imeList = (await device.shell("ime list -s -a"))
+ .toString("utf-8")
+ .split("\n");
+ return SUPPORTED_KEYBOARDS.filter((keyboard) =>
+ imeList.includes(keyboard.ime)
+ );
+}
+
+export async function setKeyboard(device: AndroidDevice, ime: string) {
+ const output = (await device.shell(`ime set ${ime}`)).toString("utf-8");
+ return output.includes(`Input method ${ime} selected`);
+}
+
+export async function type(
+ page: Page,
+ device: AndroidDevice,
+ keyboard: Keyboard,
+ deviceSize: DeviceSize,
+ str: string
+) {
+ for (const char of str) {
+ const specialKey = SPECIAL_KEY_MAP[char];
+ if (specialKey)
+ await device.input.tap(getSpecialKey(keyboard, deviceSize, specialKey));
+ else await device.input.tap(getKey(keyboard, deviceSize, char));
+
+ await page.waitForTimeout(50);
+ }
+}
+
+export function getKey(
+ keyboard: Keyboard,
+ deviceSize: DeviceSize,
+ key: string
+) {
+ key = key.toUpperCase();
+ const rowIndex = KEYBOARD_ROWS.findIndex((r) => r.includes(key));
+ if (rowIndex < 0) throw new Error(`Key (${key}) not found in any row.`);
+ const keyIndex = KEYBOARD_ROWS[rowIndex].indexOf(key);
+ const specialKeysCount = KEYBOARD_ROWS[rowIndex].filter(
+ (k, i) => k.length > 1 && i <= keyIndex
+ ).length;
+ const emptySpaceCount = KEYBOARD_ROWS[rowIndex].filter(
+ (k, i) => k.length < 1 && i <= keyIndex
+ ).length;
+
+ const keyHeight = deviceSize.h(keyboard.layout.keyHeight);
+ const rowMargin = deviceSize.h(keyboard.layout.rowMargin);
+ const keyWidth = deviceSize.w(keyboard.layout.keyWidth);
+ const specialKeyWidth = deviceSize.w(keyboard.layout.specialKeyWidth);
+ const start = deviceSize.h(keyboard.layout.start);
+
+ const specialKeysX = specialKeysCount * specialKeyWidth;
+ const emptySpaceX = emptySpaceCount * (keyWidth / 2);
+ const keysX = (keyIndex + 1 - specialKeysCount - emptySpaceCount) * keyWidth;
+
+ const y = (rowIndex + 1) * (keyHeight + rowMargin) + start;
+
+ //console.log(key, keysX + specialKeysX + emptySpaceX, y);
+
+ return { y, x: keysX + specialKeysX + emptySpaceX };
+}
+
+export function getSpecialKey(
+ keyboard: Keyboard,
+ deviceSize: DeviceSize,
+ key: "Space" | "Enter" | "Period"
+) {
+ const keyHeight = deviceSize.h(keyboard.layout.keyHeight);
+ const rowMargin = deviceSize.h(keyboard.layout.rowMargin);
+ const keyWidth = deviceSize.w(keyboard.layout.keyWidth);
+ const specialKeyWidth = deviceSize.w(keyboard.layout.specialKeyWidth);
+ const spaceBarWidth = deviceSize.w(keyboard.layout.spaceBarWidth);
+ const start = deviceSize.h(keyboard.layout.start);
+
+ return {
+ x:
+ key === "Space"
+ ? specialKeyWidth + 2 * keyWidth + spaceBarWidth / 2
+ : key === "Period"
+ ? specialKeyWidth + 3 * keyWidth + spaceBarWidth
+ : specialKeyWidth + 4 * keyWidth + spaceBarWidth,
+ y: keyboard.layout.rows * (keyHeight + rowMargin) + start
+ };
+}
diff --git a/packages/editor-mobile/__e2e__/test-utils.ts b/packages/editor-mobile/__e2e__/test-utils.ts
new file mode 100644
index 000000000..b3f688640
--- /dev/null
+++ b/packages/editor-mobile/__e2e__/test-utils.ts
@@ -0,0 +1,83 @@
+/*
+This file is part of the Notesnook project (https://notesnook.com/)
+
+Copyright (C) 2023 Streetwriters (Private) Limited
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+import {
+ AndroidDevice,
+ BrowserContext,
+ TestInfo,
+ _android as android,
+ test
+} from "@playwright/test";
+import { Keyboard, SUPPORTED_KEYBOARDS, getKeyboards } from "./keyboard-utils";
+import * as ip from "ip";
+import { DeviceSize, getDeviceSize } from "./device-utils";
+
+type AndroidTestArgs = {
+ chrome: BrowserContext;
+ device: AndroidDevice;
+ baseURL: string;
+ keyboards: Keyboard[];
+ size: DeviceSize;
+};
+
+const SERVER_ADDRESS = `http://${ip.address("Wi-Fi", "ipv4")}:3000`;
+
+export function androidTest(
+ title: string,
+ testFunction: (
+ args: AndroidTestArgs,
+ testInfo: TestInfo
+ ) => Promise | void
+) {
+ test(title, async ({ channel: _ }, testInfo) => {
+ const [device] = await android.devices();
+ if (!device) {
+ console.error("Please connect an Android device or emulator.");
+ return;
+ }
+
+ const keyboards = await getKeyboards(device);
+ if (!keyboards.length) {
+ console.error(
+ "No supported keyboard found. Please install one of",
+ SUPPORTED_KEYBOARDS
+ );
+ return;
+ }
+
+ const deviceSize = await getDeviceSize(device);
+
+ await device.shell("am force-stop com.android.chrome");
+ const chrome = await device.launchBrowser({});
+
+ await testFunction(
+ {
+ chrome: chrome,
+ device,
+ keyboards,
+ baseURL: SERVER_ADDRESS,
+ size: deviceSize
+ },
+ testInfo
+ );
+
+ await device.shell("am force-stop com.android.chrome");
+ await device.close();
+ });
+}
diff --git a/packages/editor-mobile/package-lock.json b/packages/editor-mobile/package-lock.json
index 75def13e9..64c623812 100644
--- a/packages/editor-mobile/package-lock.json
+++ b/packages/editor-mobile/package-lock.json
@@ -21,14 +21,17 @@
"zustand": "^3.6.8"
},
"devDependencies": {
+ "@playwright/test": "^1.37.1",
"@testing-library/jest-dom": "^5.16.0",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
+ "@types/ip": "^1.1.0",
"@types/jest": "^27.0.3",
"@types/node": "^16.11.11",
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.2",
"env-cmd": "^10.1.0",
+ "ip": "^1.1.8",
"react-error-overlay": "6.0.9",
"react-scripts": "^5.0.1",
"web-vitals": "^1.1.2"
@@ -40,40 +43,42 @@
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {
- "@emotion/react": "^11.10.0",
+ "@emotion/react": "11.11.1",
"@notesnook/core": "file:../core",
"@notesnook/theme": "file:../theme",
"@notesnook/ui": "file:../ui",
"@social-embed/lib": "^0.0.2-next.1",
"@theme-ui/components": ">=0.14.0",
"@theme-ui/core": ">=0.14.0",
- "@tiptap/core": "2.0.3",
- "@tiptap/extension-character-count": "2.0.3",
- "@tiptap/extension-color": "2.0.3",
- "@tiptap/extension-font-family": "2.0.3",
- "@tiptap/extension-history": "2.0.3",
- "@tiptap/extension-horizontal-rule": "2.0.3",
- "@tiptap/extension-link": "2.0.3",
- "@tiptap/extension-placeholder": "2.0.3",
- "@tiptap/extension-subscript": "2.0.3",
- "@tiptap/extension-superscript": "2.0.3",
- "@tiptap/extension-table": "2.0.3",
- "@tiptap/extension-table-cell": "2.0.3",
- "@tiptap/extension-table-header": "2.0.3",
- "@tiptap/extension-table-row": "2.0.3",
- "@tiptap/extension-task-item": "2.0.3",
- "@tiptap/extension-task-list": "2.0.3",
- "@tiptap/extension-text-align": "2.0.3",
- "@tiptap/extension-text-style": "2.0.3",
- "@tiptap/extension-underline": "2.0.3",
- "@tiptap/pm": "2.0.3",
- "@tiptap/starter-kit": "2.0.3",
+ "@tiptap/core": "2.1.7",
+ "@tiptap/extension-character-count": "2.1.7",
+ "@tiptap/extension-color": "2.1.7",
+ "@tiptap/extension-font-family": "2.1.7",
+ "@tiptap/extension-history": "2.1.7",
+ "@tiptap/extension-horizontal-rule": "2.1.7",
+ "@tiptap/extension-link": "2.1.7",
+ "@tiptap/extension-list-keymap": "2.1.7",
+ "@tiptap/extension-placeholder": "2.1.7",
+ "@tiptap/extension-subscript": "2.1.7",
+ "@tiptap/extension-superscript": "2.1.7",
+ "@tiptap/extension-table": "2.1.7",
+ "@tiptap/extension-table-cell": "2.1.7",
+ "@tiptap/extension-table-header": "2.1.7",
+ "@tiptap/extension-table-row": "2.1.7",
+ "@tiptap/extension-task-item": "2.1.7",
+ "@tiptap/extension-task-list": "2.1.7",
+ "@tiptap/extension-text-align": "2.1.7",
+ "@tiptap/extension-text-style": "2.1.7",
+ "@tiptap/extension-underline": "2.1.7",
+ "@tiptap/pm": "2.1.7",
+ "@tiptap/starter-kit": "2.1.7",
"clipboard-polyfill": "4.0.0",
"detect-indent": "^7.0.0",
"katex": "0.16.4",
"nanoid": "^4.0.1",
"prism-themes": "^1.9.0",
- "prosemirror-codemark": "^0.4.1",
+ "prosemirror-codemark": "^0.4.2",
+ "prosemirror-view": "^1.31.7",
"re-resizable": "^6.9.9",
"react-colorful": "^5.5.1",
"react-modal": "3.13.1",
@@ -3705,6 +3710,25 @@
"resolved": "../theme",
"link": true
},
+ "node_modules/@playwright/test": {
+ "version": "1.37.1",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.37.1.tgz",
+ "integrity": "sha512-bq9zTli3vWJo8S3LwB91U0qDNQDpEXnw7knhxLM0nwDvexQAwx9tO8iKDZSqqneVq+URd/WIoz+BALMqUTgdSg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "playwright-core": "1.37.1"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
"node_modules/@pmmmwh/react-refresh-webpack-plugin": {
"version": "0.5.10",
"resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz",
@@ -4390,6 +4414,15 @@
"@types/node": "*"
}
},
+ "node_modules/@types/ip": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@types/ip/-/ip-1.1.0.tgz",
+ "integrity": "sha512-dwNe8gOoF70VdL6WJBwVHtQmAX4RMd62M+mAB9HQFjG1/qiCLM/meRy95Pd14FYBbEDwCq7jgJs89cHpLBu4HQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
@@ -10201,6 +10234,12 @@
"node": ">= 0.4"
}
},
+ "node_modules/ip": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz",
+ "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==",
+ "dev": true
+ },
"node_modules/ipaddr.js": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
@@ -14167,6 +14206,18 @@
"node": ">=4"
}
},
+ "node_modules/playwright-core": {
+ "version": "1.37.1",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.37.1.tgz",
+ "integrity": "sha512-17EuQxlSIYCmEMwzMqusJ2ztDgJePjrbttaefgdsiqeLWidjYz9BxXaTaZWxH1J95SHGk6tjE+dwgWILJoUZfA==",
+ "dev": true,
+ "bin": {
+ "playwright-core": "cli.js"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
"node_modules/popmotion": {
"version": "11.0.3",
"resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz",
@@ -17820,6 +17871,20 @@
"is-typedarray": "^1.0.0"
}
},
+ "node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
"node_modules/unbox-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
@@ -20568,13 +20633,15 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz",
"integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"@csstools/selector-specificity": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.1.1.tgz",
"integrity": "sha512-jwx+WCqszn53YHOfvFMJJRd/B2GqkCBt+1MJSG6o5/s8+ytHMvDZXsJgUEWLk12UnLd7HYKac4BYU5i/Ron1Cw==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"@emotion/babel-plugin": {
"version": "11.11.0",
@@ -20692,7 +20759,8 @@
"@emotion/use-insertion-effect-with-fallbacks": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz",
- "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw=="
+ "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==",
+ "requires": {}
},
"@emotion/utils": {
"version": "1.2.1",
@@ -21577,7 +21645,7 @@
"@notesnook/editor": {
"version": "file:../editor",
"requires": {
- "@emotion/react": "^11.10.0",
+ "@emotion/react": "11.11.1",
"@mdi/js": "^7.2.96",
"@mdi/react": "^1.6.1",
"@notesnook/core": "file:../core",
@@ -21586,27 +21654,28 @@
"@social-embed/lib": "^0.0.2-next.1",
"@theme-ui/components": ">=0.14.0",
"@theme-ui/core": ">=0.14.0",
- "@tiptap/core": "2.0.3",
- "@tiptap/extension-character-count": "2.0.3",
- "@tiptap/extension-color": "2.0.3",
- "@tiptap/extension-font-family": "2.0.3",
- "@tiptap/extension-history": "2.0.3",
- "@tiptap/extension-horizontal-rule": "2.0.3",
- "@tiptap/extension-link": "2.0.3",
- "@tiptap/extension-placeholder": "2.0.3",
- "@tiptap/extension-subscript": "2.0.3",
- "@tiptap/extension-superscript": "2.0.3",
- "@tiptap/extension-table": "2.0.3",
- "@tiptap/extension-table-cell": "2.0.3",
- "@tiptap/extension-table-header": "2.0.3",
- "@tiptap/extension-table-row": "2.0.3",
- "@tiptap/extension-task-item": "2.0.3",
- "@tiptap/extension-task-list": "2.0.3",
- "@tiptap/extension-text-align": "2.0.3",
- "@tiptap/extension-text-style": "2.0.3",
- "@tiptap/extension-underline": "2.0.3",
- "@tiptap/pm": "2.0.3",
- "@tiptap/starter-kit": "2.0.3",
+ "@tiptap/core": "2.1.7",
+ "@tiptap/extension-character-count": "2.1.7",
+ "@tiptap/extension-color": "2.1.7",
+ "@tiptap/extension-font-family": "2.1.7",
+ "@tiptap/extension-history": "2.1.7",
+ "@tiptap/extension-horizontal-rule": "2.1.7",
+ "@tiptap/extension-link": "2.1.7",
+ "@tiptap/extension-list-keymap": "2.1.7",
+ "@tiptap/extension-placeholder": "2.1.7",
+ "@tiptap/extension-subscript": "2.1.7",
+ "@tiptap/extension-superscript": "2.1.7",
+ "@tiptap/extension-table": "2.1.7",
+ "@tiptap/extension-table-cell": "2.1.7",
+ "@tiptap/extension-table-header": "2.1.7",
+ "@tiptap/extension-table-row": "2.1.7",
+ "@tiptap/extension-task-item": "2.1.7",
+ "@tiptap/extension-task-list": "2.1.7",
+ "@tiptap/extension-text-align": "2.1.7",
+ "@tiptap/extension-text-style": "2.1.7",
+ "@tiptap/extension-underline": "2.1.7",
+ "@tiptap/pm": "2.1.7",
+ "@tiptap/starter-kit": "2.1.7",
"@types/katex": "^0.14.0",
"@types/prismjs": "^1.26.0",
"@types/react": "17.0.2",
@@ -21622,8 +21691,9 @@
"katex": "0.16.4",
"nanoid": "^4.0.1",
"prism-themes": "^1.9.0",
- "prosemirror-codemark": "^0.4.1",
+ "prosemirror-codemark": "^0.4.2",
"prosemirror-test-builder": "^1.1.0",
+ "prosemirror-view": "^1.31.7",
"re-resizable": "^6.9.9",
"react": "17.0.2",
"react-colorful": "^5.5.1",
@@ -21656,6 +21726,17 @@
"zustand": "^4.3.8"
}
},
+ "@playwright/test": {
+ "version": "1.37.1",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.37.1.tgz",
+ "integrity": "sha512-bq9zTli3vWJo8S3LwB91U0qDNQDpEXnw7knhxLM0nwDvexQAwx9tO8iKDZSqqneVq+URd/WIoz+BALMqUTgdSg==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*",
+ "fsevents": "2.3.2",
+ "playwright-core": "1.37.1"
+ }
+ },
"@pmmmwh/react-refresh-webpack-plugin": {
"version": "0.5.10",
"resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz",
@@ -22148,6 +22229,15 @@
"@types/node": "*"
}
},
+ "@types/ip": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@types/ip/-/ip-1.1.0.tgz",
+ "integrity": "sha512-dwNe8gOoF70VdL6WJBwVHtQmAX4RMd62M+mAB9HQFjG1/qiCLM/meRy95Pd14FYBbEDwCq7jgJs89cHpLBu4HQ==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
"@types/istanbul-lib-coverage": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
@@ -22784,13 +22874,15 @@
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
"integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"acorn-node": {
"version": "1.8.2",
@@ -23151,7 +23243,8 @@
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"json-schema-traverse": {
"version": "0.4.1",
@@ -23220,7 +23313,8 @@
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz",
"integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"babel-plugin-polyfill-corejs2": {
"version": "0.3.3",
@@ -23942,7 +24036,8 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz",
"integrity": "sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"css-has-pseudo": {
"version": "3.0.4",
@@ -24042,7 +24137,8 @@
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz",
"integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"css-select": {
"version": "4.3.0",
@@ -24157,7 +24253,8 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz",
"integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"csso": {
"version": "4.2.0",
@@ -25205,7 +25302,8 @@
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
"integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"eslint-plugin-testing-library": {
"version": "5.10.2",
@@ -25819,7 +25917,8 @@
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"chalk": {
"version": "4.1.2",
@@ -26460,7 +26559,8 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"idb": {
"version": "7.1.1",
@@ -26560,6 +26660,12 @@
"side-channel": "^1.0.4"
}
},
+ "ip": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz",
+ "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==",
+ "dev": true
+ },
"ipaddr.js": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
@@ -27793,7 +27899,8 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
"integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"jest-regex-util": {
"version": "27.5.1",
@@ -28890,7 +28997,8 @@
"mdi-react": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/mdi-react/-/mdi-react-9.1.0.tgz",
- "integrity": "sha512-QFY9BkhX5MaEFpq+0ZGbM7S0iOGkgPb3RLRyzHJIxo8LT8jGu8VY0M+3tfXAaRgYN83t7ksA7D8kuFTt8d/oag=="
+ "integrity": "sha512-QFY9BkhX5MaEFpq+0ZGbM7S0iOGkgPb3RLRyzHJIxo8LT8jGu8VY0M+3tfXAaRgYN83t7ksA7D8kuFTt8d/oag==",
+ "requires": {}
},
"mdn-data": {
"version": "2.0.4",
@@ -29564,6 +29672,12 @@
}
}
},
+ "playwright-core": {
+ "version": "1.37.1",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.37.1.tgz",
+ "integrity": "sha512-17EuQxlSIYCmEMwzMqusJ2ztDgJePjrbttaefgdsiqeLWidjYz9BxXaTaZWxH1J95SHGk6tjE+dwgWILJoUZfA==",
+ "dev": true
+ },
"popmotion": {
"version": "11.0.3",
"resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz",
@@ -29599,7 +29713,8 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz",
"integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-calc": {
"version": "8.2.4",
@@ -29709,25 +29824,29 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz",
"integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-discard-duplicates": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz",
"integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-discard-empty": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz",
"integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-discard-overridden": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz",
"integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-double-position-gradients": {
"version": "3.1.2",
@@ -29752,7 +29871,8 @@
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz",
"integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-focus-visible": {
"version": "6.0.4",
@@ -29776,13 +29896,15 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz",
"integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-gap-properties": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz",
"integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-image-set-function": {
"version": "4.0.7",
@@ -29808,7 +29930,8 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz",
"integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-js": {
"version": "4.0.1",
@@ -29880,13 +30003,15 @@
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz",
"integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-media-minmax": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz",
"integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-merge-longhand": {
"version": "5.1.7",
@@ -29954,7 +30079,8 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-modules-local-by-default": {
"version": "4.0.0",
@@ -30019,7 +30145,8 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz",
"integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-normalize-display-values": {
"version": "5.1.0",
@@ -30099,7 +30226,8 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz",
"integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-ordered-values": {
"version": "5.1.3",
@@ -30124,7 +30252,8 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz",
"integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-place": {
"version": "7.0.5",
@@ -30224,7 +30353,8 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz",
"integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"postcss-selector-not": {
"version": "6.0.1",
@@ -31171,7 +31301,8 @@
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"json-schema-traverse": {
"version": "0.4.1",
@@ -31646,7 +31777,8 @@
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz",
"integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"style-value-types": {
"version": "5.0.0",
@@ -32129,6 +32261,13 @@
"is-typedarray": "^1.0.0"
}
},
+ "typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "dev": true,
+ "peer": true
+ },
"unbox-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
@@ -32508,7 +32647,8 @@
"version": "8.12.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.12.1.tgz",
"integrity": "sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==",
- "dev": true
+ "dev": true,
+ "requires": {}
}
}
},
@@ -32977,7 +33117,8 @@
"version": "7.5.9",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"xml-name-validator": {
"version": "3.0.0",
@@ -33044,7 +33185,8 @@
"zustand": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
- "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA=="
+ "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==",
+ "requires": {}
}
}
}
diff --git a/packages/editor-mobile/package.json b/packages/editor-mobile/package.json
index 25e8597be..f5d4d22aa 100644
--- a/packages/editor-mobile/package.json
+++ b/packages/editor-mobile/package.json
@@ -3,29 +3,32 @@
"version": "1.0.0",
"private": true,
"dependencies": {
+ "@emotion/react": "11.11.1",
+ "@mdi/js": "^7.2.96",
+ "@mdi/react": "^1.6.0",
"@notesnook/editor": "file:../editor",
"@notesnook/theme": "file:../theme",
"framer-motion": "^6.5.1",
- "@mdi/js": "^7.2.96",
- "@mdi/react": "^1.6.0",
"mdi-react": "9.1.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
- "zustand": "^3.6.8",
- "@emotion/react": "11.11.1"
+ "zustand": "^3.6.8"
},
"devDependencies": {
+ "@playwright/test": "^1.37.1",
"@testing-library/jest-dom": "^5.16.0",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
+ "@types/ip": "^1.1.0",
"@types/jest": "^27.0.3",
"@types/node": "^16.11.11",
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.2",
+ "env-cmd": "^10.1.0",
+ "ip": "^1.1.8",
"react-error-overlay": "6.0.9",
"react-scripts": "^5.0.1",
- "web-vitals": "^1.1.2",
- "env-cmd": "^10.1.0"
+ "web-vitals": "^1.1.2"
},
"scripts": {
"start": "env-cmd -e all react-scripts start",
diff --git a/packages/editor-mobile/playwright.config.ts b/packages/editor-mobile/playwright.config.ts
new file mode 100644
index 000000000..63a1413ea
--- /dev/null
+++ b/packages/editor-mobile/playwright.config.ts
@@ -0,0 +1,52 @@
+/*
+This file is part of the Notesnook project (https://notesnook.com/)
+
+Copyright (C) 2023 Streetwriters (Private) Limited
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+import { PlaywrightTestConfig } from "@playwright/test";
+
+const IS_CI = !!process.env.CI;
+
+const config: PlaywrightTestConfig = {
+ webServer: {
+ command: "npm run start",
+ port: 3000,
+ timeout: 60 * 1000,
+ reuseExistingServer: false
+ },
+ // Look for test files in thcleare "tests" directory, relative to this configuration file
+ testDir: "__e2e__",
+
+ timeout: IS_CI ? 60 * 1000 : 30 * 1000,
+ workers: IS_CI ? 2 : 2,
+ reporter: "list",
+ retries: IS_CI ? 1 : 0,
+ fullyParallel: true,
+ preserveOutput: "failures-only",
+ outputDir: "test-results",
+ use: {
+ headless: true,
+ acceptDownloads: true,
+
+ // Artifacts
+ trace: "retain-on-failure",
+ screenshot: "only-on-failure",
+ video: "retry-with-video"
+ }
+};
+
+export default config;
diff --git a/packages/editor-mobile/src/theme-factory/index.tsx b/packages/editor-mobile/src/theme-factory/index.tsx
index b248e6de8..977088f03 100644
--- a/packages/editor-mobile/src/theme-factory/index.tsx
+++ b/packages/editor-mobile/src/theme-factory/index.tsx
@@ -65,7 +65,6 @@ export const EmotionEditorToolbarTheme = (props: PropsWithChildren) => {
[colors, isDark]
);
modifyToolbarTheme(theme);
- console.log(theme);
return (
{props.children}
);
diff --git a/packages/editor-mobile/src/utils/index.ts b/packages/editor-mobile/src/utils/index.ts
index eba14ae60..3c4ba72d1 100644
--- a/packages/editor-mobile/src/utils/index.ts
+++ b/packages/editor-mobile/src/utils/index.ts
@@ -186,7 +186,7 @@ export function post(
})
);
} else {
- console.log(type, value);
+ // console.log(type, value);
}
}