diff --git a/.gitattributes b/.gitattributes index 1557f6f04..ed4692f35 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ +package-lock.json linguist-generated=true **/package-lock.json linguist-generated=true \ No newline at end of file diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 295a259ce..3afb9811c 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -16,27 +16,6 @@ env: TEST_TAG: ${{ github.repository_owner }}/notes:test jobs: - build_docker: - name: Build Docker image - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up node & dependencies - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: "npm" - - run: npm ci - - name: Run the TypeScript build - run: npx tsc - - name: Create server-package.json - run: cat package.json | grep -v electron > server-package.json - - uses: docker/setup-buildx-action@v3 - - uses: docker/build-push-action@v6 - with: - context: . - cache-from: type=gha - cache-to: type=gha,mode=max test_dev: name: Test development runs-on: ubuntu-latest @@ -54,9 +33,34 @@ jobs: - name: Run the TypeScript build run: npx tsc + build_docker: + name: Build Docker image + runs-on: ubuntu-latest + needs: + - test_dev + steps: + - uses: actions/checkout@v4 + - name: Set up node & dependencies + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: "npm" + - run: npm ci + - name: Run the TypeScript build + run: npx tsc + - name: Create server-package.json + run: cat package.json | grep -v electron > server-package.json + - uses: docker/setup-buildx-action@v3 + - uses: docker/build-push-action@v6 + with: + context: . + cache-from: type=gha + cache-to: type=gha,mode=max test_docker: name: Check Docker build runs-on: ubuntu-latest + needs: + - build_docker strategy: matrix: include: diff --git a/.github/workflows/main-docker.yml b/.github/workflows/main-docker.yml index 44043f73e..e3f2393b9 100644 --- a/.github/workflows/main-docker.yml +++ b/.github/workflows/main-docker.yml @@ -48,7 +48,11 @@ jobs: node-version: 20 cache: "npm" - - run: npm ci + - name: Install npm dependencies + run: npm ci + + - name: Install Playwright Browsers + run: npx playwright install --with-deps - name: Run the TypeScript build run: npx tsc @@ -68,7 +72,7 @@ jobs: - name: Validate container run output run: | - CONTAINER_ID=$(docker run -d --log-driver=journald --rm --name trilium_local ${{ env.TEST_TAG }}) + CONTAINER_ID=$(docker run -d --log-driver=journald --rm --network=host -e TRILIUM_PORT=8082 --volume ./integration-tests/db:/home/node/trilium-data --name trilium_local ${{ env.TEST_TAG }}) echo "Container ID: $CONTAINER_ID" - name: Wait for the healthchecks to pass @@ -78,6 +82,15 @@ jobs: wait-time: 50 require-status: running require-healthy: true + + - name: Run Playwright tests + run: TRILIUM_DOCKER=1 npx playwright test + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: Playwright report (${{ matrix.dockerfile }}) + path: playwright-report/ + retention-days: 30 # Print the entire log of the container thus far, regardless if the healthcheck failed or succeeded - name: Print entire log diff --git a/e2e/i18n.spec.ts b/e2e/i18n.spec.ts new file mode 100644 index 000000000..70713f097 --- /dev/null +++ b/e2e/i18n.spec.ts @@ -0,0 +1,57 @@ +import { test, expect, Page } from "@playwright/test"; +import App from "./support/app"; + +test.afterEach(async ({ page, context }) => { + const app = new App(page, context); + // Ensure English is set after each locale change to avoid any leaks to other tests. + await app.setOption("locale", "en"); +}); + +test("Displays translation on desktop", async ({ page, context }) => { + const app = new App(page, context); + await app.goto(); + + await expect(page.locator("#left-pane .quick-search input")) + .toHaveAttribute("placeholder", "Quick search"); +}); + +test("Displays translation on mobile", async ({ page, context }) => { + const app = new App(page, context); + await app.goto({ isMobile: true }); + + await expect(page.locator("#mobile-sidebar-wrapper .quick-search input")) + .toHaveAttribute("placeholder", "Quick search"); +}); + +test("Displays translations in Settings", async ({ page, context }) => { + const app = new App(page, context); + await app.goto(); + await app.closeAllTabs(); + await app.goToSettings(); + await app.noteTree.getByText("Appearance").click(); + + await expect(app.currentNoteSplit).toContainText("Localization"); + await expect(app.currentNoteSplit).toContainText("Language"); +}); + +test("User can change language from settings", async ({ page, context }) => { + const app = new App(page, context); + await app.goto(); + + await app.closeAllTabs(); + await app.goToSettings(); + await app.noteTree.getByText("Appearance").click(); + + // Check that the default value (English) is set. + await expect(app.currentNoteSplit).toContainText("Theme"); + const languageCombobox = await app.currentNoteSplit.getByRole("combobox").first(); + await expect(languageCombobox).toHaveValue("en"); + + // Select Chinese and ensure the translation is set. + await languageCombobox.selectOption("cn"); + await expect(app.currentNoteSplit).toContainText("主题", { timeout: 15000 }); + + // Select English again. + await languageCombobox.selectOption("en"); + await expect(app.currentNoteSplit).toContainText("Language", { timeout: 15000 }); +}); diff --git a/e2e/layout/tab_bar.spec.ts b/e2e/layout/tab_bar.spec.ts index d5c2b7f15..99391c115 100644 --- a/e2e/layout/tab_bar.spec.ts +++ b/e2e/layout/tab_bar.spec.ts @@ -3,8 +3,8 @@ import App from "../support/app"; const NOTE_TITLE = "Trilium Integration Test DB"; -test("Can drag tabs around", async ({ page }) => { - const app = new App(page); +test("Can drag tabs around", async ({ page, context }) => { + const app = new App(page, context); await app.goto(); // [1]: Trilium Integration Test DB note @@ -29,8 +29,8 @@ test("Can drag tabs around", async ({ page }) => { await expect(app.getTab(0)).toContainText(NOTE_TITLE); }); -test("Can drag tab to new window", async ({ page }) => { - const app = new App(page); +test("Can drag tab to new window", async ({ page, context }) => { + const app = new App(page, context); await app.goto(); await app.closeAllTabs(); @@ -49,11 +49,11 @@ test("Can drag tab to new window", async ({ page }) => { await page.mouse.move(x, y + tabPos.height + 100, { steps: 5 }); await page.mouse.up(); } else { - fail("Unable to determine tab position"); + test.fail(true, "Unable to determine tab position"); } // Wait for the popup to show const popup = await popupPromise; - const popupApp = new App(popup); + const popupApp = new App(popup, context); await expect(popupApp.getActiveTab()).toHaveText(NOTE_TITLE); }); diff --git a/e2e/note_types/code.spec.ts b/e2e/note_types/code.spec.ts index 4f63588ee..f0f204fcc 100644 --- a/e2e/note_types/code.spec.ts +++ b/e2e/note_types/code.spec.ts @@ -1,8 +1,8 @@ import { test, expect, Page } from "@playwright/test"; import App from "../support/app"; -test("Displays lint warnings for backend script", async ({ page }) => { - const app = new App(page); +test("Displays lint warnings for backend script", async ({ page, context }) => { + const app = new App(page, context); await app.goto(); await app.closeAllTabs(); await app.goToNoteInNewTab("Backend script with lint warnings"); @@ -10,7 +10,7 @@ test("Displays lint warnings for backend script", async ({ page }) => { const codeEditor = app.currentNoteSplit.locator(".CodeMirror"); // Expect two warning signs in the gutter. - expect(codeEditor.locator(".CodeMirror-gutter-wrapper .CodeMirror-lint-marker-warning")).toHaveCount(2); + await expect(codeEditor.locator(".CodeMirror-gutter-wrapper .CodeMirror-lint-marker-warning")).toHaveCount(2); // Hover over hello await codeEditor.getByText("hello").first().hover(); @@ -21,8 +21,8 @@ test("Displays lint warnings for backend script", async ({ page }) => { await expectTooltip(page, "'world' is defined but never used."); }); -test("Displays lint errors for backend script", async ({ page }) => { - const app = new App(page); +test("Displays lint errors for backend script", async ({ page, context }) => { + const app = new App(page, context); await app.goto(); await app.closeAllTabs(); await app.goToNoteInNewTab("Backend script with lint errors"); diff --git a/e2e/note_types/mindmap.ts b/e2e/note_types/mindmap.ts new file mode 100644 index 000000000..b06076cc3 --- /dev/null +++ b/e2e/note_types/mindmap.ts @@ -0,0 +1,22 @@ +import { test, expect, Page } from "@playwright/test"; +import App from "../support/app"; + +test("displays simple map", async ({ page, context }) => { + const app = new App(page, context); + await app.goto(); + await app.goToNoteInNewTab("Sample mindmap"); + + await expect(app.currentNoteSplit).toContainText("Hello world"); + await expect(app.currentNoteSplit).toContainText("1"); + await expect(app.currentNoteSplit).toContainText("1a"); +}); + +test("displays note settings", async ({ page, context }) => { + const app = new App(page, context); + await app.goto(); + await app.goToNoteInNewTab("Sample mindmap"); + + await app.currentNoteSplit.getByText("Hello world").click({ force: true }); + const nodeMenu = app.currentNoteSplit.locator(".node-menu"); + await expect(nodeMenu).toBeVisible(); +}); diff --git a/e2e/note_types/text.spec.ts b/e2e/note_types/text.spec.ts index 2a8880f18..d7b878724 100644 --- a/e2e/note_types/text.spec.ts +++ b/e2e/note_types/text.spec.ts @@ -1,8 +1,8 @@ import { test, expect, Page } from "@playwright/test"; import App from "../support/app"; -test("Table of contents is displayed", async ({ page }) => { - const app = new App(page); +test("Table of contents is displayed", async ({ page, context }) => { + const app = new App(page, context); await app.goto(); await app.closeAllTabs(); await app.goToNoteInNewTab("Table of contents"); @@ -36,8 +36,8 @@ test("Table of contents is displayed", async ({ page }) => { await expect(rootList.locator("> ol").nth(1).locator("> ol > ol > ol")).toHaveCount(1); }); -test("Highlights list is displayed", async ({ page }) => { - const app = new App(page); +test("Highlights list is displayed", async ({ page, context }) => { + const app = new App(page, context); await app.goto(); await app.closeAllTabs(); await app.goToNoteInNewTab("Highlights list"); diff --git a/e2e/support/app.ts b/e2e/support/app.ts index 4f36dfb7b..290d9c420 100644 --- a/e2e/support/app.ts +++ b/e2e/support/app.ts @@ -1,27 +1,46 @@ -import { Locator, Page, expect } from "@playwright/test"; +import { expect, Locator, Page } from "@playwright/test"; +import type { BrowserContext } from "@playwright/test"; + +interface GotoOpts { + isMobile?: boolean; +} + +const BASE_URL = "http://127.0.0.1:8082"; export default class App { readonly page: Page; + readonly context: BrowserContext; readonly tabBar: Locator; readonly noteTree: Locator; readonly currentNoteSplit: Locator; readonly sidebar: Locator; - constructor(page: Page) { + constructor(page: Page, context: BrowserContext) { this.page = page; + this.context = context; + this.tabBar = page.locator(".tab-row-widget-container"); this.noteTree = page.locator(".tree-wrapper"); this.currentNoteSplit = page.locator(".note-split:not(.hidden-ext)") this.sidebar = page.locator("#right-pane"); } - async goto() { + async goto(opts: GotoOpts = {}) { + await this.context.addCookies([ + { + url: BASE_URL, + name: "trilium-device", + value: opts.isMobile ? "mobile" : "desktop" + } + ]); + await this.page.goto("/", { waitUntil: "networkidle" }); // Wait for the page to load. await expect(this.page.locator(".tree")) .toContainText("Trilium Integration Test"); + await this.closeAllTabs(); } async goToNoteInNewTab(noteTitle: string) { @@ -31,6 +50,10 @@ export default class App { await autocomplete.press("Enter"); } + async goToSettings() { + await this.page.locator(".launcher-button.bx-cog").click(); + } + getTab(tabIndex: number) { return this.tabBar.locator(".note-tab-wrapper").nth(tabIndex); } @@ -39,18 +62,49 @@ export default class App { return this.tabBar.locator(".note-tab[active]"); } + /** + * Closes all the tabs in the client by issuing a command. + */ async closeAllTabs() { - await this.getTab(0).click({ button: "right" }); - await this.page.waitForTimeout(500); // TODO: context menu won't dismiss otherwise - await this.page.getByText("Close all tabs").click({ force: true }); + await this.triggerCommand("closeAllTabs"); } + /** + * Adds a new tab by cliking on the + button near the tab bar. + */ async addNewTab() { await this.page.locator('[data-trigger-command="openNewTab"]').click(); } + /** + * Looks for a given title in the note tree and clicks on it. Useful for selecting option pages in settings in a similar fashion as the user. + * @param title the title of the note to click, as displayed in the note tree. + */ async clickNoteOnNoteTreeByTitle(title: string) { - this.noteTree.getByText(title).click(); + await this.noteTree.getByText(title).click(); + } + + /** + * Executes any Trilium command on the client. + * @param command the command to send. + */ + async triggerCommand(command: string) { + await this.page.evaluate(async (command: string) => { + await (window as any).glob.appContext.triggerCommand(command); + }, command); + } + + async setOption(key: string, value: string) { + const csrfToken = await this.page.evaluate(() => { + return (window as any).glob.csrfToken; + }); + + expect(csrfToken).toBeTruthy(); + await expect(await this.page.request.put(`${BASE_URL}/api/options/${key}/${value}`, { + headers: { + "x-csrf-token": csrfToken + } + })).toBeOK(); } } diff --git a/integration-tests/db/document.db b/integration-tests/db/document.db index a4a44162f..578b95cd7 100644 Binary files a/integration-tests/db/document.db and b/integration-tests/db/document.db differ diff --git a/integration-tests/i18n.spec.ts b/integration-tests/i18n.spec.ts deleted file mode 100644 index 1c3fc1d36..000000000 --- a/integration-tests/i18n.spec.ts +++ /dev/null @@ -1,43 +0,0 @@ -import test, { expect } from "@playwright/test"; - -test("User can change language from settings", async ({ page }) => { - await page.goto("http://localhost:8082"); - - // Clear all tabs - await page.locator(".note-tab:first-of-type").locator("div").nth(1).click({ button: "right" }); - await page.getByText("Close all tabs").click(); - - // Go to options -> Appearance - await page.locator("#launcher-pane div").filter({ hasText: "Options Open New Window" }).getByRole("button").click(); - await page.locator("#launcher-pane").getByText("Options").click(); - await page.locator("#center-pane").getByText("Appearance").click(); - - // Check that the default value (English) is set. - await expect(page.locator("#center-pane")).toContainText("Theme"); - const languageCombobox = await page.getByRole("combobox").first(); - await expect(languageCombobox).toHaveValue("en"); - - // Select Chinese and ensure the translation is set. - languageCombobox.selectOption("cn"); - await expect(page.locator("#center-pane")).toContainText("主题"); - - // Select English again. - languageCombobox.selectOption("en"); -}); - -test("Restores language on start-up on desktop", async ({ page, context }) => { - await page.goto("http://localhost:8082"); - await expect(page.locator("#launcher-pane").first()).toContainText("Open New Window"); -}); - -test("Restores language on start-up on mobile", async ({ page, context }) => { - await context.addCookies([ - { - url: "http://localhost:8082", - name: "trilium-device", - value: "mobile" - } - ]); - await page.goto("http://localhost:8082"); - await expect(page.locator("#launcher-pane div").first()).toContainText("Open New Window"); -}); diff --git a/package-lock.json b/package-lock.json index 2df4756a8..9cc346566 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,7 +70,7 @@ "marked": "15.0.6", "mermaid": "11.4.1", "mime-types": "2.1.35", - "mind-elixir": "4.3.5", + "mind-elixir": "4.3.6", "multer": "1.4.5-lts.1", "normalize-strings": "1.1.1", "normalize.css": "8.0.1", @@ -91,7 +91,7 @@ "stream-throttle": "0.1.3", "striptags": "3.2.0", "tmp": "0.2.3", - "ts-loader": "9.5.1", + "ts-loader": "9.5.2", "turndown": "7.2.0", "unescape": "1.0.1", "vanilla-js-wheel-zoom": "9.0.4", @@ -109,6 +109,7 @@ "@electron-forge/maker-squirrel": "7.6.0", "@electron-forge/maker-zip": "7.6.0", "@electron-forge/plugin-auto-unpack-natives": "7.6.0", + "@electron/rebuild": "3.7.1", "@playwright/test": "1.49.1", "@types/archiver": "6.0.3", "@types/better-sqlite3": "7.6.12", @@ -131,7 +132,7 @@ "@types/jsdom": "21.1.7", "@types/mime-types": "2.1.4", "@types/multer": "1.4.12", - "@types/node": "22.10.5", + "@types/node": "22.10.6", "@types/safe-compare": "1.1.2", "@types/sanitize-html": "2.13.0", "@types/sax": "1.2.7", @@ -147,8 +148,6 @@ "@types/yargs": "17.0.33", "cross-env": "7.0.3", "electron": "33.3.1", - "electron-packager": "17.1.2", - "electron-rebuild": "3.2.9", "esm": "3.2.25", "iconsur": "1.7.0", "jasmine": "5.5.0", @@ -4333,9 +4332,9 @@ } }, "node_modules/@types/node": { - "version": "22.10.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz", - "integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==", + "version": "22.10.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.6.tgz", + "integrity": "sha512-qNiuwC4ZDAUNcY47xgaSuS92cjf8JbSUoaKS77bmLG1rU7MlATVSiw/IlrjtIyyskXBZ8KkNfjK/P5na7rgXbQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5098,13 +5097,6 @@ "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", "license": "MIT" }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true, - "license": "ISC" - }, "node_modules/archiver": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", @@ -5194,36 +5186,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -5807,19 +5769,6 @@ "node": ">=8.0.0" } }, - "node_modules/buffer-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", - "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", @@ -6520,16 +6469,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -6687,13 +6626,6 @@ "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", "license": "MIT" }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true, - "license": "ISC" - }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -7706,13 +7638,6 @@ "node": ">=0.4.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true, - "license": "MIT" - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -8344,307 +8269,6 @@ "keyboardevents-areequal": "^0.2.1" } }, - "node_modules/electron-packager": { - "version": "17.1.2", - "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-17.1.2.tgz", - "integrity": "sha512-XofXdikjYI7MVBcnXeoOvRR+yFFFHOLs3J7PF5KYQweigtgLshcH4W660PsvHr4lYZ03JBpLyEcUB8DzHZ+BNw==", - "deprecated": "Please use @electron/packager moving forward. There is no API change, just a package name change", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@electron/asar": "^3.2.1", - "@electron/get": "^2.0.0", - "@electron/notarize": "^1.2.3", - "@electron/osx-sign": "^1.0.5", - "@electron/universal": "^1.3.2", - "cross-spawn-windows-exe": "^1.2.0", - "debug": "^4.0.1", - "extract-zip": "^2.0.0", - "filenamify": "^4.1.0", - "fs-extra": "^11.1.0", - "galactus": "^1.0.0", - "get-package-info": "^1.0.0", - "junk": "^3.1.0", - "parse-author": "^2.0.0", - "plist": "^3.0.0", - "rcedit": "^3.0.1", - "resolve": "^1.1.6", - "semver": "^7.1.3", - "yargs-parser": "^21.1.1" - }, - "bin": { - "electron-packager": "bin/electron-packager.js" - }, - "engines": { - "node": ">= 14.17.5" - }, - "funding": { - "url": "https://github.com/electron/electron-packager?sponsor=1" - } - }, - "node_modules/electron-packager/node_modules/@electron/get": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", - "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "got": "^11.8.5", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "global-agent": "^3.0.0" - } - }, - "node_modules/electron-packager/node_modules/@electron/get/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/electron-packager/node_modules/@electron/get/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/electron-packager/node_modules/@electron/get/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/electron-packager/node_modules/@electron/notarize": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-1.2.4.tgz", - "integrity": "sha512-W5GQhJEosFNafewnS28d3bpQ37/s91CDWqxVchHfmv2dQSTWpOzNlUVQwYzC1ay5bChRV/A9BTL68yj0Pa+TSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "fs-extra": "^9.0.1" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron-packager/node_modules/@electron/notarize/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-packager/node_modules/@electron/notarize/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-packager/node_modules/@electron/universal": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", - "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron/asar": "^3.2.1", - "@malept/cross-spawn-promise": "^1.1.0", - "debug": "^4.3.1", - "dir-compare": "^3.0.0", - "fs-extra": "^9.0.1", - "minimatch": "^3.0.4", - "plist": "^3.0.4" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/electron-packager/node_modules/@electron/universal/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-packager/node_modules/@electron/universal/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-packager/node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/electron-packager/node_modules/dir-compare": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", - "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-equal": "^1.0.0", - "minimatch": "^3.0.4" - } - }, - "node_modules/electron-packager/node_modules/rcedit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/rcedit/-/rcedit-3.1.0.tgz", - "integrity": "sha512-WRlRdY1qZbu1L11DklT07KuHfRk42l0NFFJdaExELEu4fEQ982bP5Z6OWGPj/wLLIuKRQDCxZJGAwoFsxhZhNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn-windows-exe": "^1.1.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron-rebuild": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-3.2.9.tgz", - "integrity": "sha512-FkEZNFViUem3P0RLYbZkUjC8LUFIK+wKq09GHoOITSJjfDAVQv964hwaNseTTWt58sITQX3/5fHNYcTefqaCWw==", - "deprecated": "Please use @electron/rebuild moving forward. There is no API change, just a package name change", - "dev": true, - "license": "MIT", - "dependencies": { - "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", - "debug": "^4.1.1", - "detect-libc": "^2.0.1", - "fs-extra": "^10.0.0", - "got": "^11.7.0", - "lzma-native": "^8.0.5", - "node-abi": "^3.0.0", - "node-api-version": "^0.1.4", - "node-gyp": "^9.0.0", - "ora": "^5.1.0", - "semver": "^7.3.5", - "tar": "^6.0.5", - "yargs": "^17.0.1" - }, - "bin": { - "electron-rebuild": "lib/src/cli.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/electron-rebuild/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-rebuild/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-rebuild/node_modules/node-api-version": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.1.4.tgz", - "integrity": "sha512-KGXihXdUChwJAOHO53bv9/vXcLmdUsZ6jIptbvYvkpKfth+r7jw44JkVxQFA3kX5nQjzjmGu1uAu/xNNLNlI5g==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - } - }, "node_modules/electron-squirrel-startup": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/electron-squirrel-startup/-/electron-squirrel-startup-1.0.1.tgz", @@ -10101,82 +9725,6 @@ "license": "MIT", "optional": true }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/gauge/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -10553,13 +10101,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true, - "license": "ISC" - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -12397,40 +11938,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lzma-native": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/lzma-native/-/lzma-native-8.0.6.tgz", - "integrity": "sha512-09xfg67mkL2Lz20PrrDeNYZxzeW7ADtpYFbwSQh9U8+76RIzx5QsJBMy8qikv3hbUPfpy6hqwxt6FcGK81g9AA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "node-addon-api": "^3.1.0", - "node-gyp-build": "^4.2.1", - "readable-stream": "^3.6.0" - }, - "bin": { - "lzmajs": "bin/lzmajs" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/lzma-native/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/macos-alias": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/macos-alias/-/macos-alias-0.2.12.tgz", @@ -12817,9 +12324,9 @@ } }, "node_modules/mind-elixir": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/mind-elixir/-/mind-elixir-4.3.5.tgz", - "integrity": "sha512-I1Mxc/jCwHEDMecDjQVpc+WShmzrEnIv6+MnWPauJ0LAiOXMBQB/wpKqlF4bTp+kCqzOHMYryAvIWm0jvloZ8Q==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/mind-elixir/-/mind-elixir-4.3.6.tgz", + "integrity": "sha512-6E9DT5vOYJ7DMDFXJlAnKU3Q6ekwBkR48Tjo6PchEcxJjPURJsiIASxtIeZCfvp8V39N4WyIa3Yt7Q/SFQkVfw==", "license": "MIT" }, "node_modules/minimalistic-assert": { @@ -13086,13 +12593,6 @@ "node": ">=10" } }, - "node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true, - "license": "MIT" - }, "node_modules/node-api-version": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.0.tgz", @@ -13145,61 +12645,6 @@ "webidl-conversions": "^3.0.0" } }, - "node_modules/node-gyp": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", - "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^12.13 || ^14.13 || >=16" - } - }, - "node_modules/node-gyp-build": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", - "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", - "dev": true, - "license": "MIT", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/node-gyp/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -13406,23 +12851,6 @@ "node": ">=4" } }, - "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -15761,13 +15189,6 @@ "node": ">= 4.0.0" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true, - "license": "ISC" - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -16995,9 +16416,9 @@ } }, "node_modules/ts-loader": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", - "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.2.tgz", + "integrity": "sha512-Qo4piXvOTWcMGIgRiuFa6nHNm+54HbYaZCKqc9eeZCLRy3XqafQgwX2F7mofrbJG3g7EEb+lkiR+z2Lic2s3Zw==", "license": "MIT", "dependencies": { "chalk": "^4.1.0", @@ -17941,71 +17362,6 @@ "node": ">= 8" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/wide-align/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", diff --git a/package.json b/package.json index 245e9bdd1..a8903d985 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "build-frontend-docs": "rimraf ./docs/frontend_api && jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/basic_widget.js src/public/app/widgets/note_context_aware_widget.js src/public/app/widgets/right_panel_widget.js", "build-docs": "npm run build-backend-docs && npm run build-frontend-docs", "webpack": "cross-env node --import ./loader-register.js node_modules/webpack/bin/webpack.js -c webpack.config.ts", + "test-playwright": "playwright test", "test-jasmine": "cross-env TRILIUM_DATA_DIR=./data-test tsx ./node_modules/jasmine/bin/jasmine.js", "test-es6": "tsx -r esm spec-es6/attribute_parser.spec.ts", "test": "npm run test-jasmine && npm run test-es6", @@ -115,7 +116,7 @@ "marked": "15.0.6", "mermaid": "11.4.1", "mime-types": "2.1.35", - "mind-elixir": "4.3.5", + "mind-elixir": "4.3.6", "multer": "1.4.5-lts.1", "normalize-strings": "1.1.1", "normalize.css": "8.0.1", @@ -136,7 +137,7 @@ "stream-throttle": "0.1.3", "striptags": "3.2.0", "tmp": "0.2.3", - "ts-loader": "9.5.1", + "ts-loader": "9.5.2", "turndown": "7.2.0", "unescape": "1.0.1", "vanilla-js-wheel-zoom": "9.0.4", @@ -151,6 +152,7 @@ "@electron-forge/maker-squirrel": "7.6.0", "@electron-forge/maker-zip": "7.6.0", "@electron-forge/plugin-auto-unpack-natives": "7.6.0", + "@electron/rebuild": "3.7.1", "@playwright/test": "1.49.1", "@types/archiver": "6.0.3", "@types/better-sqlite3": "7.6.12", @@ -173,7 +175,7 @@ "@types/jsdom": "21.1.7", "@types/mime-types": "2.1.4", "@types/multer": "1.4.12", - "@types/node": "22.10.5", + "@types/node": "22.10.6", "@types/safe-compare": "1.1.2", "@types/sanitize-html": "2.13.0", "@types/sax": "1.2.7", @@ -189,8 +191,6 @@ "@types/yargs": "17.0.33", "cross-env": "7.0.3", "electron": "33.3.1", - "electron-packager": "17.1.2", - "electron-rebuild": "3.2.9", "esm": "3.2.25", "iconsur": "1.7.0", "jasmine": "5.5.0", diff --git a/playwright.config.ts b/playwright.config.ts index 86de95af0..86bf074ce 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -73,9 +73,9 @@ export default defineConfig({ ], /* Run your local dev server before starting the tests */ - webServer: { + webServer: !process.env.TRILIUM_DOCKER ? { command: 'npm run integration-mem-db-dev', url: SERVER_URL, - // reuseExistingServer: !process.env.CI, - }, + reuseExistingServer: !process.env.CI, + } : undefined, }); diff --git a/spec-es6/data_dir.spec.ts b/spec-es6/data_dir.spec.ts new file mode 100644 index 000000000..70a329ff5 --- /dev/null +++ b/spec-es6/data_dir.spec.ts @@ -0,0 +1,138 @@ +import { describe, it, execute, expect } from "./mini_test.ts"; + +import { getPlatformAppDataDir, getDataDirs} from "../src/services/data_dir.ts" + + + +describe("data_dir.ts unit tests", () => { + + describe("#getPlatformAppDataDir()", () => { + + type TestCaseGetPlatformAppDataDir = [ + description: string, + fnValue: Parameters, + expectedValueFn: (val: ReturnType) => boolean + ] + const testCases: TestCaseGetPlatformAppDataDir[] = [ + + [ + "w/ unsupported OS it should return 'null'", + ["aix", undefined], + (val) => val === null + ], + + [ + "w/ win32 and no APPDATA set it should return 'null'", + ["win32", undefined], + (val) => val === null + ], + + [ + "w/ win32 and set APPDATA it should return set 'APPDATA'", + ["win32", "AppData"], + (val) => val === "AppData" + ], + + [ + "w/ linux it should return '/.local/share'", + ["linux", undefined], + (val) => val !== null && val.endsWith("/.local/share") + ], + + [ + "w/ linux and wrongly set APPDATA it should ignore APPDATA and return /.local/share", + ["linux", "FakeAppData"], + (val) => val !== null && val.endsWith("/.local/share") + ], + + [ + "w/ darwin it should return /Library/Application Support", + ["darwin", undefined], + (val) => val !== null && val.endsWith("/Library/Application Support") + ], + ]; + + testCases.forEach(testCase => { + const [testDescription, value, isExpected] = testCase; + return it(testDescription, () => { + const actual = getPlatformAppDataDir(...value); + const result = isExpected(actual); + expect(result).toBeTruthy() + + }) + }) + + + }) + + describe("#getTriliumDataDir", () => { + // TODO + }) + + describe("#getDataDirs()", () => { + + const envKeys: Omit, "TRILIUM_DATA_DIR">[] = [ + "DOCUMENT_PATH", + "BACKUP_DIR", + "LOG_DIR", + "ANONYMIZED_DB_DIR", + "CONFIG_INI_PATH", + ]; + + const setMockedEnv = (prefix: string | null) => { + envKeys.forEach(key => { + if (prefix) { + process.env[`TRILIUM_${key}`] = `${prefix}_${key}` + } else { + delete process.env[`TRILIUM_${key}`] + } + }) + }; + + it("w/ process.env values present, it should return an object using values from process.env", () => { + + // set mocked values + const mockValuePrefix = "MOCK"; + setMockedEnv(mockValuePrefix); + + // get result + const result = getDataDirs(`${mockValuePrefix}_TRILIUM_DATA_DIR`); + + for (const key in result) { + expect(result[key]).toEqual(`${mockValuePrefix}_${key}`) + } + }) + + it("w/ NO process.env values present, it should return an object using supplied TRILIUM_DATA_DIR as base", () => { + + // make sure values are undefined + setMockedEnv(null); + + const mockDataDir = "/home/test/MOCK_TRILIUM_DATA_DIR" + const result = getDataDirs(mockDataDir); + + for (const key in result) { + expect(result[key].startsWith(mockDataDir)).toBeTruthy() + } + }) + + it("should ignore attempts to change a property on the returned object", () => { + + // make sure values are undefined + setMockedEnv(null); + + const mockDataDir = "/home/test/MOCK_TRILIUM_DATA_DIR" + const result = getDataDirs(mockDataDir); + + //@ts-expect-error - attempt to change value of readonly property + result.BACKUP_DIR = "attempt to change"; + + for (const key in result) { + expect(result[key].startsWith(mockDataDir)).toBeTruthy() + } + }) + }) + +}); + +execute() \ No newline at end of file diff --git a/spec/search/becca_mocking.ts b/spec/search/becca_mocking.ts index 76ee955f6..0c65f16b6 100644 --- a/spec/search/becca_mocking.ts +++ b/spec/search/becca_mocking.ts @@ -3,7 +3,7 @@ import BBranch from "../../src/becca/entities/bbranch.js"; import BAttribute from "../../src/becca/entities/battribute.js"; import becca from "../../src/becca/becca.js"; import randtoken from "rand-token"; -import SearchResult from "../../src/services/search/search_result.js"; +import type SearchResult from "../../src/services/search/search_result.js"; import type { NoteType } from "../../src/becca/entities/rows.js"; randtoken.generator({ source: "crypto" }); diff --git a/spec/search/parser.spec.ts b/spec/search/parser.spec.ts index 09c7ce06b..76e557067 100644 --- a/spec/search/parser.spec.ts +++ b/spec/search/parser.spec.ts @@ -1,6 +1,6 @@ import AndExp from "../../src/services/search/expressions/and.js"; import AttributeExistsExp from "../../src/services/search/expressions/attribute_exists.js"; -import Expression from "../../src/services/search/expressions/expression.js"; +import type Expression from "../../src/services/search/expressions/expression.js"; import LabelComparisonExp from "../../src/services/search/expressions/label_comparison.js"; import NotExp from "../../src/services/search/expressions/not.js"; import NoteContentFulltextExp from "../../src/services/search/expressions/note_content_fulltext.js"; diff --git a/spec/support/etapi.ts b/spec/support/etapi.ts index 3e6e1ac98..d653707d5 100644 --- a/spec/support/etapi.ts +++ b/spec/support/etapi.ts @@ -1,4 +1,4 @@ -import child_process from "child_process"; +import type child_process from "child_process"; let etapiAuthToken: string | undefined; diff --git a/src/becca/becca-interface.ts b/src/becca/becca-interface.ts index 6497dad7d..cdee5d1cd 100644 --- a/src/becca/becca-interface.ts +++ b/src/becca/becca-interface.ts @@ -1,17 +1,17 @@ import sql from "../services/sql.js"; import NoteSet from "../services/search/note_set.js"; import NotFoundError from "../errors/not_found_error.js"; -import BOption from "./entities/boption.js"; -import BNote from "./entities/bnote.js"; -import BEtapiToken from "./entities/betapi_token.js"; -import BAttribute from "./entities/battribute.js"; -import BBranch from "./entities/bbranch.js"; +import type BOption from "./entities/boption.js"; +import type BNote from "./entities/bnote.js"; +import type BEtapiToken from "./entities/betapi_token.js"; +import type BAttribute from "./entities/battribute.js"; +import type BBranch from "./entities/bbranch.js"; import BRevision from "./entities/brevision.js"; import BAttachment from "./entities/battachment.js"; import type { AttachmentRow, BlobRow, RevisionRow } from "./entities/rows.js"; import BBlob from "./entities/bblob.js"; import BRecentNote from "./entities/brecent_note.js"; -import AbstractBeccaEntity from "./entities/abstract_becca_entity.js"; +import type AbstractBeccaEntity from "./entities/abstract_becca_entity.js"; interface AttachmentOpts { includeContentLength?: boolean; diff --git a/src/becca/becca_loader.ts b/src/becca/becca_loader.ts index a461828ac..8397b2dec 100644 --- a/src/becca/becca_loader.ts +++ b/src/becca/becca_loader.ts @@ -12,7 +12,7 @@ import BEtapiToken from "./entities/betapi_token.js"; import cls from "../services/cls.js"; import entityConstructor from "../becca/entity_constructor.js"; import type { AttributeRow, BranchRow, EtapiTokenRow, NoteRow, OptionRow } from "./entities/rows.js"; -import AbstractBeccaEntity from "./entities/abstract_becca_entity.js"; +import type AbstractBeccaEntity from "./entities/abstract_becca_entity.js"; import ws from "../services/ws.js"; const beccaLoaded = new Promise(async (res, rej) => { diff --git a/src/becca/entities/abstract_becca_entity.ts b/src/becca/entities/abstract_becca_entity.ts index b964a2d43..a36132f3a 100644 --- a/src/becca/entities/abstract_becca_entity.ts +++ b/src/becca/entities/abstract_becca_entity.ts @@ -9,7 +9,7 @@ import cls from "../../services/cls.js"; import log from "../../services/log.js"; import protectedSessionService from "../../services/protected_session.js"; import blobService from "../../services/blob.js"; -import Becca, { type ConstructorData } from "../becca-interface.js"; +import type { default as Becca, ConstructorData } from "../becca-interface.js"; import becca from "../becca.js"; interface ContentOpts { diff --git a/src/becca/entities/battachment.ts b/src/becca/entities/battachment.ts index 1e47fc9bf..9461647af 100644 --- a/src/becca/entities/battachment.ts +++ b/src/becca/entities/battachment.ts @@ -7,8 +7,8 @@ import sql from "../../services/sql.js"; import protectedSessionService from "../../services/protected_session.js"; import log from "../../services/log.js"; import type { AttachmentRow } from "./rows.js"; -import BNote from "./bnote.js"; -import BBranch from "./bbranch.js"; +import type BNote from "./bnote.js"; +import type BBranch from "./bbranch.js"; import noteService from "../../services/notes.js"; const attachmentRoleToNoteTypeMapping = { diff --git a/src/becca/entities/bnote.ts b/src/becca/entities/bnote.ts index d83a263ff..acc432127 100644 --- a/src/becca/entities/bnote.ts +++ b/src/becca/entities/bnote.ts @@ -15,7 +15,7 @@ import dayjs from "dayjs"; import utc from "dayjs/plugin/utc.js"; import eventService from "../../services/events.js"; import type { AttachmentRow, AttributeType, NoteRow, NoteType, RevisionRow } from "./rows.js"; -import BBranch from "./bbranch.js"; +import type BBranch from "./bbranch.js"; import BAttribute from "./battribute.js"; import type { NotePojo } from "../becca-interface.js"; import searchService from "../../services/search/services/search.js"; diff --git a/src/becca/entity_constructor.ts b/src/becca/entity_constructor.ts index 83c5bd62c..18f7a14c7 100644 --- a/src/becca/entity_constructor.ts +++ b/src/becca/entity_constructor.ts @@ -1,5 +1,5 @@ import type { ConstructorData } from "./becca-interface.js"; -import AbstractBeccaEntity from "./entities/abstract_becca_entity.js"; +import type AbstractBeccaEntity from "./entities/abstract_becca_entity.js"; import BAttachment from "./entities/battachment.js"; import BAttribute from "./entities/battribute.js"; import BBlob from "./entities/bblob.js"; diff --git a/src/becca/similarity.ts b/src/becca/similarity.ts index 5313419d6..66af0ac61 100644 --- a/src/becca/similarity.ts +++ b/src/becca/similarity.ts @@ -3,7 +3,7 @@ import log from "../services/log.js"; import beccaService from "./becca_service.js"; import dateUtils from "../services/date_utils.js"; import { JSDOM } from "jsdom"; -import BNote from "./entities/bnote.js"; +import type BNote from "./entities/bnote.js"; const DEBUG = false; diff --git a/src/etapi/app_info.ts b/src/etapi/app_info.ts index ec5b781c2..ab6deb9dd 100644 --- a/src/etapi/app_info.ts +++ b/src/etapi/app_info.ts @@ -1,4 +1,4 @@ -import { Router } from "express"; +import type { Router } from "express"; import appInfo from "../services/app_info.js"; import eu from "./etapi_utils.js"; diff --git a/src/etapi/attachments.ts b/src/etapi/attachments.ts index 5d3ce57e4..0404e11a1 100644 --- a/src/etapi/attachments.ts +++ b/src/etapi/attachments.ts @@ -3,7 +3,7 @@ import eu from "./etapi_utils.js"; import mappers from "./mappers.js"; import v from "./validators.js"; import utils from "../services/utils.js"; -import { Router } from "express"; +import type { Router } from "express"; import type { AttachmentRow } from "../becca/entities/rows.js"; import type { ValidatorMap } from "./etapi-interface.js"; diff --git a/src/etapi/attributes.ts b/src/etapi/attributes.ts index 3b9cf3451..91a441117 100644 --- a/src/etapi/attributes.ts +++ b/src/etapi/attributes.ts @@ -3,7 +3,7 @@ import eu from "./etapi_utils.js"; import mappers from "./mappers.js"; import attributeService from "../services/attributes.js"; import v from "./validators.js"; -import { Router } from "express"; +import type { Router } from "express"; import type { AttributeRow } from "../becca/entities/rows.js"; import type { ValidatorMap } from "./etapi-interface.js"; diff --git a/src/etapi/backup.ts b/src/etapi/backup.ts index 3b9f3f874..d73bf1a33 100644 --- a/src/etapi/backup.ts +++ b/src/etapi/backup.ts @@ -1,4 +1,4 @@ -import { Router } from "express"; +import type { Router } from "express"; import eu from "./etapi_utils.js"; import backupService from "../services/backup.js"; diff --git a/src/etapi/branches.ts b/src/etapi/branches.ts index 59f87c3c8..7263b3161 100644 --- a/src/etapi/branches.ts +++ b/src/etapi/branches.ts @@ -1,4 +1,4 @@ -import { Router } from "express"; +import type { Router } from "express"; import becca from "../becca/becca.js"; import eu from "./etapi_utils.js"; diff --git a/src/etapi/mappers.ts b/src/etapi/mappers.ts index 33cd2c29f..735e767c2 100644 --- a/src/etapi/mappers.ts +++ b/src/etapi/mappers.ts @@ -1,7 +1,7 @@ -import BAttachment from "../becca/entities/battachment.js"; -import BAttribute from "../becca/entities/battribute.js"; -import BBranch from "../becca/entities/bbranch.js"; -import BNote from "../becca/entities/bnote.js"; +import type BAttachment from "../becca/entities/battachment.js"; +import type BAttribute from "../becca/entities/battribute.js"; +import type BBranch from "../becca/entities/bbranch.js"; +import type BNote from "../becca/entities/bnote.js"; function mapNoteToPojo(note: BNote) { return { diff --git a/src/etapi/notes.ts b/src/etapi/notes.ts index 05b120195..5ab1727b9 100644 --- a/src/etapi/notes.ts +++ b/src/etapi/notes.ts @@ -9,7 +9,7 @@ import searchService from "../services/search/services/search.js"; import SearchContext from "../services/search/search_context.js"; import zipExportService from "../services/export/zip.js"; import zipImportService from "../services/import/zip.js"; -import { type Request, Router } from "express"; +import type { Request, Router } from "express"; import type { ParsedQs } from "qs"; import type { NoteParams } from "../services/note-interface.js"; import type { SearchParams } from "../services/search/services/types.js"; diff --git a/src/etapi/spec.ts b/src/etapi/spec.ts index 5e27be949..925ff51a6 100644 --- a/src/etapi/spec.ts +++ b/src/etapi/spec.ts @@ -1,4 +1,4 @@ -import { Router } from "express"; +import type { Router } from "express"; import fs from "fs"; import path from "path"; diff --git a/src/etapi/special_notes.ts b/src/etapi/special_notes.ts index 14626710d..23411c987 100644 --- a/src/etapi/special_notes.ts +++ b/src/etapi/special_notes.ts @@ -2,7 +2,7 @@ import specialNotesService from "../services/special_notes.js"; import dateNotesService from "../services/date_notes.js"; import eu from "./etapi_utils.js"; import mappers from "./mappers.js"; -import { Router } from "express"; +import type { Router } from "express"; const getDateInvalidError = (date: string) => new eu.EtapiError(400, "DATE_INVALID", `Date "${date}" is not valid.`); const getMonthInvalidError = (month: string) => new eu.EtapiError(400, "MONTH_INVALID", `Month "${month}" is not valid.`); diff --git a/src/public/app/components/app_context.ts b/src/public/app/components/app_context.ts index ea11d2ea4..ae416cdd9 100644 --- a/src/public/app/components/app_context.ts +++ b/src/public/app/components/app_context.ts @@ -14,15 +14,15 @@ import MainTreeExecutors from "./main_tree_executors.js"; import toast from "../services/toast.js"; import ShortcutComponent from "./shortcut_component.js"; import { t, initLocale } from "../services/i18n.js"; -import NoteDetailWidget from "../widgets/note_detail.js"; +import type NoteDetailWidget from "../widgets/note_detail.js"; import type { ResolveOptions } from "../widgets/dialogs/delete_notes.js"; import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js"; import type { ConfirmWithMessageOptions, ConfirmWithTitleOptions } from "../widgets/dialogs/confirm.js"; import type { Node } from "../services/tree.js"; -import LoadResults from "../services/load_results.js"; +import type LoadResults from "../services/load_results.js"; import type { Attribute } from "../services/attribute_parser.js"; -import NoteTreeWidget from "../widgets/note_tree.js"; -import NoteContext, { type GetTextEditorCallback } from "./note_context.js"; +import type NoteTreeWidget from "../widgets/note_tree.js"; +import type { default as NoteContext, GetTextEditorCallback } from "./note_context.js"; interface Layout { getRootWidget: (appContext: AppContext) => RootWidget; @@ -92,7 +92,7 @@ export type CommandMappings = { filePath: string; }; focusAndSelectTitle: CommandData & { - isNewNote: boolean; + isNewNote?: boolean; }; showPromptDialog: PromptDialogOptions; showInfoDialog: ConfirmWithMessageOptions; @@ -262,6 +262,9 @@ type EventMappings = { }; noteContextRemovedEvent: { ntxIds: string[]; + }; + exportSvg: { + ntxId: string; } }; @@ -274,15 +277,16 @@ export type CommandListener = { }; export type CommandListenerData = CommandMappings[T]; -export type EventData = EventMappings[T]; type CommandAndEventMappings = CommandMappings & EventMappings; +type EventOnlyNames = keyof EventMappings; +export type EventNames = CommandNames | EventOnlyNames; +export type EventData = CommandAndEventMappings[T]; /** * This type is a discriminated union which contains all the possible commands that can be triggered via {@link AppContext.triggerCommand}. */ export type CommandNames = keyof CommandMappings; -type EventNames = keyof EventMappings; type FilterByValueType = { [K in keyof T]: T[K] extends ValueType ? K : never }[keyof T]; @@ -375,12 +379,10 @@ class AppContext extends Component { this.child(rootWidget); - this.triggerEvent("initialRenderComplete"); + this.triggerEvent("initialRenderComplete", {}); } - // TODO: Remove ignore once all commands are mapped out. - //@ts-ignore - triggerEvent(name: K, data: CommandAndEventMappings[K] = {}) { + triggerEvent(name: K, data: EventData) { return this.handleEvent(name, data); } diff --git a/src/public/app/components/component.ts b/src/public/app/components/component.ts index 569b5d433..2db9f96a4 100644 --- a/src/public/app/components/component.ts +++ b/src/public/app/components/component.ts @@ -1,5 +1,5 @@ import utils from "../services/utils.js"; -import type { CommandMappings, CommandNames } from "./app_context.js"; +import type { CommandMappings, CommandNames, EventData, EventNames } from "./app_context.js"; /** * Abstract class for all components in the Trilium's frontend. @@ -46,7 +46,7 @@ export class TypedComponent> { return this; } - handleEvent(name: string, data: unknown): Promise | null { + handleEvent(name: T, data: EventData): Promise | null { try { const callMethodPromise = this.initialized ? this.initialized.then(() => this.callMethod((this as any)[`${name}Event`], data)) : this.callMethod((this as any)[`${name}Event`], data); @@ -65,11 +65,11 @@ export class TypedComponent> { return this.parent?.triggerEvent(name, data); } - handleEventInChildren(name: string, data: unknown = {}) { - const promises = []; + handleEventInChildren(name: T, data: EventData): Promise | null { + const promises: Promise[] = []; for (const child of this.children) { - const ret = child.handleEvent(name, data); + const ret = child.handleEvent(name, data) as Promise; if (ret) { promises.push(ret); diff --git a/src/public/app/components/entrypoints.ts b/src/public/app/components/entrypoints.ts index f75198cb7..69651de17 100644 --- a/src/public/app/components/entrypoints.ts +++ b/src/public/app/components/entrypoints.ts @@ -10,7 +10,7 @@ import bundleService from "../services/bundle.js"; import froca from "../services/froca.js"; import linkService from "../services/link.js"; import { t } from "../services/i18n.js"; -import FNote from "../entities/fnote.js"; +import type FNote from "../entities/fnote.js"; // TODO: Move somewhere else nicer. export type SqlExecuteResults = unknown[]; diff --git a/src/public/app/components/note_context.ts b/src/public/app/components/note_context.ts index 2bd1981cc..e5b649e56 100644 --- a/src/public/app/components/note_context.ts +++ b/src/public/app/components/note_context.ts @@ -8,7 +8,7 @@ import froca from "../services/froca.js"; import hoistedNoteService from "../services/hoisted_note.js"; import options from "../services/options.js"; import type { ViewScope } from "../services/link.js"; -import FNote from "../entities/fnote.js"; +import type FNote from "../entities/fnote.js"; interface SetNoteOpts { triggerSwitchEvent?: unknown; diff --git a/src/public/app/entities/fnote.ts b/src/public/app/entities/fnote.ts index ed42257e1..9dea5071e 100644 --- a/src/public/app/entities/fnote.ts +++ b/src/public/app/entities/fnote.ts @@ -5,8 +5,8 @@ import froca from "../services/froca.js"; import protectedSessionHolder from "../services/protected_session_holder.js"; import cssClassManager from "../services/css_class_manager.js"; import type { Froca } from "../services/froca-interface.js"; -import FAttachment from "./fattachment.js"; -import FAttribute, { type AttributeType } from "./fattribute.js"; +import type FAttachment from "./fattachment.js"; +import type { default as FAttribute, AttributeType } from "./fattribute.js"; import utils from "../services/utils.js"; const LABEL = "label"; @@ -35,7 +35,7 @@ const NOTE_TYPE_ICONS = { * end user. Those types should be used only for checking against, they are * not for direct use. */ -type NoteType = "file" | "image" | "search" | "noteMap" | "launcher" | "doc" | "contentWidget" | "text" | "relationMap" | "render" | "canvas" | "mermaid" | "book" | "webView" | "code"; +type NoteType = "file" | "image" | "search" | "noteMap" | "launcher" | "doc" | "contentWidget" | "text" | "relationMap" | "render" | "canvas" | "mermaid" | "book" | "webView" | "code" | "mindMap"; interface NotePathRecord { isArchived: boolean; diff --git a/src/public/app/layouts/mobile_layout.ts b/src/public/app/layouts/mobile_layout.ts index 0f31199fd..64e698998 100644 --- a/src/public/app/layouts/mobile_layout.ts +++ b/src/public/app/layouts/mobile_layout.ts @@ -27,7 +27,7 @@ import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolb import SidebarContainer from "../widgets/mobile_widgets/sidebar_container.js"; import AboutDialog from "../widgets/dialogs/about.js"; import HelpDialog from "../widgets/dialogs/help.js"; -import AppContext from "../components/app_context.js"; +import type AppContext from "../components/app_context.js"; import TabRowWidget from "../widgets/tab_row.js"; import JumpToNoteDialog from "../widgets/dialogs/jump_to_note.js"; diff --git a/src/public/app/menus/launcher_context_menu.ts b/src/public/app/menus/launcher_context_menu.ts index d61e0e372..8c2b157cd 100644 --- a/src/public/app/menus/launcher_context_menu.ts +++ b/src/public/app/menus/launcher_context_menu.ts @@ -5,7 +5,7 @@ import dialogService from "../services/dialog.js"; import server from "../services/server.js"; import { t } from "../services/i18n.js"; import type { SelectMenuItemEventListener } from "../components/events.js"; -import NoteTreeWidget from "../widgets/note_tree.js"; +import type NoteTreeWidget from "../widgets/note_tree.js"; import type { FilteredCommandNames, ContextMenuCommandData } from "../components/app_context.js"; type LauncherCommandNames = FilteredCommandNames; @@ -58,7 +58,7 @@ export default class LauncherContextMenu implements SelectMenuItemEventListener< { title: t("launcher_context_menu.reset"), command: "resetLauncher", uiIcon: "bx bx-reset destructive-action-icon", enabled: canBeReset } ]; - return items.filter((row) => row !== null); + return items.filter((row) => row !== null) as MenuItem[]; } async selectMenuItemHandler({ command }: MenuCommandItem) { diff --git a/src/public/app/menus/tree_context_menu.ts b/src/public/app/menus/tree_context_menu.ts index be7983faa..650432828 100644 --- a/src/public/app/menus/tree_context_menu.ts +++ b/src/public/app/menus/tree_context_menu.ts @@ -9,8 +9,8 @@ import server from "../services/server.js"; import toastService from "../services/toast.js"; import dialogService from "../services/dialog.js"; import { t } from "../services/i18n.js"; -import NoteTreeWidget from "../widgets/note_tree.js"; -import FAttachment from "../entities/fattachment.js"; +import type NoteTreeWidget from "../widgets/note_tree.js"; +import type FAttachment from "../entities/fattachment.js"; import type { SelectMenuItemEventListener } from "../components/events.js"; // TODO: Deduplicate once client/server is well split. @@ -196,7 +196,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener row !== null); + return items.filter((row) => row !== null) as MenuItem[]; } async selectMenuItemHandler({ command, type, templateNoteId }: MenuCommandItem) { diff --git a/src/public/app/services/attribute_renderer.ts b/src/public/app/services/attribute_renderer.ts index a686b7098..6c7b9412d 100644 --- a/src/public/app/services/attribute_renderer.ts +++ b/src/public/app/services/attribute_renderer.ts @@ -1,7 +1,7 @@ import ws from "./ws.js"; import froca from "./froca.js"; -import FAttribute from "../entities/fattribute.js"; -import FNote from "../entities/fnote.js"; +import type FAttribute from "../entities/fattribute.js"; +import type FNote from "../entities/fnote.js"; async function renderAttribute(attribute: FAttribute, renderIsInheritable: boolean) { const isInheritable = renderIsInheritable && attribute.isInheritable ? `(inheritable)` : ""; diff --git a/src/public/app/services/attributes.ts b/src/public/app/services/attributes.ts index b594630c5..767d8c3af 100644 --- a/src/public/app/services/attributes.ts +++ b/src/public/app/services/attributes.ts @@ -1,6 +1,6 @@ import server from "./server.js"; import froca from "./froca.js"; -import FNote from "../entities/fnote.js"; +import type FNote from "../entities/fnote.js"; import type { AttributeRow } from "./load_results.js"; async function addLabel(noteId: string, name: string, value: string = "") { diff --git a/src/public/app/services/bulk_action.ts b/src/public/app/services/bulk_action.ts index 615e1c6eb..66922ef62 100644 --- a/src/public/app/services/bulk_action.ts +++ b/src/public/app/services/bulk_action.ts @@ -14,7 +14,7 @@ import AddLabelBulkAction from "../widgets/bulk_actions/label/add_label.js"; import AddRelationBulkAction from "../widgets/bulk_actions/relation/add_relation.js"; import RenameNoteBulkAction from "../widgets/bulk_actions/note/rename_note.js"; import { t } from "./i18n.js"; -import FNote from "../entities/fnote.js"; +import type FNote from "../entities/fnote.js"; const ACTION_GROUPS = [ { diff --git a/src/public/app/services/froca-interface.ts b/src/public/app/services/froca-interface.ts index c678e220b..8d0077989 100644 --- a/src/public/app/services/froca-interface.ts +++ b/src/public/app/services/froca-interface.ts @@ -1,8 +1,8 @@ -import FAttachment from "../entities/fattachment.js"; -import FAttribute from "../entities/fattribute.js"; -import FBlob from "../entities/fblob.js"; -import FBranch from "../entities/fbranch.js"; -import FNote from "../entities/fnote.js"; +import type FAttachment from "../entities/fattachment.js"; +import type FAttribute from "../entities/fattribute.js"; +import type FBlob from "../entities/fblob.js"; +import type FBranch from "../entities/fbranch.js"; +import type FNote from "../entities/fnote.js"; export interface Froca { notes: Record; diff --git a/src/public/app/services/froca_updater.ts b/src/public/app/services/froca_updater.ts index 89de8c5b7..f10720de4 100644 --- a/src/public/app/services/froca_updater.ts +++ b/src/public/app/services/froca_updater.ts @@ -6,7 +6,7 @@ import noteAttributeCache from "./note_attribute_cache.js"; import FBranch, { type FBranchRow } from "../entities/fbranch.js"; import FAttribute, { type FAttributeRow } from "../entities/fattribute.js"; import FAttachment, { type FAttachmentRow } from "../entities/fattachment.js"; -import FNote, { type FNoteRow } from "../entities/fnote.js"; +import type { default as FNote, FNoteRow } from "../entities/fnote.js"; import type { EntityChange } from "../server_types.js"; async function processEntityChanges(entityChanges: EntityChange[]) { diff --git a/src/public/app/services/frontend_script_api.ts b/src/public/app/services/frontend_script_api.ts index acdff7444..178b0aa59 100644 --- a/src/public/app/services/frontend_script_api.ts +++ b/src/public/app/services/frontend_script_api.ts @@ -15,11 +15,11 @@ import BasicWidget from "../widgets/basic_widget.js"; import SpacedUpdate from "./spaced_update.js"; import shortcutService from "./shortcuts.js"; import dialogService from "./dialog.js"; -import FNote from "../entities/fnote.js"; +import type FNote from "../entities/fnote.js"; import { t } from "./i18n.js"; -import NoteContext from "../components/note_context.js"; -import NoteDetailWidget from "../widgets/note_detail.js"; -import Component from "../components/component.js"; +import type NoteContext from "../components/note_context.js"; +import type NoteDetailWidget from "../widgets/note_detail.js"; +import type Component from "../components/component.js"; /** * A whole number @@ -463,7 +463,7 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig await ws.waitForMaxKnownEntityChangeId(); await appContext.tabManager.getActiveContext().setNote(notePath); - await appContext.triggerEvent("focusAndSelectTitle"); + await appContext.triggerEvent("focusAndSelectTitle", {}); }; this.openTabWithNote = async (notePath, activate) => { @@ -472,7 +472,7 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig await appContext.tabManager.openTabWithNoteWithHoisting(notePath, { activate }); if (activate) { - await appContext.triggerEvent("focusAndSelectTitle"); + await appContext.triggerEvent("focusAndSelectTitle", {}); } }; @@ -485,7 +485,7 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig await appContext.triggerCommand("openNewNoteSplit", { ntxId, notePath }); if (activate) { - await appContext.triggerEvent("focusAndSelectTitle"); + await appContext.triggerEvent("focusAndSelectTitle", {}); } }; diff --git a/src/public/app/services/hoisted_note.ts b/src/public/app/services/hoisted_note.ts index 53d62c081..597de9467 100644 --- a/src/public/app/services/hoisted_note.ts +++ b/src/public/app/services/hoisted_note.ts @@ -2,7 +2,7 @@ import appContext from "../components/app_context.js"; import treeService, { type Node } from "./tree.js"; import dialogService from "./dialog.js"; import froca from "./froca.js"; -import NoteContext from "../components/note_context.js"; +import type NoteContext from "../components/note_context.js"; import { t } from "./i18n.js"; function getHoistedNoteId() { diff --git a/src/public/app/services/keyboard_actions.ts b/src/public/app/services/keyboard_actions.ts index bdd13e28b..dfa888620 100644 --- a/src/public/app/services/keyboard_actions.ts +++ b/src/public/app/services/keyboard_actions.ts @@ -1,7 +1,7 @@ import server from "./server.js"; import appContext, { type CommandNames } from "../components/app_context.js"; import shortcutService from "./shortcuts.js"; -import Component from "../components/component.js"; +import type Component from "../components/component.js"; const keyboardActionRepo: Record = {}; diff --git a/src/public/app/services/library_loader.ts b/src/public/app/services/library_loader.ts index a67bb934a..697b20a65 100644 --- a/src/public/app/services/library_loader.ts +++ b/src/public/app/services/library_loader.ts @@ -96,10 +96,6 @@ const I18NEXT: Library = { js: ["node_modules/i18next/i18next.min.js", "node_modules/i18next-http-backend/i18nextHttpBackend.min.js"] }; -const MIND_ELIXIR: Library = { - js: ["node_modules/mind-elixir/dist/MindElixir.iife.js", "node_modules/@mind-elixir/node-menu/dist/node-menu.umd.cjs"] -}; - const HIGHLIGHT_JS: Library = { js: () => { const mimeTypes = mimeTypesService.getMimeTypes(); @@ -219,6 +215,5 @@ export default { EXCALIDRAW, MARKJS, I18NEXT, - MIND_ELIXIR, HIGHLIGHT_JS }; diff --git a/src/public/app/services/note_attribute_cache.ts b/src/public/app/services/note_attribute_cache.ts index ae3993cfb..18980036f 100644 --- a/src/public/app/services/note_attribute_cache.ts +++ b/src/public/app/services/note_attribute_cache.ts @@ -1,4 +1,4 @@ -import FAttribute from "../entities/fattribute.js"; +import type FAttribute from "../entities/fattribute.js"; /** * The purpose of this class is to cache the list of attributes for notes. diff --git a/src/public/app/services/note_create.ts b/src/public/app/services/note_create.ts index a7fd5ec76..b85c8277b 100644 --- a/src/public/app/services/note_create.ts +++ b/src/public/app/services/note_create.ts @@ -6,8 +6,8 @@ import froca from "./froca.js"; import treeService from "./tree.js"; import toastService from "./toast.js"; import { t } from "./i18n.js"; -import FNote from "../entities/fnote.js"; -import FBranch from "../entities/fbranch.js"; +import type FNote from "../entities/fnote.js"; +import type FBranch from "../entities/fbranch.js"; import type { ChooseNoteTypeResponse } from "../widgets/dialogs/note_type_chooser.js"; interface CreateNoteOpts { diff --git a/src/public/app/services/note_list_renderer.ts b/src/public/app/services/note_list_renderer.ts index e6e305689..2e6652b0f 100644 --- a/src/public/app/services/note_list_renderer.ts +++ b/src/public/app/services/note_list_renderer.ts @@ -5,7 +5,7 @@ import attributeRenderer from "./attribute_renderer.js"; import libraryLoader from "./library_loader.js"; import treeService from "./tree.js"; import utils from "./utils.js"; -import FNote from "../entities/fnote.js"; +import type FNote from "../entities/fnote.js"; const TPL = `
diff --git a/src/public/app/services/note_tooltip.ts b/src/public/app/services/note_tooltip.ts index f456d7a63..32f79c73d 100644 --- a/src/public/app/services/note_tooltip.ts +++ b/src/public/app/services/note_tooltip.ts @@ -5,7 +5,7 @@ import utils from "./utils.js"; import attributeRenderer from "./attribute_renderer.js"; import contentRenderer from "./content_renderer.js"; import appContext from "../components/app_context.js"; -import FNote from "../entities/fnote.js"; +import type FNote from "../entities/fnote.js"; import { t } from "./i18n.js"; function setupGlobalTooltip() { diff --git a/src/public/app/services/protected_session.ts b/src/public/app/services/protected_session.ts index 1bf995d93..fc34a805f 100644 --- a/src/public/app/services/protected_session.ts +++ b/src/public/app/services/protected_session.ts @@ -74,9 +74,9 @@ ws.subscribeToMessages(async (message) => { if (message.type === "protectedSessionLogin") { await reloadData(); - await appContext.triggerEvent("frocaReloaded"); + await appContext.triggerEvent("frocaReloaded", {}); - appContext.triggerEvent("protectedSessionStarted"); + appContext.triggerEvent("protectedSessionStarted", {}); appContext.triggerCommand("closeProtectedSessionPasswordDialog"); diff --git a/src/public/app/services/protected_session_holder.ts b/src/public/app/services/protected_session_holder.ts index e4171f389..647c2f51d 100644 --- a/src/public/app/services/protected_session_holder.ts +++ b/src/public/app/services/protected_session_holder.ts @@ -1,4 +1,4 @@ -import FNote from "../entities/fnote.js"; +import type FNote from "../entities/fnote.js"; import server from "./server.js"; function enableProtectedSession() { diff --git a/src/public/app/services/render.ts b/src/public/app/services/render.ts index 0eb02c7a7..bec5cb514 100644 --- a/src/public/app/services/render.ts +++ b/src/public/app/services/render.ts @@ -1,6 +1,6 @@ import server from "./server.js"; import bundleService, { type Bundle } from "./bundle.js"; -import FNote from "../entities/fnote.js"; +import type FNote from "../entities/fnote.js"; async function render(note: FNote, $el: JQuery) { const relations = note.getRelations("renderNote"); diff --git a/src/public/app/types-lib.d.ts b/src/public/app/types-lib.d.ts index f91e4d553..d84101b80 100644 --- a/src/public/app/types-lib.d.ts +++ b/src/public/app/types-lib.d.ts @@ -20,3 +20,7 @@ declare module "draggabilly" { destroy(); } } + +declare module '@mind-elixir/node-menu' { + export default mindmap; +} diff --git a/src/public/app/widgets/attribute_widgets/attribute_editor.ts b/src/public/app/widgets/attribute_widgets/attribute_editor.ts index 0119bcd3b..622da6ca9 100644 --- a/src/public/app/widgets/attribute_widgets/attribute_editor.ts +++ b/src/public/app/widgets/attribute_widgets/attribute_editor.ts @@ -3,17 +3,17 @@ import NoteContextAwareWidget from "../note_context_aware_widget.js"; import noteAutocompleteService from "../../services/note_autocomplete.js"; import server from "../../services/server.js"; import contextMenuService from "../../menus/context_menu.js"; -import attributeParser from "../../services/attribute_parser.js"; +import attributeParser, { type Attribute } from "../../services/attribute_parser.js"; import libraryLoader from "../../services/library_loader.js"; import froca from "../../services/froca.js"; import attributeRenderer from "../../services/attribute_renderer.js"; import noteCreateService from "../../services/note_create.js"; import attributeService from "../../services/attributes.js"; import linkService from "../../services/link.js"; -import AttributeDetailWidget from "./attribute_detail.js"; +import type AttributeDetailWidget from "./attribute_detail.js"; import type { CommandData, EventData, EventListener, FilteredCommandNames } from "../../components/app_context.js"; -import FAttribute, { type AttributeType } from "../../entities/fattribute.js"; -import FNote from "../../entities/fnote.js"; +import type { default as FAttribute, AttributeType } from "../../entities/fattribute.js"; +import type FNote from "../../entities/fnote.js"; const HELP_TEXT = `

${t("attribute_editor.help_text_body1")}

@@ -417,7 +417,7 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget implem return null; } - let matchedAttr = null; + let matchedAttr: Attribute | null = null; for (const attr of parsedAttrs) { if (attr.startIndex && clickIndex > attr.startIndex && attr.endIndex && clickIndex <= attr.endIndex) { diff --git a/src/public/app/widgets/bulk_actions/abstract_bulk_action.ts b/src/public/app/widgets/bulk_actions/abstract_bulk_action.ts index 436f8fbd8..eb24bbd4d 100644 --- a/src/public/app/widgets/bulk_actions/abstract_bulk_action.ts +++ b/src/public/app/widgets/bulk_actions/abstract_bulk_action.ts @@ -2,7 +2,7 @@ import { t } from "../../services/i18n.js"; import server from "../../services/server.js"; import ws from "../../services/ws.js"; import utils from "../../services/utils.js"; -import FAttribute from "../../entities/fattribute.js"; +import type FAttribute from "../../entities/fattribute.js"; interface ActionDefinition { script: string; diff --git a/src/public/app/widgets/containers/container.ts b/src/public/app/widgets/containers/container.ts index 56fe050a0..679fa11a8 100644 --- a/src/public/app/widgets/containers/container.ts +++ b/src/public/app/widgets/containers/container.ts @@ -1,4 +1,4 @@ -import Component, { TypedComponent } from "../../components/component.js"; +import type { default as Component, TypedComponent } from "../../components/component.js"; import BasicWidget, { TypedBasicWidget } from "../basic_widget.js"; export default class Container> extends TypedBasicWidget { diff --git a/src/public/app/widgets/containers/flex_container.ts b/src/public/app/widgets/containers/flex_container.ts index 62660a4ee..274284775 100644 --- a/src/public/app/widgets/containers/flex_container.ts +++ b/src/public/app/widgets/containers/flex_container.ts @@ -1,4 +1,4 @@ -import { TypedComponent } from "../../components/component.js"; +import type { TypedComponent } from "../../components/component.js"; import Container from "./container.js"; export type FlexDirection = "row" | "column"; diff --git a/src/public/app/widgets/containers/launcher.ts b/src/public/app/widgets/containers/launcher.ts index 41024073a..86fbabb96 100644 --- a/src/public/app/widgets/containers/launcher.ts +++ b/src/public/app/widgets/containers/launcher.ts @@ -11,7 +11,7 @@ import utils from "../../services/utils.js"; import TodayLauncher from "../buttons/launcher/today_launcher.js"; import HistoryNavigationButton from "../buttons/history_navigation.js"; import QuickSearchLauncherWidget from "../quick_search_launcher.js"; -import FNote from "../../entities/fnote.js"; +import type FNote from "../../entities/fnote.js"; import type { CommandNames } from "../../components/app_context.js"; interface InnerWidget extends BasicWidget { diff --git a/src/public/app/widgets/containers/launcher_container.ts b/src/public/app/widgets/containers/launcher_container.ts index 9c5a6eec7..7fa833182 100644 --- a/src/public/app/widgets/containers/launcher_container.ts +++ b/src/public/app/widgets/containers/launcher_container.ts @@ -51,7 +51,7 @@ export default class LauncherContainer extends FlexContainer { this.$widget.empty(); this.renderChildren(); - await this.handleEventInChildren("initialRenderComplete"); + await this.handleEventInChildren("initialRenderComplete", {}); const activeContext = appContext.tabManager.getActiveContext(); diff --git a/src/public/app/widgets/containers/right_pane_container.ts b/src/public/app/widgets/containers/right_pane_container.ts index 4325935fe..764fad85d 100644 --- a/src/public/app/widgets/containers/right_pane_container.ts +++ b/src/public/app/widgets/containers/right_pane_container.ts @@ -1,6 +1,7 @@ import FlexContainer from "./flex_container.js"; import splitService from "../../services/resizer.js"; -import RightPanelWidget from "../right_panel_widget.js"; +import type RightPanelWidget from "../right_panel_widget.js"; +import type { EventData, EventNames } from "../../components/app_context.js"; export default class RightPaneContainer extends FlexContainer { private rightPaneHidden: boolean; @@ -19,7 +20,7 @@ export default class RightPaneContainer extends FlexContainer return super.isEnabled() && !this.rightPaneHidden && this.children.length > 0 && !!this.children.find((ch) => ch.isEnabled() && ch.canBeShown()); } - handleEventInChildren(name: string, data: unknown) { + handleEventInChildren(name: T, data: EventData): Promise | null { const promise = super.handleEventInChildren(name, data); if (["activeContextChanged", "noteSwitchedAndActivated", "noteSwitched"].includes(name)) { diff --git a/src/public/app/widgets/highlights_list.ts b/src/public/app/widgets/highlights_list.ts index 8b8fb06de..a9be2ddfa 100644 --- a/src/public/app/widgets/highlights_list.ts +++ b/src/public/app/widgets/highlights_list.ts @@ -12,7 +12,7 @@ import options from "../services/options.js"; import OnClickButtonWidget from "./buttons/onclick_button.js"; import appContext, { type EventData } from "../components/app_context.js"; import libraryLoader from "../services/library_loader.js"; -import FNote from "../entities/fnote.js"; +import type FNote from "../entities/fnote.js"; const TPL = `