Selaa lähdekoodia

fix: ensure website build doesn't rely on new mobile components

this commit also removes js e2e-tests
Tienson Qin 3 kuukautta sitten
vanhempi
sitoutus
453ee3b3b4
52 muutettua tiedostoa jossa 35 lisäystä ja 10300 poistoa
  1. 0 2
      .github/workflows/clj-e2e.yml
  2. 0 166
      .github/workflows/e2e.yml
  3. 1 2
      .gitignore
  4. 0 1
      CODEBASE_OVERVIEW.md
  5. 1 1
      clj-e2e/bb.edn
  6. 0 23
      e2e-tests/accessibility.spec.ts
  7. 0 332
      e2e-tests/basic.spec.ts
  8. 0 79
      e2e-tests/blockref.spec.ts
  9. 0 321
      e2e-tests/code-editing.spec.ts
  10. 0 60
      e2e-tests/context-menu.spec.ts
  11. 0 82
      e2e-tests/dnd.spec.ts
  12. 0 865
      e2e-tests/editor.spec.ts
  13. 0 305
      e2e-tests/fixtures.ts
  14. 0 52
      e2e-tests/flashcards.spec.ts
  15. 0 141
      e2e-tests/fs.spec.ts
  16. 0 80
      e2e-tests/headings.spec.ts
  17. 0 53
      e2e-tests/history.spec.ts
  18. 0 46
      e2e-tests/hotkey.spec.ts
  19. 0 222
      e2e-tests/logseq-api.spec.ts
  20. 0 55
      e2e-tests/logseq-url.spec.ts
  21. 0 103
      e2e-tests/page-rename.spec.ts
  22. 0 174
      e2e-tests/page-search.spec.ts
  23. 0 15
      e2e-tests/paste.spec.ts
  24. 0 15
      e2e-tests/plugin/index.html
  25. 0 61
      e2e-tests/plugin/index.js
  26. 0 1
      e2e-tests/plugin/lsplugin.user.js
  27. 0 8
      e2e-tests/plugin/package.json
  28. 0 110
      e2e-tests/plugins.spec.ts
  29. 0 180
      e2e-tests/random.spec.ts
  30. 0 48
      e2e-tests/sanitization.spec.ts
  31. 0 66
      e2e-tests/sidebar.spec.ts
  32. 0 55
      e2e-tests/types.ts
  33. 0 42
      e2e-tests/util/basic.ts
  34. 0 64
      e2e-tests/util/keyboard-event-cap.html
  35. 0 466
      e2e-tests/util/keyboard-events.ts
  36. 0 14
      e2e-tests/util/page.ts
  37. 0 64
      e2e-tests/util/search-modal.ts
  38. 0 310
      e2e-tests/utils.ts
  39. 0 526
      e2e-tests/whiteboards.spec.ts
  40. 0 34
      e2e-tests/window.spec.ts
  41. 0 28
      playwright.config.ts
  42. 5 5
      src/main/capacitor/components/app.cljs
  43. 3 3
      src/main/capacitor/components/editor_toolbar.cljs
  44. 5 5
      src/main/capacitor/components/modal.cljs
  45. 2 2
      src/main/capacitor/components/selection_toolbar.cljs
  46. 2 2
      src/main/capacitor/core.cljs
  47. 9 0
      src/main/capacitor/events.cljs
  48. 3 2
      src/main/capacitor/init.cljs
  49. 1 5
      src/main/frontend/components/container.cljs
  50. 2 4
      src/main/frontend/handler/events.cljs
  51. 0 4999
      static/yarn.lock
  52. 1 1
      typos.toml

+ 0 - 2
.github/workflows/clj-e2e.yml

@@ -79,8 +79,6 @@ jobs:
       - name: Prepare E2E test build
         run: |
           yarn gulp:build && clojure -M:cljs release app --config-merge "{:closure-defines {frontend.config/DEV-RELEASE true}}" --debug
-          rsync -avz --exclude node_modules --exclude android --exclude ios ./static/ ./public/
-          ls -lR ./public
 
       - name: Run e2e tests
         run: cd clj-e2e && timeout 30m bb dev

+ 0 - 166
.github/workflows/e2e.yml

@@ -1,166 +0,0 @@
-name: E2E
-
-# Running E2E test multiple times to confirm test stability.
-# E2E test could be randomly failed due to the batch update mechanism of React.
-# Robust E2E test could help improving dev experience.
-
-on:
-  push:
-    branches: [master]
-    paths:
-      - 'e2e-tests/**'
-  # TODO: Re-enable when ready to enable tests for file graphs
-  # pull_request:
-  #   branches: [master]
-  #   paths:
-  #     - 'e2e-tests/**'
-
-env:
-  CLOJURE_VERSION: '1.11.1.1413'
-  JAVA_VERSION: '11'
-  # This is the latest node version we can run.
-  NODE_VERSION: '20'
-  BABASHKA_VERSION: '1.0.168'
-
-jobs:
-  e2e-test-build:
-    if: false                   # disabled
-    name: Build Test Artifact
-    runs-on: ubuntu-22.04
-    steps:
-      - name: Checkout
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c  # v3.3.0
-
-      - name: Set up Node
-        uses: actions/setup-node@v3
-        with:
-          node-version: ${{ env.NODE_VERSION }}
-          cache: 'yarn'
-          cache-dependency-path: |
-            yarn.lock
-            static/yarn.lock
-
-      - name: Set up Java
-        uses: actions/setup-java@v3
-        with:
-          distribution: 'zulu'
-          java-version: ${{ env.JAVA_VERSION }}
-
-      - name: Set up Clojure
-        uses: DeLaGuardo/[email protected]
-        with:
-          cli: ${{ env.CLOJURE_VERSION }}
-
-      - name: Clojure cache
-        uses: actions/cache@v3
-        id: clojure-deps
-        with:
-          path: |
-            ~/.m2/repository
-            ~/.gitlibs
-          key: ${{ runner.os }}-clojure-deps-${{ hashFiles('deps.edn') }}
-          restore-keys: ${{ runner.os }}-clojure-deps-
-
-      - name: Fetch Clojure deps
-        if: steps.clojure-deps.outputs.cache-hit != 'true'
-        run: clojure -A:cljs -P
-
-      - name: Shadow-cljs cache
-        uses: actions/cache@v3
-        with:
-          path: .shadow-cljs
-          # ensure update cache every time
-          key: ${{ runner.os }}-shadow-cljs-${{ github.sha }}
-          # will match most recent upload
-          restore-keys: |
-            ${{ runner.os }}-shadow-cljs-
-
-      - name: Fetch yarn deps
-        run: yarn install
-        env:
-          PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: true
-
-      # NOTE: require the app to be build with DEV-RELEASE flag
-      - name: Prepare E2E test build
-        run: |
-          yarn gulp:build && clojure -M:cljs release app electron --config-merge "{:closure-defines {frontend.config/DEV-RELEASE true}}" --debug
-
-      # NOTE: should include .shadow-cljs if in dev mode(compile)
-      - name: Create Archive for build
-        run: tar czf static.tar.gz static
-
-      - name: Upload Artifact
-        uses: actions/upload-artifact@v4
-        with:
-          name: logseq-e2e-artifact
-          path: static.tar.gz
-          retention-days: 1
-
-  e2e-test-run:
-    needs: [ e2e-test-build ]
-    name: Test Shard ${{ matrix.shard }} Repeat ${{ matrix.repeat }}
-    runs-on: ubuntu-22.04
-    strategy:
-      matrix:
-        repeat: [1, 2]
-        shard: [1, 2, 3]
-
-    steps:
-      - name: Repeat message
-        run: echo ::info title=StartUp::E2E testing shard ${{ matrix.shard}}/3 repeat ${{ matrix.repeat }}
-
-      - name: Checkout
-        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c  # v3.3.0
-
-      - name: Download test build artifact
-        uses: actions/download-artifact@v4
-        with:
-          name: logseq-e2e-artifact
-
-      - name: Extract test Artifact
-        run: tar xzf static.tar.gz
-
-      - name: Set up Node
-        uses: actions/setup-node@v3
-        with:
-          node-version: ${{ env.NODE_VERSION }}
-          cache: 'yarn'
-          cache-dependency-path: |
-            yarn.lock
-            static/yarn.lock
-
-      - name: Fetch yarn deps for E2E test
-        run: |
-          yarn install
-          (cd static && yarn install && yarn rebuild:all)
-        env:
-          PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: true
-
-      - name: Ensure static yarn.lock is up to date
-        run: git diff --exit-code static/yarn.lock
-
-      - name: Install Fluxbox
-        run: sudo apt-get update && sudo apt-get install -y fluxbox
-
-      # Emulate a virtual framebuffer on machines with no display hardware
-      - name: Run XVFB
-        run: Xvfb :1 -screen 0 1024x768x24 >/dev/null 2>&1 &
-
-      # Start a lightweight window manager to simulate window actions (maximize,restore etc)
-      - name: Start Fluxbox
-        run:  DISPLAY=:1.0 fluxbox >/dev/null 2>&1 &
-
-      - name: Run Playwright test
-        run: DISPLAY=:1.0 npx playwright test --reporter github --shard=${{ matrix.shard }}/3
-        env:
-          LOGSEQ_CI: true
-          DEBUG: "pw:api"
-          RELEASE: true # skip dev only test
-
-      - name: Save e2e artifacts
-        if: ${{ failure() }}
-        uses: actions/upload-artifact@v4
-        with:
-          name: e2e-repeat-report-${{ matrix.shard}}-${{ matrix.repeat }}
-          path: e2e-dump/*
-          retention-days: 1

+ 1 - 2
.gitignore

@@ -60,8 +60,7 @@ startup.png
 android/app/src/main/assets/capacitor.config.json
 
 *.sublime-*
-/public/static
-/public/
+/public
 .yarn/
 .yarnrc.yml
 

+ 0 - 1
CODEBASE_OVERVIEW.md

@@ -61,7 +61,6 @@ This is overview of this repository's most important directories and files.
   - `packages/ui/` - The frontend's component system based on shadcn
   - `packags/tldraw/` - Custom fork of tldraw which powers whiteboards
 - `scripts` - Dev scripts
-- `e2e-tests/` - end to end frontend tests
 - `clj-e2e/` - end to end clj frontend tests
 - `android/` -  Android app
 - `ios/` - iOS app

+ 1 - 1
clj-e2e/bb.edn

@@ -7,7 +7,7 @@
   serve {:doc "Serve static assets"
          :requires ([babashka.http-server :as server])
          :task (server/exec (merge {:port 3002
-                                    :dir "../public"}
+                                    :dir "../static/"}
                                    cli-opts))}
 
   prn {:task (clojure "-X clojure.core/prn" cli-opts)}

+ 0 - 23
e2e-tests/accessibility.spec.ts

@@ -1,23 +0,0 @@
-import { test } from './fixtures'
-import { createRandomPage } from './utils'
-import { expect } from '@playwright/test'
-import AxeBuilder from '@axe-core/playwright'
-
-// TODO: more configuration is required for this test
-test.skip('should not have any automatically detectable accessibility issues', async ({ page }) => {
-  try {
-    await page.waitForSelector('.notification-clear', { timeout: 10 })
-    page.click('.notification-clear')
-  } catch (error) {
-  }
-
-  await createRandomPage(page)
-  await page.waitForTimeout(2000)
-  const accessibilityScanResults = await new AxeBuilder({ page })
-    .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
-    .disableRules(['meta-viewport'])
-    .setLegacyMode()
-    .analyze()
-
-  expect(accessibilityScanResults.violations).toEqual([]);
-})

+ 0 - 332
e2e-tests/basic.spec.ts

@@ -1,332 +0,0 @@
-import { expect } from '@playwright/test'
-import fs from 'fs/promises'
-import path from 'path'
-import { test } from './fixtures'
-import { randomString, createRandomPage, modKey } from './utils'
-
-
-test('create page and blocks, save to disk', async ({ page, block, graphDir }) => {
-  const pageTitle = await createRandomPage(page)
-
-  // do editing
-  await page.keyboard.type('first bullet')
-  await block.enterNext()
-
-  await block.waitForBlocks(2)
-
-  await page.keyboard.type('second bullet')
-  await block.enterNext()
-
-  await page.keyboard.type('third bullet')
-  expect(await block.indent()).toBe(true)
-  await block.enterNext()
-
-  await page.keyboard.type('continue editing')
-  await page.keyboard.press('Shift+Enter')
-  await page.keyboard.type('second line')
-
-  await block.enterNext()
-  expect(await block.unindent()).toBe(true)
-  expect(await block.unindent()).toBe(false)
-  await page.keyboard.type('test ok')
-  await page.keyboard.press('Escape')
-
-  await block.waitForBlocks(5)
-
-  // active edit, and create next block
-  await block.clickNext()
-  await page.keyboard.type('test')
-  for (let i = 0; i < 5; i++) {
-    await page.keyboard.press('Backspace', { delay: 100 })
-  }
-
-  await page.keyboard.press('Escape')
-  await block.waitForBlocks(5)
-
-  await page.waitForTimeout(2000) // wait for saving to disk
-  const contentOnDisk = await fs.readFile(
-    path.join(graphDir, `pages/${pageTitle}.md`),
-    'utf8'
-  )
-  expect(contentOnDisk.trim()).toEqual('- first bullet\n- second bullet\n\t- third bullet\n\t- continue editing\n\t  second line\n- test ok'.trim())
-})
-
-
-test('delete and backspace', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustFill('test')
-
-  // backspace
-  await page.keyboard.press('Backspace')
-  await page.keyboard.press('Backspace')
-  expect(await page.inputValue('textarea >> nth=0')).toBe('te')
-
-  // refill
-  await block.enterNext()
-  await block.mustType('test')
-  await page.keyboard.press('ArrowLeft', { delay: 50 })
-  await page.keyboard.press('ArrowLeft', { delay: 50 })
-
-  // delete
-  await page.keyboard.press('Delete', { delay: 50 })
-  expect(await page.inputValue('textarea >> nth=0')).toBe('tet')
-  await page.keyboard.press('Delete', { delay: 50 })
-  expect(await page.inputValue('textarea >> nth=0')).toBe('te')
-  await page.keyboard.press('Delete', { delay: 50 })
-  expect(await page.inputValue('textarea >> nth=0')).toBe('te')
-
-})
-
-
-test('block selection', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustFill('1')
-  await block.enterNext()
-  await block.mustFill('2')
-  expect(await block.indent()).toBe(true)
-  await block.enterNext()
-  await block.mustFill('3')
-  await block.enterNext()
-  await block.mustFill('4')
-  expect(await block.unindent()).toBe(true)
-  await block.enterNext()
-  await block.mustFill('5')
-  expect(await block.indent()).toBe(true)
-  await block.enterNext()
-  await block.mustFill('6')
-  await block.enterNext()
-  await block.mustFill('7')
-  expect(await block.unindent()).toBe(true)
-  await block.enterNext()
-  await block.mustFill('8')
-  expect(await block.indent()).toBe(true)
-  await block.enterNext()
-  await block.mustFill('9')
-  expect(await block.unindent()).toBe(true)
-
-  // shift+up/down
-  await page.keyboard.down('Shift')
-
-  await page.keyboard.press('ArrowUp')
-  await block.waitForSelectedBlocks(1)
-  let locator = page.locator('.ls-block >> nth=8')
-
-  await page.keyboard.press('ArrowUp')
-  await block.waitForSelectedBlocks(2)
-
-  await page.keyboard.press('ArrowUp')
-  await block.waitForSelectedBlocks(3)
-
-  await page.keyboard.press('ArrowDown')
-  await block.waitForSelectedBlocks(2)
-
-  await page.keyboard.up('Shift')
-
-  // mod+click select or deselect
-  await page.keyboard.down(modKey)
-  await page.click('.ls-block >> nth=7')
-  await block.waitForSelectedBlocks(1)
-
-  await page.click('.block-main-container >> nth=6')
-  await block.waitForSelectedBlocks(2)
-
-  // mod+shift+click
-  await page.click('.ls-block >> nth=4')
-  await block.waitForSelectedBlocks(3)
-
-  await page.keyboard.down('Shift')
-  await page.click('.ls-block >> nth=1')
-  await block.waitForSelectedBlocks(6)
-
-  await page.keyboard.up('Shift')
-  await page.keyboard.up(modKey)
-  await page.keyboard.press('Escape')
-
-  // shift+click
-  await page.keyboard.down('Shift')
-  await page.click('.block-main-container >> nth=0')
-  await page.click('.block-main-container >> nth=3')
-  await block.waitForSelectedBlocks(4)
-  await page.click('.ls-block >> nth=8')
-  await block.waitForSelectedBlocks(9)
-  await page.click('.ls-block >> nth=5')
-  await block.waitForSelectedBlocks(6)
-  await page.keyboard.up('Shift')
-})
-
-test('template', async ({ page, block }) => {
-  const randomTemplate = randomString(6)
-
-  await createRandomPage(page)
-
-  await block.mustFill('template test\ntemplate:: ')
-  await page.keyboard.type(randomTemplate, { delay: 100 })
-  await page.keyboard.press('Enter')
-  await page.keyboard.press('Escape')
-  await block.clickNext()
-
-  expect(await block.indent()).toBe(true)
-
-  await block.mustFill('line1')
-  await block.enterNext()
-  await block.mustFill('line2')
-  await block.enterNext()
-
-  expect(await block.indent()).toBe(true)
-  await block.mustFill('line3')
-  await block.enterNext()
-
-  expect(await block.unindent()).toBe(true)
-  expect(await block.unindent()).toBe(true)
-  expect(await block.unindent()).toBe(false) // already at the first level
-
-  await block.waitForBlocks(5)
-
-  // See-also: #9354
-  await block.enterNext()
-  await block.mustType('/template')
-
-  await page.click('[title="Insert a created template here"]')
-  // type to search template name
-  await page.keyboard.type(randomTemplate.substring(0, 3), { delay: 100 })
-
-  const popupMenuItem = page.locator('.absolute >> text=' + randomTemplate)
-  await popupMenuItem.waitFor({ timeout: 2000 }) // wait for template search
-  await popupMenuItem.click()
-
-  await block.waitForBlocks(9)
-
-
-  await block.clickNext()
-  await block.mustType('/template')
-
-  await page.click('[title="Insert a created template here"]')
-  // type to search template name
-  await page.keyboard.type(randomTemplate.substring(0, 3), { delay: 100 })
-
-  await popupMenuItem.waitFor({ timeout: 2000 }) // wait for template search
-  await popupMenuItem.click()
-
-  await block.waitForBlocks(13) // 9 + 4
-})
-
-test('auto completion square brackets', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  // In this test, `type` is unused instead of `fill`, to allow for auto-completion.
-
-  // [[]]
-  await block.mustType('This is a [', { toBe: 'This is a []' })
-  await block.mustType('[', { toBe: 'This is a [[]]' })
-
-  // wait for search popup
-  await page.waitForSelector('text="Search for a page"')
-
-  // re-enter edit mode
-  await page.press('textarea >> nth=0', 'Escape')
-  await page.click('.ls-block >> nth=-1')
-  await page.waitForSelector('textarea >> nth=0', { state: 'visible' })
-
-  // #3253
-  await page.press('textarea >> nth=0', 'ArrowLeft')
-  await page.press('textarea >> nth=0', 'ArrowLeft')
-  await page.press('textarea >> nth=0', 'Enter')
-  await page.waitForSelector('text="Search for a page"', { state: 'visible' })
-
-  // type more `]`s
-  await page.type('textarea >> nth=0', ']')
-  expect(await page.inputValue('textarea >> nth=0')).toBe('This is a [[]]')
-  await page.type('textarea >> nth=0', ']')
-  expect(await page.inputValue('textarea >> nth=0')).toBe('This is a [[]]')
-  await page.type('textarea >> nth=0', ']')
-  expect(await page.inputValue('textarea >> nth=0')).toBe('This is a [[]]]')
-})
-
-test('auto completion and auto pair', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustFill('Auto-completion test')
-  await block.enterNext()
-
-  // {{
-  await block.mustType('type {{', { toBe: 'type {{}}' })
-  await page.waitForTimeout(100);
-  // ((
-  await block.clickNext()
-
-  await block.mustType('type (', { toBe: 'type ()' })
-  await block.mustType('(', { toBe: 'type (())' })
-
-  await block.escapeEditing() // escape any popup from `(())`
-
-  // [[  #3251
-  await block.clickNext()
-
-  await block.mustType('type [', { toBe: 'type []' })
-  await block.mustType('[', { toBe: 'type [[]]' })
-
-  await block.escapeEditing() // escape any popup from `[[]]`
-
-  // ``
-  await block.clickNext()
-
-  await block.mustType('type `', { toBe: 'type ``' })
-  await block.mustType('code here', { toBe: 'type `code here`' })
-})
-
-test('invalid page props #3944', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustFill('public:: true\nsize:: 65535')
-  await page.press('textarea >> nth=0', 'Enter')
-  // Force rendering property block
-  await block.enterNext()
-})
-
-test('Scheduled date picker should point to the already specified Date #6985', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustFill('testTask \n SCHEDULED: <2000-05-06 Sat>')
-  await block.enterNext()
-  await page.waitForTimeout(500)
-  await block.escapeEditing()
-
-  // Open date picker
-  await page.click('a.opacity-80')
-  await page.waitForTimeout(500)
-  await expect(page.locator('text=May 2000')).toBeVisible()
-  await expect(page.locator('td:has-text("6").active')).toBeVisible()
-
-  // Close date picker
-  await page.click('a.opacity-80')
-  await page.waitForTimeout(500)
-})
-
-test('Opening a second datepicker should close the first one #7341', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustFill('testTask \n SCHEDULED: <2000-05-06 Sat>')
-
-  await block.enterNext();
-
-  await block.mustFill('testTask \n SCHEDULED: <2000-06-07 Wed>')
-  await block.enterNext();
-  await page.click('#main-content-container')
-  // Open date picker
-  await page.waitForTimeout(500)
-  await page.click('#main-content-container')
-  await page.waitForTimeout(500)
-  await page.click('a:has-text("2000-06-07 Wed").opacity-80')
-  await page.waitForTimeout(50)
-  await page.click('a:has-text("2000-05-06 Sat").opacity-80')
-  await page.waitForTimeout(50)
-  await expect(page.locator('text=May 2000')).toBeVisible()
-  await expect(page.locator('td:has-text("6").active')).toBeVisible()
-  await expect(page.locator('text=June 2000')).not.toBeVisible()
-  await expect(page.locator('td:has-text("7").active')).not.toBeVisible()
-
-  // Close date picker
-  await page.click('a:has-text("2000-05-06 Sat").opacity-80')
-})

+ 0 - 79
e2e-tests/blockref.spec.ts

@@ -1,79 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { createRandomPage, enterNextBlock, modKey, editNthBlock, moveCursorToBeginning, moveCursorToEnd } from './utils'
-import { dispatch_kb_events } from './util/keyboard-events'
-
-// Create a random page with some pre-defined blocks
-// - a
-// - b
-//   id:: UUID
-// - ((id))
-async function setUpBlocks(page, block) {
-  await createRandomPage(page)
-
-  await block.mustFill('a')
-  await block.enterNext()
-  await block.mustFill('b')
-  await page.keyboard.press(modKey + '+c', { delay: 100 })
-  await page.waitForTimeout(100)
-  await block.enterNext()
-  await page.keyboard.press(modKey + '+v', { delay: 100 })
-  await page.waitForTimeout(100)
-}
-
-test('backspace at the beginning of a refed block #9406', async ({ page, block }) => {
-  await setUpBlocks(page, block)
-  await page.waitForTimeout(100)
-  await editNthBlock(page, 1)
-  await page.waitForTimeout(100)
-  await moveCursorToBeginning(page)
-  await page.keyboard.press('Backspace', { delay: 100 })
-  await expect(page.locator('textarea >> nth=0')).toHaveText("ab")
-  await expect(await block.selectionStart()).toEqual(1)
-  await expect(page.locator('.block-ref >> text="ab"')).toHaveCount(1);
-})
-
-test('delete at the end of a prev block before a refed block #9406', async ({ page, block }) => {
-  await setUpBlocks(page, block)
-  await page.waitForTimeout(100)
-  await editNthBlock(page, 0)
-  await page.waitForTimeout(100)
-  await moveCursorToEnd(page)
-  await page.keyboard.press('Delete', { delay: 100 })
-  await page.waitForTimeout(100)
-  await expect(page.locator('textarea >> nth=0')).toHaveText("ab")
-  await expect(await block.selectionStart()).toEqual(1)
-  await expect(page.locator('.block-ref >> text="ab"')).toHaveCount(1);
-})
-
-test('delete selected blocks, block ref should be replaced by content #9406', async ({ page, block }) => {
-  await setUpBlocks(page, block)
-  await editNthBlock(page, 0)
-  await page.waitForTimeout(100)
-  await page.keyboard.down('Shift')
-  await page.keyboard.press('ArrowDown', { delay: 20 })
-  await page.keyboard.press('ArrowDown', { delay: 20 })
-  await page.keyboard.up('Shift')
-  await block.waitForSelectedBlocks(2)
-  await page.keyboard.press('Backspace')
-  await expect(page.locator('.ls-block')).toHaveCount(1)
-  await editNthBlock(page, 0)
-  await expect(page.locator('textarea >> nth=0')).toHaveText("b")
-})
-
-test('delete and undo #9406', async ({ page, block }) => {
-  await setUpBlocks(page, block)
-  await editNthBlock(page, 0)
-  await page.waitForTimeout(100)
-  await page.keyboard.down('Shift')
-  await page.keyboard.press('ArrowDown', { delay: 20 })
-  await page.keyboard.press('ArrowDown', { delay: 20 })
-  await page.keyboard.up('Shift')
-  await block.waitForSelectedBlocks(2)
-  await page.keyboard.press('Backspace', { delay: 100 })
-  await expect(page.locator('.ls-block')).toHaveCount(1)
-  await page.keyboard.press(modKey + '+z', { delay: 100 })
-  await page.waitForTimeout(100)
-  await expect(page.locator('.ls-block')).toHaveCount(3)
-  await expect(page.locator('.block-ref >> text="b"')).toHaveCount(1);
-})

+ 0 - 321
e2e-tests/code-editing.spec.ts

@@ -1,321 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import {
-  createRandomPage,
-  escapeToCodeEditor,
-  escapeToBlockEditor,
-  repeatKeyPress,
-} from './utils'
-
-/**
- * NOTE: CodeMirror is a complex library that requires a lot of setup to work.
- * This test suite is designed to test the basic functionality of the editor.
- * It is not intended to test the full functionality of CodeMirror.
- * For more information, see: https://codemirror.net/doc/manual.html
- */
-
-// TODO: Fix test that started intermittently failing some time around
-// https://github.com/logseq/logseq/pull/9540
-test.skip('switch code editing mode', async ({ page }) => {
-  await createRandomPage(page)
-
-  // NOTE: ` will trigger auto-pairing in Logseq
-  // NOTE: ( will trigger auto-pairing in CodeMirror
-  // NOTE: waitForTimeout is needed to ensure that the hotkey handler is finished (shift+enter)
-  // NOTE: waitForTimeout is needed to ensure that the CodeMirror editor is fully loaded and unloaded
-  // NOTE: multiple textarea elements are existed in the editor, be careful to select the right one
-
-  // code block with 0 line
-  await page.type('textarea >> nth=0', '```clojure\n')
-  // line number: 1
-  await page.waitForSelector('.CodeMirror pre', { state: 'visible' })
-  expect(await page.locator('.CodeMirror-gutter-wrapper .CodeMirror-linenumber').innerText()).toBe('1')
-  // lang label: clojure
-  expect(await page.innerText('.block-body .extensions__code-lang')).toBe('clojure')
-
-  await page.press('.CodeMirror textarea', 'Escape')
-  await page.waitForSelector('.CodeMirror pre', { state: 'hidden' })
-  expect(await page.inputValue('textarea >> nth=0')).toBe('```clojure\n```')
-
-  await page.waitForTimeout(200)
-  await page.press('textarea >> nth=0', 'Escape')
-  await page.waitForSelector('.CodeMirror pre', { state: 'visible' })
-
-  // NOTE: must wait here, await loading of CodeMirror editor
-  await page.waitForTimeout(200)
-  await page.click('.CodeMirror pre')
-  await page.waitForTimeout(200)
-
-  await page.type('.CodeMirror textarea', '(+ 1 1')
-  await page.press('.CodeMirror textarea', 'Escape')
-  await page.waitForSelector('.CodeMirror pre', { state: 'hidden' })
-  expect(await page.inputValue('.block-editor textarea')).toBe('```clojure\n(+ 1 1)\n```')
-
-  await page.waitForTimeout(200) // editor unloading
-  await page.press('.block-editor textarea', 'Escape')
-  await page.waitForTimeout(200) // editor loading
-  // click position is estimated to be at the beginning of the first line
-  await page.click('.CodeMirror pre', { position: { x: 1, y: 5 } })
-  await page.waitForTimeout(200)
-
-  await page.type('.CodeMirror textarea', ';; comment\n\n  \n')
-
-  await page.press('.CodeMirror textarea', 'Escape')
-  await page.waitForSelector('.CodeMirror pre', { state: 'hidden' })
-  expect(await page.inputValue('.block-editor textarea')).toBe('```clojure\n;; comment\n\n  \n(+ 1 1)\n```')
-})
-
-
-test('convert from block content to code', async ({ page }) => {
-  await createRandomPage(page)
-
-  await page.type('.block-editor textarea', '```')
-  await page.press('.block-editor textarea', 'Shift+Enter')
-  await page.waitForTimeout(200) // wait for hotkey handler
-  await page.press('.block-editor textarea', 'Escape')
-  await page.waitForSelector('.CodeMirror pre', { state: 'visible' })
-
-  await page.waitForTimeout(500)
-  await page.click('.CodeMirror pre')
-  await page.waitForTimeout(500)
-  expect(await page.locator('.CodeMirror-gutter-wrapper .CodeMirror-linenumber >> nth=-1').innerText()).toBe('1')
-
-  await page.press('.CodeMirror textarea', 'Escape')
-  await page.waitForTimeout(500)
-
-  expect(await page.inputValue('.block-editor textarea')).toBe('```\n```')
-
-  // reset block, code block with 1 line
-  await page.fill('.block-editor textarea', '```\n\n```')
-  await page.waitForTimeout(200) // wait for fill
-  await escapeToCodeEditor(page)
-  expect(await page.locator('.CodeMirror-gutter-wrapper .CodeMirror-linenumber >> nth=-1').innerText()).toBe('1')
-  await escapeToBlockEditor(page)
-  expect(await page.inputValue('.block-editor textarea')).toBe('```\n\n```')
-
-  // reset block, code block with 2 line
-  await page.fill('.block-editor textarea', '```\n\n\n```')
-  await page.waitForTimeout(200)
-  await escapeToCodeEditor(page)
-  expect(await page.locator('.CodeMirror-gutter-wrapper .CodeMirror-linenumber >> nth=-1').innerText()).toBe('2')
-  await escapeToBlockEditor(page)
-  expect(await page.inputValue('.block-editor textarea')).toBe('```\n\n\n```')
-
-  await page.fill('.block-editor textarea', '```\n  indented\nsecond line\n\n```')
-  await page.waitForTimeout(200)
-  await escapeToCodeEditor(page)
-  await escapeToBlockEditor(page)
-  expect(await page.inputValue('.block-editor textarea')).toBe('```\n  indented\nsecond line\n\n```')
-
-  await page.fill('.block-editor textarea', '```\n  indented\n  indented\n```')
-  await page.waitForTimeout(200)
-  await escapeToCodeEditor(page)
-  await escapeToBlockEditor(page)
-  expect(await page.inputValue('.block-editor textarea')).toBe('```\n  indented\n  indented\n```')
-})
-
-test('code block mixed input source', async ({ page }) => {
-  await createRandomPage(page)
-
-  await page.fill('.block-editor textarea', '```\n  ABC\n```')
-  await page.waitForTimeout(500) // wait for fill
-  await escapeToCodeEditor(page)
-  await page.type('.CodeMirror textarea', '  DEF\nGHI')
-
-  await page.waitForTimeout(500)
-  await page.press('.CodeMirror textarea', 'Escape')
-  await page.waitForTimeout(500)
-  // NOTE: auto-indent is on
-  expect(await page.inputValue('.block-editor textarea')).toBe('```\n  ABC  DEF\n  GHI\n```')
-})
-
-test('code block with text around', async ({ page }) => {
-  await createRandomPage(page)
-
-  await page.fill('.block-editor textarea', 'Heading\n```\n```\nFooter')
-  await page.waitForTimeout(200)
-  await escapeToCodeEditor(page)
-  await page.type('.CodeMirror textarea', 'first\n  second')
-
-  await page.waitForTimeout(500)
-  await page.press('.CodeMirror textarea', 'Escape')
-  await page.waitForTimeout(500)
-  expect(await page.inputValue('.block-editor textarea')).toBe('Heading\n```\nfirst\n  second\n```\nFooter')
-})
-
-test('multiple code block', async ({ page }) => {
-  await createRandomPage(page)
-
-  // NOTE: the two code blocks are of the same content
-  await page.fill('.block-editor textarea', '中文 Heading\n```clojure\n```\nMiddle 🚀\n```clojure\n```\nFooter')
-  await page.waitForTimeout(200)
-
-  await page.press('.block-editor textarea', 'Escape')
-  await page.waitForSelector('.CodeMirror pre', { state: 'visible' })
-
-  // first
-  await page.waitForTimeout(500)
-  await page.click('.CodeMirror pre >> nth=0')
-  await page.waitForTimeout(500)
-
-  await page.type('.CodeMirror textarea >> nth=0', ':key-test\n', { strict: true })
-  await page.waitForTimeout(500)
-
-  await page.press('.CodeMirror textarea >> nth=0', 'Escape')
-  await page.waitForTimeout(500)
-  expect(await page.inputValue('.block-editor textarea'))
-    .toBe('中文 Heading\n```clojure\n:key-test\n\n```\nMiddle 🚀\n```clojure\n```\nFooter')
-
-  // second
-  await page.press('.block-editor textarea', 'Escape')
-  await page.waitForSelector('.CodeMirror pre', { state: 'visible' })
-
-  await page.waitForTimeout(500)
-  await page.click('.CodeMirror >> nth=1 >> pre')
-  await page.waitForTimeout(500)
-
-  await page.type('.CodeMirror textarea >> nth=1', '\n  :key-test 日本語\n', { strict: true })
-  await page.waitForTimeout(500)
-
-  await page.press('.CodeMirror textarea >> nth=1', 'Escape')
-  await page.waitForTimeout(500)
-  expect(await page.inputValue('.block-editor textarea'))
-    .toBe('中文 Heading\n```clojure\n:key-test\n\n```\nMiddle 🚀\n```clojure\n\n  :key-test 日本語\n\n```\nFooter')
-})
-
-test('click outside to exit', async ({ page }) => {
-  await createRandomPage(page)
-
-  await page.fill('.block-editor textarea', 'Header ``Click``\n```\n  ABC\n```')
-  await page.waitForTimeout(200) // wait for fill
-  await escapeToCodeEditor(page)
-  await page.type('.CodeMirror textarea', '  DEF\nGHI')
-
-  await page.waitForTimeout(500)
-  await page.click('text=Click')
-  await page.waitForTimeout(500)
-  // NOTE: auto-indent is on
-  expect(await page.inputValue('.block-editor textarea')).toBe('Header ``Click``\n```\n  ABC  DEF\n  GHI\n```')
-})
-
-test('click language label to exit #3463', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await page.fill('.block-editor textarea', '```cpp\n```')
-  await page.waitForTimeout(200)
-  await escapeToCodeEditor(page)
-  await page.type('.CodeMirror textarea', '#include<iostream>')
-
-  await page.waitForTimeout(500)
-  await page.click('text=cpp') // the language label
-  await page.waitForTimeout(500)
-  expect(await page.inputValue('.block-editor textarea')).toBe('```cpp\n#include<iostream>\n```')
-})
-
-test('multi properties with code', async ({ page }) => {
-  await createRandomPage(page)
-
-  await page.fill('.block-editor textarea',
-    'type:: code\n' +
-    '类型:: 代码\n' +
-    '```go\n' +
-    'if err != nil {\n' +
-    '\treturn err\n' +
-    '}\n' +
-    '```'
-  )
-  await page.waitForTimeout(200)
-  await escapeToCodeEditor(page)
-
-  // first character of code
-  await page.click('.CodeMirror pre', { position: { x: 1, y: 5 } })
-  await page.waitForTimeout(500)
-  await page.type('.CodeMirror textarea', '// Returns nil\n')
-
-  await page.waitForTimeout(500)
-  await page.press('.CodeMirror textarea', 'Escape')
-  await page.waitForTimeout(500)
-  expect(await page.inputValue('.block-editor textarea')).toBe(
-    'type:: code\n' +
-    '类型:: 代码\n' +
-    '```go\n' +
-    '// Returns nil\n' +
-    'if err != nil {\n' +
-    '\treturn err\n' +
-    '}\n' +
-    '```'
-  )
-})
-
-test('Select codeblock language', async ({ page }) => {
-  await createRandomPage(page)
-
-  // Open the slash command menu
-  await page.type('textarea >> nth=0', '/code block', { delay: 20 })
-
-  expect(
-    await page.waitForSelector('[data-modal-name="commands"]', {
-      state: 'visible',
-    })
-  ).toBeTruthy()
-
-  // Select `code block` command and open the language dropdown menu
-  await page.press('textarea >> nth=0', 'Enter', { delay: 10 })
-  // wait for the modal to open
-  expect(
-    await page.waitForSelector('[data-modal-name="select-code-block-mode"]', {
-      state: 'visible',
-    })
-  ).toBeTruthy()
-
-  // Select Clojure from the dropdown menu
-  await repeatKeyPress(page, 'ArrowDown', 6)
-  await page.press('textarea >> nth=0', 'Enter', { delay: 10 })
-  await page.waitForTimeout(100)
-  // expect the codeblock to be visible
-  expect(await page.waitForSelector('.CodeMirror', { state: 'visible' }))
-
-  // Exit codeblock and return to block edit mode
-  await page.press('.CodeMirror textarea >> nth=0', 'Escape', { delay: 10 })
-
-  expect(await page.inputValue('.block-editor textarea')).toBe(
-    '```clojure\n```'
-  )
-})
-
-test('Select codeblock language while surrounded by text', async ({ page }) => {
-  await createRandomPage(page)
-  await page.type('textarea >> nth=0', 'ABC XYZ', { delay: 20 })
-  await repeatKeyPress(page, 'ArrowLeft', 3)
-
-  // Open the slash command menu
-  await page.type('textarea >> nth=0', '/code block', { delay: 20 })
-
-  expect(
-    await page.waitForSelector('[data-modal-name="commands"]', {
-      state: 'visible',
-    })
-  ).toBeTruthy()
-
-  // Select `code block` command and open the language dropdown menu
-  await page.press('textarea >> nth=0', 'Enter', { delay: 10 })
-  // wait for the modal to open
-  expect(
-    await page.waitForSelector('[data-modal-name="select-code-block-mode"]', {
-      state: 'visible',
-    })
-  ).toBeTruthy()
-
-  // Select Clojure from the dropdown menu
-  await repeatKeyPress(page, 'ArrowDown', 6)
-  await page.press('textarea >> nth=0', 'Enter', { delay: 10 })
-  // expect the codeblock to be visible
-  expect(await page.waitForSelector('.CodeMirror', { state: 'visible' }))
-
-  // Exit codeblock and return to block edit mode
-  await page.press('.CodeMirror textarea >> nth=0', 'Escape', { delay: 10 })
-
-  expect(await page.inputValue('.block-editor textarea')).toBe(
-    'ABC \n```clojure\n```\nXYZ'
-  )
-})

+ 0 - 60
e2e-tests/context-menu.spec.ts

@@ -1,60 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { createRandomPage } from './utils'
-
-test('open context menu', async ({ page }) => {
-    await createRandomPage(page)
-
-    await page.locator('span.bullet-container >> nth=0').click({button: "right"})
-
-    await expect(page.locator('#custom-context-menu')).toBeVisible()
-})
-
-test('close context menu on esc', async ({ page }) => {
-    await createRandomPage(page)
-
-    await page.locator('span.bullet-container >> nth=0').click({button: "right"})
-
-    await page.keyboard.press('Escape')
-
-    await expect(page.locator('#custom-context-menu')).toHaveCount(0)
-})
-
-test('close context menu by left clicking on empty space', async ({ page }) => {
-    await createRandomPage(page)
-
-    await page.locator('span.bullet-container >> nth=0').click({button: "right"})
-
-    await page.mouse.click(0, 200, {button: "left"})
-
-    await expect(page.locator('#custom-context-menu')).toHaveCount(0)
-})
-
-test('close context menu by clicking on a menu item', async ({ page }) => {
-    await createRandomPage(page)
-
-    await page.locator('span.bullet-container >> nth=0').click({button: "right"})
-
-    await page.locator('#custom-context-menu .menu-link >> nth=1').click()
-
-    await expect(page.locator('#custom-context-menu')).toHaveCount(0)
-})
-
-test('close context menu by clicking on a block', async ({ page, block }) => {
-    await createRandomPage(page)
-
-    await block.mustType('fist Block')
-    await block.enterNext()
-
-    await page.locator('span.bullet-container >> nth=-1').click({button: "right"})
-
-    const elementHandle = page.locator('.block-content >> nth=0');
-
-    const box = await elementHandle.boundingBox();
-    expect(box).toBeTruthy()
-    if (box) {
-        await page.mouse.click(box.x + box.width - 5, box.y + box.height / 2);
-    }
-
-    await expect(page.locator('#custom-context-menu')).toHaveCount(0)
-})

+ 0 - 82
e2e-tests/dnd.spec.ts

@@ -1,82 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { createRandomPage, enterNextBlock } from './utils'
-
-/**
- * Drag and Drop tests.
- *
- * NOTE: x = 30 is an estimation of left position of the drop target.
- */
-
-test('drop to left center', async ({ page }) => {
-  await createRandomPage(page)
-
-  await page.fill('textarea >> nth=0', 'block a')
-  await enterNextBlock(page)
-
-  await page.fill('textarea >> nth=0', 'block b')
-  await page.press('textarea >> nth=0', 'Escape')
-
-  const bullet = page.locator('span.bullet-container >> nth=-1')
-  const where = page.locator('.ls-block >> nth=0')
-  await bullet.dragTo(where, {
-    targetPosition: {
-      x: 30,
-      y: (await where.boundingBox()).height * 0.5
-    }
-  })
-
-  await page.keyboard.press('Escape')
-
-  const pageElem = page.locator('.page-blocks-inner')
-  await expect(pageElem).toHaveText('block b\nblock a', {useInnerText: true})
-})
-
-
-test('drop to upper left', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustFill('block a')
-  await block.enterNext()
-
-  await block.mustFill('block b')
-  await block.escapeEditing()
-
-  const bullet = page.locator('span.bullet-container >> nth=-1')
-  const where = page.locator('.ls-block >> nth=0')
-  await bullet.dragTo(where, {
-    targetPosition: {
-      x: 0,
-      y: 0
-    }
-  })
-
-  await page.keyboard.press('Escape')
-
-  const pageElem = page.locator('.page-blocks-inner')
-  await expect(pageElem).toHaveText('block b\nblock a', {useInnerText: true})
-})
-
-test('drop to bottom left', async ({ page }) => {
-  await createRandomPage(page)
-
-  await page.fill('textarea >> nth=0', 'block a')
-  await enterNextBlock(page)
-
-  await page.fill('textarea >> nth=0', 'block b')
-  await page.press('textarea >> nth=0', 'Escape')
-
-  const bullet = page.locator('span.bullet-container >> nth=-1')
-  const where = page.locator('.ls-block >> nth=0')
-  await bullet.dragTo(where, {
-    targetPosition: {
-      x: 30,
-      y: (await where.boundingBox()).height * 0.75
-    }
-  })
-
-  await page.keyboard.press('Escape')
-
-  const pageElem = page.locator('.page-blocks-inner')
-  await expect(pageElem).toHaveText('block a\nblock b', {useInnerText: true})
-})

+ 0 - 865
e2e-tests/editor.spec.ts

@@ -1,865 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import {
-  createRandomPage,
-  enterNextBlock,
-  modKey,
-  repeatKeyPress,
-  moveCursor,
-  selectCharacters,
-  getSelection,
-  getCursorPos,
-} from './utils'
-import { dispatch_kb_events } from './util/keyboard-events'
-import * as kb_events from './util/keyboard-events'
-
-test('hashtag and quare brackets in same line #4178', async ({ page }) => {
-  try {
-    await page.waitForSelector('.notification-clear', { timeout: 10 })
-    page.click('.notification-clear')
-  } catch (error) {
-  }
-
-  await createRandomPage(page)
-
-  await page.type('textarea >> nth=0', '#foo bar')
-  await enterNextBlock(page)
-  await page.type('textarea >> nth=0', 'bar [[blah]]', { delay: 100 })
-
-  for (let i = 0; i < 12; i++) {
-    await page.press('textarea >> nth=0', 'ArrowLeft')
-  }
-  await page.type('textarea >> nth=0', ' ')
-  await page.press('textarea >> nth=0', 'ArrowLeft')
-
-  await page.type('textarea >> nth=0', '#')
-  await page.waitForSelector('text="Search for a page"', { state: 'visible' })
-
-  await page.type('textarea >> nth=0', 'fo')
-
-  await page.click('.absolute >> text=' + 'foo')
-
-  expect(await page.inputValue('textarea >> nth=0')).toBe(
-    '#foo bar [[blah]]'
-  )
-})
-
-test('hashtag search page auto-complete', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.activeEditing(0)
-
-  await page.type('textarea >> nth=0', '#', { delay: 100 })
-  await page.waitForSelector('text="Search for a page"', { state: 'visible' })
-  await page.keyboard.press('Escape', { delay: 50 })
-
-  await block.mustFill("done")
-
-  await enterNextBlock(page)
-  await page.type('textarea >> nth=0', 'Some #', { delay: 100 })
-  await page.waitForSelector('text="Search for a page"', { state: 'visible' })
-  await page.keyboard.press('Escape', { delay: 50 })
-
-  await block.mustFill("done")
-})
-
-test('hashtag search #[[ page auto-complete', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.activeEditing(0)
-
-  await page.type('textarea >> nth=0', '#[[', { delay: 100 })
-  await page.waitForSelector('text="Search for a page"', { state: 'visible' })
-  await page.keyboard.press('Escape', { delay: 50 })
-})
-
-test('disappeared children #4814', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustType('parent')
-  await block.enterNext()
-  expect(await block.indent()).toBe(true)
-
-  for (let i = 0; i < 5; i++) {
-    await block.mustType(i.toString())
-    await block.enterNext()
-  }
-
-  // collapse
-  await page.click('.block-control >> nth=0')
-
-  // expand
-  await page.click('.block-control >> nth=0')
-
-  await block.waitForBlocks(7) // 1 + 5 + 1 empty
-
-  // Ensures there's no active editor
-  await expect(page.locator('.editor-inner')).toHaveCount(0, { timeout: 500 })
-})
-
-test('create new page from bracketing text #4971', async ({ page, block }) => {
-  let title = 'Page not Exists yet'
-  await createRandomPage(page)
-
-  await block.mustType(`[[${title}]]`)
-
-  await page.keyboard.press(modKey + '+o')
-
-  // Check page title equals to `title`
-  await page.waitForTimeout(100)
-  expect(await page.locator('h1.title').innerText()).toContain(title)
-
-  // Check there're linked references
-  await page.waitForSelector(`.references .ls-block >> nth=1`, { state: 'detached', timeout: 100 })
-})
-
-test.skip('backspace and cursor position #4897', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  // Delete to previous block, and check cursor position, with markup
-  await block.mustFill('`012345`')
-  await block.enterNext()
-  await block.mustType('`abcdef', { toBe: '`abcdef`' }) // "`" auto-completes
-
-  expect(await block.selectionStart()).toBe(7)
-  expect(await block.selectionEnd()).toBe(7)
-  for (let i = 0; i < 7; i++) {
-    await page.keyboard.press('ArrowLeft')
-  }
-  expect(await block.selectionStart()).toBe(0)
-
-  await page.keyboard.press('Backspace')
-  await block.waitForBlocks(1) // wait for delete and re-render
-  expect(await block.selectionStart()).toBe(8)
-})
-
-test.skip('next block and cursor position', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  // Press Enter and check cursor position, with markup
-  await block.mustType('abcde`12345', { toBe: 'abcde`12345`' }) // "`" auto-completes
-  for (let i = 0; i < 7; i++) {
-    await page.keyboard.press('ArrowLeft')
-  }
-  expect(await block.selectionStart()).toBe(5) // after letter 'e'
-
-  await block.enterNext()
-  expect(await block.selectionStart()).toBe(0) // should at the beginning of the next block
-
-  const locator = page.locator('textarea >> nth=0')
-  await expect(locator).toHaveText('`12345`', { timeout: 1000 })
-})
-
-test(
-  "Press CJK Left Black Lenticular Bracket `【` by 2 times #3251 should trigger [[]], " +
-  "but dont trigger RIME #3440 ",
-  // cases should trigger [[]] #3251
-  async ({ page, block }) => {
-    // This test requires dev mode
-    test.skip(process.env.RELEASE === 'true', 'not available for release version')
-
-    // @ts-ignore
-    for (let [idx, events] of [
-      kb_events.win10_pinyin_left_full_square_bracket,
-      kb_events.macos_pinyin_left_full_square_bracket
-      // TODO: support #3741
-      // kb_events.win10_legacy_pinyin_left_full_square_bracket,
-    ].entries()) {
-      await createRandomPage(page)
-      let check_text = "#3251 test " + idx
-      await block.mustFill(check_text + "【")
-      await dispatch_kb_events(page, ':nth-match(textarea, 1)', events)
-      expect(await page.inputValue(':nth-match(textarea, 1)')).toBe(check_text + '【')
-      await block.mustFill(check_text + "【【")
-      await dispatch_kb_events(page, ':nth-match(textarea, 1)', events)
-      expect(await page.inputValue(':nth-match(textarea, 1)')).toBe(check_text + '[[]]')
-    };
-
-    // @ts-ignore dont trigger RIME #3440
-    for (let [idx, events] of [
-      kb_events.macos_pinyin_selecting_candidate_double_left_square_bracket,
-      kb_events.win10_RIME_selecting_candidate_double_left_square_bracket
-    ].entries()) {
-      await createRandomPage(page)
-      let check_text = "#3440 test " + idx
-      await block.mustFill(check_text)
-      await dispatch_kb_events(page, ':nth-match(textarea, 1)', events)
-      expect(await page.inputValue(':nth-match(textarea, 1)')).toBe(check_text)
-      await dispatch_kb_events(page, ':nth-match(textarea, 1)', events)
-      expect(await page.inputValue(':nth-match(textarea, 1)')).toBe(check_text)
-    }
-  })
-
-test('copy & paste block ref and replace its content', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustType('Some random text')
-
-  await page.keyboard.press(modKey + '+c')
-  await page.waitForTimeout(200)
-  await page.press('textarea >> nth=0', 'Enter')
-  await page.waitForTimeout(100)
-  await block.waitForBlocks(2)
-  await page.waitForTimeout(100)
-  await page.keyboard.press(modKey + '+v', { delay: 100 })
-  await page.waitForTimeout(100)
-  await page.keyboard.press('Enter', { delay: 100 })
-
-  // Check if the newly created block-ref has the same referenced content
-  await expect(page.locator('.block-ref >> text="Some random text"')).toHaveCount(1);
-
-  // Move cursor into the block ref
-  for (let i = 0; i < 4; i++) {
-    await page.press('textarea >> nth=0', 'ArrowLeft', { delay: 10 })
-  }
-
-  await expect(page.locator('textarea >> nth=0')).not.toHaveValue('Some random text')
-
-  for (let i = 0; i < 4; i++) {
-    await page.press('textarea >> nth=0', 'ArrowLeft', { delay: 10 } )
-  }
-
-  // Trigger replace-block-reference-with-content-at-point
-  await page.keyboard.press(modKey + '+Shift+r')
-
-  await expect(page.locator('textarea >> nth=0')).toHaveValue('Some random text')
-
-  await block.escapeEditing()
-
-  await expect(page.locator('.block-ref >> text="Some random text"')).toHaveCount(0);
-  await expect(page.locator('text="Some random text"')).toHaveCount(2);
-})
-
-test('copy and paste block after editing new block #5962', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  // Create a block and copy it in block-select mode
-  await block.mustType('Block being copied')
-  await page.keyboard.press('Escape')
-  await expect(page.locator('.ls-block.selected')).toHaveCount(1)
-
-  await page.keyboard.press(modKey + '+c', { delay: 100 })
-
-  await page.keyboard.press('Enter')
-  await expect(page.locator('.ls-block.selected')).toHaveCount(0)
-  await expect(page.locator('textarea >> nth=0')).toBeVisible()
-  await page.keyboard.press('Enter')
-  await block.waitForBlocks(2)
-
-  await page.waitForTimeout(100)
-
-  await block.mustType('Typed block')
-
-  await page.keyboard.press(modKey + '+v')
-  await expect(page.locator('text="Typed block"')).toHaveCount(1)
-  await block.waitForBlocks(3)
-})
-
-test('undo and redo after starting an action should not destroy text #6267', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  // Get one piece of undo state onto the stack
-  await block.mustType('text1 ')
-  await page.waitForTimeout(1000) // auto save
-
-  // Then type more, start an action prompt, and undo
-  await page.keyboard.type('text2 [[', { delay: 50 })
-
-  await expect(page.locator(`[data-modal-name="page-search"]`)).toBeVisible()
-
-  await page.waitForTimeout(1000) // auto save
-
-  await page.keyboard.press(modKey + '+z', { delay: 100 })
-
-  // Should close the action menu when we undo the action prompt
-  // await expect(page.locator(`[data-modal-name="page-search"]`)).not.toBeVisible()
-
-  // It should undo to the last saved state, and not erase the previous undo action too
-  await expect(page.locator('text="text1"')).toHaveCount(1)
-
-  // And it should keep what was undone as a redo action
-  await page.keyboard.press(modKey + '+Shift+z')
-  await expect(page.locator('text="text1 text2 [[]]"')).toHaveCount(1)
-})
-
-test('undo after starting an action should close the action menu #6269', async ({ page, block }) => {
-  for (const [commandTrigger, modalName] of [['/', 'commands'], ['[[', 'page-search']]) {
-    await createRandomPage(page)
-
-    // Open the action modal
-    await block.mustType('text1 ')
-    await page.waitForTimeout(550)
-    await page.keyboard.type(commandTrigger, { delay: 20 })
-
-    await page.waitForTimeout(100) // Tolerable delay for the action menu to open
-    await expect(page.locator(`[data-modal-name="${modalName}"]`)).toBeVisible()
-
-    // Undo, removing "/today", and closing the action modal
-    await page.keyboard.press(modKey + '+z', { delay: 100 })
-
-    await expect(page.locator('text="/today"')).toHaveCount(0)
-    await expect(page.locator(`[data-modal-name="${modalName}"]`)).not.toBeVisible()
-  }
-})
-
-test('#6266 moving cursor outside of brackets should close autocomplete menu', async ({ page, block, autocompleteMenu }) => {
-  for (const [commandTrigger, modalName] of [['[[', 'page-search'], ['((', 'block-search']]) {
-    // First, left arrow
-    await createRandomPage(page)
-
-    await block.mustFill('t ')
-    await page.keyboard.type(commandTrigger, { delay: 20 })
-
-    await page.waitForTimeout(100) // Sometimes it doesn't trigger without this
-    await autocompleteMenu.expectVisible(modalName)
-
-    await page.keyboard.press('ArrowLeft')
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectHidden(modalName)
-
-    // Then, right arrow
-    await createRandomPage(page)
-
-    await block.mustFill('t ')
-    await page.keyboard.type(commandTrigger, { delay: 20 })
-
-    await autocompleteMenu.expectVisible(modalName)
-
-    await page.waitForTimeout(100)
-    // Move cursor outside of the space strictly between the double brackets
-    await page.keyboard.press('ArrowRight')
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectHidden(modalName)
-  }
-})
-
-// Old logic would fail this because it didn't do the check if @search-timeout was set
-test('#6266 moving cursor outside of parens immediately after searching should still close autocomplete menu', async ({ page, block, autocompleteMenu }) => {
-  for (const [commandTrigger, modalName] of [['((', 'block-search']]) {
-    await createRandomPage(page)
-
-    // Open the autocomplete menu
-    await block.mustFill('t ')
-    await page.keyboard.type(commandTrigger, { delay: 20 })
-
-    await page.waitForTimeout(100)
-    await page.keyboard.type("some block search text")
-    await page.waitForTimeout(100) // Sometimes it doesn't trigger without this
-    await autocompleteMenu.expectVisible(modalName)
-
-    // Move cursor outside of the space strictly between the double parens
-    await page.keyboard.press('ArrowRight')
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectHidden(modalName)
-  }
-})
-
-test('pressing up and down should NOT close autocomplete menu', async ({ page, block, autocompleteMenu }) => {
-  for (const [commandTrigger, modalName] of [['[[', 'page-search'], ['((', 'block-search']]) {
-    await createRandomPage(page)
-
-    // Open the autocomplete menu
-    await block.mustFill('t ')
-    await page.keyboard.type(commandTrigger, { delay: 20 })
-
-    await autocompleteMenu.expectVisible(modalName)
-    const cursorPos = await block.selectionStart()
-
-    await page.keyboard.press('ArrowUp')
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectVisible(modalName)
-    await expect(await block.selectionStart()).toEqual(cursorPos)
-
-    await page.keyboard.press('ArrowDown')
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectVisible(modalName)
-    await expect(await block.selectionStart()).toEqual(cursorPos)
-  }
-})
-
-test('moving cursor inside of brackets should NOT close autocomplete menu', async ({ page, block, autocompleteMenu }) => {
-  for (const [commandTrigger, modalName] of [['[[', 'page-search'], ['((', 'block-search']]) {
-    await createRandomPage(page)
-
-    // Open the autocomplete menu
-    await block.mustType('test ')
-    await page.keyboard.type(commandTrigger, { delay: 20 })
-
-    await page.waitForTimeout(100)
-    if (commandTrigger === '[[') {
-      await autocompleteMenu.expectVisible(modalName)
-    }
-
-    await page.keyboard.type("search", { delay: 20 })
-    await autocompleteMenu.expectVisible(modalName)
-
-    // Move cursor, still inside the brackets
-    await page.keyboard.press('ArrowLeft')
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectVisible(modalName)
-  }
-})
-
-test('moving cursor inside of brackets when autocomplete menu is closed should NOT open autocomplete menu', async ({ page, block, autocompleteMenu }) => {
-  // Note: (( behaves differently and doesn't auto-trigger when typing in it after exiting the search prompt once
-  for (const [commandTrigger, modalName] of [['[[', 'page-search']]) {
-    await createRandomPage(page)
-
-    // Open the autocomplete menu
-    await block.mustFill('')
-    await page.keyboard.type(commandTrigger, { delay: 20 })
-
-    await page.waitForTimeout(100) // Sometimes it doesn't trigger without this
-    await autocompleteMenu.expectVisible(modalName)
-
-    await block.escapeEditing()
-    await autocompleteMenu.expectHidden(modalName)
-
-    // Move cursor left until it's inside the brackets; shouldn't open autocomplete menu
-    await page.locator('.block-content').click()
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectHidden(modalName)
-
-    await page.keyboard.press('ArrowLeft', { delay: 50 })
-    await autocompleteMenu.expectHidden(modalName)
-
-    await page.keyboard.press('ArrowLeft', { delay: 50 })
-    await autocompleteMenu.expectHidden(modalName)
-
-    // Type a letter, this should open the autocomplete menu
-    await page.keyboard.type('z', { delay: 20 })
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectVisible(modalName)
-  }
-})
-
-test('selecting text inside of brackets should NOT close autocomplete menu', async ({ page, block, autocompleteMenu }) => {
-  for (const [commandTrigger, modalName] of [['[[', 'page-search'], ['((', 'block-search']]) {
-    await createRandomPage(page)
-
-    // Open the autocomplete menu
-    await block.mustFill('')
-    await page.keyboard.type(commandTrigger, { delay: 20 })
-
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectVisible(modalName)
-
-    await page.keyboard.type("some page search text", { delay: 10 })
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectVisible(modalName)
-
-    // Select some text within the brackets
-    await page.keyboard.press('Shift+ArrowLeft')
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectVisible(modalName)
-  }
-})
-
-test('pressing backspace and remaining inside of brackets should NOT close autocomplete menu', async ({ page, block, autocompleteMenu }) => {
-  for (const [commandTrigger, modalName] of [['[[', 'page-search'], ['((', 'block-search']]) {
-    await createRandomPage(page)
-
-    // Open the autocomplete menu
-    await block.mustFill('test ')
-    await page.keyboard.type(commandTrigger, { delay: 20 })
-
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectVisible(modalName)
-
-    await page.keyboard.type("some page search text", { delay: 10 })
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectVisible(modalName)
-
-    // Delete one character inside the brackets
-    await page.keyboard.press('Backspace')
-    await page.waitForTimeout(100)
-    await autocompleteMenu.expectVisible(modalName)
-  }
-})
-
-test('press escape when autocomplete menu is open, should close autocomplete menu only #6270', async ({ page, block }) => {
-  for (const [commandTrigger, modalName] of [['[[', 'page-search'], ['/', 'commands']]) {
-    await createRandomPage(page)
-
-    // Open the action modal
-    await block.mustFill('text ')
-    await page.waitForTimeout(550)
-    await page.keyboard.type(commandTrigger, { delay: 20 })
-
-    await page.waitForTimeout(100)
-    await expect(page.locator(`[data-modal-name="${modalName}"]`)).toBeVisible()
-    await page.waitForTimeout(100)
-
-    // Press escape; should close action modal instead of exiting edit mode
-    await page.keyboard.press('Escape')
-    await page.waitForTimeout(100)
-    await expect(page.locator(`[data-modal-name="${modalName}"]`)).not.toBeVisible()
-    await page.waitForTimeout(1000)
-    expect(await block.isEditing()).toBe(true)
-  }
-})
-
-test('press escape when link/image dialog is open, should restore focus to input', async ({ page, block }) => {
-  for (const [commandTrigger, modalName] of [['/link', 'commands']]) {
-    await createRandomPage(page)
-
-    // Open the action modal
-    await block.mustFill('')
-    await page.waitForTimeout(550)
-    await page.keyboard.type(commandTrigger, { delay: 20 })
-
-    await page.waitForTimeout(100)
-    await expect(page.locator(`[data-modal-name="${modalName}"]`)).toBeVisible()
-    await page.waitForTimeout(100)
-
-    // Press enter to open the link dialog
-    await page.keyboard.press('Enter')
-    await expect(page.locator(`[data-modal-name="input"]`)).toBeVisible()
-
-    // Press escape; should close link dialog and restore focus to the block textarea
-    await page.keyboard.press('Escape')
-    await page.waitForTimeout(100)
-    await expect(page.locator(`[data-modal-name="input"]`)).not.toBeVisible()
-    await page.waitForTimeout(1000)
-    expect(await block.isEditing()).toBe(true)
-  }
-})
-
-test('should show text after soft return when node is collapsed #5074', async ({ page, block }) => {
-  const delay = 300
-  await createRandomPage(page)
-
-  await page.type('textarea >> nth=0', 'Before soft return', { delay: 10 })
-  await page.keyboard.press('Shift+Enter', { delay: 10 })
-  await page.type('textarea >> nth=0', 'After soft return', { delay: 10 })
-
-  await block.enterNext()
-  expect(await block.indent()).toBe(true)
-  await block.mustType('Child text')
-
-  // collapse
-  await page.click('.block-control >> nth=0')
-  await block.waitForBlocks(1)
-
-  // select the block that has the soft return
-  await page.keyboard.press('ArrowDown')
-  await page.waitForTimeout(delay)
-  await page.keyboard.press('Enter')
-  await page.waitForTimeout(delay)
-
-  await expect(page.locator('textarea >> nth=0')).toHaveText('Before soft return\nAfter soft return')
-
-  // zoom into the block
-  page.click('a.block-control + a')
-  await page.waitForNavigation()
-  await page.waitForTimeout(delay * 3)
-
-  // select the block that has the soft return
-  await page.keyboard.press('ArrowDown')
-  await page.waitForTimeout(delay)
-  await page.keyboard.press('Enter')
-  await page.waitForTimeout(delay)
-
-  await expect(page.locator('textarea >> nth=0')).toHaveText('Before soft return\nAfter soft return')
-})
-
-test('should not erase typed text when expanding block quickly after typing #3891', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustFill('initial text,')
-  await page.waitForTimeout(1000)
-  await page.type('textarea >> nth=0', ' then expand', { delay: 10 })
-  // A quick cmd-down must not destroy the typed text
-  await page.keyboard.press(modKey + '+ArrowDown')
-  expect(await page.inputValue('textarea >> nth=0')).toBe(
-    'initial text, then expand'
-  )
-
-  await page.waitForTimeout(1000)
-
-  // First undo should delete the last typed information, not undo a no-op expand action
-  await page.keyboard.press(modKey + '+z', { delay: 100 })
-  expect(await page.inputValue('textarea >> nth=0')).toBe(
-    'initial text,'
-  )
-
-  await page.keyboard.press(modKey + '+z')
-  await page.waitForTimeout(100)
-  expect(await page.inputValue('textarea >> nth=0')).toBe(
-    ''
-  )
-})
-
-test('should keep correct undo and redo seq after indenting or outdenting the block #7615',async({page,block}) => {
-  await createRandomPage(page)
-
-  await block.mustFill("foo")
-
-  await page.keyboard.press("Enter")
-  await expect(page.locator('textarea >> nth=0')).toHaveText("")
-  await page.waitForTimeout(100)
-  await block.indent()
-  await page.waitForTimeout(100)
-  await block.mustFill("bar")
-  await expect(page.locator('textarea >> nth=0')).toHaveText("bar")
-
-  // await page.keyboard.press(modKey + '+z')
-  // // should undo "bar" input
-  // await expect(page.locator('textarea >> nth=0')).toHaveText("")
-
-  // await page.keyboard.press(modKey + '+Shift+z', { delay: 100 })
-
-  // // should redo "bar" input
-  // await expect(page.locator('textarea >> nth=0')).toHaveText("bar")
-  // await page.keyboard.press("Shift+Tab", { delay: 100 })
-
-  // await page.keyboard.press("Enter", { delay: 100 })
-  // await expect(page.locator('textarea >> nth=0')).toHaveText("")
-
-  // #7615
-  await enterNextBlock(page)
-  await page.keyboard.type("aaa")
-  await block.indent()
-  await page.waitForTimeout(550)
-  await page.keyboard.type(" bbb")
-  await page.waitForTimeout(550)
-  await expect(page.locator('textarea >> nth=0')).toHaveText("aaa bbb")
-  await page.keyboard.press(modKey + '+z')
-  await page.waitForTimeout(100)
-  await expect(page.locator('textarea >> nth=0')).toHaveText("aaa")
-  await page.keyboard.press(modKey + '+Shift+z')
-  await page.waitForTimeout(100)
-  await expect(page.locator('textarea >> nth=0')).toHaveText("aaa bbb")
-})
-
-test.describe('Text Formatting', () => {
-  const formats = [
-    { name: 'bold', prefix: '**', postfix: '**', shortcut: modKey + '+b' },
-    { name: 'italic', prefix: '*', postfix: '*', shortcut: modKey + '+i' },
-    {
-      name: 'strikethrough',
-      prefix: '~~',
-      postfix: '~~',
-      shortcut: modKey + '+Shift+s',
-    },
-    // {
-    //   name: 'underline',
-    //   prefix: '<u>',
-    //   postfix: '</u>',
-    //   shortcut: modKey + '+u',
-    // },
-  ]
-
-  for (const format of formats) {
-    test.describe(`${format.name} formatting`, () => {
-      test('Applying to an empty selection inserts placeholder formatting and places cursor correctly', async ({
-        page,
-        block,
-      }) => {
-        await createRandomPage(page)
-
-        const text = 'Lorem ipsum'
-        await block.mustFill(text)
-
-        // move the cursor to the end of Lorem
-        await repeatKeyPress(page, 'ArrowLeft', text.length - 'ipsum'.length)
-        await page.keyboard.press('Space')
-
-        // Apply formatting
-        await page.keyboard.press(format.shortcut)
-
-        await expect(page.locator('textarea >> nth=0')).toHaveText(
-          `Lorem ${format.prefix}${format.postfix} ipsum`
-        )
-
-        // Verify cursor position
-        const cursorPos = await getCursorPos(page)
-        expect(cursorPos).toBe(' ipsum'.length + format.prefix.length)
-      })
-
-      test('Applying to an entire block encloses the block in formatting and places cursor correctly', async ({
-        page,
-        block,
-      }) => {
-        await createRandomPage(page)
-
-        const text = 'Lorem ipsum-dolor sit.'
-        await block.mustFill(text)
-
-        // Select the entire block
-        await page.keyboard.press(modKey + '+a')
-
-        // Apply formatting
-        await page.keyboard.press(format.shortcut)
-
-        await expect(page.locator('textarea >> nth=0')).toHaveText(
-          `${format.prefix}${text}${format.postfix}`
-        )
-
-        // Verify cursor position
-        const cursorPosition = await getCursorPos(page)
-        expect(cursorPosition).toBe(format.prefix.length + text.length)
-      })
-
-      test('Applying and then removing from a word connected with a special character correctly formats and then reverts', async ({
-        page,
-        block,
-      }) => {
-        await createRandomPage(page)
-
-        await block.mustFill('Lorem ipsum-dolor sit.')
-
-        // Select 'ipsum'
-        // Move the cursor to the desired position
-        await moveCursor(page, -16)
-
-        // Select the desired length of text
-        await selectCharacters(page, 5)
-
-        // Apply formatting
-        await page.keyboard.press(format.shortcut)
-
-        // Verify that 'ipsum' is formatted
-        await expect(page.locator('textarea >> nth=0')).toHaveText(
-          `Lorem ${format.prefix}ipsum${format.postfix}-dolor sit.`
-        )
-
-        // Re-select 'ipsum'
-        // Move the cursor to the desired position
-        await moveCursor(page, -5)
-
-        // Select the desired length of text
-        await selectCharacters(page, 5)
-
-        // Remove formatting
-        await page.keyboard.press(format.shortcut)
-        await expect(page.locator('textarea >> nth=0')).toHaveText(
-          'Lorem ipsum-dolor sit.'
-        )
-
-        // Verify the word 'ipsum' is still selected
-        const selection = await getSelection(page)
-        expect(selection).toBe('ipsum')
-      })
-    })
-  }
-})
-
-test.describe('Always auto-pair symbols', () => {
-  // Define the symbols that should be auto-paired
-  const autoPairSymbols = [
-    { name: 'square brackets', prefix: '[', postfix: ']' },
-    { name: 'curly brackets', prefix: '{', postfix: '}' },
-    { name: 'parentheses', prefix: '(', postfix: ')' },
-    // { name: 'angle brackets', prefix: '<', postfix: '>' },
-    { name: 'backtick', prefix: '`', postfix: '`' },
-    // { name: 'single quote', prefix: "'", postfix: "'" },
-    // { name: 'double quote', prefix: '"', postfix: '"' },
-  ]
-
-  for (const symbol of autoPairSymbols) {
-    test(`${symbol.name} auto-pairing`, async ({ page }) => {
-      await createRandomPage(page)
-
-      // Type prefix and check that the postfix is automatically added
-      page.type('textarea >> nth=0', symbol.prefix, { delay: 100 })
-      await expect(page.locator('textarea >> nth=0')).toHaveText(
-        `${symbol.prefix}${symbol.postfix}`
-      )
-
-      // Check that the cursor is positioned correctly between the prefix and postfix
-      const CursorPos = await getCursorPos(page)
-      expect(CursorPos).toBe(symbol.prefix.length)
-    })
-  }
-})
-
-test.describe('Auto-pair symbols only with text selection', () => {
-  const autoPairSymbols = [
-    // { name: 'tilde', prefix: '~', postfix: '~' },
-    { name: 'asterisk', prefix: '*', postfix: '*' },
-    { name: 'underscore', prefix: '_', postfix: '_' },
-    { name: 'caret', prefix: '^', postfix: '^' },
-    { name: 'equal', prefix: '=', postfix: '=' },
-    { name: 'slash', prefix: '/', postfix: '/' },
-    { name: 'plus', prefix: '+', postfix: '+' },
-  ]
-
-  for (const symbol of autoPairSymbols) {
-    test(`Only auto-pair ${symbol.name} with text selection`, async ({
-      page,
-      block,
-    }) => {
-      await createRandomPage(page)
-
-      // type the symbol
-      page.type('textarea >> nth=0', symbol.prefix, { delay: 100 })
-
-      // Verify that there is no auto-pairing
-      await expect(page.locator('textarea >> nth=0')).toHaveText(symbol.prefix)
-
-      // remove prefix
-      await page.keyboard.press('Backspace')
-
-      // add text
-      await block.mustType('Lorem')
-      // select text
-      await page.keyboard.press(modKey + '+a')
-
-      // Type the prefix
-      await page.type('textarea >> nth=0', symbol.prefix, { delay: 100 })
-
-      // Verify that an additional postfix was automatically added around 'Lorem'
-      await expect(page.locator('textarea >> nth=0')).toHaveText(
-        `${symbol.prefix}Lorem${symbol.postfix}`
-      )
-
-      // Verify 'Lorem' is selected
-      const selection = await getSelection(page)
-      expect(selection).toBe('Lorem')
-    })
-  }
-})
-
-test('copy blocks should remove all ref-related values', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustFill('test')
-  await page.keyboard.press(modKey + '+c', { delay: 100 })
-  await page.waitForTimeout(100)
-  await block.clickNext()
-  await page.keyboard.press(modKey + '+v', { delay: 100 })
-  await expect(page.locator('.open-block-ref-link')).toHaveCount(1)
-
-  await page.keyboard.press('ArrowUp', { delay: 10 })
-  await page.waitForTimeout(100)
-  await page.keyboard.press('Escape')
-  await expect(page.locator('.ls-block.selected')).toHaveCount(1)
-  await page.keyboard.press(modKey + '+c', { delay: 100 })
-  await block.clickNext()
-  await page.keyboard.press(modKey + '+v', { delay: 100 })
-  await block.clickNext() // let 3rd block leave editing state
-  await expect(page.locator('.open-block-ref-link')).toHaveCount(1)
-})
-
-test('undo cut block should recover refs', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustFill('test')
-  await page.keyboard.press(modKey + '+c', { delay: 100 })
-  await page.waitForTimeout(100)
-  await block.clickNext()
-  await page.keyboard.press(modKey + '+v', { delay: 100 })
-  await expect(page.locator('.open-block-ref-link')).toHaveCount(1)
-
-  await page.keyboard.press('ArrowUp', { delay: 10 })
-  await page.waitForTimeout(100)
-  await page.keyboard.press('Escape')
-  await expect(page.locator('.ls-block.selected')).toHaveCount(1)
-  await page.keyboard.press(modKey + '+x', { delay: 100 })
-  await expect(page.locator('.ls-block')).toHaveCount(1)
-  await page.keyboard.press(modKey + '+z')
-  await page.waitForTimeout(100)
-  await expect(page.locator('.ls-block')).toHaveCount(2)
-  await expect(page.locator('.open-block-ref-link')).toHaveCount(1)
-})

+ 0 - 305
e2e-tests/fixtures.ts

@@ -1,305 +0,0 @@
-import fs from 'fs'
-import path from 'path'
-import { test as base, expect, ConsoleMessage, Locator } from '@playwright/test';
-import { ElectronApplication, Page, BrowserContext, _electron as electron } from 'playwright'
-import { loadLocalGraph, openLeftSidebar, randomString } from './utils';
-import { autocompleteMenu, LogseqFixtures } from './types';
-
-let electronApp: ElectronApplication
-let context: BrowserContext
-let page: Page
-
-// For testing special characters in graph name / path
-let repoName = "@" + randomString(10)
-let testTmpDir = path.resolve(__dirname, '../tmp')
-
-if (fs.existsSync(testTmpDir)) {
-  fs.rmSync(testTmpDir, { recursive: true })
-}
-
-export let graphDir = path.resolve(testTmpDir, "#e2e-test", repoName)
-
-// NOTE: This following is a console log watcher for error logs.
-// Save and print all logs when error happens.
-let logs: string = '';
-const consoleLogWatcher = (msg: ConsoleMessage) => {
-  const text = msg.text();
-
-  // List of error messages to ignore
-  const ignoreErrors = [
-    /net/,
-    /^Error with Permissions-Policy header:/
-  ];
-
-  // If the text matches any of the ignoreErrors, return early
-  if (ignoreErrors.some(error => text.match(error))) {
-    console.log(`WARN:: ${text}\n`)
-    return;
-  }
-
-  logs += text + '\n';
-  expect(text, logs).not.toMatch(/^(Failed to|Uncaught|Assert failed)/);
-  expect(text, logs).not.toMatch(/^Error/);
-}
-
-base.beforeAll(async () => {
-  if (electronApp) {
-    return
-  }
-
-  console.log(`Creating test graph directory: ${graphDir}`)
-  fs.mkdirSync(graphDir, {
-    recursive: true,
-  });
-
-  electronApp = await electron.launch({
-    cwd: "./static",
-    args: ["electron.js"],
-    locale: 'en',
-    timeout: 10_000, // should be enough for the app to start
-  })
-  context = electronApp.context()
-  await context.tracing.start({ screenshots: true, snapshots: true });
-  await context.tracing.startChunk();
-
-  // NOTE: The following ensures App first start with the correct path.
-  const info = await electronApp.evaluate(async ({ app }) => {
-
-    return {
-      "appPath": app.getAppPath(),
-      "appData": app.getPath("appData"),
-      "userData": app.getPath("userData"),
-      "appName": app.getName(),
-      "electronVersion": app.getVersion(),
-    }
-  })
-  console.log("Test start with:", info)
-
-  page = await electronApp.firstWindow()
-
-  // inject testing flags
-  await page.evaluate(
-    () => {
-      Object.assign(window, {
-        __E2E_TESTING__: true,
-      })
-    },
-  )
-
-  // Direct Electron console to watcher
-  page.on('console', consoleLogWatcher)
-  page.on('crash', () => {
-    expect(false, "Page must not crash").toBeTruthy()
-  })
-  page.on('pageerror', (err) => {
-    console.log(err)
-    // expect(false, 'Page must not have errors!').toBeTruthy()
-  })
-
-  await page.waitForLoadState('domcontentloaded')
-  // NOTE: The following ensures first start.
-  // await page.waitForSelector('text=This is a demo graph, changes will not be saved until you open a local folder')
-
-  await page.waitForSelector(':has-text("Loading")', {
-    state: "hidden",
-    timeout: 1000 * 15,
-  });
-
-  page.once('load', async () => {
-    console.log('Page loaded!')
-    await page.screenshot({ path: 'startup.png' })
-  })
-
-  await loadLocalGraph(page, graphDir);
-
-  // render app
-  await page.waitForFunction('window.document.title !== "Loading"')
-  expect(await page.title()).toMatch(/^Logseq.*?/)
-  await openLeftSidebar(page)
-})
-
-base.beforeEach(async () => {
-  // discard any dialog by ESC
-  if (page) {
-    await page.keyboard.press('Escape')
-    await page.keyboard.press('Escape')
-
-    await expect(page.locator('.notification-close-button')).not.toBeVisible()
-
-    if (await page.locator('.notification-clear button').isVisible()) {
-      await page.locator('.notification-clear button').click()
-    }
-
-    const rightSidebar = page.locator('.cp__right-sidebar-inner')
-    if (await rightSidebar.isVisible()) {
-      await page.click('button.toggle-right-sidebar', {delay: 100})
-    }
-  }
-})
-
-// hijack electron app into the test context
-// FIXME: add type to `block`
-export const test = base.extend<LogseqFixtures>({
-  page: async ({ }, use) => {
-    await use(page);
-  },
-
-  // Timeout is used to avoid global timeout, local timeout will have a meaningful error report.
-  // 1s timeout is enough for most of the test cases.
-  // Timeout won't introduce additional sleeps.
-  block: async ({ page }, use) => {
-    const block = {
-      mustFill: async (value: string) => {
-        const locator: Locator = page.locator('textarea >> nth=0')
-        await locator.waitFor({ timeout: 1000 })
-        await locator.fill(value)
-        await expect(locator).toHaveText(value, { timeout: 1000 })
-      },
-      mustType: async (value: string, options?: { delay?: number, toBe?: string }) => {
-        const locator: Locator = page.locator('textarea >> nth=0')
-        await locator.waitFor({ timeout: 1000 })
-        const { delay = 50 } = options || {};
-        const { toBe = value } = options || {};
-        await locator.type(value, { delay })
-        await expect(locator).toHaveText(toBe, { timeout: 1000 })
-      },
-      enterNext: async (): Promise<Locator> => {
-        let blockCount = await page.locator('.page-blocks-inner .ls-block').count()
-        await page.press('textarea >> nth=0', 'Enter')
-        await page.waitForSelector(`.ls-block >> nth=${blockCount} >> textarea`, { state: 'visible', timeout: 1000 })
-        return page.locator('textarea >> nth=0')
-      },
-      clickNext: async (): Promise<Locator> => {
-        await page.$eval('.add-button-link-wrap', (element) => {
-          element.scrollIntoView();
-        });
-        let blockCount = await page.locator('.page-blocks-inner .ls-block').count()
-        // the next element after all blocks.
-        await page.click('.add-button-link-wrap', { delay: 100 })
-        await page.waitForSelector(`.ls-block >> nth=${blockCount} >> textarea`, { state: 'visible', timeout: 1000 })
-        return page.locator('textarea >> nth=0')
-      },
-      indent: async (): Promise<boolean> => {
-        const locator = page.locator('textarea >> nth=0')
-        const before = await locator.boundingBox()
-        await locator.press('Tab', { delay: 100 })
-        return (await locator.boundingBox()).x > before.x
-      },
-      unindent: async (): Promise<boolean> => {
-        const locator = page.locator('textarea >> nth=0')
-        const before = await locator.boundingBox()
-        await locator.press('Shift+Tab', { delay: 100 })
-        return (await locator.boundingBox()).x < before.x
-      },
-      waitForBlocks: async (total: number): Promise<void> => {
-        // NOTE: `nth=` counts from 0.
-        await page.waitForSelector(`.ls-block >> nth=${total - 1}`, { state: 'attached', timeout: 50000 })
-        await page.waitForSelector(`.ls-block >> nth=${total}`, { state: 'detached', timeout: 50000 })
-      },
-      waitForSelectedBlocks: async (total: number): Promise<void> => {
-        // NOTE: `nth=` counts from 0.
-        await page.waitForSelector(`.ls-block.selected >> nth=${total - 1}`, { timeout: 1000 })
-      },
-      escapeEditing: async (): Promise<void> => {
-        const blockEdit = page.locator('.ls-block textarea >> nth=0')
-        while (await blockEdit.isVisible()) {
-          await page.keyboard.press('Escape')
-        }
-        const blockSelect = page.locator('.ls-block.selected')
-        while (await blockSelect.isVisible()) {
-          await page.keyboard.press('Escape')
-        }
-      },
-      activeEditing: async (nth: number): Promise<void> => {
-        await page.waitForSelector(`.ls-block >> nth=${nth}`, { timeout: 1000 })
-        // scroll, for isVisible test
-        await page.$eval(`.ls-block >> nth=${nth}`, (element) => {
-          element.scrollIntoView();
-        });
-        // when blocks are nested, the first block(the parent) is selected.
-        if (
-          (await page.isVisible(`.ls-block >> nth=${nth} >> .editor-wrapper >> textarea`)) &&
-          !(await page.isVisible(`.ls-block >> nth=${nth} >> .block-children-container >> textarea`))) {
-          return;
-        }
-        await page.click(`.ls-block >> nth=${nth} >> .block-content`, { delay: 10, timeout: 100000 })
-        await page.waitForSelector(`.ls-block >> nth=${nth} >> .editor-wrapper >> textarea`, { timeout: 1000, state: 'visible' })
-      },
-      isEditing: async (): Promise<boolean> => {
-        const locator = page.locator('.ls-block textarea >> nth=0')
-        return await locator.isVisible()
-      },
-      selectionStart: async (): Promise<number> => {
-        return await page.locator('textarea >> nth=0').evaluate(node => {
-          const elem = <HTMLTextAreaElement>node
-          return elem.selectionStart
-        })
-      },
-      selectionEnd: async (): Promise<number> => {
-        return await page.locator('textarea >> nth=0').evaluate(node => {
-          const elem = <HTMLTextAreaElement>node
-          return elem.selectionEnd
-        })
-      }
-    }
-    use(block)
-  },
-
-  autocompleteMenu: async ({ }, use) => {
-    const autocompleteMenu: autocompleteMenu = {
-      expectVisible: async (modalName?: string) => {
-        const modal = page.locator(modalName ? `[data-modal-name="${modalName}"]` : `[data-modal-name]`)
-        if (await modal.isVisible()) {
-          await page.waitForTimeout(100)
-          await expect(modal).toBeVisible()
-        } else {
-          await modal.waitFor({ state: 'visible', timeout: 1000 })
-        }
-      },
-      expectHidden: async (modalName?: string) => {
-        const modal = page.locator(modalName ? `[data-modal-name="${modalName}"]` : `[data-modal-name]`)
-        if (!await modal.isVisible()) {
-          await page.waitForTimeout(100)
-          await expect(modal).not.toBeVisible()
-        } else {
-          await modal.waitFor({ state: 'hidden', timeout: 1000 })
-        }
-      }
-    }
-    await use(autocompleteMenu)
-  },
-
-  context: async ({ }, use) => {
-    await use(context);
-  },
-  app: async ({ }, use) => {
-    await use(electronApp);
-  },
-  graphDir: async ({ }, use) => {
-    await use(graphDir);
-  },
-});
-
-
-let getTracingFilePath = function(): string {
-  return `e2e-dump/trace-${Date.now()}.zip.dump`
-}
-
-
-test.afterAll(async () => {
-  await context.tracing.stopChunk({ path: getTracingFilePath() });
-})
-
-
-/**
- * Trace all tests in a file
- */
-export let traceAll = function(){
-  test.beforeAll(async () => {
-    await context.tracing.startChunk();
-  })
-
-  test.afterAll(async () => {
-    await context.tracing.stopChunk({ path: getTracingFilePath() });
-  })
-}

+ 0 - 52
e2e-tests/flashcards.spec.ts

@@ -1,52 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { createRandomPage } from './utils'
-
-
-test('flashcard demo', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustFill('Why do you add cards? #card #logseq')
-  await block.enterNext()
-  expect(await block.indent()).toBe(true)
-  await block.mustFill('To augment our minds')
-
-  await block.enterNext()
-  expect(await block.unindent()).toBe(true)
-  expect(await block.unindent()).toBe(false)
-
-  await block.mustFill('How do you create clozes? #card #logseq')
-  await block.enterNext()
-  expect(await block.indent()).toBe(true)
-
-  await block.mustType('/clo')
-  const popupMenuItem = page.locator('.absolute >> text=Cloze')
-  await popupMenuItem.waitFor({ timeout: 1000 }) // wait for electric-input
-  await popupMenuItem.click({ delay: 10 })
-  await page.waitForTimeout(500)
-
-  await page.type('textarea >> nth=0', 'Something')
-  await page.keyboard.press('ArrowRight')
-  await page.keyboard.press('ArrowRight')
-
-  await page.type('textarea >> nth=0', ' like this')
-
-  await block.enterNext()
-  expect(await block.unindent()).toBe(true)
-
-  // navigate to another page, query cards
-  await createRandomPage(page)
-
-  await block.mustFill('{{cards [[logseq]]}}')
-  await page.keyboard.press('Enter')
-  const queryCards = page.locator('text="No matched cards"')
-  await queryCards.waitFor({ state: 'hidden', timeout: 6000 })
-
-  const numberLabel = page.locator('.cards-title')
-  await numberLabel.waitFor({ state: 'visible' })
-  expect(await numberLabel.innerText()).toMatch(/\[\[logseq\]\]\s+2\/2/)
-
-  // DO NOT check number label for now
-  //const cardsNum = page.locator('.flashcards-nav span >> nth=1')
-  //expect(await cardsNum.innerText()).toBe('2')
-})

+ 0 - 141
e2e-tests/fs.spec.ts

@@ -1,141 +0,0 @@
-import fsp from 'fs/promises';
-import path from 'path';
-import { expect } from '@playwright/test'
-import { test } from './fixtures';
-import { searchPage, captureConsoleWithPrefix, closeSearchBox, createPage, IsWindows, randomString } from './utils';
-
-test('create file on disk then delete', async ({ page, block, graphDir }) => {
-  // Since have to wait for file watchers
-  test.slow();
-
-  // Special page names: namespaced, chars require escaping, chars require unicode normalization, "%" chars, "%" with 2 hexdigests
-  const testCases = [
-    {pageTitle: "User:John", fileName: "User%3AJohn"},
-    // invalid url decode escaping as %ff is not parsable but match the common URL encode regex
-    {pageTitle: "%ff", fileName: "%ff"},
-    // valid url decode escaping
-    {pageTitle: "%23", fileName: "%2523"},
-    {pageTitle: "@!%", fileName: "@!%"},
-    {pageTitle: "aàáâ", fileName: "aàáâ"},
-    {pageTitle: "%gggg", fileName: "%gggg"}
-  ]
-  if (!IsWindows)
-    testCases.push({pageTitle: "User:Bob", fileName: "User:Bob"})
-
-  function getFullPath(fileName: string) {
-    return path.join(graphDir, "pages", `${fileName}.md`);
-  }
-
-  // Test putting files on disk
-  for (const {pageTitle, fileName} of testCases) {
-    // Put the file on disk
-    const filePath = getFullPath(fileName);
-    await fsp.writeFile(filePath, `- content for ${pageTitle}`);
-    await captureConsoleWithPrefix(page, "Parsing finished:", 5000)
-
-    // Check that the page is created
-    const results = await searchPage(page, pageTitle);
-    const firstResultRow = await results[0].innerText()
-    expect(firstResultRow).toContain(pageTitle);
-    expect(firstResultRow).not.toContain("Create");
-    await closeSearchBox(page);
-  }
-
-  // Test removing files on disk
-  for (const {pageTitle, fileName} of testCases) {
-    // Remove the file on disk
-    const filePath = getFullPath(fileName);
-    await fsp.unlink(filePath);
-    await captureConsoleWithPrefix(page, "Delete page:", 5000);
-
-    // Test that the page is deleted
-    const results = await searchPage(page, pageTitle);
-    const firstResultRow = await results[0].innerText()
-    // expect(firstResultRow).toContain("Create");
-    await closeSearchBox(page);
-  }
-});
-
-test("Rename file on disk", async ({ page, block, graphDir }) => {
-  // Since have to wait for file watchers
-  test.slow();
-
-  const testCases = [
-    // Normal -> NameSpace
-    {pageTitle: "User:John", fileName: "User%3AJohn",
-    newPageTitle: "User/John", newFileName: "User___John"},
-    // NameSpace -> Normal
-    {pageTitle: "!/%23", fileName: "!___%2523",
-    newPageTitle: "%23", newFileName: "%2523"}
-  ]
-  if (!IsWindows)
-    testCases.push({pageTitle: "User:Bob", fileName: "User:Bob",
-      newPageTitle: "User/Bob", newFileName: "User___Bob"})
-
-  function getFullPath(fileName: string) {
-    return path.join(graphDir, "pages", `${fileName}.md`);
-  }
-
-  // Test putting files on disk
-  for (const {pageTitle, fileName} of testCases) {
-    // Put the file on disk
-    const filePath = getFullPath(fileName);
-    await fsp.writeFile(filePath, `- content for ${pageTitle}`);
-    await captureConsoleWithPrefix(page, "Parsing finished:", 5000)
-
-    // Check that the page is created
-    const results = await searchPage(page, pageTitle);
-    const firstResultRow = await results[0].innerText()
-    expect(firstResultRow).toContain(pageTitle);
-    expect(firstResultRow).not.toContain("Create");
-    await closeSearchBox(page);
-  }
-
-  // Test renaming files on disk
-  for (const {pageTitle, fileName, newPageTitle, newFileName} of testCases) {
-    // Rename the file on disk
-    const filePath = getFullPath(fileName);
-    const newFilePath = getFullPath(newFileName);
-    await fsp.rename(filePath, newFilePath);
-    await captureConsoleWithPrefix(page, "Parsing finished:", 5000);
-
-    await page.waitForTimeout(500);
-
-    // Test that the page is renamed
-    const results = await searchPage(page, newPageTitle);
-    const firstResultRow = await results[0].innerText()
-    expect(firstResultRow).toContain(newPageTitle);
-    expect(firstResultRow).not.toContain(pageTitle);
-    expect(firstResultRow).not.toContain("Create");
-    await closeSearchBox(page);
-  }
-})
-
-test('special page names', async ({ page, block, graphDir }) => {
-  const testCases = [
-    {pageTitle: "User:John", fileName: "User%3AJohn"},
-    {pageTitle: "_%ff", fileName: "_%25ff"},
-    {pageTitle: "@!%", fileName: "@!%"},
-    {pageTitle: "aàáâ", fileName: "aàáâ"},
-    {pageTitle: "_%gggg", fileName: "_%gggg"}
-  ]
-
-  // Test putting files on disk
-  for (const {pageTitle, fileName} of testCases) {
-    const prefix = randomString(10)
-    const fullTitle = `${prefix}${pageTitle}`
-    // Create page in Logseq
-    await createPage(page, fullTitle)
-    const text = `content for ${pageTitle}`
-    await block.mustFill(text)
-    await page.keyboard.press("Enter", { delay: 50 })
-    await page.keyboard.press("Escape", { delay: 50 })
-
-    // Wait for the file to be created on disk
-    await page.waitForTimeout(2500);
-    // Validate that the file is created on disk with the content
-    const filePath = path.join(graphDir, "pages", `${prefix}${fileName}.md`);
-    const fileContent = await fsp.readFile(filePath, "utf8");
-    expect(fileContent).toContain(text);
-  }
-});

+ 0 - 80
e2e-tests/headings.spec.ts

@@ -1,80 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { createRandomPage, editFirstBlock, newInnerBlock } from './utils'
-
-test('set heading to 1', async ({ page }) => {
-    await createRandomPage(page)
-
-    await page.type('textarea >> nth=0', 'foo')
-
-    await page.keyboard.press('Escape', { delay: 50 })
-
-    await page.locator('span.bullet-container >> nth=0').click({button: "right"})
-
-    await page.locator('#custom-context-menu .to-heading-button[title="Heading 1"]').click()
-
-    await editFirstBlock(page)
-    await page.waitForTimeout(500)
-
-    expect(await page.inputValue('textarea >> nth=0')).toBe('# foo')
-
-    await page.keyboard.press('Escape', { delay: 50 })
-
-    expect(await page.locator('.ls-block .block-content >> nth=0').innerHTML()).toContain('<h1>foo</h1>')
-})
-
-test('remove heading', async ({ page }) => {
-  await page.locator('span.bullet-container >> nth=0').click({button: "right"})
-
-  await page.locator('#custom-context-menu .to-heading-button[title="Remove heading"]').click()
-
-  expect(await page.locator('.ls-block .block-content >> nth=0').innerHTML()).toContain('foo')
-})
-
-test('set heading to 2', async ({ page }) => {
-  await page.locator('span.bullet-container >> nth=0').click({button: "right"})
-  await page.locator('#custom-context-menu .to-heading-button[title="Heading 2"]').click({ delay: 400})
-
-  expect(await page.locator('.ls-block .block-content >> nth=0').innerHTML()).toContain('<h2>foo</h2>')
-})
-
-test('switch to auto heading', async ({ page }) => {
-  await page.locator('span.bullet-container >> nth=0').click({button: "right"})
-
-  await page.locator('#custom-context-menu .to-heading-button[title="Auto heading"]').click()
-
-  await editFirstBlock(page)
-  await page.waitForTimeout(500)
-
-  expect(await page.inputValue('textarea >> nth=0')).toBe('foo')
-
-  await page.keyboard.press('Escape', { delay: 50 })
-
-  expect(await page.locator('.ls-block .block-content >> nth=0').innerHTML()).toContain('<h1>foo</h1>')
-})
-
-test('set heading of nested block to auto', async ({ page }) => {
-  await newInnerBlock(page)
-  await page.waitForTimeout(500)
-
-  await page.type('textarea >> nth=0', 'bar')
-
-  await page.keyboard.press("Tab", { delay: 100 })
-
-  await page.keyboard.press('Escape', { delay: 100 })
-
-  await page.locator('span.bullet-container >> nth=1').click({button: "right"})
-
-  await page.locator('#custom-context-menu .to-heading-button[title="Auto heading"]').click()
-
-  await page.waitForTimeout(100)
-
-  expect(await page.locator('.ls-block .block-content >> nth=1').innerHTML()).toContain('<h2>bar</h2>')
-})
-
-test('view nested block on a dedicated page', async ({ page }) => {
-  await page.locator('span.bullet-container >> nth=1').click()
-  await page.waitForTimeout(200)
-
-  expect(await page.locator('.ls-block .block-content >> nth=0').innerHTML()).toContain('<h1>bar</h1>')
-})

+ 0 - 53
e2e-tests/history.spec.ts

@@ -1,53 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { createRandomPage, modKey, searchAndJumpToPage, renamePage, randomString } from './utils'
-
-test('undo/redo on a page should work as expected', async ({ page, block }) => {
-  const page1 = await createRandomPage(page)
-
-  await block.mustType('text 1')
-  await page.waitForTimeout(500) // Wait for 500ms autosave period to expire
-  await expect(page.locator('text="text 1"')).toHaveCount(1)
-
-  await page.keyboard.press(modKey + '+z')
-  await page.waitForTimeout(100)
-  await expect(page.locator('text="text 1"')).toHaveCount(0)
-
-  await page.keyboard.press(modKey + '+Shift+z')
-  await page.waitForTimeout(100)
-  await expect(page.locator('text="text 1"')).toHaveCount(1)
-})
-
-test('should navigate to corresponding page on undo', async ({ page, block }) => {
-  const page1 = await createRandomPage(page)
-
-  await block.mustType('text 1')
-  await page.waitForTimeout(500) // Wait for 500ms autosave period to expire
-
-  const page2 = await createRandomPage(page)
-
-  await page.keyboard.press(modKey + '+z')
-  await page.waitForTimeout(100)
-  expect(await page.innerText('.page-title .title')).toBe(page1)
-
-  await page.keyboard.press(modKey + '+z')
-  await page.waitForTimeout(100)
-  await expect(page.locator('text="text 1"')).toHaveCount(0)
-})
-
-
-test('undo/redo of a renamed page should be preserved', async ({ page, block }) => {
-  const page1 = await createRandomPage(page)
-
-  await block.mustType('text 1')
-  await page.waitForTimeout(500) // Wait for 500ms autosave period to expire
-
-  await renamePage(page, randomString(10))
-
-  await page.keyboard.press(modKey + '+z') // undo rename page
-  await page.waitForTimeout(100)
-  await page.keyboard.press(modKey + '+z') // undo text edit
-  await page.waitForTimeout(100)
-
-  await expect(page.locator('text="text 1"')).toHaveCount(0)
-})

+ 0 - 46
e2e-tests/hotkey.spec.ts

@@ -1,46 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { createRandomPage, enterNextBlock, lastBlock, modKey, IsLinux, closeSearchBox } from './utils'
-
-test('open search dialog', async ({ page }) => {
-  await page.waitForTimeout(200)
-  await closeSearchBox(page)
-  await page.keyboard.press(modKey + '+k')
-
-  await page.waitForSelector('[placeholder="What are you looking for?"]', { state: 'visible' })
-  await page.keyboard.press('Escape')
-  await page.waitForSelector('[placeholder="What are you looking for?"]', { state: 'hidden' })
-})
-
-test('insert link #3278', async ({ page }) => {
-  await createRandomPage(page)
-
-  let hotKey = modKey + '+l'
-  let selectAll = modKey + '+a'
-
-  // Case 1: empty link
-  await lastBlock(page)
-  await page.press('textarea >> nth=0', hotKey)
-  expect(await page.inputValue('textarea >> nth=0')).toBe('[]()')
-  await page.type('textarea >> nth=0', 'Logseq Website')
-  expect(await page.inputValue('textarea >> nth=0')).toBe('[Logseq Website]()')
-  await page.fill('textarea >> nth=0', '[Logseq Website](https://logseq.com)')
-
-  // Case 2: link with label
-  await enterNextBlock(page)
-  await page.type('textarea >> nth=0', 'Logseq')
-  await page.press('textarea >> nth=0', selectAll)
-  await page.press('textarea >> nth=0', hotKey)
-  expect(await page.inputValue('textarea >> nth=0')).toBe('[Logseq]()')
-  await page.type('textarea >> nth=0', 'https://logseq.com/')
-  expect(await page.inputValue('textarea >> nth=0')).toBe('[Logseq](https://logseq.com/)')
-
-  // Case 3: link with URL
-  await enterNextBlock(page)
-  await page.type('textarea >> nth=0', 'https://logseq.com/')
-  await page.press('textarea >> nth=0', selectAll)
-  await page.press('textarea >> nth=0', hotKey)
-  expect(await page.inputValue('textarea >> nth=0')).toBe('[](https://logseq.com/)')
-  await page.type('textarea >> nth=0', 'Logseq')
-  expect(await page.inputValue('textarea >> nth=0')).toBe('[Logseq](https://logseq.com/)')
-})

+ 0 - 222
e2e-tests/logseq-api.spec.ts

@@ -1,222 +0,0 @@
-import { test } from './fixtures'
-import { expect } from '@playwright/test'
-import { callPageAPI } from './utils'
-import { Page } from 'playwright'
-
-async function createDBGraph(page: Page) {
-  await page.locator(`#left-sidebar .cp__graphs-selector > a`).click()
-  await page.click('text="Create db graph"')
-  await page.waitForSelector('.new-graph')
-  const name = `e2e-db-${Date.now()}`
-  await page.waitForTimeout(100)
-  await page.keyboard.type(name)
-  await page.locator('.new-graph > .ui__button').click()
-  return name
-}
-
-test.skip('test db graph', async ({ page }) => {
-  const name = await createDBGraph(page)
-  await page.waitForSelector(`a[title="logseq_db_${name}"]`)
-
-  await page.pause()
-})
-
-test('(File graph): block related apis',
-  async ({ page }) => {
-    const callAPI = callPageAPI.bind(null, page)
-
-    const bPageName = 'block-test-page'
-    await callAPI('create_page', bPageName, null, { createFirstBlock: false })
-    await callAPI('create_page', bPageName, null, { createFirstBlock: false })
-    await page.waitForSelector(`body[data-page="${bPageName}"]`)
-
-    let p = await callAPI('get_current_page')
-    const bp = await callAPI('append_block_in_page', bPageName, 'tests')
-
-    expect(p.name).toBe(bPageName)
-
-    p = await callAPI('get_page', bPageName)
-
-    expect(p.name).toBe(bPageName)
-
-    await callAPI('edit_block', bp.uuid)
-
-    const b = (await callAPI('get_current_block'))
-    expect(Object.keys(b)).toContain('uuid')
-
-    await page.waitForSelector('.block-editor > textarea')
-    await page.locator('.block-editor > textarea').fill('')
-    const content = 'test api'
-    await page.type('.block-editor > textarea', content)
-
-    const editingContent = await callAPI('get_editing_block_content')
-    expect(editingContent).toBe(content)
-
-    // create
-    let b1 = await callAPI('insert_block', b.uuid, content)
-    b1 = await callAPI('get_block', b1.uuid)
-
-    expect(b1.parent.id).toBe(b.id)
-
-    // update
-    const content1 = content + '+ update!'
-    await callAPI('update_block', b1.uuid, content1)
-    b1 = await callAPI('get_block', b1.uuid)
-
-    expect(b1.content).toBe(content1)
-
-    // remove
-    await callAPI('remove_block', b1.uuid)
-    b1 = await callAPI('get_block', b1.uuid)
-
-    expect(b1).toBeNull()
-
-    // traverse
-    b1 = await callAPI('insert_block', b.uuid, content1, { sibling: true })
-    const nb = await callAPI('get_next_sibling_block', b.uuid)
-    const pb = await callAPI('get_previous_sibling_block', b1.uuid)
-
-    expect(nb.uuid).toBe(b1.uuid)
-    expect(pb.uuid).toBe(b.uuid)
-
-    // move
-    await callAPI('move_block', b.uuid, b1.uuid)
-    const mb = await callAPI('get_next_sibling_block', b1.uuid)
-
-    expect(mb.uuid).toBe(b.uuid)
-
-    // properties
-    // FIXME: redundant api call
-    await callAPI('upsert_block_property', b1.uuid, 'a')
-    await callAPI('upsert_block_property', b1.uuid, 'a', 1)
-    let prop1 = await callAPI('get_block_property', b1.uuid, 'a')
-
-    expect(prop1).toBe(1)
-
-    await callAPI('upsert_block_property', b1.uuid, 'a', 2)
-    prop1 = await callAPI('get_block_property', b1.uuid, 'a')
-
-    expect(prop1).toBe(2)
-
-    await callAPI('remove_block_property', b1.uuid, 'a')
-    prop1 = await callAPI('get_block_property', b1.uuid, 'a')
-
-    expect(prop1).toBeNull()
-
-    await callAPI('upsert_block_property', b1.uuid, 'a', 1)
-    await callAPI('upsert_block_property', b1.uuid, 'b', 1)
-
-    prop1 = await callAPI('get_block_properties', b1.uuid)
-
-    expect(prop1).toEqual({ a: 1, b: 1 })
-
-    // await page.pause()
-  })
-
-test('(DB graph): block related apis',
-  async ({ page }) => {
-    const name = await createDBGraph(page)
-    await page.waitForSelector(`a[title="logseq_db_${name}"]`)
-
-    const callAPI = callPageAPI.bind(null, page)
-
-    const bPageName = 'block-test-page'
-    await callAPI('create_page', bPageName, null, { createFirstBlock: false })
-    await callAPI('create_page', bPageName, null, { createFirstBlock: false })
-    await page.waitForSelector(`body[data-page="${bPageName}"]`)
-
-    let p = await callAPI('get_current_page')
-    const bp = await callAPI('append_block_in_page', bPageName, 'tests')
-
-    expect(p.name).toBe(bPageName)
-
-    p = await callAPI('get_page', bPageName)
-
-    expect(p.name).toBe(bPageName)
-
-    await callAPI('edit_block', bp.uuid)
-
-    const b = (await callAPI('get_current_block'))
-    expect(Object.keys(b)).toContain('uuid')
-
-    await page.waitForSelector('.block-editor > textarea')
-    await page.locator('.block-editor > textarea').fill('')
-    const content = 'test api'
-    await page.type('.block-editor > textarea', content)
-
-    const editingContent = await callAPI('get_editing_block_content')
-    expect(editingContent).toBe(content)
-
-    // create
-    let b1 = await callAPI('insert_block', b.uuid, content)
-    b1 = await callAPI('get_block', b1.uuid)
-
-    expect(b1.parent.id).toBe(b.id)
-
-    // update
-    const content1 = content + '+ update!'
-    await callAPI('update_block', b1.uuid, content1)
-    b1 = await callAPI('get_block', b1.uuid)
-
-    expect(b1.content).toBe(content1)
-
-    // remove
-    await callAPI('remove_block', b1.uuid)
-    b1 = await callAPI('get_block', b1.uuid)
-
-    expect(b1).toBeNull()
-
-    // traverse
-    b1 = await callAPI('insert_block', b.uuid, content1, { sibling: true })
-    const nb = await callAPI('get_next_sibling_block', b.uuid)
-    const pb = await callAPI('get_previous_sibling_block', b1.uuid)
-
-    expect(nb.uuid).toBe(b1.uuid)
-    expect(pb.uuid).toBe(b.uuid)
-
-    // move
-    await callAPI('move_block', b.uuid, b1.uuid)
-    const mb = await callAPI('get_next_sibling_block', b1.uuid)
-
-    expect(mb.uuid).toBe(b.uuid)
-
-    // properties
-    await callAPI('upsert_block_property', b1.uuid, 'a', 'a')
-    let prop1 = await callAPI('get_block_property', b1.uuid, 'a')
-
-    expect(prop1.title).toBe('a')
-
-    await callAPI('upsert_block_property', b1.uuid, 'a', 'b')
-    prop1 = await callAPI('get_block_property', b1.uuid, 'a')
-
-    expect(prop1.title).toBe('b')
-
-    await callAPI('remove_block_property', b1.uuid, 'a')
-    prop1 = await callAPI('get_block_property', b1.uuid, 'a')
-
-    expect(prop1).toBeNull()
-
-    await callAPI('upsert_block_property', b1.uuid, 'a', 'a')
-    await callAPI('upsert_block_property', b1.uuid, 'b', 'b')
-
-    prop1 = await callAPI('get_block_properties', b1.uuid)
-
-    expect(prop1).toEqual({ ':plugin.property/a': 'a', ':plugin.property/b': 'b' })
-
-    // properties entity & schema
-    await callAPI('upsert_property', 'p1')
-    prop1 = await callAPI('get_property', 'p1')
-
-    expect(prop1.title).toBe('p1')
-    expect(prop1.ident).toBe(':plugin.property/p1')
-
-    await callAPI('upsert_property', 'map1', { type: 'map' })
-    await callAPI('upsert_block_property', b1.uuid, 'map1', { a: 1 })
-    prop1 = await callAPI('get_property', 'map1')
-    const b1p = await callAPI('get_block_property', b1.uuid, 'map1')
-
-    expect(prop1.type).toBe('map')
-    expect(b1p).toEqual({a: 1})
-
-    // await page.pause()
-  })

+ 0 - 55
e2e-tests/logseq-url.spec.ts

@@ -1,55 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { createRandomPage, lastBlock, IsMac, IsLinux } from './utils'
-
-test("Logseq URLs (same graph)", async ({ page, block }) => {
-  try {
-    await page.waitForSelector('.notification-clear', { timeout: 10 })
-    page.click('.notification-clear')
-  } catch (error) {
-  }
-
-  let paste_key = IsMac ? 'Meta+v' : 'Control+v'
-  // create a page with identify block
-  let identify_text = "URL redirect target"
-  let page_title = await createRandomPage(page)
-  await block.mustFill(identify_text)
-
-  // paste current page's URL to another page, then redirect through the URL
-  await page.click('.ui__dropdown-trigger .toolbar-dots-btn')
-  await page.locator("text=Copy page URL").click()
-  await createRandomPage(page)
-  await block.mustFill("") // to enter editing mode
-  await page.keyboard.press(paste_key)
-  // paste returns a promise which is async, so we need give it a little bit
-  // more time
-  await page.waitForTimeout(100)
-  let cursor_locator = page.locator('textarea >> nth=0')
-  expect(await cursor_locator.inputValue()).toContain("page=" + page_title)
-  await cursor_locator.press("Enter")
-  if (IsMac) { // FIXME: support Logseq URL on Linux (XDG)
-    page.locator('a.external-link >> nth=0').click()
-    await page.waitForNavigation()
-    await page.waitForTimeout(500)
-    cursor_locator = await lastBlock(page)
-    expect(await cursor_locator.inputValue()).toBe(identify_text)
-  }
-
-  // paste the identify block's URL to another page, then redirect through the URL
-  await page.click('span.bullet >> nth=0', { button: "right" })
-  await page.locator("text=Copy block URL").click()
-  await createRandomPage(page)
-  await block.mustFill("") // to enter editing mode
-  await page.keyboard.press(paste_key)
-  await page.waitForTimeout(100)
-  cursor_locator = page.locator('textarea >> nth=0')
-  expect(await cursor_locator.inputValue()).toContain("block-id=")
-  await cursor_locator.press("Enter")
-  if (IsMac) { // FIXME: support Logseq URL on Linux (XDG)
-    page.locator('a.external-link >> nth=0').click()
-    await page.waitForNavigation()
-    await page.waitForTimeout(500)
-    cursor_locator = await lastBlock(page)
-    expect(await cursor_locator.inputValue()).toBe(identify_text)
-  }
-})

+ 0 - 103
e2e-tests/page-rename.spec.ts

@@ -1,103 +0,0 @@
-import { expect, Page } from '@playwright/test'
-import { test } from './fixtures'
-import { closeSearchBox, createPage, randomLowerString, randomString, renamePage, searchPage } from './utils'
-
-/***
- * Test rename feature
- ***/
-
-async function page_rename_test(page: Page, original_page_name: string, new_page_name: string) {
-  const rand = randomString(10)
-  let original_name = original_page_name + rand
-  let new_name = new_page_name + rand
-
-  await createPage(page, original_name)
-
-  // Rename page in UI
-  await renamePage(page, new_name)
-
-  expect(await page.innerText('.page-title .title')).toBe(new_name)
-
-  // TODO: Test if page is renamed in re-entrance
-
-  // TODO: Test if page is hierarchy
-}
-
-async function homepage_rename_test(page: Page, original_page_name: string, new_page_name: string) {
-
-  const rand = randomString(10)
-  let original_name = original_page_name + rand
-  let new_name = new_page_name + rand
-
-  await createPage(page, original_name)
-
-  // Toggle settings
-  await page.click('#main-content-container')
-  await page.keyboard.press('t')
-  await page.keyboard.press('s')
-
-  await page.click('a[data-id="features"]')
-  await page.click('#settings div:nth-child(1) a')
-
-  await page.type('input', original_name)
-  await page.click('[aria-label="Close"]')
-
-  expect(await page.locator('.home-nav span.flex-1').innerText()).toBe(original_name);
-
-  await renamePage(page, new_name)
-
-  expect(await page.locator('.home-nav span.flex-1').innerText()).toBe(new_name);
-
-  // Reenable journal
-  await page.click('#main-content-container')
-  await page.keyboard.press('t')
-  await page.keyboard.press('s')
-  await page.click('a[data-id="features"]')
-  await page.click('#settings div:nth-child(1) a')
-  await page.click('[aria-label="Close"]')
-
-}
-
-test('page rename test', async ({ page }) => {
-  // TODO: Fix commented out test. Started failing after https://github.com/logseq/logseq/pull/6945
-  // await homepage_rename_test(page, "abcd", "a/b/c/d")
-  await page_rename_test(page, "abcd", "a.b.c.d")
-  await page_rename_test(page, "abcd", "a/b/c/d")
-
-  // Disabled for now since it's unstable:
-  // The page name in page search are not updated after changing the capitalization of the page name #9577
-  // https://github.com/logseq/logseq/issues/9577
-  // Expect the page name to be updated in the search results
-  // await page_rename_test(page, "DcBA_", "dCBA_")
-  // const results = await searchPage(page, "DcBA_")
-  // // search result 0 is the new page & 1 is the new whiteboard
-  // const resultRow = await results[0].innerText()
-  // expect(resultRow).toContain("dCBA_");
-  // expect(resultRow).not.toContain("DcBA_");
-  await closeSearchBox(page)
-})
-
-// TODO introduce more samples when #4722 is fixed
-test('page title property test', async ({ page }) => {
-  // Edit Title Property and Double Enter (ETPDE)
-  // exit editing via insert new block
-  let rand = randomLowerString(10)
-  let original_name = "etpde old" + rand
-  let new_name = "etpde new" + rand
-  await createPage(page, original_name)
-  // add some spaces to test if it is trimmed
-  await page.type(':nth-match(textarea, 1)', 'title:: ' + new_name + "     ")
-  await page.press(':nth-match(textarea, 1)', 'Enter') // DWIM property mode creates new line
-  await page.press(':nth-match(textarea, 1)', 'Enter')
-  await expect(page.locator('.page-title .title')).toHaveText(new_name)
-
-  // Edit Title Property and Esc (ETPE)
-  // exit editing via moving out focus
-  rand = randomLowerString(10)
-  original_name = "etpe old " + rand
-  new_name = "etpe new " + rand
-  await createPage(page, original_name)
-  await page.type(':nth-match(textarea, 1)', 'title:: ' + new_name)
-  await page.press(':nth-match(textarea, 1)', 'Escape')
-  await expect(page.locator('.page-title .title')).toHaveText(new_name)
-})

+ 0 - 174
e2e-tests/page-search.spec.ts

@@ -1,174 +0,0 @@
-import { expect, Page } from '@playwright/test'
-import { test } from './fixtures'
-import { Block } from './types'
-import { modKey, createRandomPage, newInnerBlock, randomString, lastBlock, enterNextBlock } from './utils'
-import { searchPage, closeSearchBox } from './util/search-modal'
-
-/***
- * Test alias features
- * Test search referring features
- * Consider diacritics
- ***/
-
-let hotkeyOpenLink = modKey + '+o'
-let hotkeyBack = modKey + '+['
-
-test('Search page and blocks (diacritics)', async ({ page, block }) => {
-  const rand = randomString(20)
-
-  // diacritic opening test
-  await createRandomPage(page)
-
-  await block.mustType('[[Einführung in die Allgemeine Sprachwissenschaft' + rand + ']] diacritic-block-1', { delay: 10 })
-  await page.waitForTimeout(500)
-  await page.keyboard.press(hotkeyOpenLink, { delay: 10 })
-  await page.waitForTimeout(500)
-
-  const pageTitle = page.locator('.page-title').first()
-  expect(await pageTitle.innerText()).toEqual('Einführung in die Allgemeine Sprachwissenschaft' + rand)
-
-  await page.waitForTimeout(500)
-
-  // build target Page with diacritics
-  await block.activeEditing(0)
-  await block.mustType('Diacritic title test content', { delay: 10 })
-
-  await block.enterNext()
-  await block.mustType('[[Einführung in die Allgemeine Sprachwissenschaft' + rand + ']] diacritic-block-2', { delay: 10 })
-  await page.waitForTimeout(500)
-  await page.keyboard.press(hotkeyBack)
-
-  // check if diacritics are indexed
-  const results = await searchPage(page, 'Einführung in die Allgemeine Sprachwissenschaft' + rand)
-  // await expect(results.length).toEqual(5) //  2 block + 1 current page
-  await closeSearchBox(page)
-})
-
-test('Search CJK', async ({ page, block }) => {
-  const rand = randomString(20)
-
-  // diacritic opening test
-  await createRandomPage(page)
-
-  await block.mustType('[[今日daytime进度条' + rand + ']] diacritic-block-1', { delay: 10 })
-  await page.waitForTimeout(500)
-  await page.keyboard.press(hotkeyOpenLink, { delay: 10 })
-  await page.waitForTimeout(500)
-
-  const pageTitle = page.locator('.page-title').first()
-  expect(await pageTitle.innerText()).toEqual('今日daytime进度条' + rand)
-
-  await page.waitForTimeout(500)
-
-  // check if CJK are indexed
-  const results = await searchPage(page, '进度')
-  // await expect(results.length).toEqual(4) // 1 page + 1 block + new whiteboard
-  await closeSearchBox(page)
-})
-
-async function alias_test(block: Block, page: Page, page_name: string, search_kws: string[]) {
-  await createRandomPage(page)
-
-  const rand = randomString(10)
-  let target_name = page_name + ' target ' + rand
-  let alias_name = page_name + ' alias ' + rand
-  let alias_test_content_1 = randomString(20)
-  let alias_test_content_2 = randomString(20)
-  let alias_test_content_3 = randomString(20)
-
-  await page.type('textarea >> nth=0', '[[' + target_name)
-  await page.keyboard.press(hotkeyOpenLink)
-
-  await lastBlock(page)
-
-  // build target Page with alias
-  // the target page will contains the content in
-  //   alias_test_content_1,
-  //   alias_test_content_2, and
-  //   alias_test_content_3 sequentially, to validate the target page state
-  await page.type('textarea >> nth=0', 'alias:: [[' + alias_name, { delay: 10 })
-  await page.keyboard.press('Enter', { delay: 200 }) // Enter for finishing selection
-  await page.keyboard.press('Enter', { delay: 200 })
-  await page.keyboard.press('Escape')
-  await page.waitForTimeout(100)
-  await block.clickNext()
-  await block.activeEditing(1)
-  await page.type('textarea >> nth=0', alias_test_content_1)
-  await lastBlock(page)
-  page.keyboard.press(hotkeyBack)
-
-  await page.waitForNavigation()
-  await block.escapeEditing()
-  // create alias ref in origin Page
-  await block.activeEditing(0)
-  await block.enterNext()
-  await page.type('textarea >> nth=0', '[[' + alias_name, { delay: 20 })
-  await page.keyboard.press('Enter') // Enter for finishing selection
-  await page.waitForTimeout(100)
-
-  page.keyboard.press(hotkeyOpenLink)
-  await page.waitForNavigation()
-  await block.escapeEditing()
-
-  // shortcut opening test
-  await block.activeEditing(1)
-  expect(await page.inputValue('textarea >> nth=0')).toBe(alias_test_content_1)
-
-  await enterNextBlock(page)
-  await page.waitForTimeout(100)
-  await page.type('textarea >> nth=0', alias_test_content_2)
-  await page.waitForTimeout(100)
-  page.keyboard.press(hotkeyBack)
-
-  await page.waitForNavigation()
-  await block.escapeEditing()
-  // pressing enter on alias opening test
-  await block.activeEditing(1)
-  await page.press('textarea >> nth=0', 'ArrowLeft')
-  await page.press('textarea >> nth=0', 'ArrowLeft')
-  await page.press('textarea >> nth=0', 'ArrowLeft')
-  page.press('textarea >> nth=0', 'Enter')
-  await page.waitForNavigation()
-  await block.escapeEditing()
-  await block.activeEditing(2)
-  expect(await page.inputValue('textarea >> nth=0')).toBe(alias_test_content_2)
-  await newInnerBlock(page)
-  await page.waitForTimeout(100)
-  await page.type('textarea >> nth=0', alias_test_content_3)
-  await page.waitForTimeout(100)
-  page.keyboard.press(hotkeyBack)
-
-  await page.waitForNavigation()
-  await block.escapeEditing()
-  // clicking alias ref opening test
-  await block.activeEditing(1)
-  await block.enterNext()
-  await page.waitForSelector('.page-blocks-inner .ls-block .page-ref >> nth=-1')
-  await page.click('.page-blocks-inner .ls-block .page-ref >> nth=-1')
-  await lastBlock(page)
-  expect(await page.inputValue('textarea >> nth=0')).toBe(alias_test_content_3)
-
-  // TODO: test alias from graph clicking
-
-  // test alias from search
-  for (let kw of search_kws) {
-    let kw_name = kw + ' alias ' + rand
-
-    const results = await searchPage(page, kw_name)
-
-    // test search results
-    expect(await results[0].innerText()).toContain(alias_name.normalize('NFKC'))
-
-    // test search entering (page)
-    page.keyboard.press("Enter")
-    await page.waitForNavigation()
-    await page.waitForSelector('.ls-block span.inline')
-
-    // test search clicking (block)
-    await searchPage(page, kw_name)
-  }
-}
-
-test.skip('page diacritic alias', async ({ block, page }) => {
-  await alias_test(block, page, "ü", ["ü", "ü", "Ü"])
-})

+ 0 - 15
e2e-tests/paste.spec.ts

@@ -1,15 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { createRandomPage, enterNextBlock, lastBlock, modKey } from './utils'
-import { dispatch_kb_events } from './util/keyboard-events'
-import * as kb_events from './util/keyboard-events'
-
-test('property text deleted on Ctrl+C when its value mixes [[link]] and other text #9100', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await block.mustType('category:: [[A]] and [[B]] test')
-
-  await page.keyboard.press(modKey + '+c', { delay: 10 })
-
-  await expect(page.locator('textarea >> nth=0')).toHaveValue('category:: [[A]] and [[B]] test')
-})

+ 0 - 15
e2e-tests/plugin/index.html

@@ -1,15 +0,0 @@
-<!doctype html>
-<html lang="en">
-<head>
-    <meta charset="UTF-8">
-    <meta name="viewport"
-          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
-    <meta http-equiv="X-UA-Compatible" content="ie=edge">
-    <title>Document</title>
-    <script src="./lsplugin.user.js"></script>
-</head>
-<body>
-<div id="root"></div>
-<script src="./index.js"></script>
-</body>
-</html>

+ 0 - 61
e2e-tests/plugin/index.js

@@ -1,61 +0,0 @@
-async function main () {
-  logseq.UI.showMsg('Hi, e2e tests from a local plugin!')
-
-  // await (new Promise(resolve => setTimeout(resolve, 3000)))
-
-  let msg = 0
-
-  const logPane = (input) => {
-    logseq.provideUI({
-      key: `log-${++msg}`,
-      path: `#a-plugin-for-e2e-tests > ul`,
-      template: `<li>${input}</li>`,
-    })
-  }
-
-  // log pane
-  logseq.provideUI({
-    key: 'logseq-e2e-tests',
-    template: `<div id="a-plugin-for-e2e-tests">
-    <h2>Plugin e2e tests ...</h2>
-    <ul></ul>
-    </div>`,
-    path: 'body',
-    style: {
-      width: '300px',
-      position: 'fixed',
-      top: '300px',
-      left: '300px',
-      zIndex: 99,
-    },
-  })
-
-  logseq.provideStyle(`
-   #a-plugin-for-e2e-tests {
-     padding: 20px;
-     background-color: red;
-     color: white;
-     width: 300px;
-   }
-  `)
-
-  let dbChangedDid = false
-  let blockChangedDid = false
-
-  // hook db change
-  logseq.DB.onChanged((e) => {
-    if (dbChangedDid) return
-    logPane(`[DB] hook: changed`)
-    dbChangedDid = true
-  })
-
-  logseq.DB.onBlockChanged('65a0beee-7e01-4e72-8d38-089d923a63de',
-    (e) => {
-      if (blockChangedDid) return
-      logPane(`[DB] hook: block changed`)
-      blockChangedDid = true
-    })
-}
-
-// bootstrap
-logseq.ready(main).catch(null)

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 1
e2e-tests/plugin/lsplugin.user.js


+ 0 - 8
e2e-tests/plugin/package.json

@@ -1,8 +0,0 @@
-{
-  "name": "e2e-plugin",
-  "description": "A plugin for e2e tests",
-  "main": "./index.html",
-  "logseq": {
-    "id": "a-logseq-plugin-for-e2e-tests"
-  }
-}

+ 0 - 110
e2e-tests/plugins.spec.ts

@@ -1,110 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { callPageAPI } from './utils'
-
-/**
- * load local tests plugin
- */
-export async function loadLocalE2eTestsPlugin(page) {
-  const pid = 'a-logseq-plugin-for-e2e-tests'
-  const hasLoaded = await page.evaluate(async ([pid]) => {
-    // @ts-ignore
-    const p = window.LSPluginCore.registeredPlugins.get(pid)
-    // @ts-ignore
-    await window.LSPluginCore.enable(pid)
-    return p != null
-  }, [pid])
-
-  if (hasLoaded) return true
-
-  await callPageAPI(page, 'set_state_from_store',
-    'ui/developer-mode?', true)
-  await page.keyboard.press('t+p')
-  await page.locator('text=Load unpacked plugin')
-  await callPageAPI(page, 'set_state_from_store',
-    'plugin/selected-unpacked-pkg', `${__dirname}/plugin`)
-  await page.keyboard.press('Escape')
-  await page.keyboard.press('Escape')
-}
-
-test.skip('enabled plugin system default', async ({ page }) => {
-  const callAPI = callPageAPI.bind(null, page)
-
-  const pluginEnabled = await callAPI('get_state_from_store', 'plugin/enabled')
-  await expect(pluginEnabled).toBe(true)
-
-  expect(await page.evaluate(`typeof logseq.api.get_current_graph`))
-    .toBe('function')
-
-  const currentGraph = await callAPI('get_current_graph')
-  expect(Object.keys(currentGraph)).toEqual(['url', 'name', 'path'])
-})
-
-test.skip('play a plugin<logseq-journals-calendar> from the Marketplace', async ({ page }) => {
-  await page.keyboard.press('t+p')
-  const searchInput = page.locator('.search-ctls .form-input')
-  await searchInput.type('journals')
-
-  const pluginCards = page.locator('.cp__plugins-item-card')
-
-  if (await pluginCards.count()) {
-    await pluginCards.locator('.ctl .ls-icon-settings').hover()
-    await page.locator('text=Uninstall').click()
-
-    const confirmYes = page.locator('button').locator('text=Yes')
-    await confirmYes.click()
-  }
-
-  // install a plugin from Marketplace
-  await page.locator('button').locator('text=Marketplace').click()
-  await page.locator('text=Journals calendar')
-
-  await page.locator('.cp__plugins-item-card').first().locator('text=Install').click()
-  // wait for the plugin installed
-  await page.locator('.cp__plugins-item-card').first().locator('text=Installed')
-  await page.locator('a.ui__modal-close').click()
-
-  // toolbar plugins manager
-  const pluginFlag = page.locator('.toolbar-plugins-manager-trigger')
-
-  await expect(pluginFlag).toBeVisible()
-
-  await pluginFlag.click()
-
-  await expect(pluginFlag.locator('text=Plugins')).toBeVisible()
-  await expect(pluginFlag.locator('text=Settings')).toBeVisible()
-
-  await page.locator('text=goto-today').click()
-  await page.locator('body').click()
-
-  const goToToday = page.locator('#logseq-journals-calendar--goto-today').locator('a.button')
-  await expect(goToToday).toBeVisible()
-  await goToToday.click()
-
-  // TODO: debug
-  await expect(page.locator('body[data-page="page"]')).toBeVisible()
-})
-
-test(`play a plugin from local`, async ({ page }) => {
-  const callAPI = callPageAPI.bind(null, page)
-  const _pLoaded = await loadLocalE2eTestsPlugin(page)
-
-  const loc = page.locator('#a-plugin-for-e2e-tests')
-  await loc.waitFor({ state: 'visible' })
-
-  await callAPI(`push_state`, 'page', {name: 'contents'})
-
-  const b = await callAPI(`append_block_in_page`, 'Contents', 'target e2e block')
-
-  expect(typeof b?.uuid).toBe('string')
-  await expect(page.locator('text=[DB] hook: changed')).toBeVisible()
-
-  // 65a0beee-7e01-4e72-8d38-089d923a63de
-  await callAPI(`insert_block`, b.uuid,
-    'new custom uuid block', { customUUID: '65a0beee-7e01-4e72-8d38-089d923a63de' })
-
-  await expect(page.locator('text=[DB] hook: block changed')).toBeVisible()
-
-  // await page.waitForSelector('#test-pause')
-})
-

+ 0 - 180
e2e-tests/random.spec.ts

@@ -1,180 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import {
-  createRandomPage, randomInt, IsMac, randomString,
-} from './utils'
-
-/**
- * Randomized test for single page editing. Block-wise.
- *
- * For now, only check total number of blocks.
- */
-
-interface RandomTestStep {
-  /// target block
-  target: number;
-  /// action
-  op: string;
-  text: string;
-  /// expected total block number
-  expectedBlocks: number;
-}
-
-// TODO: add better frequency support
-const availableOps = [
-  "insertByEnter",
-  "insertAtLast",
-  // "backspace", // FIXME: cannot backspace to delete block if has children, and prev is a parent, so skip
-  // "delete", // FIXME: cannot delete to delete block if next is outdented
-  "edit",
-  "moveUp",
-  "moveDown",
-  "indent",
-  "unindent",
-  "indent",
-  "unindent",
-  "indent",
-  "indent",
-  // TODO: selection
-]
-
-
-const generateRandomTest = (size: number): RandomTestStep[] => {
-  let blockCount = 1; // default block
-  let steps: RandomTestStep[] = []
-  for (let i = 0; i < size; i++) {
-    let op = availableOps[Math.floor(Math.random() * availableOps.length)];
-    // freq adjust
-    if (Math.random() > 0.9) {
-      op = "insertByEnter"
-    }
-    let loc = Math.floor(Math.random() * blockCount)
-    let text = randomString(randomInt(2, 3))
-
-    if (op === "insertByEnter" || op === "insertAtLast") {
-      blockCount++
-    } else if (op === "backspace") {
-      if (blockCount == 1) {
-        continue
-      }
-      blockCount--
-      text = null
-    } else if (op === "delete") {
-      if (blockCount == 1) {
-        continue
-      }
-      // cannot delete last block
-      if (loc === blockCount - 1) {
-        continue
-      }
-      blockCount--
-      text = null
-    } else if (op === "moveUp" || op === "moveDown") {
-      // no op
-      text = null
-    } else if (op === "indent" || op === "unindent") {
-      // no op
-      text = null
-    } else if (op === "edit") {
-      // no ap
-    } else {
-      throw new Error("unexpected op");
-    }
-    if (blockCount < 1) {
-      blockCount = 1
-    }
-
-    let step: RandomTestStep = {
-      target: loc,
-      op,
-      text,
-      expectedBlocks: blockCount,
-    }
-    steps.push(step)
-  }
-
-  return steps
-}
-
-// TODO: Fix test that intermittently started failing after https://github.com/logseq/logseq/pull/6945
-test.skip('Random editor operations', async ({ page, block }) => {
-  const steps = generateRandomTest(20)
-
-  await createRandomPage(page)
-  await block.mustType("randomized test!")
-
-  for (let i = 0; i < steps.length; i++) {
-    let step = steps[i]
-    const { target, op, expectedBlocks, text } = step;
-
-    console.log(step)
-
-    if (op === "insertByEnter") {
-      await block.activeEditing(target)
-      let charCount = (await page.inputValue('textarea >> nth=0')).length
-      // FIXME: CHECK expect(await block.selectionStart()).toBe(charCount)
-
-      await page.keyboard.press('Enter', { delay: 50 })
-      // FIXME: CHECK await block.waitForBlocks(expectedBlocks)
-      // FIXME: use await block.mustType(text)
-      await block.mustFill(text)
-    } else if (op === "insertAtLast") {
-      await block.clickNext()
-      await block.mustType(text)
-    } else if (op === "backspace") {
-      await block.activeEditing(target)
-      const charCount = (await page.inputValue('textarea >> nth=0')).length
-      for (let i = 0; i < charCount + 1; i++) {
-        await page.keyboard.press('Backspace', { delay: 50 })
-      }
-    } else if (op === "delete") {
-      // move text-cursor to beginning
-      // then press delete
-      // then move text-cursor to the end
-      await block.activeEditing(target)
-      let charCount = (await page.inputValue('textarea >> nth=0')).length
-      for (let i = 0; i < charCount; i++) {
-        await page.keyboard.press('ArrowLeft', { delay: 50 })
-      }
-      expect.soft(await block.selectionStart()).toBe(0)
-      for (let i = 0; i < charCount + 1; i++) {
-        await page.keyboard.press('Delete', { delay: 50 })
-      }
-      await block.waitForBlocks(expectedBlocks)
-      charCount = (await page.inputValue('textarea >> nth=0')).length
-      for (let i = 0; i < charCount; i++) {
-        await page.keyboard.press('ArrowRight', { delay: 50 })
-      }
-    } else if (op === "edit") {
-      await block.activeEditing(target)
-      await block.mustFill('') // clear old text
-      await block.mustType(text)
-    } else if (op === "moveUp") {
-      await block.activeEditing(target)
-      if (IsMac) {
-        await page.keyboard.press('Meta+Shift+ArrowUp')
-      } else {
-        await page.keyboard.press('Alt+Shift+ArrowUp')
-      }
-
-    } else if (op === "moveDown") {
-      await block.activeEditing(target)
-      if (IsMac) {
-        await page.keyboard.press('Meta+Shift+ArrowDown')
-      } else {
-        await page.keyboard.press('Alt+Shift+ArrowDown')
-      }
-    } else if (op === "indent") {
-      await block.activeEditing(target)
-      await page.keyboard.press('Tab', { delay: 50 })
-    } else if (op === "unindent") {
-      await block.activeEditing(target)
-      await page.keyboard.press('Shift+Tab', { delay: 50 })
-    } else {
-      throw new Error("unexpected op");
-    }
-
-    // FIXME: CHECK await block.waitForBlocks(expectedBlocks)
-    await page.waitForTimeout(50)
-  }
-})

+ 0 - 48
e2e-tests/sanitization.spec.ts

@@ -1,48 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { createRandomPage } from './utils'
-
-test('custom html should not spawn any dialogs', async ({ page, block }) => {
-  page.on('dialog', async dialog => {
-    expect(false).toBeTruthy()
-    await dialog.dismiss()
-  })
-
-  await createRandomPage(page)
-
-  await page.keyboard.type('<iframe src="javascript:confirm(1);" />', { delay: 5 })
-  await block.enterNext()
-
-  await page.keyboard.type('<button id="test-xss-button" onclick="confirm(1)">Click me!</button>', { delay: 5 })
-  await block.enterNext()
-  await page.keyboard.type('<details open id="test-xss-toggle" ontoggle="confirm(1)">test</details>', { delay: 5 })
-  await block.enterNext()
-
-  await page.click('#test-xss-toggle')
-  await page.click('#test-xss-button')
-
-  expect(true).toBeTruthy()
-})
-
-test('custom hiccup should not spawn any dialogs', async ({ page, block }) => {
-  page.on('dialog', async dialog => {
-    expect(false).toBeTruthy()
-    await dialog.dismiss()
-  })
-
-  await createRandomPage(page)
-
-  await page.keyboard.type('[:iframe {:src "javascript:confirm(1);"}]', { delay: 5 })
-  await block.enterNext()
-
-  expect(true).toBeTruthy()
-})
-
-test('"is" attribute should be allowed for plugin purposes', async ({ page, block }) => {
-  await createRandomPage(page)
-
-  await page.keyboard.type('[:div {:is "custom-element" :id "custom-element-id"}]', { delay: 5 })
-  await block.enterNext()
-
-  await expect(page.locator('#custom-element-id')).toHaveAttribute('is', 'custom-element');
-})

+ 0 - 66
e2e-tests/sidebar.spec.ts

@@ -1,66 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { createPage, createRandomPage, openLeftSidebar, randomString, searchAndJumpToPage } from './utils'
-
-/***
- * Test side bar features
- ***/
-
-test('favorite item and recent item test', async ({ page }) => {
-  await openLeftSidebar(page)
-  // add page to fav
-  const fav_page_name = await createRandomPage(page)
-  let favs = await page.$$('.favorite-item a')
-  let previous_fav_count = favs.length
-  await page.click('.ui__dropdown-trigger .toolbar-dots-btn')
-  await page.locator("text=Add to Favorites").click()
-  // click from another page
-  const another_page_name = await createRandomPage(page)
-  expect(await page.innerText(':nth-match(.favorite-item a, 1)')).toBe(fav_page_name)
-  await page.waitForTimeout(500);
-  await page.click(":nth-match(.favorite-item, 1)")
-  await page.waitForTimeout(500);
-  expect(await page.innerText('.page-title .title')).toBe(fav_page_name)
-
-  expect(await page.innerText(':nth-match(.recent-item a, 1)')).toBe(fav_page_name)
-  expect(await page.innerText(':nth-match(.recent-item a, 2)')).toBe(another_page_name)
-
-  // remove fav
-  await page.click('.ui__dropdown-trigger .toolbar-dots-btn')
-  await page.locator("text=Unfavorite page").click()
-  await expect(page.locator('.favorite-item a')).toHaveCount(previous_fav_count)
-
-  // click from fav page
-  await page.click(':nth-match(.recent-item a, 2)')
-  await expect(page.locator('.page-title .title')).toHaveText(another_page_name)
-})
-
-
-test('recent is updated #4320', async ({ page }) => {
-  const page1 = await createRandomPage(page)
-  await page.fill('textarea >> nth=0', 'Random Thought')
-
-  const page2 = await createRandomPage(page)
-  await page.fill('textarea >> nth=0', 'Another Random Thought')
-
-  const firstRecent = page.locator('.nav-content-item.recent li >> nth=0')
-  expect(await firstRecent.textContent()).toContain(page2)
-
-  const secondRecent = page.locator('.nav-content-item.recent li >> nth=1')
-  expect(await secondRecent.textContent()).toContain(page1)
-
-  // then jump back
-  await searchAndJumpToPage(page, page1)
-  await page.waitForTimeout(500)
-  expect(await firstRecent.textContent()).toContain(page1)
-  expect(await secondRecent.textContent()).toContain(page2)
-})
-
-test('recent file name is displayed correctly #6297', async ({ page }) => {
-  const pageName = randomString(5) + "_@#$%^&*()_" + randomString(5)
-  await createPage(page, pageName)
-  await page.fill('textarea >> nth=0', 'Random Content')
-
-  const firstRecent = page.locator('.nav-content-item.recent li >> nth=0')
-  expect(await firstRecent.textContent()).toContain(pageName)
-})

+ 0 - 55
e2e-tests/types.ts

@@ -1,55 +0,0 @@
-import { BrowserContext, ElectronApplication, Locator, Page } from '@playwright/test';
-
-/**
- * Block provides helper functions for Logseq's block testing.
- */
-export interface Block {
-  /** Must fill some text into a block, use `textarea >> nth=0` as selector. */
-  mustFill(value: string): Promise<void>;
-  /**
-   * Must type input some text into an **empty** block.
-   * **DO NOT USE** this if there's auto-complete
-   */
-  mustType(value: string, options?: { delay?: number, toBe?: string }): Promise<void>;
-  /**
-   * Press Enter and go to next block, require cursor to be in current block(editing mode).
-   * When cursor is not at the end of block, trailing text will be moved to the next block.
-   */
-  enterNext(): Promise<Locator>;
-  /** Click `.add-button-link-wrap` and create the next block. */
-  clickNext(): Promise<Locator>;
-  /** Indent block, return whether it's success. */
-  indent(): Promise<boolean>;
-  /** Unindent block, return whether it's success. */
-  unindent(): Promise<boolean>;
-  /** Await for a certain number of blocks, with default timeout. */
-  waitForBlocks(total: number): Promise<void>;
-  /** Await for a certain number of selected blocks, with default timeout. */
-  waitForSelectedBlocks(total: number): Promise<void>;
-  /** Escape editing mode, modal popup and selection. */
-  escapeEditing(): Promise<void>;
-  /** Active block editing, by click */
-  activeEditing(nth: number): Promise<void>;
-  /** Is editing block now? */
-  isEditing(): Promise<boolean>;
-  /** Find current selectionStart, i.e. text cursor position. */
-  selectionStart(): Promise<number>;
-  /** Find current selectionEnd. */
-  selectionEnd(): Promise<number>;
-}
-
-export interface autocompleteMenu {
-  // Expect or wait for autocomplete menu to be or become visible
-  expectVisible(modalName?: string): Promise<void>
-  // Expect or wait for autocomplete menu to be or become hidden
-  expectHidden(modalName?: string): Promise<void>
-}
-
-export interface LogseqFixtures {
-  page: Page;
-  block: Block;
-  autocompleteMenu: autocompleteMenu;
-  context: BrowserContext;
-  app: ElectronApplication;
-  graphDir: string;
-}

+ 0 - 42
e2e-tests/util/basic.ts

@@ -1,42 +0,0 @@
-// This file is used to store basic functions that are used in other utils
-// Should have no dependency on other utils
-
-import * as process from 'process'
-
-export const IsMac = process.platform === 'darwin'
-export const IsLinux = process.platform === 'linux'
-export const IsWindows = process.platform === 'win32'
-export const IsCI = process.env.CI === 'true'
-export const modKey = IsMac ? 'Meta' : 'Control'
-
-export function randomString(length: number) {
-  const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
-
-  let result = '';
-  const charactersLength = characters.length;
-  for (let i = 0; i < length; i++) {
-    result += characters.charAt(Math.floor(Math.random() * charactersLength));
-  }
-
-  return result;
-}
-
-export function randomLowerString(length: number) {
-  const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
-
-  let result = '';
-  const charactersLength = characters.length;
-  for (let i = 0; i < length; i++) {
-    result += characters.charAt(Math.floor(Math.random() * charactersLength));
-  }
-
-  return result;
-}
-
-export function randomInt(min: number, max: number): number {
-  return Math.floor(Math.random() * (max - min + 1) + min)
-}
-  
-export function randomBoolean(): boolean {
-  return Math.random() < 0.5;
-}

+ 0 - 64
e2e-tests/util/keyboard-event-cap.html

@@ -1,64 +0,0 @@
-<!DOCTYPE html>
-<html>
-
-<head>
-  <script>
-    'use strict';
-
-    const keys = [
-      // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent
-      // without deprecated / non-standard
-      "altKey", "code", "ctrlKey", "isComposing", "key", "locale", "location", "metaKey",
-      "repeat", "shiftKey"
-    ]
-
-    let output_list = [];
-    let last_timestamp = Date.now();
-
-    function select_keys(obj, keys) {
-      let new_obj = {}
-      for (let k in event)
-        if (keys.indexOf(k) != -1)
-          new_obj[k] = event[k];
-      return new_obj
-    }
-
-    let key_handler_builder = (event_type) => (event) => {
-      if (event["target"].id != "input")
-        return;
-      let cur_timestamp = Date.now();
-      let output = {
-        "event_type": event_type,
-        "event": select_keys(event, keys),
-        "latency": cur_timestamp - last_timestamp // Time to wait before firing event
-      }
-      last_timestamp = cur_timestamp;
-      output_list.push(output);
-      let to_print = JSON.stringify(
-        output_list,
-        undefined,
-        2);
-      document.getElementById("outputs").innerText = to_print;
-    }
-
-    document.addEventListener('keydown', key_handler_builder('keydown'), false);
-    document.addEventListener('keyup', key_handler_builder('keyup'), false);
-    document.addEventListener('keypress', key_handler_builder('keypress'), false);
-    document.addEventListener('compositionstart', key_handler_builder('compositionstart'), false);
-    document.addEventListener('compositionend', key_handler_builder('compositionend'), false);
-    document.addEventListener('compositionupdate', key_handler_builder('compositionupdate'), false);
-
-    window.onload = (e) => {
-      document.getElementById("input").focus();
-    }
-
-  </script>
-</head>
-
-<body>
-  <input id="input" />
-  <h2>Key Down</h2>
-  <p id="outputs" style="white-space: pre;" />
-</body>
-
-</html>

+ 0 - 466
e2e-tests/util/keyboard-events.ts

@@ -1,466 +0,0 @@
-/***
- * Author: Junyi Du <[email protected]>
- * References:
- * https://stackoverflow.com/questions/8892238/detect-keyboard-layout-with-javascript
- * ***/
-
-import { Page } from '@playwright/test'
-
-interface RecordedEvent {
-  event_type: string;
-  event: any; // KeyboardEvent is too heavy
-  latency: number;
-}
-
-export let dispatch_kb_events = async function (page: Page, selector: string, keyboard_events: RecordedEvent[] ){
-  for (let kbev of keyboard_events){
-    let { event_type, event, latency } = kbev
-    await page.waitForTimeout(latency)
-    await page.dispatchEvent(selector, event_type, event)
-  }
-}
-
-export let macos_pinyin_left_full_square_bracket: RecordedEvent[] = [
-  {
-    "event_type": "keydown",
-    "event": {
-      "key": "【",
-      "code": "BracketLeft",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": false
-    },
-    "latency": 0
-  },
-  {
-    "event_type": "keypress",
-    "event": {
-      "key": "【",
-      "code": "BracketLeft",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": false
-    },
-    "latency": 1
-  },
-  {
-    "event_type": "keyup",
-    "event": {
-      "key": "【",
-      "code": "BracketLeft",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": false
-    },
-    "latency": 17
-  }
-]
-
-export let win10_pinyin_left_full_square_bracket: RecordedEvent[] = [
-  {
-    "event_type": "keydown",
-    "event": {
-      "key": "Process",
-      "code": "BracketLeft",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": false
-    },
-    "latency": 0
-  },
-  {
-    "event_type": "compositionstart",
-    "event": {},
-    "latency": 4
-  },
-  {
-    "event_type": "compositionupdate",
-    "event": {},
-    "latency": 0
-  },
-  {
-    "event_type": "compositionupdate",
-    "event": {},
-    "latency": 12
-  },
-  {
-    "event_type": "compositionend",
-    "event": {},
-    "latency": 1
-  },
-  {
-    "event_type": "keyup",
-    "event": {
-      "key": "Process",
-      "code": "BracketLeft",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": false
-    },
-    "latency": 61
-  },
-  {
-    "event_type": "keyup",
-    "event": {
-      "key": "[",
-      "code": "BracketLeft",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": false
-    },
-    "latency": 1
-  }
-]
-
-export let win10_legacy_pinyin_left_full_square_bracket: RecordedEvent[] = [
-  {
-    "event_type": "keydown",
-    "event": {
-      "key": "Process",
-      "code": "BracketLeft",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": false
-    },
-    "latency": 0
-  },
-  {
-    "event_type": "compositionstart",
-    "event": {},
-    "latency": 1
-  },
-  {
-    "event_type": "compositionupdate",
-    "event": {},
-    "latency": 0
-  },
-  {
-    "event_type": "compositionupdate",
-    "event": {},
-    "latency": 0
-  },
-  {
-    "event_type": "compositionend",
-    "event": {},
-    "latency": 1
-  },
-  {
-    "event_type": "keyup",
-    "event": {
-      "key": "Process",
-      "code": "BracketLeft",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": false
-    },
-    "latency": 93
-  }
-]
-
-export let macos_pinyin_selecting_candidate_double_left_square_bracket: RecordedEvent[] = [
-  {
-    "event_type": "keydown",
-    "event": {
-      "key": "b",
-      "code": "KeyB",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": false
-    },
-    "latency": 0
-  },
-  {
-    "event_type": "compositionstart",
-    "event": {},
-    "latency": 1
-  },
-  {
-    "event_type": "compositionupdate",
-    "event": {},
-    "latency": 0
-  },
-  {
-    "event_type": "keyup",
-    "event": {
-      "key": "b",
-      "code": "KeyB",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 48
-  },
-  {
-    "event_type": "keydown",
-    "event": {
-      "key": "】",
-      "code": "BracketRight",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 200
-  },
-  {
-    "event_type": "keyup",
-    "event": {
-      "key": "】",
-      "code": "BracketRight",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 59
-  },
-  {
-    "event_type": "keydown",
-    "event": {
-      "key": "】",
-      "code": "BracketRight",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 289
-  },
-  {
-    "event_type": "keyup",
-    "event": {
-      "key": "】",
-      "code": "BracketRight",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 73
-  },
-  {
-    "event_type": "keydown",
-    "event": {
-      "key": "【",
-      "code": "BracketLeft",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 443
-  },
-  {
-    "event_type": "keyup",
-    "event": {
-      "key": "【",
-      "code": "BracketLeft",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 79
-  },
-  {
-    "event_type": "keydown",
-    "event": {
-      "key": "【",
-      "code": "BracketLeft",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 155
-  },
-  {
-    "event_type": "keyup",
-    "event": {
-      "key": "【",
-      "code": "BracketLeft",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 44
-  },
-  {
-    "event_type": "compositionend",
-    "event": {},
-    "latency": 200
-  }
-]
-
-export let win10_RIME_selecting_candidate_double_left_square_bracket: RecordedEvent[] = [
-  {
-    "event_type": "keydown",
-    "event": {
-      "key": "Process",
-      "code": "BracketRight",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": false
-    },
-    "latency": 0
-  },
-  {
-    "event_type": "compositionstart",
-    "event": {},
-    "latency": 0
-  },
-  {
-    "event_type": "compositionupdate",
-    "event": {},
-    "latency": 0
-  },
-  {
-    "event_type": "keyup",
-    "event": {
-      "key": "Process",
-      "code": "BracketRight",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 79
-  },
-  {
-    "event_type": "keyup",
-    "event": {
-      "key": "]",
-      "code": "BracketRight",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 3
-  },
-  {
-    "event_type": "keydown",
-    "event": {
-      "key": "Process",
-      "code": "BracketRight",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 200
-  },
-  {
-    "event_type": "keyup",
-    "event": {
-      "key": "Process",
-      "code": "BracketRight",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 96
-  },
-  {
-    "event_type": "keyup",
-    "event": {
-      "key": "]",
-      "code": "BracketRight",
-      "location": 0,
-      "ctrlKey": false,
-      "shiftKey": false,
-      "altKey": false,
-      "metaKey": false,
-      "repeat": false,
-      "isComposing": true
-    },
-    "latency": 3
-  },
-  {
-    "event_type": "compositionend",
-    "event": {},
-    "latency": 200
-  }
-]

+ 0 - 14
e2e-tests/util/page.ts

@@ -1,14 +0,0 @@
-import { Page } from '@playwright/test'
-
-export async function activateNewPage(page: Page) {
-  await page.click('.ls-block >> nth=0')
-  await page.waitForTimeout(500)
-}
-
-export async function renamePage(page: Page, new_name: string) {
-  await page.click('.ls-page-title .page-title')
-  await page.waitForSelector('input[type="text"]')
-  await page.fill('input[type="text"]', '')
-  await page.type('.title input', new_name)
-  await page.keyboard.press('Enter')
-}

+ 0 - 64
e2e-tests/util/search-modal.ts

@@ -1,64 +0,0 @@
-import { Page, Locator, ElementHandle } from '@playwright/test'
-import { randomString } from './basic'
-
-export async function closeSearchBox(page: Page): Promise<void> {
-    await page.keyboard.press("Escape", { delay: 50 }) // escape (potential) search box typing
-    await page.waitForTimeout(500)
-    await page.keyboard.press("Escape", { delay: 50 }) // escape modal
-}
-
-export async function createRandomPage(page: Page) {
-    const randomTitle = randomString(20)
-    await closeSearchBox(page)
-    // Click #search-button
-    await page.click('#search-button')
-    // Fill [placeholder="What are you looking for?"]
-    await page.fill('[placeholder="What are you looking for?"]', randomTitle)
-    await page.keyboard.press('Enter', { delay: 50 })
-    // Wait for h1 to be from our new page
-    await page.waitForSelector(`h1 >> text="${randomTitle}"`, { state: 'visible' })
-    // wait for textarea of first block
-    await page.waitForSelector('textarea >> nth=0', { state: 'visible' })
-
-    return randomTitle;
-}
-
-export async function createPage(page: Page, page_name: string) {// Click #search-button
-    await closeSearchBox(page)
-    await page.click('#search-button')
-    // Fill [placeholder="What are you looking for?"]
-    await page.fill('[placeholder="What are you looking for?"]', page_name)
-    await page.locator('text="Create page"').waitFor({ state: 'visible' })
-    await page.keyboard.press('Enter', { delay: 100 })
-    // wait for textarea of first block
-    await page.waitForSelector('textarea >> nth=0', { state: 'visible' })
-
-    return page_name;
-}
-
-export async function searchAndJumpToPage(page: Page, pageTitle: string) {
-    await closeSearchBox(page)
-    await page.click('#search-button')
-    await page.type('[placeholder="What are you looking for?"]', pageTitle)
-    await page.waitForTimeout(200)
-    await page.keyboard.press('Enter', { delay: 50 })
-    return pageTitle;
-}
-
-/**
- * type a search query into the search box
- * stop at the point where search box shows up
- *
- * @param page the pw page object
- * @param query the search query to type into the search box
- * @returns the HTML element for the search results ui
- */
-export async function searchPage(page: Page, query: string): Promise<ElementHandle<SVGElement | HTMLElement>[]> {
-    await closeSearchBox(page)
-    await page.click('#search-button')
-    await page.waitForSelector('[placeholder="What are you looking for?"]')
-    await page.fill('[placeholder="What are you looking for?"]', query)
-    await page.waitForTimeout(2000) // wait longer for search contents to render
-
-    return page.$$('.search-results>div');
-}

+ 0 - 310
e2e-tests/utils.ts

@@ -1,310 +0,0 @@
-import { Page, Locator } from 'playwright'
-import { expect, ConsoleMessage } from '@playwright/test'
-import * as pathlib from 'path'
-import { modKey } from './util/basic'
-import { Block } from './types'
-
-// TODO: The file should be a facade of utils in the /util folder
-// No more additional functions should be added to this file
-// Move the functions to the corresponding files in the /util folder
-// Criteria: If the same selector is shared in multiple functions, they should be in the same file
-export * from './util/basic'
-export * from './util/search-modal'
-export * from './util/page'
-
-/**
-* Locate the last block in the inner editor
-* @param page The Playwright Page object.
-* @returns The locator of the last block.
-*/
-export async function lastBlock(page: Page): Promise<Locator> {
-  // discard any popups
-  await page.keyboard.press('Escape')
-  // click last block
-  if (await page.locator('text="Click here to edit..."').isVisible()) {
-    await page.click('text="Click here to edit..."')
-  } else {
-    await page.click('.page-blocks-inner .ls-block >> nth=-1')
-  }
-  // wait for textarea
-  await page.waitForSelector('textarea >> nth=0', { state: 'visible' })
-  await page.waitForTimeout(100)
-  return page.locator('textarea >> nth=0')
-}
-
-/**
- * Move the cursor to the beginning of the current editor
- * @param page The Playwright Page object.
- */
-export async function moveCursorToBeginning(page: Page): Promise<Locator> {
-  await page.press('textarea >> nth=0', modKey + '+a') // select all
-  await page.press('textarea >> nth=0', 'ArrowLeft')
-  return page.locator('textarea >> nth=0')
-}
-
-/**
- * Move the cursor to the end of the current editor
- * @param page The Playwright Page object.
- */
-export async function moveCursorToEnd(page: Page): Promise<Locator> {
-  await page.press('textarea >> nth=0', modKey + '+a') // select all
-  await page.press('textarea >> nth=0', 'ArrowRight')
-  return page.locator('textarea >> nth=0')
-}
-
-/**
- * Press Enter and create the next block.
- * @param page The Playwright Page object.
- */
-export async function enterNextBlock(page: Page): Promise<Locator> {
-  // Move cursor to the end of the editor
-  await page.press('textarea >> nth=0', modKey + '+a') // select all
-  await page.press('textarea >> nth=0', 'ArrowRight')
-  let blockCount = await page.locator('.page-blocks-inner .ls-block').count()
-  await page.press('textarea >> nth=0', 'Enter')
-  await page.waitForTimeout(10)
-  await page.waitForSelector(`.ls-block >> nth=${blockCount} >> textarea`, { state: 'visible' })
-  return page.locator('textarea >> nth=0')
-}
-
-/**
-* Create and locate a new block at the end of the inner editor
-* @param page The Playwright Page object
-* @returns The locator of the last block
-*/
-export async function newInnerBlock(page: Page): Promise<Locator> {
-  await lastBlock(page)
-  await page.press('textarea >> nth=0', 'Enter')
-
-  return page.locator('textarea >> nth=0')
-}
-
-export async function escapeToCodeEditor(page: Page): Promise<void> {
-  await page.press('.block-editor textarea', 'Escape')
-  await page.waitForSelector('.CodeMirror pre', { state: 'visible' })
-
-  await page.waitForTimeout(300)
-  await page.click('.CodeMirror pre')
-  await page.waitForTimeout(300)
-
-  await page.waitForSelector('.CodeMirror textarea', { state: 'visible' })
-}
-
-export async function escapeToBlockEditor(page: Page): Promise<void> {
-  await page.waitForTimeout(300)
-  await page.click('.CodeMirror pre')
-  await page.waitForTimeout(300)
-
-  await page.press('.CodeMirror textarea', 'Escape')
-  await page.waitForTimeout(300)
-}
-
-export async function setMockedOpenDirPath(
-  page: Page,
-  path?: string
-): Promise<void> {
-  // set next open directory
-  await page.evaluate(
-    ([path]) => {
-      Object.assign(window, {
-        __MOCKED_OPEN_DIR_PATH__: path,
-      })
-    },
-    [path]
-  )
-}
-
-export async function openLeftSidebar(page: Page): Promise<void> {
-  let sidebar = page.locator('#left-sidebar')
-
-  // Left sidebar is toggled by `is-open` class
-  if (!/is-open/.test(await sidebar.getAttribute('class') || '')) {
-    await page.click('#left-menu.button')
-    await page.waitForTimeout(10)
-    await expect(sidebar).toHaveClass(/is-open/)
-  }
-}
-
-export async function loadLocalGraph(page: Page, path: string): Promise<void> {
-  await setMockedOpenDirPath(page, path);
-
-  const sidebar = page.locator('#left-sidebar')
-
-  if (!/is-open/.test(await sidebar.getAttribute('class') || '')) {
-    await page.click('#left-menu.button')
-    await expect(sidebar).toHaveClass(/is-open/)
-  }
-
-  await page.click('#left-sidebar .cp__graphs-selector > a')
-  await page.waitForTimeout(300)
-  await page.waitForSelector('.cp__repos-quick-actions >> text="Add new graph"',
-    { state: 'attached', timeout: 5000 })
-  await page.click('text=Add new graph')
-
-  await setMockedOpenDirPath(page, ''); // reset it
-
-  await page.waitForSelector(':has-text("Parsing files")', {
-    state: 'hidden',
-    timeout: 1000 * 60 * 5,
-  })
-
-  const title = await page.title()
-  if (title === "Import data into Logseq" || title === "Add another repo") {
-    await page.click('a.button >> text=Skip')
-  }
-
-  await page.waitForFunction('window.document.title === "Logseq"')
-  await page.waitForTimeout(500)
-
-  // If there is an error notification from a previous test graph being deleted,
-  // close it first so it doesn't cover up the UI
-  let n = await page.locator('.notification-close-button').count()
-  if (n > 1) {
-    await page.locator('button >> text="Clear all"').click()
-  } else if (n == 1) {
-    await page.locator('.notification-close-button').click()
-  }
-  await expect(page.locator('.notification-close-button').first()).not.toBeVisible({ timeout: 2000 })
-
-  console.log('Graph loaded for ' + path)
-}
-
-export async function editNthBlock(page: Page, n) {
-  await page.click(`.ls-block .block-content >> nth=${n}`)
-}
-
-export async function editFirstBlock(page: Page) {
-  await editNthBlock(page, 0)
-}
-
-/**
- * Wait for a console message with a given prefix to appear, and return the full text of the message
- * Or reject after a timeout
- *
- * @param page
- * @param prefix - the prefix to look for
- * @param timeout - the timeout in ms
- * @returns the full text of the console message
- */
-export async function captureConsoleWithPrefix(page: Page, prefix: string, timeout: number = 3000): Promise<string> {
-  return new Promise((resolve, reject) => {
-    let console_handler = (msg: ConsoleMessage) => {
-      let text = msg.text()
-      if (text.startsWith(prefix)) {
-        page.removeListener('console', console_handler)
-        resolve(text.substring(prefix.length))
-      }
-    }
-    page.on('console', console_handler)
-    setTimeout(reject.bind("timeout"), timeout)
-  })
-}
-
-export async function queryPermission(page: Page, permission: PermissionName): Promise<boolean> {
-  // Check if WebAPI clipboard supported
-  return await page.evaluate(async (eval_permission: PermissionName): Promise<boolean> => {
-    if (typeof navigator.permissions == "undefined")
-      return Promise.resolve(false);
-    return navigator.permissions.query({
-      name: eval_permission
-    }).then((result: PermissionStatus): boolean => {
-      return (result.state == "granted" || result.state == "prompt")
-    })
-  }, permission)
-}
-
-export async function doesClipboardItemExists(page: Page): Promise<boolean> {
-  // Check if WebAPI clipboard supported
-  return await page.evaluate((): boolean => {
-    return typeof ClipboardItem !== "undefined"
-  })
-}
-
-export async function getIsWebAPIClipboardSupported(page: Page): Promise<boolean> {
-  // @ts-ignore "clipboard-write" is not included in TS's type definition for permissionName
-  return await queryPermission(page, "clipboard-write") && await doesClipboardItemExists(page)
-}
-
-export async function navigateToStartOfBlock(page: Page, block: Block) {
-  const selectionStart = await block.selectionStart()
-  for (let i = 0; i < selectionStart; i++) {
-    await page.keyboard.press('ArrowLeft')
-  }
-}
-
-/**
- * Repeats a key press a certain number of times.
- * @param {Page} page - The Page object.
- * @param {string} key - The key to press.
- * @param {number} times - The number of times to press the key.
- * @return {Promise<void>} - Promise which resolves when the key press repetition is done.
- */
-export async function repeatKeyPress(page: Page, key: string, times: number): Promise<void> {
-  for (let i = 0; i < times; i++) {
-    await page.keyboard.press(key);
-  }
-}
-
-/**
- * Moves the cursor a certain number of characters to the right (positive value) or left (negative value).
- * @param {Page} page - The Page object.
- * @param {number} shift - The number of characters to move the cursor. Positive moves to the right, negative to the left.
- * @return {Promise<void>} - Promise which resolves when the cursor has moved.
- */
-export async function moveCursor(page: Page, shift: number): Promise<void> {
-  const direction = shift < 0 ? 'ArrowLeft' : 'ArrowRight';
-  const absShift = Math.abs(shift);
-  await repeatKeyPress(page, direction, absShift);
-}
-
-/**
- * Selects a certain length of text in a textarea to the right of the cursor.
- * @param {Page} page - The Page object.
- * @param {number} length - The number of characters to select.
- * @return {Promise<void>} - Promise which resolves when the text selection is done.
- */
-export async function selectCharacters(page: Page, length: number): Promise<void> {
-  await page.keyboard.down('Shift');
-  await repeatKeyPress(page, 'ArrowRight', length);
-  await page.keyboard.up('Shift');
-}
-
-/**
- * Retrieves the selected text in a textarea.
- * @param {Page} page - The page object.
- * @return {Promise<string | null>} - Promise which resolves to the selected text or null.
- */
-export async function getSelection(page: Page): Promise<string | null> {
-  const selection = await page.evaluate(() => {
-    const textarea = document.querySelector('textarea')
-    return textarea?.value.substring(textarea.selectionStart, textarea.selectionEnd) || null
-  })
-
-  return selection
-}
-
-/**
- * Retrieves the current cursor position in a textarea.
- * @param {Page} page - The page object.
- * @return {Promise<number | null>} - Promise which resolves to the cursor position or null.
- */
-export async function getCursorPos(page: Page): Promise<number | null> {
-  const cursorPosition = await page.evaluate(() => {
-    const textarea = document.querySelector('textarea');
-    return textarea ? textarea.selectionStart : null;
-  });
-
-  return cursorPosition;
-}
-
-/**
- * @param page
- * @param method
- * @param args
- */
-export async function callPageAPI(page, method, ...args) {
-  return await page.evaluate(([method, args]) => {
-    // @ts-ignore
-    return window.logseq.api[method]?.(...args)
-  }, [method, args])
-}

+ 0 - 526
e2e-tests/whiteboards.spec.ts

@@ -1,526 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { modKey, renamePage } from './utils'
-
-test('enable whiteboards', async ({ page }) => {
-  if (await page.$('.nav-header .whiteboard') === null) {
-    await page.click('#head .toolbar-dots-btn')
-    await page.click('#head .dropdown-wrapper >> text=Settings')
-    await page.click('.settings-modal a[data-id=features]')
-    await page.click('text=Whiteboards >> .. >> .ui__toggle')
-    await page.waitForTimeout(1000)
-    await page.keyboard.press('Escape')
-  }
-
-  await expect(page.locator('.nav-header .whiteboard')).toBeVisible()
-})
-
-test('should display onboarding tour', async ({ page }) => {
-  // ensure onboarding tour is going to be triggered locally
-  await page.evaluate(`window.clearWhiteboardStorage()`)
-  await page.click('.nav-header .whiteboard')
-
-  await expect(page.locator('.cp__whiteboard-welcome')).toBeVisible()
-  await page.click('.cp__whiteboard-welcome button.skip-welcome')
-  await expect(page.locator('.cp__whiteboard-welcome')).toBeHidden()
-})
-
-test('create new whiteboard', async ({ page }) => {
-  await page.click('#tl-create-whiteboard')
-  await expect(page.locator('.logseq-tldraw')).toBeVisible()
-})
-
-test('can right click title to show context menu', async ({ page }) => {
-  await page.click('.whiteboard-page-title', {
-    button: 'right',
-  })
-
-  await expect(page.locator('#custom-context-menu')).toBeVisible()
-
-  await page.keyboard.press('Escape')
-
-  await expect(page.locator('#custom-context-menu')).toHaveCount(0)
-})
-
-test('newly created whiteboard should have a default title', async ({ page }) => {
-  await expect(page.locator('.whiteboard-page-title .title')).toContainText(
-    'Untitled'
-  )
-})
-
-test('set whiteboard title', async ({ page }) => {
-  const title = 'my-whiteboard'
-
-  await page.click('.nav-header .whiteboard')
-  await page.click('#tl-create-whiteboard')
-  await page.click('.whiteboard-page-title')
-  await page.fill('.whiteboard-page-title input', title)
-  await page.keyboard.press('Enter')
-  await expect(page.locator('.whiteboard-page-title .title')).toContainText(
-    title
-  )
-})
-
-test('update whiteboard title', async ({ page }) => {
-  const title = 'my-whiteboard'
-
-  await page.click('.whiteboard-page-title')
-  await page.fill('.whiteboard-page-title input', title + '-2')
-  await page.keyboard.press('Enter')
-
-  await expect(page.locator('.whiteboard-page-title .title')).toContainText(
-    title + '-2'
-  )
-})
-
-test('draw a rectangle', async ({ page }) => {
-  const canvas = await page.waitForSelector('.logseq-tldraw')
-  const bounds = (await canvas.boundingBox())!
-
-  await page.keyboard.type('wr')
-
-  await page.mouse.move(bounds.x + 105, bounds.y + 105)
-  await page.mouse.down()
-
-  await page.mouse.move(bounds.x + 150, bounds.y + 150 )
-  await page.mouse.up()
-  await page.keyboard.press('Escape')
-
-  await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(1)
-})
-
-test('undo the rectangle action', async ({ page }) => {
-  await page.keyboard.press(modKey + '+z', { delay: 100 })
-  await expect(page.locator('.logseq-tldraw .tl-positioned-svg rect')).toHaveCount(0)
-})
-
-test('redo the rectangle action', async ({ page }) => {
-  await page.waitForTimeout(100)
-  await page.keyboard.press(modKey + '+Shift+z', { delay: 100 })
-
-  await page.keyboard.press('Escape')
-
-  await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(1)
-})
-
-test('clone the rectangle', async ({ page }) => {
-  const canvas = await page.waitForSelector('.logseq-tldraw')
-  const bounds = (await canvas.boundingBox())!
-
-  await page.mouse.move(bounds.x + 400, bounds.y + 400)
-
-  await page.mouse.move(bounds.x + 120, bounds.y + 120, {steps: 5})
-
-  await page.keyboard.down('Alt')
-  await page.mouse.down()
-
-  await page.mouse.move(bounds.x + 200, bounds.y + 200, {steps: 5})
-  await page.mouse.up()
-  await page.keyboard.up('Alt')
-
-  await page.waitForTimeout(100)
-  await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
-})
-
-test('group the rectangles', async ({ page }) => {
-  await page.keyboard.press(modKey + '+a')
-  await page.keyboard.press(modKey + '+g')
-
-  await expect(page.locator('.logseq-tldraw .tl-group-container')).toHaveCount(1)
-})
-
-test('delete the group', async ({ page }) => {
-  await page.keyboard.press(modKey + '+a')
-
-  await page.keyboard.press('Delete')
-
-  await expect(page.locator('.logseq-tldraw .tl-group-container')).toHaveCount(0)
-    // should also delete the grouped shapes
-  await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(0)
-})
-
-test('undo the group deletion', async ({ page }) => {
-  await page.keyboard.press(modKey + '+z')
-
-  await expect(page.locator('.logseq-tldraw .tl-group-container')).toHaveCount(1)
-  await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
-})
-
-test('undo the group action', async ({ page }) => {
-  await page.keyboard.press(modKey + '+z')
-
-  await expect(page.locator('.logseq-tldraw .tl-group-container')).toHaveCount(0)
-  await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
-})
-
-test('connect rectangles with an arrow', async ({ page }) => {
-  const canvas = await page.waitForSelector('.logseq-tldraw')
-  const bounds = (await canvas.boundingBox())!
-
-  await page.keyboard.type('wc')
-
-  await page.mouse.move(bounds.x + 120, bounds.y + 120)
-  await page.mouse.down()
-
-  await page.mouse.move(bounds.x + 200, bounds.y + 200, {steps: 5}) // will fail without steps
-  await page.mouse.up()
-  await page.keyboard.press('Escape')
-
-  await expect(page.locator('.logseq-tldraw .tl-line-container')).toHaveCount(1)
-})
-
-test('delete the first rectangle', async ({ page }) => {
-  await page.keyboard.press('Escape', { delay: 100 })
-  await page.keyboard.press('Escape', { delay: 100 })
-
-  await page.click('.logseq-tldraw .tl-box-container:first-of-type')
-  await page.keyboard.press('Delete')
-
-  await page.waitForTimeout(200)
-  await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(1)
-  await expect(page.locator('.logseq-tldraw .tl-line-container')).toHaveCount(0)
-})
-
-test('undo the delete action', async ({ page }) => {
-  await page.keyboard.press(modKey + '+z')
-
-  await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
-  await expect(page.locator('.logseq-tldraw .tl-line-container')).toHaveCount(1)
-})
-
-test('convert the first rectangle to ellipse', async ({ page }) => {
-  const canvas = await page.waitForSelector('.logseq-tldraw')
-  const bounds = (await canvas.boundingBox())!
-
-  await page.keyboard.press('Escape')
-  await page.mouse.move(bounds.x + 220, bounds.y + 220)
-  await page.mouse.down()
-  await page.mouse.up()
-  await page.mouse.move(bounds.x + 520, bounds.y + 520)
-
-  await page.click('.tl-context-bar .tl-geometry-tools-pane-anchor')
-  await page.click('.tl-context-bar .tl-geometry-toolbar [data-tool=ellipse]')
-
-  await expect(page.locator('.logseq-tldraw .tl-ellipse-container')).toHaveCount(1)
-  await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(1)
-})
-
-test('change the color of the ellipse', async ({ page }) => {
-  await page.click('.tl-context-bar .tl-color-bg')
-  await page.click('.tl-context-bar .tl-color-palette .bg-red-500')
-
-  await expect(page.locator('.logseq-tldraw .tl-ellipse-container ellipse:last-of-type')).toHaveAttribute('fill', 'var(--ls-wb-background-color-red)')
-})
-
-test('undo the color switch', async ({ page }) => {
-  await page.keyboard.press(modKey + '+z')
-
-  await expect(page.locator('.logseq-tldraw .tl-ellipse-container ellipse:last-of-type')).toHaveAttribute('fill', 'var(--ls-wb-background-color-default)')
-})
-
-test('undo the shape conversion', async ({ page }) => {
-  await page.keyboard.press(modKey + '+z')
-
-  await page.waitForTimeout(100)
-
-  await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
-  await expect(page.locator('.logseq-tldraw .tl-ellipse-container')).toHaveCount(0)
-})
-
-test('locked elements should not be removed', async ({ page }) => {
-  const canvas = await page.waitForSelector('.logseq-tldraw')
-  const bounds = (await canvas.boundingBox())!
-
-  await page.keyboard.press('Escape')
-  await page.mouse.move(bounds.x + 220, bounds.y + 220)
-  await page.mouse.down()
-  await page.mouse.up()
-  await page.mouse.move(bounds.x + 520, bounds.y + 520)
-  await page.keyboard.press(`${modKey}+l`, { delay: 100 })
-  await page.keyboard.press('Delete', { delay: 100 })
-  await page.keyboard.press(`${modKey}+Shift+l`, { delay: 100 })
-
-  await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
-
-})
-
-test('move arrow to back', async ({ page }) => {
-  await page.keyboard.press('Escape')
-  await page.waitForTimeout(1000)
-  await page.click('.logseq-tldraw .tl-line-container')
-  await page.keyboard.press('Shift+[')
-
-  await expect(page.locator('.logseq-tldraw .tl-canvas .tl-layer > div:first-of-type > div:first-of-type')).toHaveClass('tl-line-container')
-})
-
-test('move arrow to front', async ({ page }) => {
-  await page.keyboard.press('Escape')
-  await page.waitForTimeout(1000)
-  await page.click('.logseq-tldraw .tl-line-container')
-  await page.keyboard.press('Shift+]')
-
-  await expect(page.locator('.logseq-tldraw .tl-canvas .tl-layer > div:first-of-type > div:first-of-type')).not.toHaveClass('tl-line-container')
-})
-
-test('undo the move action', async ({ page }) => {
-  await page.keyboard.press(modKey + '+z')
-
-  await page.waitForTimeout(100)
-
-  await expect(page.locator('.logseq-tldraw .tl-canvas .tl-layer > div:first-of-type > div:first-of-type')).toHaveClass('tl-line-container')
-})
-
-test('cleanup the shapes', async ({ page }) => {
-  await page.keyboard.press(`${modKey}+a`)
-  await page.keyboard.press('Delete')
-  await page.waitForTimeout(100)
-  await expect(page.locator('[data-type=Shape]')).toHaveCount(0)
-})
-
-test('create a block', async ({ page }) => {
-  const canvas = await page.waitForSelector('.logseq-tldraw')
-  const bounds = (await canvas.boundingBox())!
-
-  await page.keyboard.type('ws')
-  await page.mouse.dblclick(bounds.x + 105, bounds.y + 105)
-  await page.waitForTimeout(100)
-
-  await page.keyboard.type('a')
-  await page.keyboard.press('Enter')
-
-
-  await expect(page.locator('.logseq-tldraw .tl-logseq-portal-container')).toHaveCount(1)
-})
-
-// TODO: Fix the failing test
-test.skip('expand the block', async ({ page }) => {
-  await page.keyboard.press('Escape')
-  await page.keyboard.press(modKey + '+ArrowDown')
-  await page.waitForTimeout(100)
-
-  await expect(page.locator('.logseq-tldraw .tl-logseq-portal-container .tl-logseq-portal-header')).toHaveCount(1)
-})
-
-// TODO: Depends on the previous test
-test.skip('undo the expand action', async ({ page }) => {
-  await page.keyboard.press(modKey + '+z')
-
-  await expect(page.locator('.logseq-tldraw .tl-logseq-portal-container .tl-logseq-portal-header')).toHaveCount(0)
-})
-
-// TODO: Fix the failing test
-test.skip('undo the block action', async ({ page }) => {
-  await page.keyboard.press(modKey + '+z')
-
-  await expect(page.locator('.logseq-tldraw .tl-logseq-portal-container')).toHaveCount(0)
-})
-
-test('copy/paste url to create an iFrame shape', async ({ page }) => {
-  const canvas = await page.waitForSelector('.logseq-tldraw')
-  const bounds = (await canvas.boundingBox())!
-
-  await page.keyboard.type('wt')
-  await page.mouse.move(bounds.x + 105, bounds.y + 105)
-  await page.mouse.down()
-  await page.waitForTimeout(100)
-
-  await page.keyboard.type('https://logseq.com')
-  await page.keyboard.press(modKey + '+a')
-  await page.keyboard.press(modKey + '+c')
-  await page.keyboard.press('Escape')
-
-  await page.keyboard.press(modKey + '+v')
-
-  await expect( page.locator('.logseq-tldraw .tl-iframe-container')).toHaveCount(1)
-})
-
-test('copy/paste X status url to create a Post shape', async ({ page }) => {
-  const canvas = await page.waitForSelector('.logseq-tldraw')
-  const bounds = (await canvas.boundingBox())!
-
-  await page.keyboard.type('wt')
-  await page.mouse.move(bounds.x + 105, bounds.y + 105)
-  await page.mouse.down()
-  await page.waitForTimeout(100)
-
-  await page.keyboard.type('https://x.com/logseq/status/1605224589046386689')
-  await page.keyboard.press(modKey + '+a')
-  await page.keyboard.press(modKey + '+c')
-  await page.keyboard.press('Escape')
-
-  await page.keyboard.press(modKey + '+v')
-
-  await expect( page.locator('.logseq-tldraw .tl-tweet-container')).toHaveCount(1)
-})
-
-test('copy/paste twitter status url to create a Tweet shape', async ({ page }) => {
-  const canvas = await page.waitForSelector('.logseq-tldraw')
-  const bounds = (await canvas.boundingBox())!
-
-  await page.keyboard.type('wt')
-  await page.mouse.move(bounds.x + 105, bounds.y + 105)
-  await page.mouse.down()
-  await page.waitForTimeout(100)
-
-  await page.keyboard.type('https://twitter.com/logseq/status/1605224589046386689')
-  await page.keyboard.press(modKey + '+a')
-  await page.keyboard.press(modKey + '+c')
-  await page.keyboard.press('Escape')
-
-  await page.keyboard.press(modKey + '+v')
-
-  await expect( page.locator('.logseq-tldraw .tl-tweet-container')).toHaveCount(2)
-})
-
-test('copy/paste youtube video url to create a Youtube shape', async ({ page }) => {
-  const canvas = await page.waitForSelector('.logseq-tldraw')
-  const bounds = (await canvas.boundingBox())!
-
-  await page.keyboard.type('wt')
-  await page.mouse.move(bounds.x + 105, bounds.y + 105)
-  await page.mouse.down()
-  await page.waitForTimeout(100)
-
-  await page.keyboard.type('https://www.youtube.com/watch?v=hz2BacySDXE')
-  await page.keyboard.press(modKey + '+a')
-  await page.keyboard.press(modKey + '+c')
-  await page.keyboard.press('Escape')
-
-  await page.keyboard.press(modKey + '+v')
-
-  await expect(page.locator('.logseq-tldraw .tl-youtube-container')).toHaveCount(1)
-})
-
-test('zoom in', async ({ page }) => {
-  await page.keyboard.press('Shift+0') // reset zoom
-  await page.waitForTimeout(1500) // wait for the zoom animation to finish
-  await page.keyboard.press('Shift+=')
-  await page.waitForTimeout(1500) // wait for the zoom animation to finish
-  await expect(page.locator('#tl-zoom')).toContainText('125%')
-})
-
-test('zoom out', async ({ page }) => {
-  await page.keyboard.press('Shift+0')
-  await page.waitForTimeout(1500) // wait for the zoom animation to finish
-  await page.keyboard.press('Shift+-')
-  await page.waitForTimeout(1500) // wait for the zoom animation to finish
-  await expect(page.locator('#tl-zoom')).toContainText('80%')
-})
-
-test('open context menu', async ({ page }) => {
-  await page.locator('.logseq-tldraw').click({ button: 'right' })
-  await expect(page.locator('.tl-context-menu')).toBeVisible()
-})
-
-test('close context menu on esc', async ({ page }) => {
-  await page.keyboard.press('Escape')
-  await expect(page.locator('.tl-context-menu')).toBeHidden()
-})
-
-test('quick add another whiteboard', async ({ page }) => {
-  // create a new board first
-  await page.click('.nav-header .whiteboard')
-  await page.click('#tl-create-whiteboard')
-
-  await page.click('.whiteboard-page-title')
-  await page.fill('.whiteboard-page-title input', 'my-whiteboard-3')
-  await page.keyboard.press('Enter')
-
-  await page.waitForTimeout(300)
-
-  const canvas = await page.waitForSelector('.logseq-tldraw')
-  await canvas.dblclick({
-    position: {
-      x: 200,
-      y: 200,
-    },
-  })
-
-  const quickAdd$ = page.locator('.tl-quick-search')
-  await expect(quickAdd$).toBeVisible()
-
-  await page.fill('.tl-quick-search input', 'my-whiteboard')
-  await quickAdd$
-    .locator('.tl-quick-search-option >> text=my-whiteboard-2')
-    .first()
-    .click()
-
-  await expect(quickAdd$).toBeHidden()
-  await expect(
-    page.locator('.tl-logseq-portal-container >> text=my-whiteboard-2')
-  ).toBeVisible()
-})
-
-test('go to another board and check reference', async ({ page }) => {
-  await page
-    .locator('.tl-logseq-portal-container >> text=my-whiteboard-2')
-    .click()
-  await expect(page.locator('.whiteboard-page-title .title')).toContainText(
-    'my-whiteboard-2'
-  )
-
-  const pageRefCount$ = page.locator('.whiteboard-page-refs-count')
-  await expect(pageRefCount$.locator('.open-page-ref-link')).toContainText('1')
-})
-
-test('Create an embedded whiteboard', async ({ page }) => {
-  const canvas = await page.waitForSelector('.logseq-tldraw')
-  await canvas.dblclick({
-    position: {
-      x: 110,
-      y: 110,
-    },
-  })
-
-  const quickAdd$ = page.locator('.tl-quick-search')
-  await expect(quickAdd$).toBeVisible()
-
-  await page.fill('.tl-quick-search input', 'My embedded whiteboard')
-  await quickAdd$
-    .locator('div[data-index="2"] .tl-quick-search-option')
-    .first()
-    .click()
-
-  await expect(quickAdd$).toBeHidden()
-  await expect(page.locator('.tl-logseq-portal-header a')).toContainText('My embedded whiteboard')
-})
-
-test('New whiteboard should have the correct name', async ({ page }) => {
-  page.locator('.tl-logseq-portal-header a').click()
-
-  await expect(page.locator('.whiteboard-page-title')).toContainText('My embedded whiteboard')
-})
-
-test('Create an embedded page', async ({ page }) => {
-  const canvas = await page.waitForSelector('.logseq-tldraw')
-  await canvas.dblclick({
-    position: {
-      x: 150,
-      y: 150,
-    },
-  })
-
-  const quickAdd$ = page.locator('.tl-quick-search')
-  await expect(quickAdd$).toBeVisible()
-
-  await page.fill('.tl-quick-search input', 'My page')
-  await quickAdd$
-    .locator('div[data-index="1"] .tl-quick-search-option')
-    .first()
-    .click()
-
-  await expect(quickAdd$).toBeHidden()
-  await expect(page.locator('.tl-logseq-portal-header a')).toContainText('My page')
-})
-
-test('New page should have the correct name', async ({ page }) => {
-  page.locator('.tl-logseq-portal-header a').click()
-
-  await expect(page.locator('.ls-page-title')).toContainText('My page')
-})
-
-test('Renaming a page to an existing whiteboard name should be prohibited', async ({ page }) => {
-  await renamePage(page, "My embedded whiteboard")
-
-  await expect(page.locator('.page-title input')).toHaveValue('My page')
-})

+ 0 - 34
e2e-tests/window.spec.ts

@@ -1,34 +0,0 @@
-import { expect } from '@playwright/test'
-import { test } from './fixtures'
-import { IsMac } from './utils';
-
-if (!IsMac) {
-    test('window should not be maximized on first launch', async ({ page, app }) => {
-        await expect(page.locator('.window-controls .maximize-toggle.maximize')).toHaveCount(1)
-    })
-
-    test('window should be maximized and icon should change on maximize-toggle click', async ({ page }) => {
-        await page.click('.window-controls .maximize-toggle.maximize')
-
-        await expect(page.locator('.window-controls .maximize-toggle.restore')).toHaveCount(1)
-    })
-
-    test('window should be restored and icon should change on maximize-toggle click', async ({ page }) => {
-        await page.click('.window-controls .maximize-toggle.restore')
-
-        await expect(page.locator('.window-controls .maximize-toggle.maximize')).toHaveCount(1)
-    })
-
-    test('window controls should be hidden on fullscreen mode', async ({ page }) => {
-        // Keyboard press F11 won't work, probably because it's a chromium shortcut (not a document event)
-        await page.evaluate(`window.document.body.requestFullscreen()`)
-
-        await expect(page.locator('.window-controls .maximize-toggle')).toHaveCount(0)
-    })
-
-    test('window controls should be visible when we exit fullscreen mode', async ({ page }) => {
-        await page.click('.window-controls .fullscreen-toggle')
-
-        await expect(page.locator('.window-controls')).toHaveCount(1)
-    })
-}

+ 0 - 28
playwright.config.ts

@@ -1,28 +0,0 @@
-import { PlaywrightTestConfig } from '@playwright/test'
-
-const config: PlaywrightTestConfig = {
-  // The directory where the tests are located
-  // The order of the tests is determined by the file names alphabetically.
-  testDir: './e2e-tests',
-
-  // The number of retries before marking a test as failed.
-  maxFailures: 1,
-
-  // The number of Logseq instances to run in parallel.
-  // NOTE: must be 1 for now, otherwise tests will fail.
-  workers: 1,
-
-  // 'github' for GitHub Actions CI to generate annotations, plus a concise 'dot'.
-  // default 'list' when running locally.
-  reporter: process.env.CI ? 'github' : 'list',
-
-  // Fail the build on CI if test.only is present.
-  forbidOnly: !!process.env.CI,
-
-  use: {
-    // SCapture screenshot after each test failure.
-    screenshot: 'only-on-failure',
-  },
-}
-
-export default config

+ 5 - 5
src/main/capacitor/components/app.cljs

@@ -1,8 +1,10 @@
 (ns capacitor.components.app
   (:require ["../externals.js"]
+            [capacitor.components.editor-toolbar :as editor-toolbar]
             [capacitor.components.modal :as modal]
             [capacitor.components.popup :as popup]
             [capacitor.components.search :as search]
+            [capacitor.components.selection-toolbar :as selection-toolbar]
             [capacitor.components.settings :as settings]
             [capacitor.components.ui :as ui-component]
             [capacitor.ionic :as ion]
@@ -17,8 +19,6 @@
             [frontend.handler.page :as page-handler]
             [frontend.handler.repo :as repo-handler]
             [frontend.handler.user :as user-handler]
-            [frontend.mobile.action-bar :as action-bar]
-            [frontend.mobile.mobile-bar :as mobile-bar]
             [frontend.mobile.util :as mobile-util]
             [frontend.rum :as frum]
             [frontend.state :as fstate]
@@ -202,7 +202,7 @@
      {:id "app-ion-tabs"
       :onIonTabsDidChange (fn [^js e]
                             (state/set-tab! (.-tab (.-detail e))
-                              (.-target e)))}
+                                            (.-target e)))}
      (ion/tab
       {:tab "home"}
       (ion/content
@@ -237,6 +237,6 @@
      (tabs current-repo)
      (when-not open?
        [:<>
-        (mobile-bar/mobile-bar)
+        (editor-toolbar/mobile-bar)
         (when show-action-bar?
-          (action-bar/action-bar))]))))
+          (selection-toolbar/action-bar))]))))

+ 3 - 3
src/main/frontend/mobile/mobile_bar.cljs → src/main/capacitor/components/editor_toolbar.cljs

@@ -1,11 +1,11 @@
-(ns frontend.mobile.mobile-bar
+(ns capacitor.components.editor-toolbar
   (:require [dommy.core :as dom]
             [frontend.commands :as commands]
             [frontend.date :as date]
             [frontend.handler.editor :as editor-handler]
             [frontend.handler.page :as page-handler]
             [frontend.mobile.camera :as mobile-camera]
-            [frontend.mobile.core :as mobile]
+            [capacitor.init :as init]
             [frontend.mobile.haptics :as haptics]
             [frontend.state :as state]
             [frontend.ui :as ui]
@@ -125,4 +125,4 @@
        [:div.toolbar-hide-keyboard
         (command #(do
                     (state/clear-edit!)
-                    (mobile/keyboard-hide)) {:icon "keyboard-show"})]])))
+                    (init/keyboard-hide)) {:icon "keyboard-show"})]])))

+ 5 - 5
src/main/capacitor/components/modal.cljs

@@ -1,15 +1,15 @@
 (ns capacitor.components.modal
   (:require ["../externals.js"]
+            [capacitor.components.editor-toolbar :as mobile-bar]
+            [capacitor.components.selection-toolbar :as selection-toolbar]
             [capacitor.components.ui :as ui]
+            [capacitor.init :as init]
             [capacitor.ionic :as ion]
             [capacitor.state :as state]
             [frontend.components.page :as page]
             [frontend.db :as db]
             [frontend.handler.notification :as notification]
             [frontend.handler.page :as page-handler]
-            [frontend.mobile.action-bar :as action-bar]
-            [frontend.mobile.core :as mobile]
-            [frontend.mobile.mobile-bar :as mobile-bar]
             [frontend.state :as fstate]
             [frontend.ui :as frontend-ui]
             [rum.core :as rum]))
@@ -21,7 +21,7 @@
         close! #(swap! state/*modal-data assoc :open? false)]
     (when open?
       (fstate/clear-edit!)
-      (mobile/keyboard-hide))
+      (init/keyboard-hide))
     (ion/modal
      {:isOpen (boolean open?)
       :presenting-element presenting-element
@@ -77,4 +77,4 @@
                     (page/page-cp (db/entity [:block/uuid (:block/uuid block)])))
                    (mobile-bar/mobile-bar)
                    (when show-action-bar?
-                     (action-bar/action-bar)))))))
+                     (selection-toolbar/action-bar)))))))

+ 2 - 2
src/main/frontend/mobile/action_bar.cljs → src/main/capacitor/components/selection_toolbar.cljs

@@ -1,5 +1,5 @@
-(ns frontend.mobile.action-bar
-  "Block Action bar, activated when swipe on a block"
+(ns capacitor.components.selection-toolbar
+  "Selection action bar, activated when swipe on a block"
   (:require [frontend.db :as db]
             [frontend.handler.editor :as editor-handler]
             [frontend.state :as state]

+ 2 - 2
src/main/capacitor/core.cljs

@@ -1,13 +1,13 @@
 (ns capacitor.core
   (:require ["react-dom/client" :as rdc]
             [capacitor.components.app :as app]
+            [capacitor.init :as init]
             [capacitor.state :as state]
             [frontend.background-tasks]
             [frontend.components.page :as page]
             [frontend.handler :as fhandler]
             [frontend.handler.db-based.rtc-background-tasks]
             [frontend.handler.route :as route-handler]
-            [frontend.mobile.core :as mobile]
             [frontend.util :as util]
             [reitit.frontend :as rf]
             [reitit.frontend.easy :as rfe]))
@@ -51,7 +51,7 @@
   ;; so it is available even in :advanced release builds
   (prn "[capacitor-new] init!")
   (set-router!)
-  (mobile/init!)
+  (init/init!)
   (fhandler/start! render!))
 
 (defn ^:export stop! []

+ 9 - 0
src/main/capacitor/events.cljs

@@ -0,0 +1,9 @@
+(ns capacitor.events
+  (:require [capacitor.init :as init]
+            [frontend.handler.events :as events]
+            [promesa.core :as p]))
+
+(defmethod events/handle :mobile/post-init [_]
+  (p/do!
+   (p/delay 1000)
+   (init/mobile-post-init)))

+ 3 - 2
src/main/frontend/mobile/core.cljs → src/main/capacitor/init.cljs

@@ -1,4 +1,4 @@
-(ns frontend.mobile.core
+(ns capacitor.init
   "Main ns for handling mobile start"
   (:require ["@capacitor/app" :refer [^js App]]
             ["@capacitor/keyboard" :refer [^js Keyboard]]
@@ -20,7 +20,7 @@
 (def *last-shared-url (atom nil))
 (def *last-shared-seconds (atom 0))
 
-(defn mobile-postinit
+(defn mobile-post-init
   "postinit logic of mobile platforms: handle deeplink and intent"
   []
   (when (mobile-util/native-ios?)
@@ -44,6 +44,7 @@
                 (and (js/document.querySelector ".pswp"))
                 (some-> js/window.photoLightbox (.destroy))
 
+                ;; TODO: move ui-related code to mobile events
                 (not-empty (cc-ui/get-modal))
                 (cc-ui/close-modal!)
 

+ 1 - 5
src/main/frontend/components/container.cljs

@@ -33,7 +33,6 @@
             [frontend.handler.user :as user-handler]
             [frontend.handler.whiteboard :as whiteboard-handler]
             [frontend.mixins :as mixins]
-            [frontend.mobile.action-bar :as action-bar]
             [frontend.mobile.footer :as footer]
             [frontend.mobile.util :as mobile-util]
             [frontend.modules.shortcut.data-helper :as shortcut-dh]
@@ -611,7 +610,7 @@
                    (when-let [el (gdom/getElement "main-content-container")]
                      (dnd/unsubscribe! el :upload-files))
                    state)}
-  [{:keys [route-match margin-less-pages? route-name indexeddb-support? db-restoring? main-content show-action-bar? show-recording-bar?]}]
+  [{:keys [route-match margin-less-pages? route-name indexeddb-support? db-restoring? main-content show-recording-bar?]}]
   (let [left-sidebar-open? (state/sub :ui/left-sidebar-open?)
         onboarding-and-home? (and (or (nil? (state/get-current-repo)) (config/demo-graph?))
                                   (not config/publishing?)
@@ -629,9 +628,6 @@
       {:tabIndex "-1"
        :data-is-margin-less-pages margin-less-pages?}
 
-      (when show-action-bar?
-        (action-bar/action-bar))
-
       [:div.cp__sidebar-main-content
        {:data-is-margin-less-pages margin-less-pages?
         :data-is-full-width (or margin-less-pages?

+ 2 - 4
src/main/frontend/handler/events.cljs

@@ -38,7 +38,6 @@
             [frontend.handler.search :as search-handler]
             [frontend.handler.shell :as shell-handler]
             [frontend.handler.ui :as ui-handler]
-            [frontend.mobile.core :as mobile]
             [frontend.mobile.util :as mobile-util]
             [frontend.modules.instrumentation.posthog :as posthog]
             [frontend.modules.outliner.pipeline :as pipeline]
@@ -185,9 +184,8 @@
     (p/do!
      (state/pub-event! [:graph/sync-context])
     ;; re-render-root is async and delegated to rum, so we need to wait for main ui to refresh
-     (when (mobile-util/native-ios?)
-       (js/setTimeout #(mobile/mobile-postinit) 1000))
-    ;; FIXME: an ugly implementation for redirecting to page on new window is restored
+     (state/pub-event! [:mobile/post-init])
+     ;; FIXME: an ugly implementation for redirecting to page on new window is restored
      (repo-handler/graph-ready! repo)
      (if db-based?
        (export/auto-db-backup! repo {:backup-now? true})

+ 0 - 4999
static/yarn.lock

@@ -1,4999 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-"7zip-bin@~5.2.0":
-  version "5.2.0"
-  resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.2.0.tgz#7a03314684dd6572b7dfa89e68ce31d60286854d"
-  integrity sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==
-
-"@bitdisaster/exe-icon-extractor@^1.0.10":
-  version "1.0.10"
-  resolved "https://registry.yarnpkg.com/@bitdisaster/exe-icon-extractor/-/exe-icon-extractor-1.0.10.tgz#3f5107864254c351db1db5c5922452d9d4154e8f"
-  integrity sha512-iTZ8cVGZ5dglNRyFdSj8U60mHIrC8XNIuOHN/NkM5/dQP4nsmpyqeQTAADLLQgoFCNJD+DiwQCv8dR2cCeWP4g==
-
-"@develar/schema-utils@~2.6.5":
-  version "2.6.5"
-  resolved "https://registry.yarnpkg.com/@develar/schema-utils/-/schema-utils-2.6.5.tgz#3ece22c5838402419a6e0425f85742b961d9b6c6"
-  integrity sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==
-  dependencies:
-    ajv "^6.12.0"
-    ajv-keywords "^3.4.1"
-
-"@electron-forge/cli@^7.8.0":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/cli/-/cli-7.8.1.tgz#9ba3e19b58d1ce7bb4ab566ba36d23af2d00ffbd"
-  integrity sha512-QI3EShutfq9Y+2TWWrPjm4JZM3eSAKzoQvRZdVhAfVpUbyJ8K23VqJShg3kGKlPf9BXHAGvE+8LyH5s2yDr1qA==
-  dependencies:
-    "@electron-forge/core" "7.8.1"
-    "@electron-forge/core-utils" "7.8.1"
-    "@electron-forge/shared-types" "7.8.1"
-    "@electron/get" "^3.0.0"
-    chalk "^4.0.0"
-    commander "^11.1.0"
-    debug "^4.3.1"
-    fs-extra "^10.0.0"
-    listr2 "^7.0.2"
-    log-symbols "^4.0.0"
-    semver "^7.2.1"
-
-"@electron-forge/[email protected]":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/core-utils/-/core-utils-7.8.1.tgz#9c94e31e146258bbb9eeb07f7b084fde5892e83d"
-  integrity sha512-mRoPLDNZgmjyOURE/K0D3Op53XGFmFRgfIvFC7c9S/BqsRpovVblrqI4XxPRdNmH9dvhd8On9gGz+XIYAKD3aQ==
-  dependencies:
-    "@electron-forge/shared-types" "7.8.1"
-    "@electron/rebuild" "^3.7.0"
-    "@malept/cross-spawn-promise" "^2.0.0"
-    chalk "^4.0.0"
-    debug "^4.3.1"
-    find-up "^5.0.0"
-    fs-extra "^10.0.0"
-    log-symbols "^4.0.0"
-    semver "^7.2.1"
-
-"@electron-forge/[email protected]":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/core/-/core-7.8.1.tgz#55eb23b60a9ce873aedcdc0e41fcd4870a67ad7a"
-  integrity sha512-jkh0QPW5p0zmruu1E8+2XNufc4UMxy13WLJcm7hn9jbaXKLkMbKuEvhrN1tH/9uGp1mhr/t8sC4N67gP+gS87w==
-  dependencies:
-    "@electron-forge/core-utils" "7.8.1"
-    "@electron-forge/maker-base" "7.8.1"
-    "@electron-forge/plugin-base" "7.8.1"
-    "@electron-forge/publisher-base" "7.8.1"
-    "@electron-forge/shared-types" "7.8.1"
-    "@electron-forge/template-base" "7.8.1"
-    "@electron-forge/template-vite" "7.8.1"
-    "@electron-forge/template-vite-typescript" "7.8.1"
-    "@electron-forge/template-webpack" "7.8.1"
-    "@electron-forge/template-webpack-typescript" "7.8.1"
-    "@electron-forge/tracer" "7.8.1"
-    "@electron/get" "^3.0.0"
-    "@electron/packager" "^18.3.5"
-    "@electron/rebuild" "^3.7.0"
-    "@malept/cross-spawn-promise" "^2.0.0"
-    chalk "^4.0.0"
-    debug "^4.3.1"
-    fast-glob "^3.2.7"
-    filenamify "^4.1.0"
-    find-up "^5.0.0"
-    fs-extra "^10.0.0"
-    global-dirs "^3.0.0"
-    got "^11.8.5"
-    interpret "^3.1.1"
-    jiti "^2.4.2"
-    listr2 "^7.0.2"
-    lodash "^4.17.20"
-    log-symbols "^4.0.0"
-    node-fetch "^2.6.7"
-    rechoir "^0.8.0"
-    semver "^7.2.1"
-    source-map-support "^0.5.13"
-    sudo-prompt "^9.1.1"
-    username "^5.1.0"
-
-"@electron-forge/[email protected]":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/maker-base/-/maker-base-7.8.1.tgz#92d953b52e1173323c9498b8c8de1568328a5012"
-  integrity sha512-GUZqschGuEBzSzE0bMeDip65IDds48DZXzldlRwQ+85SYVA6RMU2AwDDqx3YiYsvP2OuxKruuqIJZtOF5ps4FQ==
-  dependencies:
-    "@electron-forge/shared-types" "7.8.1"
-    fs-extra "^10.0.0"
-    which "^2.0.2"
-
-"@electron-forge/maker-base@^7.3.1":
-  version "7.8.0"
-  resolved "https://registry.yarnpkg.com/@electron-forge/maker-base/-/maker-base-7.8.0.tgz#4790a4cd477bd5952aba783e9ff433d15a56217c"
-  integrity sha512-yGRvz70w+NnKO7PhzNFRgYM+x6kxYFgpbChJIQBs3WChd9bGjL+MZLrwYqmxOFLpWNwRAJ6PEi4E/8U5GgV6AQ==
-  dependencies:
-    "@electron-forge/shared-types" "7.8.0"
-    fs-extra "^10.0.0"
-    which "^2.0.2"
-
-"@electron-forge/maker-deb@^7.8.0":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/maker-deb/-/maker-deb-7.8.1.tgz#814edb21b8d59a4248c1f1727662874e6142c95d"
-  integrity sha512-tjjeesQtCP5Xht1X7gl4+K9bwoETPmQfBkOVAY/FZIxPj40uQh/hOUtLX2tYENNGNVZ1ryDYRs8TuPi+I41Vfw==
-  dependencies:
-    "@electron-forge/maker-base" "7.8.1"
-    "@electron-forge/shared-types" "7.8.1"
-  optionalDependencies:
-    electron-installer-debian "^3.2.0"
-
-"@electron-forge/maker-dmg@^7.8.0":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/maker-dmg/-/maker-dmg-7.8.1.tgz#c8a90fecbc38d78c8f91c28438f07dea6bf04053"
-  integrity sha512-l449QvY2Teu+J9rHnjkTHEm/wOJ1LRfmrQ2QkGtFoTRcqvFWdUAEN8nK2/08w3j2h6tvOY3QSUjRzXrhJZRNRA==
-  dependencies:
-    "@electron-forge/maker-base" "7.8.1"
-    "@electron-forge/shared-types" "7.8.1"
-    fs-extra "^10.0.0"
-  optionalDependencies:
-    electron-installer-dmg "^5.0.1"
-
-"@electron-forge/maker-rpm@^7.8.0":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/maker-rpm/-/maker-rpm-7.8.1.tgz#ff68a31dfb556585460a21d7253c104989869d6d"
-  integrity sha512-TF6wylft3BHkw9zdHcxmjEPBZYgTIc0jE31skFnMEQ/aExbNRiNaCZvsXy+7ptTWZxhxUKRc9KHhLFRMCmOK8g==
-  dependencies:
-    "@electron-forge/maker-base" "7.8.1"
-    "@electron-forge/shared-types" "7.8.1"
-  optionalDependencies:
-    electron-installer-redhat "^3.2.0"
-
-"@electron-forge/maker-squirrel@^7.8.0":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/maker-squirrel/-/maker-squirrel-7.8.1.tgz#38a02fb8f9886cc22f7b0c760547cbab5cc0304c"
-  integrity sha512-qT1PMvT7ALF0ONOkxlA0oc0PiFuKCAKgoMPoxYo9gGOqFvnAb+TBcnLxflQ4ashE/ZkrHpykr4LcDJxqythQTA==
-  dependencies:
-    "@electron-forge/maker-base" "7.8.1"
-    "@electron-forge/shared-types" "7.8.1"
-    fs-extra "^10.0.0"
-  optionalDependencies:
-    electron-winstaller "^5.3.0"
-
-"@electron-forge/maker-wix@^7.8.0":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/maker-wix/-/maker-wix-7.8.1.tgz#a558c798849171590d45ac7e0d25d7b904ef09f1"
-  integrity sha512-Gb7JYx7QZQIqiG5rqYjQ3BqQKOtQdKZ79i9QuezOznxFRaRv0EAOiqkQc+wyG6Int6aeob7xS1uY1iP7/4p/Iw==
-  dependencies:
-    "@electron-forge/maker-base" "7.8.1"
-    "@electron-forge/shared-types" "7.8.1"
-    chalk "^4.0.0"
-    electron-wix-msi "^5.1.3"
-    log-symbols "^4.0.0"
-    parse-author "^2.0.0"
-    semver "^7.2.1"
-
-"@electron-forge/maker-zip@^7.8.0":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/maker-zip/-/maker-zip-7.8.1.tgz#537c5203363de08d4f4c8b3487ff754f7816df28"
-  integrity sha512-unIxEoV1lnK4BLVqCy3L2y897fTyg8nKY1WT4rrpv0MUKnQG4qmigDfST5zZNNHHaulEn/ElAic2GEiP7d6bhQ==
-  dependencies:
-    "@electron-forge/maker-base" "7.8.1"
-    "@electron-forge/shared-types" "7.8.1"
-    cross-zip "^4.0.0"
-    fs-extra "^10.0.0"
-    got "^11.8.5"
-
-"@electron-forge/[email protected]":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/plugin-base/-/plugin-base-7.8.1.tgz#29b88971dba7c28bc1e4880be4d5db6a7c3404be"
-  integrity sha512-iCZC2d7CbsZ9l6j5d+KPIiyQx0U1QBfWAbKnnQhWCSizjcrZ7A9V4sMFZeTO6+PVm48b/r9GFPm+slpgZtYQLg==
-  dependencies:
-    "@electron-forge/shared-types" "7.8.1"
-
-"@electron-forge/[email protected]":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/publisher-base/-/publisher-base-7.8.1.tgz#62240adb5ea94b9db2a64a75c816a68d1b87525f"
-  integrity sha512-z2C+C4pcFxyCXIFwXGDcxhU8qtVUPZa3sPL6tH5RuMxJi77768chLw2quDWk2/dfupcSELXcOMYCs7aLysCzeQ==
-  dependencies:
-    "@electron-forge/shared-types" "7.8.1"
-
-"@electron-forge/[email protected]", "@electron-forge/shared-types@^7.3.1":
-  version "7.8.0"
-  resolved "https://registry.yarnpkg.com/@electron-forge/shared-types/-/shared-types-7.8.0.tgz#dbc9b20ecd547d0758d7abc90587983c7f2fd3e8"
-  integrity sha512-Ul+7HPvAZiAirqpZm0vc9YvlkAE+2bcrI10p3t50mEtuxn5VO/mB72NXiEKfWzHm8F31JySIe9bUV6s1MHQcCw==
-  dependencies:
-    "@electron-forge/tracer" "7.8.0"
-    "@electron/packager" "^18.3.5"
-    "@electron/rebuild" "^3.7.0"
-    listr2 "^7.0.2"
-
-"@electron-forge/[email protected]":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/shared-types/-/shared-types-7.8.1.tgz#32b1f79eb9bca28a59ca67cf1d70e7a9b49afdb3"
-  integrity sha512-guLyGjIISKQQRWHX+ugmcjIOjn2q/BEzCo3ioJXFowxiFwmZw/oCZ2KlPig/t6dMqgUrHTH5W/F0WKu0EY4M+Q==
-  dependencies:
-    "@electron-forge/tracer" "7.8.1"
-    "@electron/packager" "^18.3.5"
-    "@electron/rebuild" "^3.7.0"
-    listr2 "^7.0.2"
-
-"@electron-forge/[email protected]":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/template-base/-/template-base-7.8.1.tgz#81da376241355c559744fad8c43c3012096d420d"
-  integrity sha512-k8jEUr0zWFWb16ZGho+Es2OFeKkcbTgbC6mcH4eNyF/sumh/4XZMcwRtX1i7EiZAYiL9sVxyI6KVwGu254g+0g==
-  dependencies:
-    "@electron-forge/core-utils" "7.8.1"
-    "@electron-forge/shared-types" "7.8.1"
-    "@malept/cross-spawn-promise" "^2.0.0"
-    debug "^4.3.1"
-    fs-extra "^10.0.0"
-    username "^5.1.0"
-
-"@electron-forge/[email protected]":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.8.1.tgz#f8a1fd5bd1f0d76ef3c3e0f953af6cb2dc365087"
-  integrity sha512-CccQhwUjZcc6svzuOi3BtbDal591DzyX2J5GPa6mwVutDP8EMtqJL1VyOHdcWO/7XjI6GNAD0fiXySOJiUAECA==
-  dependencies:
-    "@electron-forge/shared-types" "7.8.1"
-    "@electron-forge/template-base" "7.8.1"
-    fs-extra "^10.0.0"
-
-"@electron-forge/[email protected]":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/template-vite/-/template-vite-7.8.1.tgz#0b9c7abbe2218eed6b9818b9f3fe15a34aa19f6f"
-  integrity sha512-qzSlJaBYYqQAbBdLk4DqAE3HCNz4yXbpkb+VC74ddL4JGwPdPU57DjCthr6YetKJ2FsOVy9ipovA8HX5UbXpAg==
-  dependencies:
-    "@electron-forge/shared-types" "7.8.1"
-    "@electron-forge/template-base" "7.8.1"
-    fs-extra "^10.0.0"
-
-"@electron-forge/[email protected]":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.8.1.tgz#2d1de5fdde28d9bfde80b311e7eaf3e47342b493"
-  integrity sha512-h922E+6zWwym1RT6WKD79BLTc4H8YxEMJ7wPWkBX59kw/exsTB/KFdiJq6r82ON5jSJ+Q8sDGqSmDWdyCfo+Gg==
-  dependencies:
-    "@electron-forge/shared-types" "7.8.1"
-    "@electron-forge/template-base" "7.8.1"
-    fs-extra "^10.0.0"
-
-"@electron-forge/[email protected]":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack/-/template-webpack-7.8.1.tgz#f9c54e93208972eb0ab5280793bba25234f170d1"
-  integrity sha512-DA77o9kTCHrq+W211pyNP49DyAt0d1mzMp2gisyNz7a+iKvlv2DsMAeRieLoCQ44akb/z8ZsL0YLteSjKLy4AA==
-  dependencies:
-    "@electron-forge/shared-types" "7.8.1"
-    "@electron-forge/template-base" "7.8.1"
-    fs-extra "^10.0.0"
-
-"@electron-forge/[email protected]":
-  version "7.8.0"
-  resolved "https://registry.yarnpkg.com/@electron-forge/tracer/-/tracer-7.8.0.tgz#19a9a8164efd2b7a9fa144d424d5e714f115cf77"
-  integrity sha512-t4fIATZEX6/7PJNfyh6tLzKEsNMpO01Nz/rgHWBxeRvjCw5UNul9OOxoM7b43vfFAO9Jv++34oI3VJ09LeVQ2Q==
-  dependencies:
-    chrome-trace-event "^1.0.3"
-
-"@electron-forge/[email protected]":
-  version "7.8.1"
-  resolved "https://registry.yarnpkg.com/@electron-forge/tracer/-/tracer-7.8.1.tgz#87e2f63cba05a73f26ace903b2b7435ae8474bb5"
-  integrity sha512-r2i7aHVp2fylGQSPDw3aTcdNfVX9cpL1iL2MKHrCRNwgrfR+nryGYg434T745GGm1rNQIv5Egdkh5G9xf00oWA==
-  dependencies:
-    chrome-trace-event "^1.0.3"
-
-"@electron/[email protected]":
-  version "3.2.18"
-  resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.2.18.tgz#fa607f829209bab8b9e0ce6658d3fe81b2cba517"
-  integrity sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==
-  dependencies:
-    commander "^5.0.0"
-    glob "^7.1.6"
-    minimatch "^3.0.4"
-
-"@electron/asar@^3.2.1", "@electron/asar@^3.2.13", "@electron/asar@^3.2.5", "@electron/asar@^3.2.7", "@electron/asar@^3.3.1":
-  version "3.4.1"
-  resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.4.1.tgz#4e9196a4b54fba18c56cd8d5cac67c5bdc588065"
-  integrity sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==
-  dependencies:
-    commander "^5.0.0"
-    glob "^7.1.6"
-    minimatch "^3.0.4"
-
-"@electron/fuses@^1.8.0":
-  version "1.8.0"
-  resolved "https://registry.yarnpkg.com/@electron/fuses/-/fuses-1.8.0.tgz#ad34d3cc4703b1258b83f6989917052cfc1490a0"
-  integrity sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==
-  dependencies:
-    chalk "^4.1.1"
-    fs-extra "^9.0.1"
-    minimist "^1.2.5"
-
-"@electron/get@^2.0.0":
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/@electron/get/-/get-2.0.3.tgz#fba552683d387aebd9f3fcadbcafc8e12ee4f960"
-  integrity sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==
-  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"
-  optionalDependencies:
-    global-agent "^3.0.0"
-
-"@electron/get@^3.0.0":
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/@electron/get/-/get-3.1.0.tgz#22c5a0bd917ab201badeb77bc4ad18cba54cb4ec"
-  integrity sha512-F+nKc0xW+kVbBRhFzaMgPy3KwmuNTYX1fx6+FxxoSnNgwYX6LD7AKBTWkU0MQ6IBoe7dz069CNkR673sPAgkCQ==
-  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"
-  optionalDependencies:
-    global-agent "^3.0.0"
-
-"@electron/node-gyp@https://github.com/electron/node-gyp#06b29aafb7708acef8b3669835c8a7857ebc92d2":
-  version "10.2.0-electron.1"
-  resolved "https://github.com/electron/node-gyp#06b29aafb7708acef8b3669835c8a7857ebc92d2"
-  dependencies:
-    env-paths "^2.2.0"
-    exponential-backoff "^3.1.1"
-    glob "^8.1.0"
-    graceful-fs "^4.2.6"
-    make-fetch-happen "^10.2.1"
-    nopt "^6.0.0"
-    proc-log "^2.0.1"
-    semver "^7.3.5"
-    tar "^6.2.1"
-    which "^2.0.2"
-
-"@electron/[email protected]":
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/@electron/notarize/-/notarize-2.2.1.tgz#d0aa6bc43cba830c41bfd840b85dbe0e273f59fe"
-  integrity sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==
-  dependencies:
-    debug "^4.1.1"
-    fs-extra "^9.0.1"
-    promise-retry "^2.0.1"
-
-"@electron/[email protected]", "@electron/notarize@^2.1.0":
-  version "2.5.0"
-  resolved "https://registry.yarnpkg.com/@electron/notarize/-/notarize-2.5.0.tgz#d4d25356adfa29df4a76bd64a8bd347237cd251e"
-  integrity sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==
-  dependencies:
-    debug "^4.1.1"
-    fs-extra "^9.0.1"
-    promise-retry "^2.0.1"
-
-"@electron/[email protected]":
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/@electron/osx-sign/-/osx-sign-1.0.5.tgz#0af7149f2fce44d1a8215660fd25a9fb610454d8"
-  integrity sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==
-  dependencies:
-    compare-version "^0.1.2"
-    debug "^4.3.4"
-    fs-extra "^10.0.0"
-    isbinaryfile "^4.0.8"
-    minimist "^1.2.6"
-    plist "^3.0.5"
-
-"@electron/[email protected]":
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/@electron/osx-sign/-/osx-sign-1.3.1.tgz#faf7eeca7ca004a6be541dc4cf7a1bd59ec59b1c"
-  integrity sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==
-  dependencies:
-    compare-version "^0.1.2"
-    debug "^4.3.4"
-    fs-extra "^10.0.0"
-    isbinaryfile "^4.0.8"
-    minimist "^1.2.6"
-    plist "^3.0.5"
-
-"@electron/osx-sign@^1.0.5":
-  version "1.3.3"
-  resolved "https://registry.yarnpkg.com/@electron/osx-sign/-/osx-sign-1.3.3.tgz#af751510488318d9f7663694af85819690d75583"
-  integrity sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg==
-  dependencies:
-    compare-version "^0.1.2"
-    debug "^4.3.4"
-    fs-extra "^10.0.0"
-    isbinaryfile "^4.0.8"
-    minimist "^1.2.6"
-    plist "^3.0.5"
-
-"@electron/packager@^18.3.5":
-  version "18.3.6"
-  resolved "https://registry.yarnpkg.com/@electron/packager/-/packager-18.3.6.tgz#3596399334866737bc33ab663e90376d7aad89e4"
-  integrity sha512-1eXHB5t+SQKvUiDpWGpvr90ZSSbXj+isrh3YbjCTjKT4bE4SQrKSBfukEAaBvp67+GXHFtCHjQgN9qSTFIge+Q==
-  dependencies:
-    "@electron/asar" "^3.2.13"
-    "@electron/get" "^3.0.0"
-    "@electron/notarize" "^2.1.0"
-    "@electron/osx-sign" "^1.0.5"
-    "@electron/universal" "^2.0.1"
-    "@electron/windows-sign" "^1.0.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"
-    resedit "^2.0.0"
-    resolve "^1.1.6"
-    semver "^7.1.3"
-    yargs-parser "^21.1.1"
-
-"@electron/[email protected]":
-  version "3.7.0"
-  resolved "https://registry.yarnpkg.com/@electron/rebuild/-/rebuild-3.7.0.tgz#82e20c467ddedbb295d7f641592c52e68c141e9f"
-  integrity sha512-VW++CNSlZwMYP7MyXEbrKjpzEwhB5kDNbzGtiPEjwYysqyTCF+YbNJ210Dj3AjWsGSV4iEEwNkmJN9yGZmVvmw==
-  dependencies:
-    "@electron/node-gyp" "https://github.com/electron/node-gyp#06b29aafb7708acef8b3669835c8a7857ebc92d2"
-    "@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"
-    node-abi "^3.45.0"
-    node-api-version "^0.2.0"
-    ora "^5.1.0"
-    read-binary-file-arch "^1.0.6"
-    semver "^7.3.5"
-    tar "^6.0.5"
-    yargs "^17.0.1"
-
-"@electron/[email protected]", "@electron/rebuild@^3.7.0":
-  version "3.7.2"
-  resolved "https://registry.yarnpkg.com/@electron/rebuild/-/rebuild-3.7.2.tgz#8d808b29159c50086d27a5dec72b40bf16b4b582"
-  integrity sha512-19/KbIR/DAxbsCkiaGMXIdPnMCJLkcf8AvGnduJtWBs/CBwiAjY1apCqOLVxrXg+rtXFCngbXhBanWjxLUt1Mg==
-  dependencies:
-    "@electron/node-gyp" "https://github.com/electron/node-gyp#06b29aafb7708acef8b3669835c8a7857ebc92d2"
-    "@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"
-    node-abi "^3.45.0"
-    node-api-version "^0.2.0"
-    ora "^5.1.0"
-    read-binary-file-arch "^1.0.6"
-    semver "^7.3.5"
-    tar "^6.0.5"
-    yargs "^17.0.1"
-
-"@electron/[email protected]":
-  version "1.5.1"
-  resolved "https://registry.yarnpkg.com/@electron/universal/-/universal-1.5.1.tgz#f338bc5bcefef88573cf0ab1d5920fac10d06ee5"
-  integrity sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==
-  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"
-
-"@electron/[email protected]":
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/@electron/universal/-/universal-2.0.1.tgz#7b070ab355e02957388f3dbd68e2c3cd08c448ae"
-  integrity sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==
-  dependencies:
-    "@electron/asar" "^3.2.7"
-    "@malept/cross-spawn-promise" "^2.0.0"
-    debug "^4.3.1"
-    dir-compare "^4.2.0"
-    fs-extra "^11.1.1"
-    minimatch "^9.0.3"
-    plist "^3.1.0"
-
-"@electron/universal@^2.0.1":
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/@electron/universal/-/universal-2.0.3.tgz#1680df6ced8f128ca0ff24e29c2165d41d78b3ce"
-  integrity sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g==
-  dependencies:
-    "@electron/asar" "^3.3.1"
-    "@malept/cross-spawn-promise" "^2.0.0"
-    debug "^4.3.1"
-    dir-compare "^4.2.0"
-    fs-extra "^11.1.1"
-    minimatch "^9.0.3"
-    plist "^3.1.0"
-
-"@electron/windows-sign@^1.0.0", "@electron/windows-sign@^1.1.2":
-  version "1.2.2"
-  resolved "https://registry.yarnpkg.com/@electron/windows-sign/-/windows-sign-1.2.2.tgz#8ceaad52d5c1eb18702f48103d5f3bc7c338fa9d"
-  integrity sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==
-  dependencies:
-    cross-dirname "^0.1.0"
-    debug "^4.3.4"
-    fs-extra "^11.1.1"
-    minimist "^1.2.8"
-    postject "^1.0.0-alpha.6"
-
-"@fastify/ajv-compiler@^4.0.0":
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/@fastify/ajv-compiler/-/ajv-compiler-4.0.2.tgz#da05938cf852901bfb953738764f553b5449b80b"
-  integrity sha512-Rkiu/8wIjpsf46Rr+Fitd3HRP+VsxUFDDeag0hs9L0ksfnwx2g7SPQQTFL0E8Qv+rfXzQOxBJnjUB9ITUDjfWQ==
-  dependencies:
-    ajv "^8.12.0"
-    ajv-formats "^3.0.1"
-    fast-uri "^3.0.0"
-
-"@fastify/[email protected]":
-  version "11.0.1"
-  resolved "https://registry.yarnpkg.com/@fastify/cors/-/cors-11.0.1.tgz#5f35396f12231f093b3d05f26fa5d43cab6a7d86"
-  integrity sha512-dmZaE7M1f4SM8ZZuk5RhSsDJ+ezTgI7v3HHRj8Ow9CneczsPLZV6+2j2uwdaSLn8zhTv6QV0F4ZRcqdalGx1pQ==
-  dependencies:
-    fastify-plugin "^5.0.0"
-    toad-cache "^3.7.0"
-
-"@fastify/error@^4.0.0":
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/@fastify/error/-/error-4.1.0.tgz#a6a3a8d2309bd8d3441512dff9a7c739d0c35fe2"
-  integrity sha512-KeFcciOr1eo/YvIXHP65S94jfEEqn1RxTRBT1aJaHxY5FK0/GDXYozsQMMWlZoHgi8i0s+YtrLsgj/JkUUjSkQ==
-
-"@fastify/fast-json-stringify-compiler@^5.0.0":
-  version "5.0.3"
-  resolved "https://registry.yarnpkg.com/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-5.0.3.tgz#fae495bf30dbbd029139839ec5c2ea111bde7d3f"
-  integrity sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ==
-  dependencies:
-    fast-json-stringify "^6.0.0"
-
-"@fastify/forwarded@^3.0.0":
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/@fastify/forwarded/-/forwarded-3.0.0.tgz#0fc96cdbbb5a38ad453d2d5533a34f09b4949b37"
-  integrity sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==
-
-"@fastify/merge-json-schemas@^0.2.0":
-  version "0.2.1"
-  resolved "https://registry.yarnpkg.com/@fastify/merge-json-schemas/-/merge-json-schemas-0.2.1.tgz#3aa30d2f0c81a8ac5995b6d94ed4eaa2c3055824"
-  integrity sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==
-  dependencies:
-    dequal "^2.0.3"
-
-"@fastify/proxy-addr@^5.0.0":
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/@fastify/proxy-addr/-/proxy-addr-5.0.0.tgz#e9d1c7a49b8380d9f92a879fdc623ac47ee27de3"
-  integrity sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==
-  dependencies:
-    "@fastify/forwarded" "^3.0.0"
-    ipaddr.js "^2.1.0"
-
-"@gar/promisify@^1.1.3":
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
-  integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
-
-"@isaacs/cliui@^8.0.2":
-  version "8.0.2"
-  resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
-  integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
-  dependencies:
-    string-width "^5.1.2"
-    string-width-cjs "npm:string-width@^4.2.0"
-    strip-ansi "^7.0.1"
-    strip-ansi-cjs "npm:strip-ansi@^6.0.1"
-    wrap-ansi "^8.1.0"
-    wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
-
-"@isaacs/fs-minipass@^4.0.0":
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32"
-  integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==
-  dependencies:
-    minipass "^7.0.4"
-
-"@logseq/[email protected]":
-  version "0.0.92"
-  resolved "https://registry.yarnpkg.com/@logseq/rsapi-darwin-arm64/-/rsapi-darwin-arm64-0.0.92.tgz#8826d11c5e1e4a1540aeae10b3725bf1dd185d6c"
-  integrity sha512-Fak9tz9TsGOzOkrm5wI9R0gnRsNTRpj5F2QwIPEC6XThKCYsrNUxMvmDzlL0TSTE1T6EEfxdYZUgd/spTs5zGA==
-
-"@logseq/[email protected]":
-  version "0.0.92"
-  resolved "https://registry.yarnpkg.com/@logseq/rsapi-darwin-x64/-/rsapi-darwin-x64-0.0.92.tgz#645e7890783e20e8602668e97a92597e20d65d25"
-  integrity sha512-AyxuRlNNNwAnnF2sojWJO978rwntJaK6owtDS3EJSN+LmKPn8sEcQ6l5ChMVIzjcZHAjFvc+FVuxTwOeEExJUQ==
-
-"@logseq/[email protected]":
-  version "0.0.92"
-  resolved "https://registry.yarnpkg.com/@logseq/rsapi-freebsd-x64/-/rsapi-freebsd-x64-0.0.92.tgz#49b36ab2e74e3243ae5c53f88f28ff752a048b30"
-  integrity sha512-Bu2yXMCzYN4Kwv93/qnetOQ30zfHb5DwjSMvaApqMxTkg/b2b+VBJSm+KgB9fPP8gyYAp9jYHFEriGGRqm0V4Q==
-
-"@logseq/[email protected]":
-  version "0.0.92"
-  resolved "https://registry.yarnpkg.com/@logseq/rsapi-linux-arm64-gnu/-/rsapi-linux-arm64-gnu-0.0.92.tgz#b983c76f21b23579050b8c7cd53f27f09581dc9f"
-  integrity sha512-DKeixTnCdNAaVd3w2b095OpHextsP0e12UR/wtR7l096PLE3o0GzOamQSWmVMYhyySlpdSfv4mZvvTtG7QEfdw==
-
-"@logseq/[email protected]":
-  version "0.0.92"
-  resolved "https://registry.yarnpkg.com/@logseq/rsapi-linux-x64-gnu/-/rsapi-linux-x64-gnu-0.0.92.tgz#8ebb3324c8681c1f44f6d6b6364dca18c9c5ee29"
-  integrity sha512-FyvNgMB2EiHn3R22dhDsXw5p4BDc5dpKMbomu+6G4X9Bet6MzIxam3vToS/OelUwGErwbFjtdDswpBVrhe5WFg==
-
-"@logseq/[email protected]":
-  version "0.0.92"
-  resolved "https://registry.yarnpkg.com/@logseq/rsapi-win32-x64-msvc/-/rsapi-win32-x64-msvc-0.0.92.tgz#c3bb8e88c92da0a0289625da32d04c64c54668e7"
-  integrity sha512-EWv+IfKo5f7QOSFkmousMJAaetpCZL08h+qTg73YhWPxenZALQr35qwWykbUASraERwjsxkTFimv86lXMu/GZw==
-
-"@logseq/[email protected]":
-  version "0.0.92"
-  resolved "https://registry.yarnpkg.com/@logseq/rsapi/-/rsapi-0.0.92.tgz#fac6834098a0280d923f0d68c71041b949d5a304"
-  integrity sha512-HR6HN9Q2SlYegPD5yLd7S5LOyZVwwHhJAYwdx8AE9Rc+wwD+tLEHEbamG0ocTZdcbjl7YERnYOhd7eH9fUncfQ==
-  optionalDependencies:
-    "@logseq/rsapi-darwin-arm64" "0.0.92"
-    "@logseq/rsapi-darwin-x64" "0.0.92"
-    "@logseq/rsapi-freebsd-x64" "0.0.92"
-    "@logseq/rsapi-linux-arm64-gnu" "0.0.92"
-    "@logseq/rsapi-linux-x64-gnu" "0.0.92"
-    "@logseq/rsapi-win32-x64-msvc" "0.0.92"
-
-"@malept/cross-spawn-promise@^1.0.0", "@malept/cross-spawn-promise@^1.1.0":
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d"
-  integrity sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==
-  dependencies:
-    cross-spawn "^7.0.1"
-
-"@malept/cross-spawn-promise@^2.0.0":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz#d0772de1aa680a0bfb9ba2f32b4c828c7857cb9d"
-  integrity sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==
-  dependencies:
-    cross-spawn "^7.0.1"
-
-"@malept/flatpak-bundler@^0.4.0":
-  version "0.4.0"
-  resolved "https://registry.yarnpkg.com/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz#e8a32c30a95d20c2b1bb635cc580981a06389858"
-  integrity sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==
-  dependencies:
-    debug "^4.1.1"
-    fs-extra "^9.0.0"
-    lodash "^4.17.15"
-    tmp-promise "^3.0.2"
-
-"@nodelib/[email protected]":
-  version "2.1.5"
-  resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
-  integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
-  dependencies:
-    "@nodelib/fs.stat" "2.0.5"
-    run-parallel "^1.1.9"
-
-"@nodelib/[email protected]", "@nodelib/fs.stat@^2.0.2":
-  version "2.0.5"
-  resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
-  integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
-
-"@nodelib/fs.walk@^1.2.3":
-  version "1.2.8"
-  resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
-  integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
-  dependencies:
-    "@nodelib/fs.scandir" "2.1.5"
-    fastq "^1.6.0"
-
-"@npmcli/agent@^3.0.0":
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/@npmcli/agent/-/agent-3.0.0.tgz#1685b1fbd4a1b7bb4f930cbb68ce801edfe7aa44"
-  integrity sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==
-  dependencies:
-    agent-base "^7.1.0"
-    http-proxy-agent "^7.0.0"
-    https-proxy-agent "^7.0.1"
-    lru-cache "^10.0.1"
-    socks-proxy-agent "^8.0.3"
-
-"@npmcli/fs@^2.1.0":
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-2.1.2.tgz#a9e2541a4a2fec2e69c29b35e6060973da79b865"
-  integrity sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==
-  dependencies:
-    "@gar/promisify" "^1.1.3"
-    semver "^7.3.5"
-
-"@npmcli/fs@^4.0.0":
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-4.0.0.tgz#a1eb1aeddefd2a4a347eca0fab30bc62c0e1c0f2"
-  integrity sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==
-  dependencies:
-    semver "^7.3.5"
-
-"@npmcli/move-file@^2.0.0":
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-2.0.1.tgz#26f6bdc379d87f75e55739bab89db525b06100e4"
-  integrity sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==
-  dependencies:
-    mkdirp "^1.0.4"
-    rimraf "^3.0.2"
-
-"@pkgjs/parseargs@^0.11.0":
-  version "0.11.0"
-  resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
-  integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
-
-"@sentry/[email protected]":
-  version "6.7.1"
-  resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.7.1.tgz#e01144a08984a486ecc91d7922cc457e9c9bd6b7"
-  integrity sha512-R5PYx4TTvifcU790XkK6JVGwavKaXwycDU0MaAwfc4Vf7BLm5KCNJCsDySu1RPAap/017MVYf54p6dWvKiRviA==
-  dependencies:
-    "@sentry/core" "6.7.1"
-    "@sentry/types" "6.7.1"
-    "@sentry/utils" "6.7.1"
-    tslib "^1.9.3"
-
-"@sentry/[email protected]":
-  version "6.7.1"
-  resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.7.1.tgz#c3aaa6415d06bec65ac446b13b84f073805633e3"
-  integrity sha512-VAv8OR/7INn2JfiLcuop4hfDcyC7mfL9fdPndQEhlacjmw8gRrgXjR7qyhnCTgzFLkHI7V5bcdIzA83TRPYQpA==
-  dependencies:
-    "@sentry/hub" "6.7.1"
-    "@sentry/minimal" "6.7.1"
-    "@sentry/types" "6.7.1"
-    "@sentry/utils" "6.7.1"
-    tslib "^1.9.3"
-
-"@sentry/[email protected]":
-  version "2.5.1"
-  resolved "https://registry.yarnpkg.com/@sentry/electron/-/electron-2.5.1.tgz#6d1d42117e074c4b9f2f200def8ffb602c0221b6"
-  integrity sha512-1rVE1IgGZTAy2qlLQxDsuhv7/0sT88oHYyD4f6ZTDzge3lsReeMu4xA32M4ldo4yRlRQM5gpdSS/D7Q/4huH0A==
-  dependencies:
-    "@sentry/browser" "6.7.1"
-    "@sentry/core" "6.7.1"
-    "@sentry/minimal" "6.7.1"
-    "@sentry/node" "6.7.1"
-    "@sentry/types" "6.7.1"
-    "@sentry/utils" "6.7.1"
-    tslib "^2.2.0"
-
-"@sentry/[email protected]":
-  version "6.7.1"
-  resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.7.1.tgz#d46d24deec67f0731a808ca16796e6765b371bc1"
-  integrity sha512-eVCTWvvcp6xa0A5GGNHMQEWslmKPlisE5rGmsV/kjvSUv3zSrI0eIDfb51ikdnCiBjHpK2NBWP8Vy8cZOEJegg==
-  dependencies:
-    "@sentry/types" "6.7.1"
-    "@sentry/utils" "6.7.1"
-    tslib "^1.9.3"
-
-"@sentry/[email protected]":
-  version "6.7.1"
-  resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.7.1.tgz#babf85ee2f167e9dcf150d750d7a0b250c98449c"
-  integrity sha512-HDDPEnQRD6hC0qaHdqqKDStcdE1KhkFh0RCtJNMCDn0zpav8Dj9AteF70x6kLSlliAJ/JFwi6AmQrLz+FxPexw==
-  dependencies:
-    "@sentry/hub" "6.7.1"
-    "@sentry/types" "6.7.1"
-    tslib "^1.9.3"
-
-"@sentry/[email protected]":
-  version "6.7.1"
-  resolved "https://registry.yarnpkg.com/@sentry/node/-/node-6.7.1.tgz#b09e2eca8e187168feba7bd865a23935bf0f5cc0"
-  integrity sha512-rtZo1O8ROv4lZwuljQz3iFZW89oXSlgXCG2VqkxQyRspPWu89abROpxLjYzsWwQ8djnur1XjFv51kOLDUTS6Qw==
-  dependencies:
-    "@sentry/core" "6.7.1"
-    "@sentry/hub" "6.7.1"
-    "@sentry/tracing" "6.7.1"
-    "@sentry/types" "6.7.1"
-    "@sentry/utils" "6.7.1"
-    cookie "^0.4.1"
-    https-proxy-agent "^5.0.0"
-    lru_map "^0.3.3"
-    tslib "^1.9.3"
-
-"@sentry/[email protected]":
-  version "6.7.1"
-  resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.7.1.tgz#b11f0c17a6c5dc14ef44733e5436afb686683268"
-  integrity sha512-wyS3nWNl5mzaC1qZ2AIp1hjXnfO9EERjMIJjCihs2LWBz1r3efxrHxJHs8wXlNWvrT3KLhq/7vvF5CdU82uPeQ==
-  dependencies:
-    "@sentry/hub" "6.7.1"
-    "@sentry/minimal" "6.7.1"
-    "@sentry/types" "6.7.1"
-    "@sentry/utils" "6.7.1"
-    tslib "^1.9.3"
-
-"@sentry/[email protected]":
-  version "6.7.1"
-  resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.7.1.tgz#c8263e1886df5e815570c4668eb40a1cfaa1c88b"
-  integrity sha512-9AO7HKoip2MBMNQJEd6+AKtjj2+q9Ze4ooWUdEvdOVSt5drg7BGpK221/p9JEOyJAZwEPEXdcMd3VAIMiOb4MA==
-
-"@sentry/[email protected]":
-  version "6.7.1"
-  resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.7.1.tgz#909184ad580f0f6375e1e4d4a6ffd33dfe64a4d1"
-  integrity sha512-Tq2otdbWlHAkctD+EWTYKkEx6BL1Qn3Z/imkO06/PvzpWvVhJWQ5qHAzz5XnwwqNHyV03KVzYB6znq1Bea9HuA==
-  dependencies:
-    "@sentry/types" "6.7.1"
-    tslib "^1.9.3"
-
-"@sindresorhus/is@^4.0.0":
-  version "4.6.0"
-  resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f"
-  integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==
-
-"@szmarczak/http-timer@^4.0.5":
-  version "4.0.6"
-  resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807"
-  integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==
-  dependencies:
-    defer-to-connect "^2.0.0"
-
-"@tootallnate/once@2":
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
-  integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
-
-"@types/appdmg@^0.5.5":
-  version "0.5.5"
-  resolved "https://registry.yarnpkg.com/@types/appdmg/-/appdmg-0.5.5.tgz#141a4f565395acf587c3f35642a021aea97deea2"
-  integrity sha512-G+n6DgZTZFOteITE30LnWj+HRVIGr7wMlAiLWOO02uJFWVEitaPU9JVXm9wJokkgshBawb2O1OykdcsmkkZfgg==
-  dependencies:
-    "@types/node" "*"
-
-"@types/cacheable-request@^6.0.1":
-  version "6.0.3"
-  resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183"
-  integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==
-  dependencies:
-    "@types/http-cache-semantics" "*"
-    "@types/keyv" "^3.1.4"
-    "@types/node" "*"
-    "@types/responselike" "^1.0.0"
-
-"@types/debug@^4.1.6":
-  version "4.1.12"
-  resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917"
-  integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==
-  dependencies:
-    "@types/ms" "*"
-
-"@types/electron@^1.6.10":
-  version "1.6.12"
-  resolved "https://registry.yarnpkg.com/@types/electron/-/electron-1.6.12.tgz#0921813f95b92fdce9f642f85cb561318fcf0a04"
-  integrity sha512-NIJokDkGv9h+MStCL1IuiL1FOHYVkszoWeNxJtSI5dcEKRGbX83JcVYNAgk019qOQgJkHtz9WdP0CDXvrArrGg==
-  dependencies:
-    electron "*"
-
-"@types/[email protected]", "@types/fs-extra@^9.0.1", "@types/fs-extra@^9.0.11":
-  version "9.0.13"
-  resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45"
-  integrity sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==
-  dependencies:
-    "@types/node" "*"
-
-"@types/http-cache-semantics@*":
-  version "4.0.4"
-  resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4"
-  integrity sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==
-
-"@types/keyv@^3.1.4":
-  version "3.1.4"
-  resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6"
-  integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==
-  dependencies:
-    "@types/node" "*"
-
-"@types/ms@*":
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78"
-  integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==
-
-"@types/node@*":
-  version "22.15.16"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.16.tgz#685cf0338ad9f5b14860f50a6ac2c3ebd58582cd"
-  integrity sha512-3pr+KjwpVujqWqOKT8mNR+rd09FqhBLwg+5L/4t0cNYBzm/yEiYGCxWttjaPBsLtAo+WFNoXzGJfolM1JuRXoA==
-  dependencies:
-    undici-types "~6.21.0"
-
-"@types/node@^20.9.0":
-  version "20.17.50"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.50.tgz#d2640af991fc839ba746f799516fc6a4e47ebe50"
-  integrity sha512-Mxiq0ULv/zo1OzOhwPqOA13I81CV/W3nvd3ChtQZRT5Cwz3cr0FKo/wMSsbTqL3EXpaBAEQhva2B8ByRkOIh9A==
-  dependencies:
-    undici-types "~6.19.2"
-
-"@types/plist@^3.0.1":
-  version "3.0.5"
-  resolved "https://registry.yarnpkg.com/@types/plist/-/plist-3.0.5.tgz#9a0c49c0f9886c8c8696a7904dd703f6284036e0"
-  integrity sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==
-  dependencies:
-    "@types/node" "*"
-    xmlbuilder ">=11.0.1"
-
-"@types/responselike@^1.0.0":
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.3.tgz#cc29706f0a397cfe6df89debfe4bf5cea159db50"
-  integrity sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==
-  dependencies:
-    "@types/node" "*"
-
-"@types/verror@^1.10.3":
-  version "1.10.11"
-  resolved "https://registry.yarnpkg.com/@types/verror/-/verror-1.10.11.tgz#d3d6b418978c8aa202d41e5bb3483227b6ecc1bb"
-  integrity sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==
-
-"@types/yauzl@^2.9.1":
-  version "2.10.3"
-  resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.3.tgz#e9b2808b4f109504a03cda958259876f61017999"
-  integrity sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==
-  dependencies:
-    "@types/node" "*"
-
-"@xmldom/xmldom@^0.8.8":
-  version "0.8.10"
-  resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99"
-  integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==
-
-abbrev@^1.0.0:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
-  integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
-
-abbrev@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-3.0.1.tgz#8ac8b3b5024d31464fe2a5feeea9f4536bf44025"
-  integrity sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==
-
[email protected]:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
-  integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
-  dependencies:
-    event-target-shim "^5.0.0"
-
-abstract-logging@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839"
-  integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==
-
-agent-base@6, agent-base@^6.0.2:
-  version "6.0.2"
-  resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
-  integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
-  dependencies:
-    debug "4"
-
-agent-base@^7.0.2, agent-base@^7.1.0, agent-base@^7.1.2:
-  version "7.1.3"
-  resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.3.tgz#29435eb821bc4194633a5b89e5bc4703bafc25a1"
-  integrity sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==
-
-agent-base@^7.1.1:
-  version "7.1.1"
-  resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317"
-  integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==
-  dependencies:
-    debug "^4.3.4"
-
-agentkeepalive@^4.2.1:
-  version "4.6.0"
-  resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz#35f73e94b3f40bf65f105219c623ad19c136ea6a"
-  integrity sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==
-  dependencies:
-    humanize-ms "^1.2.1"
-
-aggregate-error@^3.0.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
-  integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==
-  dependencies:
-    clean-stack "^2.0.0"
-    indent-string "^4.0.0"
-
-ajv-formats@^3.0.1:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578"
-  integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==
-  dependencies:
-    ajv "^8.0.0"
-
-ajv-keywords@^3.4.1:
-  version "3.5.2"
-  resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
-  integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
-
-ajv@^6.10.0, ajv@^6.12.0:
-  version "6.12.6"
-  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
-  integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
-  dependencies:
-    fast-deep-equal "^3.1.1"
-    fast-json-stable-stringify "^2.0.0"
-    json-schema-traverse "^0.4.1"
-    uri-js "^4.2.2"
-
-ajv@^8.0.0, ajv@^8.12.0:
-  version "8.17.1"
-  resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6"
-  integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==
-  dependencies:
-    fast-deep-equal "^3.1.3"
-    fast-uri "^3.0.1"
-    json-schema-traverse "^1.0.0"
-    require-from-string "^2.0.2"
-
-ansi-escapes@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-5.0.0.tgz#b6a0caf0eef0c41af190e9a749e0c00ec04bb2a6"
-  integrity sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==
-  dependencies:
-    type-fest "^1.0.2"
-
-ansi-regex@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
-  integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
-
-ansi-styles@^4.0.0, ansi-styles@^4.1.0:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
-  integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
-  dependencies:
-    color-convert "^2.0.1"
-
-ansi-styles@^6.0.0:
-  version "6.2.1"
-  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
-  integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
-
-anymatch@~3.1.2:
-  version "3.1.3"
-  resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
-  integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
-  dependencies:
-    normalize-path "^3.0.0"
-    picomatch "^2.0.4"
-
[email protected]:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-4.0.0.tgz#1df8e654bd1395e4a319d82545c98667d7eed2f0"
-  integrity sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==
-
[email protected]:
-  version "5.0.0-alpha.12"
-  resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-5.0.0-alpha.12.tgz#2daf82f8badc698e0adcc95ba36af4ff0650dc80"
-  integrity sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w==
-
[email protected]:
-  version "26.0.12"
-  resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-26.0.12.tgz#2e33df936e0f78d4266b058ece90308ea981eefb"
-  integrity sha512-+/CEPH1fVKf6HowBUs6LcAIoRcjeqgvAeoSE+cl7Y7LndyQ9ViGPYibNk7wmhMHzNgHIuIbw4nWADPO+4mjgWw==
-  dependencies:
-    "@develar/schema-utils" "~2.6.5"
-    "@electron/asar" "3.2.18"
-    "@electron/fuses" "^1.8.0"
-    "@electron/notarize" "2.5.0"
-    "@electron/osx-sign" "1.3.1"
-    "@electron/rebuild" "3.7.0"
-    "@electron/universal" "2.0.1"
-    "@malept/flatpak-bundler" "^0.4.0"
-    "@types/fs-extra" "9.0.13"
-    async-exit-hook "^2.0.1"
-    builder-util "26.0.11"
-    builder-util-runtime "9.3.1"
-    chromium-pickle-js "^0.2.0"
-    config-file-ts "0.2.8-rc1"
-    debug "^4.3.4"
-    dotenv "^16.4.5"
-    dotenv-expand "^11.0.6"
-    ejs "^3.1.8"
-    electron-publish "26.0.11"
-    fs-extra "^10.1.0"
-    hosted-git-info "^4.1.0"
-    is-ci "^3.0.0"
-    isbinaryfile "^5.0.0"
-    js-yaml "^4.1.0"
-    json5 "^2.2.3"
-    lazy-val "^1.0.5"
-    minimatch "^10.0.0"
-    plist "3.1.0"
-    resedit "^1.7.0"
-    semver "^7.3.8"
-    tar "^6.1.12"
-    temp-file "^3.4.0"
-    tiny-async-pool "1.3.0"
-
-app-builder-lib@^24.13.3:
-  version "24.13.3"
-  resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-24.13.3.tgz#36e47b65fecb8780bb73bff0fee4e0480c28274b"
-  integrity sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==
-  dependencies:
-    "@develar/schema-utils" "~2.6.5"
-    "@electron/notarize" "2.2.1"
-    "@electron/osx-sign" "1.0.5"
-    "@electron/universal" "1.5.1"
-    "@malept/flatpak-bundler" "^0.4.0"
-    "@types/fs-extra" "9.0.13"
-    async-exit-hook "^2.0.1"
-    bluebird-lst "^1.0.9"
-    builder-util "24.13.1"
-    builder-util-runtime "9.2.4"
-    chromium-pickle-js "^0.2.0"
-    debug "^4.3.4"
-    ejs "^3.1.8"
-    electron-publish "24.13.1"
-    form-data "^4.0.0"
-    fs-extra "^10.1.0"
-    hosted-git-info "^4.1.0"
-    is-ci "^3.0.0"
-    isbinaryfile "^5.0.0"
-    js-yaml "^4.1.0"
-    lazy-val "^1.0.5"
-    minimatch "^5.1.1"
-    read-config-file "6.3.2"
-    sanitize-filename "^1.6.3"
-    semver "^7.3.8"
-    tar "^6.1.12"
-    temp-file "^3.4.0"
-
-appdmg@^0.6.4:
-  version "0.6.6"
-  resolved "https://registry.yarnpkg.com/appdmg/-/appdmg-0.6.6.tgz#d06bd82b530032fd7a8f0970a1c6ee6196e1efce"
-  integrity sha512-GRmFKlCG+PWbcYF4LUNonTYmy0GjguDy6Jh9WP8mpd0T6j80XIJyXBiWlD0U+MLNhqV9Nhx49Gl9GpVToulpLg==
-  dependencies:
-    async "^1.4.2"
-    ds-store "^0.1.5"
-    execa "^1.0.0"
-    fs-temp "^1.0.0"
-    fs-xattr "^0.3.0"
-    image-size "^0.7.4"
-    is-my-json-valid "^2.20.0"
-    minimist "^1.1.3"
-    parse-color "^1.0.0"
-    path-exists "^4.0.0"
-    repeat-string "^1.5.4"
-
-argparse@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
-  integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
-
-assert-plus@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
-  integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==
-
-astral-regex@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
-  integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
-
-async-exit-hook@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/async-exit-hook/-/async-exit-hook-2.0.1.tgz#8bd8b024b0ec9b1c01cccb9af9db29bd717dfaf3"
-  integrity sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==
-
-async@^1.4.2:
-  version "1.5.2"
-  resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
-  integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==
-
-async@^3.2.3:
-  version "3.2.6"
-  resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce"
-  integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==
-
-asynckit@^0.4.0:
-  version "0.4.0"
-  resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
-  integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
-
-at-least-node@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
-  integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
-
-atomic-sleep@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b"
-  integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==
-
-author-regex@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/author-regex/-/author-regex-1.0.0.tgz#d08885be6b9bbf9439fe087c76287245f0a81450"
-  integrity sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g==
-
-avvio@^9.0.0:
-  version "9.1.0"
-  resolved "https://registry.yarnpkg.com/avvio/-/avvio-9.1.0.tgz#0ff80ed211682441d8aa39ff21a4b9d022109c44"
-  integrity sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==
-  dependencies:
-    "@fastify/error" "^4.0.0"
-    fastq "^1.17.1"
-
-balanced-match@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
-  integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
-
-"base32-encode@^0.1.0 || ^1.0.0":
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/base32-encode/-/base32-encode-1.2.0.tgz#e150573a5e431af0a998e32bdfde7045725ca453"
-  integrity sha512-cHFU8XeRyx0GgmoWi5qHMCVRiqU6J3MHWxVgun7jggCBUpVzm1Ir7M9dYr2whjSNc3tFeXfQ/oZjQu/4u55h9A==
-  dependencies:
-    to-data-view "^1.1.0"
-
-base64-js@^1.3.1, base64-js@^1.5.1:
-  version "1.5.1"
-  resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
-  integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
-
-binary-extensions@^2.0.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"
-  integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
-
-bindings@^1.5.0:
-  version "1.5.0"
-  resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
-  integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
-  dependencies:
-    file-uri-to-path "1.0.0"
-
-bl@^4.1.0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
-  integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
-  dependencies:
-    buffer "^5.5.0"
-    inherits "^2.0.4"
-    readable-stream "^3.4.0"
-
-bluebird-lst@^1.0.9:
-  version "1.0.9"
-  resolved "https://registry.yarnpkg.com/bluebird-lst/-/bluebird-lst-1.0.9.tgz#a64a0e4365658b9ab5fe875eb9dfb694189bb41c"
-  integrity sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==
-  dependencies:
-    bluebird "^3.5.5"
-
-bluebird@^3.1.1, bluebird@^3.5.5:
-  version "3.7.2"
-  resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
-  integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
-
-boolean@^3.0.1:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b"
-  integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==
-
-bplist-creator@~0.0.3:
-  version "0.0.8"
-  resolved "https://registry.yarnpkg.com/bplist-creator/-/bplist-creator-0.0.8.tgz#56b2a6e79e9aec3fc33bf831d09347d73794e79c"
-  integrity sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA==
-  dependencies:
-    stream-buffers "~2.2.0"
-
-brace-expansion@^1.1.7:
-  version "1.1.11"
-  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
-  integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
-  dependencies:
-    balanced-match "^1.0.0"
-    concat-map "0.0.1"
-
-brace-expansion@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
-  integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
-  dependencies:
-    balanced-match "^1.0.0"
-
-braces@^3.0.3, braces@~3.0.2:
-  version "3.0.3"
-  resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
-  integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
-  dependencies:
-    fill-range "^7.1.1"
-
-buffer-crc32@~0.2.3:
-  version "0.2.13"
-  resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
-  integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
-
-buffer-equal@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.1.tgz#2f7651be5b1b3f057fcd6e7ee16cf34767077d90"
-  integrity sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==
-
-buffer-from@^1.0.0:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
-  integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
-
-buffer@^5.1.0, buffer@^5.5.0:
-  version "5.7.1"
-  resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
-  integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
-  dependencies:
-    base64-js "^1.3.1"
-    ieee754 "^1.1.13"
-
[email protected]:
-  version "9.2.4"
-  resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz#13cd1763da621e53458739a1e63f7fcba673c42a"
-  integrity sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==
-  dependencies:
-    debug "^4.3.4"
-    sax "^1.2.4"
-
[email protected]:
-  version "9.3.1"
-  resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.3.1.tgz#0daedde0f6d381f2a00a50a407b166fe7dca1a67"
-  integrity sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ==
-  dependencies:
-    debug "^4.3.4"
-    sax "^1.2.4"
-
[email protected]:
-  version "24.13.1"
-  resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-24.13.1.tgz#4a4c4f9466b016b85c6990a0ea15aa14edec6816"
-  integrity sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==
-  dependencies:
-    "7zip-bin" "~5.2.0"
-    "@types/debug" "^4.1.6"
-    app-builder-bin "4.0.0"
-    bluebird-lst "^1.0.9"
-    builder-util-runtime "9.2.4"
-    chalk "^4.1.2"
-    cross-spawn "^7.0.3"
-    debug "^4.3.4"
-    fs-extra "^10.1.0"
-    http-proxy-agent "^5.0.0"
-    https-proxy-agent "^5.0.1"
-    is-ci "^3.0.0"
-    js-yaml "^4.1.0"
-    source-map-support "^0.5.19"
-    stat-mode "^1.0.0"
-    temp-file "^3.4.0"
-
[email protected]:
-  version "26.0.11"
-  resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-26.0.11.tgz#ad85b92c93f2b976b973e1d87337e0c6813fcb8f"
-  integrity sha512-xNjXfsldUEe153h1DraD0XvDOpqGR0L5eKFkdReB7eFW5HqysDZFfly4rckda6y9dF39N3pkPlOblcfHKGw+uA==
-  dependencies:
-    "7zip-bin" "~5.2.0"
-    "@types/debug" "^4.1.6"
-    app-builder-bin "5.0.0-alpha.12"
-    builder-util-runtime "9.3.1"
-    chalk "^4.1.2"
-    cross-spawn "^7.0.6"
-    debug "^4.3.4"
-    fs-extra "^10.1.0"
-    http-proxy-agent "^7.0.0"
-    https-proxy-agent "^7.0.0"
-    is-ci "^3.0.0"
-    js-yaml "^4.1.0"
-    sanitize-filename "^1.6.3"
-    source-map-support "^0.5.19"
-    stat-mode "^1.0.0"
-    temp-file "^3.4.0"
-    tiny-async-pool "1.3.0"
-
-cacache@^16.1.0:
-  version "16.1.3"
-  resolved "https://registry.yarnpkg.com/cacache/-/cacache-16.1.3.tgz#a02b9f34ecfaf9a78c9f4bc16fceb94d5d67a38e"
-  integrity sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==
-  dependencies:
-    "@npmcli/fs" "^2.1.0"
-    "@npmcli/move-file" "^2.0.0"
-    chownr "^2.0.0"
-    fs-minipass "^2.1.0"
-    glob "^8.0.1"
-    infer-owner "^1.0.4"
-    lru-cache "^7.7.1"
-    minipass "^3.1.6"
-    minipass-collect "^1.0.2"
-    minipass-flush "^1.0.5"
-    minipass-pipeline "^1.2.4"
-    mkdirp "^1.0.4"
-    p-map "^4.0.0"
-    promise-inflight "^1.0.1"
-    rimraf "^3.0.2"
-    ssri "^9.0.0"
-    tar "^6.1.11"
-    unique-filename "^2.0.0"
-
-cacache@^19.0.1:
-  version "19.0.1"
-  resolved "https://registry.yarnpkg.com/cacache/-/cacache-19.0.1.tgz#3370cc28a758434c85c2585008bd5bdcff17d6cd"
-  integrity sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==
-  dependencies:
-    "@npmcli/fs" "^4.0.0"
-    fs-minipass "^3.0.0"
-    glob "^10.2.2"
-    lru-cache "^10.0.1"
-    minipass "^7.0.3"
-    minipass-collect "^2.0.1"
-    minipass-flush "^1.0.5"
-    minipass-pipeline "^1.2.4"
-    p-map "^7.0.2"
-    ssri "^12.0.0"
-    tar "^7.4.3"
-    unique-filename "^4.0.0"
-
-cacheable-lookup@^5.0.3:
-  version "5.0.4"
-  resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005"
-  integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==
-
-cacheable-request@^7.0.2:
-  version "7.0.4"
-  resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817"
-  integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==
-  dependencies:
-    clone-response "^1.0.2"
-    get-stream "^5.1.0"
-    http-cache-semantics "^4.0.0"
-    keyv "^4.0.0"
-    lowercase-keys "^2.0.0"
-    normalize-url "^6.0.1"
-    responselike "^2.0.0"
-
-call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6"
-  integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==
-  dependencies:
-    es-errors "^1.3.0"
-    function-bind "^1.1.2"
-
-chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
-  version "4.1.2"
-  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
-  integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
-  dependencies:
-    ansi-styles "^4.1.0"
-    supports-color "^7.1.0"
-
-chokidar@^3.5.1:
-  version "3.6.0"
-  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
-  integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
-  dependencies:
-    anymatch "~3.1.2"
-    braces "~3.0.2"
-    glob-parent "~5.1.2"
-    is-binary-path "~2.1.0"
-    is-glob "~4.0.1"
-    normalize-path "~3.0.0"
-    readdirp "~3.6.0"
-  optionalDependencies:
-    fsevents "~2.3.2"
-
-chownr@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
-  integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
-
-chownr@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4"
-  integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==
-
-chrome-trace-event@^1.0.3:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b"
-  integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==
-
-chromium-pickle-js@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205"
-  integrity sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==
-
-ci-info@^3.2.0:
-  version "3.9.0"
-  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4"
-  integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==
-
-clean-stack@^2.0.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
-  integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
-
-cli-cursor@^3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
-  integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
-  dependencies:
-    restore-cursor "^3.1.0"
-
-cli-cursor@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea"
-  integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==
-  dependencies:
-    restore-cursor "^4.0.0"
-
-cli-spinners@^2.5.0:
-  version "2.9.2"
-  resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41"
-  integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==
-
-cli-truncate@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7"
-  integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==
-  dependencies:
-    slice-ansi "^3.0.0"
-    string-width "^4.2.0"
-
-cli-truncate@^3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389"
-  integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==
-  dependencies:
-    slice-ansi "^5.0.0"
-    string-width "^5.0.0"
-
-cliui@^7.0.2:
-  version "7.0.4"
-  resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
-  integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
-  dependencies:
-    string-width "^4.2.0"
-    strip-ansi "^6.0.0"
-    wrap-ansi "^7.0.0"
-
-cliui@^8.0.1:
-  version "8.0.1"
-  resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
-  integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
-  dependencies:
-    string-width "^4.2.0"
-    strip-ansi "^6.0.1"
-    wrap-ansi "^7.0.0"
-
-clone-response@^1.0.2:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3"
-  integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==
-  dependencies:
-    mimic-response "^1.0.0"
-
-clone@^1.0.2:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
-  integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
-
-color-convert@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
-  integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
-  dependencies:
-    color-name "~1.1.4"
-
-color-convert@~0.5.0:
-  version "0.5.3"
-  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd"
-  integrity sha512-RwBeO/B/vZR3dfKL1ye/vx8MHZ40ugzpyfeVG5GsiuGnrlMWe2o8wxBbLCpw9CsxV+wHuzYlCiWnybrIA0ling==
-
-color-name@~1.1.4:
-  version "1.1.4"
-  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
-  integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-
-colorette@^2.0.20:
-  version "2.0.20"
-  resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
-  integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
-
-combined-stream@^1.0.8:
-  version "1.0.8"
-  resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
-  integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
-  dependencies:
-    delayed-stream "~1.0.0"
-
[email protected]:
-  version "1.2.9"
-  resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69"
-  integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==
-
-commander@^11.1.0:
-  version "11.1.0"
-  resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906"
-  integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==
-
-commander@^5.0.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
-  integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
-
-commander@^9.4.0:
-  version "9.5.0"
-  resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30"
-  integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==
-
-compare-version@^0.1.2:
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/compare-version/-/compare-version-0.1.2.tgz#0162ec2d9351f5ddd59a9202cba935366a725080"
-  integrity sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==
-
[email protected]:
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
-  integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
-
[email protected]:
-  version "0.2.8-rc1"
-  resolved "https://registry.yarnpkg.com/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz#fb7fc6ccb2e313f69dbeb78f1db0b00038049de0"
-  integrity sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==
-  dependencies:
-    glob "^10.3.12"
-    typescript "^5.4.3"
-
-config-file-ts@^0.2.4:
-  version "0.2.6"
-  resolved "https://registry.yarnpkg.com/config-file-ts/-/config-file-ts-0.2.6.tgz#b424ff74612fb37f626d6528f08f92ddf5d22027"
-  integrity sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==
-  dependencies:
-    glob "^10.3.10"
-    typescript "^5.3.3"
-
-cookie@^0.4.1:
-  version "0.4.2"
-  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432"
-  integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
-
-cookie@^1.0.1:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/cookie/-/cookie-1.0.2.tgz#27360701532116bd3f1f9416929d176afe1e4610"
-  integrity sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==
-
[email protected]:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
-  integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==
-
-core-util-is@~1.0.0:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
-  integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
-
-crc@^3.8.0:
-  version "3.8.0"
-  resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6"
-  integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==
-  dependencies:
-    buffer "^5.1.0"
-
-cross-dirname@^0.1.0:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/cross-dirname/-/cross-dirname-0.1.0.tgz#b899599f30a5389f59e78c150e19f957ad16a37c"
-  integrity sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==
-
-cross-spawn-windows-exe@^1.1.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/cross-spawn-windows-exe/-/cross-spawn-windows-exe-1.2.0.tgz#46253b0f497676e766faf4a7061004618b5ac5ec"
-  integrity sha512-mkLtJJcYbDCxEG7Js6eUnUNndWjyUZwJ3H7bErmmtOYU/Zb99DyUkpamuIZE0b3bhmJyZ7D90uS6f+CGxRRjOw==
-  dependencies:
-    "@malept/cross-spawn-promise" "^1.1.0"
-    is-wsl "^2.2.0"
-    which "^2.0.2"
-
-cross-spawn@^6.0.0:
-  version "6.0.6"
-  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.6.tgz#30d0efa0712ddb7eb5a76e1e8721bffafa6b5d57"
-  integrity sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==
-  dependencies:
-    nice-try "^1.0.4"
-    path-key "^2.0.1"
-    semver "^5.5.0"
-    shebang-command "^1.2.0"
-    which "^1.2.9"
-
-cross-spawn@^7.0.1, cross-spawn@^7.0.3, cross-spawn@^7.0.6:
-  version "7.0.6"
-  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
-  integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
-  dependencies:
-    path-key "^3.1.0"
-    shebang-command "^2.0.0"
-    which "^2.0.1"
-
-cross-zip@^4.0.0:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/cross-zip/-/cross-zip-4.0.1.tgz#1bbf5d3b0e5a77b5f5ca130a6d38f770786e1270"
-  integrity sha512-n63i0lZ0rvQ6FXiGQ+/JFCKAUyPFhLQYJIqKaa+tSJtfKeULF/IDNDAbdnSIxgS4NTuw2b0+lj8LzfITuq+ZxQ==
-
-debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4:
-  version "4.4.0"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a"
-  integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
-  dependencies:
-    ms "^2.1.3"
-
-debug@^2.2.0:
-  version "2.6.9"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
-  integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
-  dependencies:
-    ms "2.0.0"
-
-decompress-response@^6.0.0:
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
-  integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==
-  dependencies:
-    mimic-response "^3.1.0"
-
-defaults@^1.0.3:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a"
-  integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==
-  dependencies:
-    clone "^1.0.2"
-
-defer-to-connect@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587"
-  integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==
-
-define-data-property@^1.0.1:
-  version "1.1.4"
-  resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
-  integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
-  dependencies:
-    es-define-property "^1.0.0"
-    es-errors "^1.3.0"
-    gopd "^1.0.1"
-
-define-properties@^1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c"
-  integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==
-  dependencies:
-    define-data-property "^1.0.1"
-    has-property-descriptors "^1.0.0"
-    object-keys "^1.1.1"
-
-delayed-stream@~1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
-  integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
-
-dequal@^2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
-  integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
-
-detect-libc@^2.0.1:
-  version "2.0.4"
-  resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.4.tgz#f04715b8ba815e53b4d8109655b6508a6865a7e8"
-  integrity sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==
-
-detect-node@^2.0.4:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
-  integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==
-
[email protected]:
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37"
-  integrity sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==
-
-dir-compare@^3.0.0:
-  version "3.3.0"
-  resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-3.3.0.tgz#2c749f973b5c4b5d087f11edaae730db31788416"
-  integrity sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==
-  dependencies:
-    buffer-equal "^1.0.0"
-    minimatch "^3.0.4"
-
-dir-compare@^4.2.0:
-  version "4.2.0"
-  resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-4.2.0.tgz#d1d4999c14fbf55281071fdae4293b3b9ce86f19"
-  integrity sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==
-  dependencies:
-    minimatch "^3.0.5"
-    p-limit "^3.1.0 "
-
[email protected]:
-  version "26.0.12"
-  resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-26.0.12.tgz#6996ad0bab80a861c9a7b33ee9734d4f60566b46"
-  integrity sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==
-  dependencies:
-    app-builder-lib "26.0.12"
-    builder-util "26.0.11"
-    builder-util-runtime "9.3.1"
-    fs-extra "^10.1.0"
-    iconv-lite "^0.6.2"
-    js-yaml "^4.1.0"
-  optionalDependencies:
-    dmg-license "^1.0.11"
-
-dmg-license@^1.0.11:
-  version "1.0.11"
-  resolved "https://registry.yarnpkg.com/dmg-license/-/dmg-license-1.0.11.tgz#7b3bc3745d1b52be7506b4ee80cb61df6e4cd79a"
-  integrity sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==
-  dependencies:
-    "@types/plist" "^3.0.1"
-    "@types/verror" "^1.10.3"
-    ajv "^6.10.0"
-    crc "^3.8.0"
-    iconv-corefoundation "^1.1.7"
-    plist "^3.0.4"
-    smart-buffer "^4.0.2"
-    verror "^1.10.0"
-
-dotenv-expand@^11.0.6:
-  version "11.0.7"
-  resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-11.0.7.tgz#af695aea007d6fdc84c86cd8d0ad7beb40a0bd08"
-  integrity sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==
-  dependencies:
-    dotenv "^16.4.5"
-
-dotenv-expand@^5.1.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0"
-  integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==
-
-dotenv@^16.4.5:
-  version "16.5.0"
-  resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.5.0.tgz#092b49f25f808f020050051d1ff258e404c78692"
-  integrity sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==
-
-dotenv@^9.0.2:
-  version "9.0.2"
-  resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-9.0.2.tgz#dacc20160935a37dea6364aa1bef819fb9b6ab05"
-  integrity sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==
-
-ds-store@^0.1.5:
-  version "0.1.6"
-  resolved "https://registry.yarnpkg.com/ds-store/-/ds-store-0.1.6.tgz#d1024ef746ed0c13f0f7fec85c7e858e8c4b7ca7"
-  integrity sha512-kY21M6Lz+76OS3bnCzjdsJSF7LBpLYGCVfavW8TgQD2XkcqIZ86W0y9qUDZu6fp7SIZzqosMDW2zi7zVFfv4hw==
-  dependencies:
-    bplist-creator "~0.0.3"
-    macos-alias "~0.2.5"
-    tn1150 "^0.1.0"
-
[email protected]:
-  version "2.7.1"
-  resolved "https://registry.yarnpkg.com/dugite/-/dugite-2.7.1.tgz#277275fd490bddf20180e124d119f84f708dfb32"
-  integrity sha512-X7v7JngMG6RGHKCKKF0fdqYC9Xcw0CDes43an6dQW2N2dYNd/OOLq3BFszCOyOObgKnrmNVvyggk3O4WGJMpcA==
-  dependencies:
-    progress "^2.0.3"
-    tar "^6.1.11"
-
-dunder-proto@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
-  integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==
-  dependencies:
-    call-bind-apply-helpers "^1.0.1"
-    es-errors "^1.3.0"
-    gopd "^1.2.0"
-
-ejs@^3.1.8:
-  version "3.1.10"
-  resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b"
-  integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==
-  dependencies:
-    jake "^10.8.5"
-
[email protected]:
-  version "26.0.12"
-  resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-26.0.12.tgz#797af2e70efdd96c9ea5d8a8164b8728c90d65ff"
-  integrity sha512-cD1kz5g2sgPTMFHjLxfMjUK5JABq3//J4jPswi93tOPFz6btzXYtK5NrDt717NRbukCUDOrrvmYVOWERlqoiXA==
-  dependencies:
-    app-builder-lib "26.0.12"
-    builder-util "26.0.11"
-    builder-util-runtime "9.3.1"
-    chalk "^4.1.2"
-    dmg-builder "26.0.12"
-    fs-extra "^10.1.0"
-    is-ci "^3.0.0"
-    lazy-val "^1.0.5"
-    simple-update-notifier "2.0.0"
-    yargs "^17.6.2"
-
[email protected]:
-  version "1.0.10"
-  resolved "https://registry.yarnpkg.com/electron-deeplink/-/electron-deeplink-1.0.10.tgz#0ad827cc84f890d4f7712b38055e92fabfc2cc8b"
-  integrity sha512-kyvjPdOtPfzNfdJYymIMPsC3N+eLv0SIobx6XYVX3j5zgwQ6XKz0P9qOCBwdlK8DhY3MX6l/jhx3gKSecOyWoA==
-  dependencies:
-    "@types/electron" "^1.6.10"
-    bindings "^1.5.0"
-    electron-log "^4.2.3"
-    node-addon-api "^2.0.0"
-
-electron-devtools-installer@^3.2.0:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/electron-devtools-installer/-/electron-devtools-installer-3.2.1.tgz#338a0ada7b4232ee42cd88fe5cf305c6be95cfe9"
-  integrity sha512-FaCi+oDCOBTw0gJUsuw5dXW32b2Ekh5jO8lI1NRCQigo3azh2VogsIi0eelMVrP1+LkN/bewyH3Xoo1USjO0eQ==
-  dependencies:
-    rimraf "^3.0.2"
-    semver "^7.2.1"
-    tslib "^2.1.0"
-    unzip-crx-3 "^0.2.0"
-
[email protected]:
-  version "3.3.0"
-  resolved "https://registry.yarnpkg.com/electron-dl/-/electron-dl-3.3.0.tgz#4e422e276c627373ba61fcf3f92ffa088988db1a"
-  integrity sha512-Zwaz/OMGPIfBLV2SQH4sTsdDOs/U4y5AOHfremMBXEpjIxX+SiTx845DZAvJJwgb5hfowyWOBLiJhd/emBNLLQ==
-  dependencies:
-    ext-name "^5.0.0"
-    pupa "^2.0.1"
-    unused-filename "^2.1.0"
-
-"electron-forge-maker-appimage@https://github.com/logseq/electron-forge-maker-appimage.git":
-  version "1.0.0"
-  resolved "https://github.com/logseq/electron-forge-maker-appimage.git#4bf4d4eb5925f72945841bd2fa7148322bc44189"
-  dependencies:
-    "@electron-forge/maker-base" "^7.3.1"
-    "@electron-forge/shared-types" "^7.3.1"
-    app-builder-lib "^24.13.3"
-
-electron-installer-common@^0.10.2:
-  version "0.10.4"
-  resolved "https://registry.yarnpkg.com/electron-installer-common/-/electron-installer-common-0.10.4.tgz#7a81265e0ec158eafd9dd474d5bb3a13946195e7"
-  integrity sha512-8gMNPXfAqUE5CfXg8RL0vXpLE9HAaPkgLXVoHE3BMUzogMWenf4LmwQ27BdCUrEhkjrKl+igs2IHJibclR3z3Q==
-  dependencies:
-    "@electron/asar" "^3.2.5"
-    "@malept/cross-spawn-promise" "^1.0.0"
-    debug "^4.1.1"
-    fs-extra "^9.0.0"
-    glob "^7.1.4"
-    lodash "^4.17.15"
-    parse-author "^2.0.0"
-    semver "^7.1.1"
-    tmp-promise "^3.0.2"
-  optionalDependencies:
-    "@types/fs-extra" "^9.0.1"
-
-electron-installer-debian@^3.2.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/electron-installer-debian/-/electron-installer-debian-3.2.0.tgz#2a9c8220f50a57807de8f93619a0d61ec41271e0"
-  integrity sha512-58ZrlJ1HQY80VucsEIG9tQ//HrTlG6sfofA3nRGr6TmkX661uJyu4cMPPh6kXW+aHdq/7+q25KyQhDrXvRL7jw==
-  dependencies:
-    "@malept/cross-spawn-promise" "^1.0.0"
-    debug "^4.1.1"
-    electron-installer-common "^0.10.2"
-    fs-extra "^9.0.0"
-    get-folder-size "^2.0.1"
-    lodash "^4.17.4"
-    word-wrap "^1.2.3"
-    yargs "^16.0.2"
-
-electron-installer-dmg@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/electron-installer-dmg/-/electron-installer-dmg-5.0.1.tgz#309662eccce4a8585a79fe4bce79c23976a950f0"
-  integrity sha512-qOa1aAQdX57C+vzhDk3549dd/PRlNL4F8y736MTD1a43qptD+PvHY97Bo9gSf+OZ8iUWE7BrYSpk/FgLUe40EA==
-  dependencies:
-    "@types/appdmg" "^0.5.5"
-    debug "^4.3.2"
-    minimist "^1.2.7"
-  optionalDependencies:
-    appdmg "^0.6.4"
-
-electron-installer-redhat@^3.2.0:
-  version "3.4.0"
-  resolved "https://registry.yarnpkg.com/electron-installer-redhat/-/electron-installer-redhat-3.4.0.tgz#4a7f8d67b48b7d5b23bd1eb074f4b684ae43b192"
-  integrity sha512-gEISr3U32Sgtj+fjxUAlSDo3wyGGq6OBx7rF5UdpIgbnpUvMN4W5uYb0ThpnAZ42VEJh/3aODQXHbFS4f5J3Iw==
-  dependencies:
-    "@malept/cross-spawn-promise" "^1.0.0"
-    debug "^4.1.1"
-    electron-installer-common "^0.10.2"
-    fs-extra "^9.0.0"
-    lodash "^4.17.15"
-    word-wrap "^1.2.3"
-    yargs "^16.0.2"
-
-electron-is-dev@^0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-0.3.0.tgz#14e6fda5c68e9e4ecbeff9ccf037cbd7c05c5afe"
-  integrity sha512-jLttuuq8QK67n3mXmIe9pkrO7IH3LGIk12xJkhTmc852U2sCJaRAOpRGPSh+1Xnzck5v9escd9YXzuze9nGejg==
-
[email protected]:
-  version "4.3.1"
-  resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-4.3.1.tgz#1405fef9d4e6964a5fdb8790a69163aa237ffe91"
-  integrity sha512-S/0CMjYjgyWUsZ3d27VvErPaI5W4oILp4jfeCuN4DhDqrJW6jKRUD2PxFfTdeZEIjM7+fttGg7A61rPcAcZC1w==
-
-electron-log@^4.2.3:
-  version "4.4.8"
-  resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-4.4.8.tgz#fcb9f714dbcaefb6ac7984c4683912c74730248a"
-  integrity sha512-QQ4GvrXO+HkgqqEOYbi+DHL7hj5JM+nHi/j+qrN9zeeXVKy8ZABgbu4CnG+BBqDZ2+tbeq9tUC4DZfIWFU5AZA==
-
[email protected]:
-  version "24.13.1"
-  resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-24.13.1.tgz#57289b2f7af18737dc2ad134668cdd4a1b574a0c"
-  integrity sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==
-  dependencies:
-    "@types/fs-extra" "^9.0.11"
-    builder-util "24.13.1"
-    builder-util-runtime "9.2.4"
-    chalk "^4.1.2"
-    fs-extra "^10.1.0"
-    lazy-val "^1.0.5"
-    mime "^2.5.2"
-
[email protected]:
-  version "26.0.11"
-  resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-26.0.11.tgz#92c9329a101af2836d9d228c82966eca1eee9a7b"
-  integrity sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==
-  dependencies:
-    "@types/fs-extra" "^9.0.11"
-    builder-util "26.0.11"
-    builder-util-runtime "9.3.1"
-    chalk "^4.1.2"
-    form-data "^4.0.0"
-    fs-extra "^10.1.0"
-    lazy-val "^1.0.5"
-    mime "^2.5.2"
-
[email protected]:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/electron-squirrel-startup/-/electron-squirrel-startup-1.0.0.tgz#19b4e55933fa0ef8f556784b9c660f772546a0b8"
-  integrity sha512-Oce8mvgGdFmwr+DsAcXBmFK8jFfN6yaFAP9IvyhTfupM3nFkBku/7VS/mdtJteWumImkC6P+BKGsxScoDDkv9Q==
-  dependencies:
-    debug "^2.2.0"
-
[email protected]:
-  version "5.0.3"
-  resolved "https://registry.yarnpkg.com/electron-window-state/-/electron-window-state-5.0.3.tgz#4f36d09e3f953d87aff103bf010f460056050aa8"
-  integrity sha512-1mNTwCfkolXl3kMf50yW3vE2lZj0y92P/HYWFBrb+v2S/pCka5mdwN3cagKm458A7NjndSwijynXgcLWRodsVg==
-  dependencies:
-    jsonfile "^4.0.0"
-    mkdirp "^0.5.1"
-
-electron-winstaller@^5.3.0:
-  version "5.4.0"
-  resolved "https://registry.yarnpkg.com/electron-winstaller/-/electron-winstaller-5.4.0.tgz#f0660d476d5c4f579fdf7edd2f0cf01d54c4d0b2"
-  integrity sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==
-  dependencies:
-    "@electron/asar" "^3.2.1"
-    debug "^4.1.1"
-    fs-extra "^7.0.1"
-    lodash "^4.17.21"
-    temp "^0.9.0"
-  optionalDependencies:
-    "@electron/windows-sign" "^1.1.2"
-
-electron-wix-msi@^5.1.3:
-  version "5.1.3"
-  resolved "https://registry.yarnpkg.com/electron-wix-msi/-/electron-wix-msi-5.1.3.tgz#ab85dc1145a7ce7ae7724ed3ca3f92c447988c9a"
-  integrity sha512-EYj1cm1nZoVHmIIx3o0aKt784lxdEpJnXbEnyypklUCnglqSb7ni+1xi1Vp/gtrGS/mzIxnWBT+x5fIfuDjhvA==
-  dependencies:
-    "@electron/windows-sign" "^1.1.2"
-    debug "^4.3.4"
-    fs-extra "^10.1.0"
-    klaw "^4.1.0"
-    lodash "^4.17.21"
-    rcedit "^4.0.1"
-    rcinfo "^0.1.3"
-    semver "^7.6.0"
-  optionalDependencies:
-    "@bitdisaster/exe-icon-extractor" "^1.0.10"
-
-electron@*, [email protected]:
-  version "34.5.6"
-  resolved "https://registry.yarnpkg.com/electron/-/electron-34.5.6.tgz#b18f1973df9846ff41ab98c7f9a25c35d5ebf731"
-  integrity sha512-cmP0CDnWFwyZrzn72AXS9oJiOjNIRPgKpGO2ykz3Syo+9B2RJ9WQzxOKkpntcWE5/nRsyFkRUCMTgGo3uNvCxQ==
-  dependencies:
-    "@electron/get" "^2.0.0"
-    "@types/node" "^20.9.0"
-    extract-zip "^2.0.1"
-
-emoji-regex@^8.0.0:
-  version "8.0.0"
-  resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
-  integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
-
-encode-utf8@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda"
-  integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==
-
-encoding@^0.1.13:
-  version "0.1.13"
-  resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
-  integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==
-  dependencies:
-    iconv-lite "^0.6.2"
-
-end-of-stream@^1.1.0:
-  version "1.4.4"
-  resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
-  integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
-  dependencies:
-    once "^1.4.0"
-
-env-paths@^2.2.0:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
-  integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
-
-err-code@^2.0.2:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9"
-  integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
-
-error-ex@^1.2.0:
-  version "1.3.2"
-  resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
-  integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
-  dependencies:
-    is-arrayish "^0.2.1"
-
-es-define-property@^1.0.0, es-define-property@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa"
-  integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==
-
-es-errors@^1.3.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
-  integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
-
-es-object-atoms@^1.0.0, es-object-atoms@^1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1"
-  integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==
-  dependencies:
-    es-errors "^1.3.0"
-
-es-set-tostringtag@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d"
-  integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==
-  dependencies:
-    es-errors "^1.3.0"
-    get-intrinsic "^1.2.6"
-    has-tostringtag "^1.0.2"
-    hasown "^2.0.2"
-
-es6-error@^4.1.1:
-  version "4.1.1"
-  resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d"
-  integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==
-
-escalade@^3.1.1:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
-  integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
-
-escape-goat@^2.0.0:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675"
-  integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==
-
-escape-string-regexp@^1.0.2:
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
-  integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
-
-escape-string-regexp@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
-  integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
-
-event-target-shim@^5.0.0:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
-  integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
-
-eventemitter3@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4"
-  integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
-
-execa@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
-  integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
-  dependencies:
-    cross-spawn "^6.0.0"
-    get-stream "^4.0.0"
-    is-stream "^1.1.0"
-    npm-run-path "^2.0.0"
-    p-finally "^1.0.0"
-    signal-exit "^3.0.0"
-    strip-eof "^1.0.0"
-
-exponential-backoff@^3.1.1:
-  version "3.1.2"
-  resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.2.tgz#a8f26adb96bf78e8cd8ad1037928d5e5c0679d91"
-  integrity sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==
-
-ext-list@^2.0.0:
-  version "2.2.2"
-  resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37"
-  integrity sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==
-  dependencies:
-    mime-db "^1.28.0"
-
-ext-name@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/ext-name/-/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6"
-  integrity sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==
-  dependencies:
-    ext-list "^2.0.0"
-    sort-keys-length "^1.0.0"
-
[email protected], extract-zip@^2.0.0, extract-zip@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
-  integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
-  dependencies:
-    debug "^4.1.1"
-    get-stream "^5.1.0"
-    yauzl "^2.10.0"
-  optionalDependencies:
-    "@types/yauzl" "^2.9.1"
-
-extsprintf@^1.2.0:
-  version "1.4.1"
-  resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07"
-  integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==
-
-fast-decode-uri-component@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543"
-  integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==
-
-fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
-  version "3.1.3"
-  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
-  integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
-
-fast-glob@^3.2.7:
-  version "3.3.3"
-  resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818"
-  integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==
-  dependencies:
-    "@nodelib/fs.stat" "^2.0.2"
-    "@nodelib/fs.walk" "^1.2.3"
-    glob-parent "^5.1.2"
-    merge2 "^1.3.0"
-    micromatch "^4.0.8"
-
-fast-json-stable-stringify@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
-  integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
-
-fast-json-stringify@^6.0.0:
-  version "6.0.1"
-  resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-6.0.1.tgz#82f1cb45fa96d0ca24b601f1738066976d6e2430"
-  integrity sha512-s7SJE83QKBZwg54dIbD5rCtzOBVD43V1ReWXXYqBgwCwHLYAAT0RQc/FmrQglXqWPpz6omtryJQOau5jI4Nrvg==
-  dependencies:
-    "@fastify/merge-json-schemas" "^0.2.0"
-    ajv "^8.12.0"
-    ajv-formats "^3.0.1"
-    fast-uri "^3.0.0"
-    json-schema-ref-resolver "^2.0.0"
-    rfdc "^1.2.0"
-
-fast-querystring@^1.0.0:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/fast-querystring/-/fast-querystring-1.1.2.tgz#a6d24937b4fc6f791b4ee31dcb6f53aeafb89f53"
-  integrity sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==
-  dependencies:
-    fast-decode-uri-component "^1.0.1"
-
-fast-redact@^3.1.1:
-  version "3.5.0"
-  resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4"
-  integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==
-
-fast-uri@^3.0.0, fast-uri@^3.0.1:
-  version "3.0.6"
-  resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748"
-  integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==
-
-fastify-plugin@^5.0.0:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-5.0.1.tgz#82d44e6fe34d1420bb5a4f7bee434d501e41939f"
-  integrity sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ==
-
[email protected]:
-  version "5.3.2"
-  resolved "https://registry.yarnpkg.com/fastify/-/fastify-5.3.2.tgz#88c895a30c0f67166979077ac8649fe8b205a1b3"
-  integrity sha512-AIPqBgtqBAwkOkrnwesEE+dOyU30dQ4kh7udxeGVR05CRGwubZx+p2H8P0C4cRnQT0+EPK4VGea2DTL2RtWttg==
-  dependencies:
-    "@fastify/ajv-compiler" "^4.0.0"
-    "@fastify/error" "^4.0.0"
-    "@fastify/fast-json-stringify-compiler" "^5.0.0"
-    "@fastify/proxy-addr" "^5.0.0"
-    abstract-logging "^2.0.1"
-    avvio "^9.0.0"
-    fast-json-stringify "^6.0.0"
-    find-my-way "^9.0.0"
-    light-my-request "^6.0.0"
-    pino "^9.0.0"
-    process-warning "^5.0.0"
-    rfdc "^1.3.1"
-    secure-json-parse "^4.0.0"
-    semver "^7.6.0"
-    toad-cache "^3.7.0"
-
-fastq@^1.17.1, fastq@^1.6.0:
-  version "1.19.1"
-  resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5"
-  integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==
-  dependencies:
-    reusify "^1.0.4"
-
-fd-slicer@~1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
-  integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==
-  dependencies:
-    pend "~1.2.0"
-
-fflate@^0.4.1:
-  version "0.4.8"
-  resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae"
-  integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==
-
[email protected]:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
-  integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
-
-filelist@^1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5"
-  integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==
-  dependencies:
-    minimatch "^5.0.1"
-
-filename-reserved-regex@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229"
-  integrity sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==
-
-filenamify@^4.1.0:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-4.3.0.tgz#62391cb58f02b09971c9d4f9d63b3cf9aba03106"
-  integrity sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==
-  dependencies:
-    filename-reserved-regex "^2.0.0"
-    strip-outer "^1.0.1"
-    trim-repeated "^1.0.0"
-
-fill-range@^7.1.1:
-  version "7.1.1"
-  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
-  integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
-  dependencies:
-    to-regex-range "^5.0.1"
-
-find-my-way@^9.0.0:
-  version "9.3.0"
-  resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-9.3.0.tgz#9f57786b5d772cc45142bf39dd5349f9cc883f91"
-  integrity sha512-eRoFWQw+Yv2tuYlK2pjFS2jGXSxSppAs3hSQjfxVKxM5amECzIgYYc1FEI8ZmhSh/Ig+FrKEz43NLRKJjYCZVg==
-  dependencies:
-    fast-deep-equal "^3.1.3"
-    fast-querystring "^1.0.0"
-    safe-regex2 "^5.0.0"
-
-find-up@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
-  integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==
-  dependencies:
-    locate-path "^2.0.0"
-
-find-up@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
-  integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
-  dependencies:
-    locate-path "^6.0.0"
-    path-exists "^4.0.0"
-
-flora-colossus@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/flora-colossus/-/flora-colossus-2.0.0.tgz#af1e85db0a8256ef05f3fb531c1235236c97220a"
-  integrity sha512-dz4HxH6pOvbUzZpZ/yXhafjbR2I8cenK5xL0KtBFb7U2ADsR+OwXifnxZjij/pZWF775uSCMzWVd+jDik2H2IA==
-  dependencies:
-    debug "^4.3.4"
-    fs-extra "^10.1.0"
-
-fmix@^0.1.0:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c"
-  integrity sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==
-  dependencies:
-    imul "^1.0.0"
-
-foreground-child@^3.1.0:
-  version "3.3.1"
-  resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f"
-  integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==
-  dependencies:
-    cross-spawn "^7.0.6"
-    signal-exit "^4.0.1"
-
-form-data@^4.0.0:
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.2.tgz#35cabbdd30c3ce73deb2c42d3c8d3ed9ca51794c"
-  integrity sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==
-  dependencies:
-    asynckit "^0.4.0"
-    combined-stream "^1.0.8"
-    es-set-tostringtag "^2.1.0"
-    mime-types "^2.1.12"
-
[email protected], fs-extra@^9.0.0, fs-extra@^9.0.1:
-  version "9.1.0"
-  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
-  integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==
-  dependencies:
-    at-least-node "^1.0.0"
-    graceful-fs "^4.2.0"
-    jsonfile "^6.0.1"
-    universalify "^2.0.0"
-
-fs-extra@^10.0.0, fs-extra@^10.1.0:
-  version "10.1.0"
-  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
-  integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
-  dependencies:
-    graceful-fs "^4.2.0"
-    jsonfile "^6.0.1"
-    universalify "^2.0.0"
-
-fs-extra@^11.1.0, fs-extra@^11.1.1:
-  version "11.3.0"
-  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d"
-  integrity sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==
-  dependencies:
-    graceful-fs "^4.2.0"
-    jsonfile "^6.0.1"
-    universalify "^2.0.0"
-
-fs-extra@^7.0.1:
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
-  integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
-  dependencies:
-    graceful-fs "^4.1.2"
-    jsonfile "^4.0.0"
-    universalify "^0.1.0"
-
-fs-extra@^8.1.0:
-  version "8.1.0"
-  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
-  integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
-  dependencies:
-    graceful-fs "^4.2.0"
-    jsonfile "^4.0.0"
-    universalify "^0.1.0"
-
-fs-minipass@^2.0.0, fs-minipass@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
-  integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
-  dependencies:
-    minipass "^3.0.0"
-
-fs-minipass@^3.0.0:
-  version "3.0.3"
-  resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54"
-  integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==
-  dependencies:
-    minipass "^7.0.3"
-
-fs-temp@^1.0.0:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/fs-temp/-/fs-temp-1.2.1.tgz#ffd136ef468177accc3c267d4510f6ce3b2b9697"
-  integrity sha512-okTwLB7/Qsq82G6iN5zZJFsOfZtx2/pqrA7Hk/9fvy+c+eJS9CvgGXT2uNxwnI14BDY9L/jQPkaBgSvlKfSW9w==
-  dependencies:
-    random-path "^0.1.0"
-
-fs-xattr@^0.3.0:
-  version "0.3.1"
-  resolved "https://registry.yarnpkg.com/fs-xattr/-/fs-xattr-0.3.1.tgz#a23d88571031f6c56f26d59e0bab7d2e12f49f77"
-  integrity sha512-UVqkrEW0GfDabw4C3HOrFlxKfx0eeigfRne69FxSBdHIP8Qt5Sq6Pu3RM9KmMlkygtC4pPKkj5CiPO5USnj2GA==
-
-fs.realpath@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
-  integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
-
-fsevents@~2.3.2:
-  version "2.3.3"
-  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
-  integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
-
-function-bind@^1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
-  integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
-
-galactus@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/galactus/-/galactus-1.0.0.tgz#c2615182afa0c6d0859b92e56ae36d052827db7e"
-  integrity sha512-R1fam6D4CyKQGNlvJne4dkNF+PvUUl7TAJInvTGa9fti9qAv95quQz29GXapA4d8Ec266mJJxFVh82M4GIIGDQ==
-  dependencies:
-    debug "^4.3.4"
-    flora-colossus "^2.0.0"
-    fs-extra "^10.1.0"
-
-gar@^1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/gar/-/gar-1.0.4.tgz#f777bc7db425c0572fdeb52676172ca1ae9888b8"
-  integrity sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w==
-
-generate-function@^2.0.0:
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f"
-  integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==
-  dependencies:
-    is-property "^1.0.2"
-
-generate-object-property@^1.1.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
-  integrity sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ==
-  dependencies:
-    is-property "^1.0.0"
-
-get-caller-file@^2.0.5:
-  version "2.0.5"
-  resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
-  integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
-
-get-folder-size@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/get-folder-size/-/get-folder-size-2.0.1.tgz#3fe0524dd3bad05257ef1311331417bcd020a497"
-  integrity sha512-+CEb+GDCM7tkOS2wdMKTn9vU7DgnKUTuDlehkNJKNSovdCOVxs14OfKCk4cvSaR3za4gj+OBdl9opPN9xrJ0zA==
-  dependencies:
-    gar "^1.0.4"
-    tiny-each-async "2.0.3"
-
-get-intrinsic@^1.2.6:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01"
-  integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==
-  dependencies:
-    call-bind-apply-helpers "^1.0.2"
-    es-define-property "^1.0.1"
-    es-errors "^1.3.0"
-    es-object-atoms "^1.1.1"
-    function-bind "^1.1.2"
-    get-proto "^1.0.1"
-    gopd "^1.2.0"
-    has-symbols "^1.1.0"
-    hasown "^2.0.2"
-    math-intrinsics "^1.1.0"
-
-get-package-info@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/get-package-info/-/get-package-info-1.0.0.tgz#6432796563e28113cd9474dbbd00052985a4999c"
-  integrity sha512-SCbprXGAPdIhKAXiG+Mk6yeoFH61JlYunqdFQFHDtLjJlDjFf6x07dsS8acO+xWt52jpdVo49AlVDnUVK1sDNw==
-  dependencies:
-    bluebird "^3.1.1"
-    debug "^2.2.0"
-    lodash.get "^4.0.0"
-    read-pkg-up "^2.0.0"
-
-get-proto@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
-  integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==
-  dependencies:
-    dunder-proto "^1.0.1"
-    es-object-atoms "^1.0.0"
-
-get-stream@^4.0.0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
-  integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
-  dependencies:
-    pump "^3.0.0"
-
-get-stream@^5.1.0:
-  version "5.2.0"
-  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
-  integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
-  dependencies:
-    pump "^3.0.0"
-
-github-url-to-object@^4.0.4:
-  version "4.0.6"
-  resolved "https://registry.yarnpkg.com/github-url-to-object/-/github-url-to-object-4.0.6.tgz#5ea8701dc8c336b8d582dc3fa5bf964165c3b365"
-  integrity sha512-NaqbYHMUAlPcmWFdrAB7bcxrNIiiJWJe8s/2+iOc9vlcHlwHqSGrPk+Yi3nu6ebTwgsZEa7igz+NH2vEq3gYwQ==
-  dependencies:
-    is-url "^1.1.0"
-
-glob-parent@^5.1.2, glob-parent@~5.1.2:
-  version "5.1.2"
-  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
-  integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
-  dependencies:
-    is-glob "^4.0.1"
-
-glob@^10.2.2, glob@^10.3.10, glob@^10.3.12:
-  version "10.4.5"
-  resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956"
-  integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==
-  dependencies:
-    foreground-child "^3.1.0"
-    jackspeak "^3.1.2"
-    minimatch "^9.0.4"
-    minipass "^7.1.2"
-    package-json-from-dist "^1.0.0"
-    path-scurry "^1.11.1"
-
-glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
-  version "7.2.3"
-  resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
-  integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
-  dependencies:
-    fs.realpath "^1.0.0"
-    inflight "^1.0.4"
-    inherits "2"
-    minimatch "^3.1.1"
-    once "^1.3.0"
-    path-is-absolute "^1.0.0"
-
-glob@^8.0.1, glob@^8.1.0:
-  version "8.1.0"
-  resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
-  integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
-  dependencies:
-    fs.realpath "^1.0.0"
-    inflight "^1.0.4"
-    inherits "2"
-    minimatch "^5.0.1"
-    once "^1.3.0"
-
-global-agent@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-3.0.0.tgz#ae7cd31bd3583b93c5a16437a1afe27cc33a1ab6"
-  integrity sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==
-  dependencies:
-    boolean "^3.0.1"
-    es6-error "^4.1.1"
-    matcher "^3.0.0"
-    roarr "^2.15.3"
-    semver "^7.3.2"
-    serialize-error "^7.0.1"
-
-global-dirs@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485"
-  integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==
-  dependencies:
-    ini "2.0.0"
-
-globalthis@^1.0.1:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236"
-  integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==
-  dependencies:
-    define-properties "^1.2.1"
-    gopd "^1.0.1"
-
-gopd@^1.0.1, gopd@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1"
-  integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
-
-got@^11.7.0, got@^11.8.5:
-  version "11.8.6"
-  resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a"
-  integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==
-  dependencies:
-    "@sindresorhus/is" "^4.0.0"
-    "@szmarczak/http-timer" "^4.0.5"
-    "@types/cacheable-request" "^6.0.1"
-    "@types/responselike" "^1.0.0"
-    cacheable-lookup "^5.0.3"
-    cacheable-request "^7.0.2"
-    decompress-response "^6.0.0"
-    http2-wrapper "^1.0.0-beta.5.2"
-    lowercase-keys "^2.0.0"
-    p-cancelable "^2.0.0"
-    responselike "^2.0.0"
-
-graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.6:
-  version "4.2.11"
-  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
-  integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
-
-has-flag@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
-  integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
-
-has-property-descriptors@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
-  integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
-  dependencies:
-    es-define-property "^1.0.0"
-
-has-symbols@^1.0.3, has-symbols@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
-  integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==
-
-has-tostringtag@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc"
-  integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==
-  dependencies:
-    has-symbols "^1.0.3"
-
-hasown@^2.0.2:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
-  integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
-  dependencies:
-    function-bind "^1.1.2"
-
-hosted-git-info@^2.1.4:
-  version "2.8.9"
-  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
-  integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
-
-hosted-git-info@^4.1.0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224"
-  integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==
-  dependencies:
-    lru-cache "^6.0.0"
-
-http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1:
-  version "4.1.1"
-  resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
-  integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
-
-http-proxy-agent@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
-  integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
-  dependencies:
-    "@tootallnate/once" "2"
-    agent-base "6"
-    debug "4"
-
-http-proxy-agent@^7.0.0:
-  version "7.0.2"
-  resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e"
-  integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==
-  dependencies:
-    agent-base "^7.1.0"
-    debug "^4.3.4"
-
-http2-wrapper@^1.0.0-beta.5.2:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d"
-  integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==
-  dependencies:
-    quick-lru "^5.1.1"
-    resolve-alpn "^1.0.0"
-
[email protected]:
-  version "7.0.2"
-  resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b"
-  integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==
-  dependencies:
-    agent-base "^7.0.2"
-    debug "4"
-
-https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
-  integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
-  dependencies:
-    agent-base "6"
-    debug "4"
-
-https-proxy-agent@^7.0.0:
-  version "7.0.6"
-  resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9"
-  integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==
-  dependencies:
-    agent-base "^7.1.2"
-    debug "4"
-
-https-proxy-agent@^7.0.1:
-  version "7.0.5"
-  resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2"
-  integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==
-  dependencies:
-    agent-base "^7.0.2"
-    debug "4"
-
-humanize-ms@^1.2.1:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
-  integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==
-  dependencies:
-    ms "^2.0.0"
-
-iconv-corefoundation@^1.1.7:
-  version "1.1.7"
-  resolved "https://registry.yarnpkg.com/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz#31065e6ab2c9272154c8b0821151e2c88f1b002a"
-  integrity sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==
-  dependencies:
-    cli-truncate "^2.1.0"
-    node-addon-api "^1.6.3"
-
-iconv-lite@^0.6.2:
-  version "0.6.3"
-  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
-  integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
-  dependencies:
-    safer-buffer ">= 2.1.2 < 3.0.0"
-
-ieee754@^1.1.13:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
-  integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
-
-image-size@^0.7.4:
-  version "0.7.5"
-  resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.7.5.tgz#269f357cf5797cb44683dfa99790e54c705ead04"
-  integrity sha512-Hiyv+mXHfFEP7LzUL/llg9RwFxxY+o9N3JVLIeG5E7iFIFAalxvRU9UZthBdYDEVnzHMgjnKJPPpay5BWf1g9g==
-
-immediate@~3.0.5:
-  version "3.0.6"
-  resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
-  integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==
-
-imul@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9"
-  integrity sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==
-
-imurmurhash@^0.1.4:
-  version "0.1.4"
-  resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
-  integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
-
-indent-string@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
-  integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
-
-infer-owner@^1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
-  integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==
-
-inflight@^1.0.4:
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
-  integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
-  dependencies:
-    once "^1.3.0"
-    wrappy "1"
-
-inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
-  version "2.0.4"
-  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
-  integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-
[email protected]:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5"
-  integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==
-
-interpret@^3.1.1:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4"
-  integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==
-
-ip-address@^9.0.5:
-  version "9.0.5"
-  resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a"
-  integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==
-  dependencies:
-    jsbn "1.1.0"
-    sprintf-js "^1.1.3"
-
-ipaddr.js@^2.1.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8"
-  integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==
-
-is-arrayish@^0.2.1:
-  version "0.2.1"
-  resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
-  integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
-
-is-binary-path@~2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
-  integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
-  dependencies:
-    binary-extensions "^2.0.0"
-
-is-ci@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867"
-  integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==
-  dependencies:
-    ci-info "^3.2.0"
-
-is-core-module@^2.16.0:
-  version "2.16.1"
-  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4"
-  integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==
-  dependencies:
-    hasown "^2.0.2"
-
-is-docker@^2.0.0:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
-  integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
-
-is-extglob@^2.1.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
-  integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
-
-is-fullwidth-code-point@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
-  integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
-
-is-fullwidth-code-point@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88"
-  integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==
-
-is-glob@^4.0.1, is-glob@~4.0.1:
-  version "4.0.3"
-  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
-  integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
-  dependencies:
-    is-extglob "^2.1.1"
-
-is-interactive@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
-  integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
-
-is-lambda@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5"
-  integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==
-
-is-my-ip-valid@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.1.tgz#f7220d1146257c98672e6fba097a9f3f2d348442"
-  integrity sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg==
-
-is-my-json-valid@^2.20.0:
-  version "2.20.6"
-  resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.6.tgz#a9d89e56a36493c77bda1440d69ae0dc46a08387"
-  integrity sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw==
-  dependencies:
-    generate-function "^2.0.0"
-    generate-object-property "^1.1.0"
-    is-my-ip-valid "^1.0.0"
-    jsonpointer "^5.0.0"
-    xtend "^4.0.0"
-
-is-number@^7.0.0:
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
-  integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
-
-is-plain-obj@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
-  integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==
-
-is-property@^1.0.0, is-property@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
-  integrity sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==
-
-is-stream@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
-  integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==
-
-is-unicode-supported@^0.1.0:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
-  integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
-
-is-url@^1.1.0, is-url@^1.2.4:
-  version "1.2.4"
-  resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52"
-  integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==
-
-is-wsl@^2.1.1, is-wsl@^2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
-  integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
-  dependencies:
-    is-docker "^2.0.0"
-
-isarray@~1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
-  integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
-
-isbinaryfile@^4.0.8:
-  version "4.0.10"
-  resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3"
-  integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==
-
-isbinaryfile@^5.0.0:
-  version "5.0.4"
-  resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-5.0.4.tgz#2a2edefa76cafa66613fe4c1ea52f7f031017bdf"
-  integrity sha512-YKBKVkKhty7s8rxddb40oOkuP0NbaeXrQvLin6QMHL7Ypiy2RW9LwOVrVgZRyOrhQlayMd9t+D8yDy8MKFTSDQ==
-
-isexe@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
-  integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
-
-isexe@^3.1.1:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d"
-  integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==
-
-jackspeak@^3.1.2:
-  version "3.4.3"
-  resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a"
-  integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==
-  dependencies:
-    "@isaacs/cliui" "^8.0.2"
-  optionalDependencies:
-    "@pkgjs/parseargs" "^0.11.0"
-
-jake@^10.8.5:
-  version "10.9.2"
-  resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f"
-  integrity sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==
-  dependencies:
-    async "^3.2.3"
-    chalk "^4.0.2"
-    filelist "^1.0.4"
-    minimatch "^3.1.2"
-
-jiti@^2.4.2:
-  version "2.4.2"
-  resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560"
-  integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==
-
-js-yaml@^4.1.0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
-  integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
-  dependencies:
-    argparse "^2.0.1"
-
[email protected]:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040"
-  integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==
-
[email protected]:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
-  integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
-
-json-schema-ref-resolver@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/json-schema-ref-resolver/-/json-schema-ref-resolver-2.0.1.tgz#c92f16b452df069daac53e1984159e0f9af0598d"
-  integrity sha512-HG0SIB9X4J8bwbxCbnd5FfPEbcXAJYTi1pBJeP/QPON+w8ovSME8iRG+ElHNxZNX2Qh6eYn1GdzJFS4cDFfx0Q==
-  dependencies:
-    dequal "^2.0.3"
-
-json-schema-traverse@^0.4.1:
-  version "0.4.1"
-  resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
-  integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
-
-json-schema-traverse@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
-  integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
-
-json-stringify-safe@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
-  integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==
-
-json5@^2.2.0, json5@^2.2.3:
-  version "2.2.3"
-  resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
-  integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
-
-jsonfile@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
-  integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==
-  optionalDependencies:
-    graceful-fs "^4.1.6"
-
-jsonfile@^6.0.1:
-  version "6.1.0"
-  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
-  integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
-  dependencies:
-    universalify "^2.0.0"
-  optionalDependencies:
-    graceful-fs "^4.1.6"
-
-jsonpointer@^5.0.0:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559"
-  integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==
-
-jszip@^3.1.0:
-  version "3.10.1"
-  resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2"
-  integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==
-  dependencies:
-    lie "~3.3.0"
-    pako "~1.0.2"
-    readable-stream "~2.3.6"
-    setimmediate "^1.0.5"
-
-junk@^3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1"
-  integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==
-
-keyv@^4.0.0:
-  version "4.5.4"
-  resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
-  integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
-  dependencies:
-    json-buffer "3.0.1"
-
-klaw@^4.1.0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/klaw/-/klaw-4.1.0.tgz#5df608067d8cb62bbfb24374f8e5d956323338f3"
-  integrity sha512-1zGZ9MF9H22UnkpVeuaGKOjfA2t6WrfdrJmGjy16ykcjnKQDmHVX+KI477rpbGevz/5FD4MC3xf1oxylBgcaQw==
-
-lazy-val@^1.0.4, lazy-val@^1.0.5:
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.5.tgz#6cf3b9f5bc31cee7ee3e369c0832b7583dcd923d"
-  integrity sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==
-
-lie@~3.3.0:
-  version "3.3.0"
-  resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
-  integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==
-  dependencies:
-    immediate "~3.0.5"
-
-light-my-request@^6.0.0:
-  version "6.6.0"
-  resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-6.6.0.tgz#c9448772323f65f33720fb5979c7841f14060add"
-  integrity sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==
-  dependencies:
-    cookie "^1.0.1"
-    process-warning "^4.0.0"
-    set-cookie-parser "^2.6.0"
-
-listr2@^7.0.2:
-  version "7.0.2"
-  resolved "https://registry.yarnpkg.com/listr2/-/listr2-7.0.2.tgz#3aa3e1549dfaf3c57ab5eeaba754da3b87f33063"
-  integrity sha512-rJysbR9GKIalhTbVL2tYbF2hVyDnrf7pFUZBwjPaMIdadYHmeT+EVi/Bu3qd7ETQPahTotg2WRCatXwRBW554g==
-  dependencies:
-    cli-truncate "^3.1.0"
-    colorette "^2.0.20"
-    eventemitter3 "^5.0.1"
-    log-update "^5.0.1"
-    rfdc "^1.3.0"
-    wrap-ansi "^8.1.0"
-
-load-json-file@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8"
-  integrity sha512-3p6ZOGNbiX4CdvEd1VcE6yi78UrGNpjHO33noGwHCnT/o2fyllJDepsm8+mFFv/DvtwFHht5HIHSyOy5a+ChVQ==
-  dependencies:
-    graceful-fs "^4.1.2"
-    parse-json "^2.2.0"
-    pify "^2.0.0"
-    strip-bom "^3.0.0"
-
-locate-path@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
-  integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==
-  dependencies:
-    p-locate "^2.0.0"
-    path-exists "^3.0.0"
-
-locate-path@^6.0.0:
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
-  integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
-  dependencies:
-    p-locate "^5.0.0"
-
-lodash.get@^4.0.0:
-  version "4.4.2"
-  resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
-  integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==
-
-lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4:
-  version "4.17.21"
-  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
-  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
-
-log-symbols@^4.0.0, log-symbols@^4.1.0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
-  integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
-  dependencies:
-    chalk "^4.1.0"
-    is-unicode-supported "^0.1.0"
-
-log-update@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/log-update/-/log-update-5.0.1.tgz#9e928bf70cb183c1f0c9e91d9e6b7115d597ce09"
-  integrity sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==
-  dependencies:
-    ansi-escapes "^5.0.0"
-    cli-cursor "^4.0.0"
-    slice-ansi "^5.0.0"
-    strip-ansi "^7.0.1"
-    wrap-ansi "^8.0.1"
-
-lowercase-keys@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
-  integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
-
-lru-cache@^10.0.1, lru-cache@^10.2.0:
-  version "10.4.3"
-  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
-  integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
-
-lru-cache@^6.0.0:
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
-  integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
-  dependencies:
-    yallist "^4.0.0"
-
-lru-cache@^7.7.1:
-  version "7.18.3"
-  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89"
-  integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==
-
-lru_map@^0.3.3:
-  version "0.3.3"
-  resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd"
-  integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==
-
-macos-alias@~0.2.5:
-  version "0.2.12"
-  resolved "https://registry.yarnpkg.com/macos-alias/-/macos-alias-0.2.12.tgz#c984db71b7c2372924548291a0790b43c080606b"
-  integrity sha512-yiLHa7cfJcGRFq4FrR4tMlpNHb4Vy4mWnpajlSSIFM5k4Lv8/7BbbDLzCAVogWNl0LlLhizRp1drXv0hK9h0Yw==
-  dependencies:
-    nan "^2.4.0"
-
-make-fetch-happen@^10.2.1:
-  version "10.2.1"
-  resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz#f5e3835c5e9817b617f2770870d9492d28678164"
-  integrity sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==
-  dependencies:
-    agentkeepalive "^4.2.1"
-    cacache "^16.1.0"
-    http-cache-semantics "^4.1.0"
-    http-proxy-agent "^5.0.0"
-    https-proxy-agent "^5.0.0"
-    is-lambda "^1.0.1"
-    lru-cache "^7.7.1"
-    minipass "^3.1.6"
-    minipass-collect "^1.0.2"
-    minipass-fetch "^2.0.3"
-    minipass-flush "^1.0.5"
-    minipass-pipeline "^1.2.4"
-    negotiator "^0.6.3"
-    promise-retry "^2.0.1"
-    socks-proxy-agent "^7.0.0"
-    ssri "^9.0.0"
-
-make-fetch-happen@^14.0.3:
-  version "14.0.3"
-  resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz#d74c3ecb0028f08ab604011e0bc6baed483fcdcd"
-  integrity sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==
-  dependencies:
-    "@npmcli/agent" "^3.0.0"
-    cacache "^19.0.1"
-    http-cache-semantics "^4.1.1"
-    minipass "^7.0.2"
-    minipass-fetch "^4.0.0"
-    minipass-flush "^1.0.5"
-    minipass-pipeline "^1.2.4"
-    negotiator "^1.0.0"
-    proc-log "^5.0.0"
-    promise-retry "^2.0.1"
-    ssri "^12.0.0"
-
-map-age-cleaner@^0.1.1:
-  version "0.1.3"
-  resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
-  integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
-  dependencies:
-    p-defer "^1.0.0"
-
-matcher@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca"
-  integrity sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==
-  dependencies:
-    escape-string-regexp "^4.0.0"
-
-math-intrinsics@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
-  integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
-
-mem@^4.3.0:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
-  integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
-  dependencies:
-    map-age-cleaner "^0.1.1"
-    mimic-fn "^2.0.0"
-    p-is-promise "^2.0.0"
-
-merge2@^1.3.0:
-  version "1.4.1"
-  resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
-  integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
-
-micromatch@^4.0.8:
-  version "4.0.8"
-  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
-  integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
-  dependencies:
-    braces "^3.0.3"
-    picomatch "^2.3.1"
-
[email protected]:
-  version "1.52.0"
-  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
-  integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
-
-mime-db@^1.28.0:
-  version "1.54.0"
-  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5"
-  integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==
-
-mime-types@^2.1.12:
-  version "2.1.35"
-  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
-  integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
-  dependencies:
-    mime-db "1.52.0"
-
-mime@^2.5.2:
-  version "2.6.0"
-  resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367"
-  integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==
-
-mimic-fn@^2.0.0, mimic-fn@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
-  integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
-
-mimic-response@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
-  integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
-
-mimic-response@^3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
-  integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
-
-minimatch@^10.0.0:
-  version "10.0.1"
-  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b"
-  integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==
-  dependencies:
-    brace-expansion "^2.0.1"
-
-minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
-  version "3.1.2"
-  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
-  integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
-  dependencies:
-    brace-expansion "^1.1.7"
-
-minimatch@^5.0.1, minimatch@^5.1.1:
-  version "5.1.6"
-  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
-  integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
-  dependencies:
-    brace-expansion "^2.0.1"
-
-minimatch@^9.0.3, minimatch@^9.0.4:
-  version "9.0.5"
-  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5"
-  integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==
-  dependencies:
-    brace-expansion "^2.0.1"
-
-minimist@^1.1.3, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.7, minimist@^1.2.8:
-  version "1.2.8"
-  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
-  integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
-
-minipass-collect@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617"
-  integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==
-  dependencies:
-    minipass "^3.0.0"
-
-minipass-collect@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-2.0.1.tgz#1621bc77e12258a12c60d34e2276ec5c20680863"
-  integrity sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==
-  dependencies:
-    minipass "^7.0.3"
-
-minipass-fetch@^2.0.3:
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-2.1.2.tgz#95560b50c472d81a3bc76f20ede80eaed76d8add"
-  integrity sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==
-  dependencies:
-    minipass "^3.1.6"
-    minipass-sized "^1.0.3"
-    minizlib "^2.1.2"
-  optionalDependencies:
-    encoding "^0.1.13"
-
-minipass-fetch@^4.0.0:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-4.0.1.tgz#f2d717d5a418ad0b1a7274f9b913515d3e78f9e5"
-  integrity sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==
-  dependencies:
-    minipass "^7.0.3"
-    minipass-sized "^1.0.3"
-    minizlib "^3.0.1"
-  optionalDependencies:
-    encoding "^0.1.13"
-
-minipass-flush@^1.0.5:
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373"
-  integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==
-  dependencies:
-    minipass "^3.0.0"
-
-minipass-pipeline@^1.2.4:
-  version "1.2.4"
-  resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c"
-  integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==
-  dependencies:
-    minipass "^3.0.0"
-
-minipass-sized@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70"
-  integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==
-  dependencies:
-    minipass "^3.0.0"
-
-minipass@^3.0.0, minipass@^3.1.1, minipass@^3.1.6:
-  version "3.3.6"
-  resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a"
-  integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==
-  dependencies:
-    yallist "^4.0.0"
-
-minipass@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d"
-  integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==
-
-"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.2, minipass@^7.0.3, minipass@^7.0.4, minipass@^7.1.2:
-  version "7.1.2"
-  resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707"
-  integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
-
-minizlib@^2.1.1, minizlib@^2.1.2:
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
-  integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
-  dependencies:
-    minipass "^3.0.0"
-    yallist "^4.0.0"
-
-minizlib@^3.0.1:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-3.0.2.tgz#f33d638eb279f664439aa38dc5f91607468cb574"
-  integrity sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==
-  dependencies:
-    minipass "^7.1.2"
-
-mkdirp@^0.5.1:
-  version "0.5.6"
-  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
-  integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
-  dependencies:
-    minimist "^1.2.6"
-
-mkdirp@^1.0.3, mkdirp@^1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
-  integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
-
-mkdirp@^3.0.1:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50"
-  integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==
-
-modify-filename@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/modify-filename/-/modify-filename-1.1.0.tgz#9a2dec83806fbb2d975f22beec859ca26b393aa1"
-  integrity sha512-EickqnKq3kVVaZisYuCxhtKbZjInCuwgwZWyAmRIp1NTMhri7r3380/uqwrUHfaDiPzLVTuoNy4whX66bxPVog==
-
[email protected]:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
-  integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
-
-ms@^2.0.0, ms@^2.1.1, ms@^2.1.3:
-  version "2.1.3"
-  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
-  integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
-
-"murmur-32@^0.1.0 || ^0.2.0":
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/murmur-32/-/murmur-32-0.2.0.tgz#bf42b7567880db13cd92ca0c2c72eeea884f44c7"
-  integrity sha512-ZkcWZudylwF+ir3Ld1n7gL6bI2mQAzXvSobPwVtu8aYi2sbXeipeSkdcanRLzIofLcM5F53lGaKm2dk7orBi7Q==
-  dependencies:
-    encode-utf8 "^1.0.3"
-    fmix "^0.1.0"
-    imul "^1.0.0"
-
-nan@^2.4.0:
-  version "2.22.2"
-  resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.2.tgz#6b504fd029fb8f38c0990e52ad5c26772fdacfbb"
-  integrity sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==
-
-negotiator@^0.6.3:
-  version "0.6.4"
-  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7"
-  integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==
-
-negotiator@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a"
-  integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==
-
-nice-try@^1.0.4:
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
-  integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
-
[email protected], node-abi@^3.45.0:
-  version "3.75.0"
-  resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.75.0.tgz#2f929a91a90a0d02b325c43731314802357ed764"
-  integrity sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==
-  dependencies:
-    semver "^7.3.5"
-
-node-addon-api@^1.6.3:
-  version "1.7.2"
-  resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d"
-  integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==
-
-node-addon-api@^2.0.0:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
-  integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==
-
-node-api-version@^0.2.0:
-  version "0.2.1"
-  resolved "https://registry.yarnpkg.com/node-api-version/-/node-api-version-0.2.1.tgz#19bad54f6d65628cbee4e607a325e4488ace2de9"
-  integrity sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==
-  dependencies:
-    semver "^7.3.5"
-
[email protected]:
-  version "2.6.7"
-  resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
-  integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
-  dependencies:
-    whatwg-url "^5.0.0"
-
-node-fetch@^2.6.7:
-  version "2.7.0"
-  resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
-  integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
-  dependencies:
-    whatwg-url "^5.0.0"
-
[email protected]:
-  version "11.1.0"
-  resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-11.1.0.tgz#212a1d9c167c50d727d42659410780b40e07bbd3"
-  integrity sha512-/+7TuHKnBpnMvUQnsYEb0JOozDZqarQbfNuSGLXIjhStMT0fbw7IdSqWgopOP5xhRZE+lsbIvAHcekddruPZgQ==
-  dependencies:
-    env-paths "^2.2.0"
-    exponential-backoff "^3.1.1"
-    glob "^10.3.10"
-    graceful-fs "^4.2.6"
-    make-fetch-happen "^14.0.3"
-    nopt "^8.0.0"
-    proc-log "^5.0.0"
-    semver "^7.3.5"
-    tar "^7.4.3"
-    which "^5.0.0"
-
-nopt@^6.0.0:
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/nopt/-/nopt-6.0.0.tgz#245801d8ebf409c6df22ab9d95b65e1309cdb16d"
-  integrity sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==
-  dependencies:
-    abbrev "^1.0.0"
-
-nopt@^8.0.0:
-  version "8.1.0"
-  resolved "https://registry.yarnpkg.com/nopt/-/nopt-8.1.0.tgz#b11d38caf0f8643ce885818518064127f602eae3"
-  integrity sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==
-  dependencies:
-    abbrev "^3.0.0"
-
-normalize-package-data@^2.3.2:
-  version "2.5.0"
-  resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
-  integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
-  dependencies:
-    hosted-git-info "^2.1.4"
-    resolve "^1.10.0"
-    semver "2 || 3 || 4 || 5"
-    validate-npm-package-license "^3.0.1"
-
-normalize-path@^3.0.0, normalize-path@~3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
-  integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
-
-normalize-url@^6.0.1:
-  version "6.1.0"
-  resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
-  integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
-
-npm-run-path@^2.0.0:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
-  integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==
-  dependencies:
-    path-key "^2.0.0"
-
-object-keys@^1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
-  integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
-
-on-exit-leak-free@^2.1.0:
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8"
-  integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==
-
-once@^1.3.0, once@^1.3.1, once@^1.4.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
-  integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
-  dependencies:
-    wrappy "1"
-
-onetime@^5.1.0:
-  version "5.1.2"
-  resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
-  integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
-  dependencies:
-    mimic-fn "^2.1.0"
-
[email protected]:
-  version "7.3.1"
-  resolved "https://registry.yarnpkg.com/open/-/open-7.3.1.tgz#111119cb919ca1acd988f49685c4fdd0f4755356"
-  integrity sha512-f2wt9DCBKKjlFbjzGb8MOAW8LH8F0mrs1zc7KTjAJ9PZNQbfenzWbNP1VZJvw6ICMG9r14Ah6yfwPn7T7i646A==
-  dependencies:
-    is-docker "^2.0.0"
-    is-wsl "^2.1.1"
-
-ora@^5.1.0:
-  version "5.4.1"
-  resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18"
-  integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==
-  dependencies:
-    bl "^4.1.0"
-    chalk "^4.1.0"
-    cli-cursor "^3.1.0"
-    cli-spinners "^2.5.0"
-    is-interactive "^1.0.0"
-    is-unicode-supported "^0.1.0"
-    log-symbols "^4.1.0"
-    strip-ansi "^6.0.0"
-    wcwidth "^1.0.1"
-
-p-cancelable@^2.0.0:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf"
-  integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==
-
-p-defer@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
-  integrity sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==
-
-p-finally@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
-  integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==
-
-p-is-promise@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
-  integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
-
-p-limit@^1.1.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
-  integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==
-  dependencies:
-    p-try "^1.0.0"
-
-p-limit@^3.0.2, "p-limit@^3.1.0 ":
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
-  integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
-  dependencies:
-    yocto-queue "^0.1.0"
-
-p-locate@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
-  integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==
-  dependencies:
-    p-limit "^1.1.0"
-
-p-locate@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
-  integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
-  dependencies:
-    p-limit "^3.0.2"
-
-p-map@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
-  integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
-  dependencies:
-    aggregate-error "^3.0.0"
-
-p-map@^7.0.2:
-  version "7.0.3"
-  resolved "https://registry.yarnpkg.com/p-map/-/p-map-7.0.3.tgz#7ac210a2d36f81ec28b736134810f7ba4418cdb6"
-  integrity sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==
-
-p-try@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
-  integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==
-
-package-json-from-dist@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505"
-  integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==
-
-pako@~1.0.2:
-  version "1.0.11"
-  resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
-  integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
-
-parse-author@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/parse-author/-/parse-author-2.0.0.tgz#d3460bf1ddd0dfaeed42da754242e65fb684a81f"
-  integrity sha512-yx5DfvkN8JsHL2xk2Os9oTia467qnvRgey4ahSm2X8epehBLx/gWLcy5KI+Y36ful5DzGbCS6RazqZGgy1gHNw==
-  dependencies:
-    author-regex "^1.0.0"
-
-parse-color@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/parse-color/-/parse-color-1.0.0.tgz#7b748b95a83f03f16a94f535e52d7f3d94658619"
-  integrity sha512-fuDHYgFHJGbpGMgw9skY/bj3HL/Jrn4l/5rSspy00DoT4RyLnDcRvPxdZ+r6OFwIsgAuhDh4I09tAId4mI12bw==
-  dependencies:
-    color-convert "~0.5.0"
-
-parse-json@^2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
-  integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==
-  dependencies:
-    error-ex "^1.2.0"
-
-path-exists@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
-  integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==
-
-path-exists@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
-  integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
-
-path-is-absolute@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
-  integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
-
-path-key@^2.0.0, path-key@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
-  integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==
-
-path-key@^3.1.0:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
-  integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
-
-path-parse@^1.0.7:
-  version "1.0.7"
-  resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
-  integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
-
-path-scurry@^1.11.1:
-  version "1.11.1"
-  resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2"
-  integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==
-  dependencies:
-    lru-cache "^10.2.0"
-    minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
-
-path-type@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
-  integrity sha512-dUnb5dXUf+kzhC/W/F4e5/SkluXIFf5VUHolW1Eg1irn1hGWjPGdsRcvYJ1nD6lhk8Ir7VM0bHJKsYTx8Jx9OQ==
-  dependencies:
-    pify "^2.0.0"
-
-pe-library@^0.4.1:
-  version "0.4.1"
-  resolved "https://registry.yarnpkg.com/pe-library/-/pe-library-0.4.1.tgz#e269be0340dcb13aa6949d743da7d658c3e2fbea"
-  integrity sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==
-
-pe-library@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/pe-library/-/pe-library-1.0.1.tgz#02735430885a622576a53cd8827658b7d2fada0e"
-  integrity sha512-nh39Mo1eGWmZS7y+mK/dQIqg7S1lp38DpRxkyoHf0ZcUs/HDc+yyTjuOtTvSMZHmfSLuSQaX945u05Y2Q6UWZg==
-
-pend@~1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
-  integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==
-
-picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
-  integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
-
-pify@^2.0.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
-  integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
-
-pino-abstract-transport@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz#de241578406ac7b8a33ce0d77ae6e8a0b3b68a60"
-  integrity sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==
-  dependencies:
-    split2 "^4.0.0"
-
-pino-std-serializers@^7.0.0:
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz#7c625038b13718dbbd84ab446bd673dc52259e3b"
-  integrity sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==
-
-pino@^9.0.0:
-  version "9.6.0"
-  resolved "https://registry.yarnpkg.com/pino/-/pino-9.6.0.tgz#6bc628159ba0cc81806d286718903b7fc6b13169"
-  integrity sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==
-  dependencies:
-    atomic-sleep "^1.0.0"
-    fast-redact "^3.1.1"
-    on-exit-leak-free "^2.1.0"
-    pino-abstract-transport "^2.0.0"
-    pino-std-serializers "^7.0.0"
-    process-warning "^4.0.0"
-    quick-format-unescaped "^4.0.3"
-    real-require "^0.2.0"
-    safe-stable-stringify "^2.3.1"
-    sonic-boom "^4.0.1"
-    thread-stream "^3.0.0"
-
[email protected], plist@^3.0.0, plist@^3.0.4, plist@^3.0.5, plist@^3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/plist/-/plist-3.1.0.tgz#797a516a93e62f5bde55e0b9cc9c967f860893c9"
-  integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==
-  dependencies:
-    "@xmldom/xmldom" "^0.8.8"
-    base64-js "^1.5.1"
-    xmlbuilder "^15.1.1"
-
[email protected]:
-  version "1.10.2"
-  resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.10.2.tgz#74d6c84f9675b65dfd4ff6f4051ed8d3cb974076"
-  integrity sha512-JNjWstHEexhj5CEKldSeYNyPJbtOvZQ3ZPL55fxU7+f+gTBL8RlOb8eFohCPYIk0VhMf2UM1rXxwVBOeMQQQFw==
-  dependencies:
-    fflate "^0.4.1"
-
-postject@^1.0.0-alpha.6:
-  version "1.0.0-alpha.6"
-  resolved "https://registry.yarnpkg.com/postject/-/postject-1.0.0-alpha.6.tgz#9d022332272e2cfce8dea4cfce1ee6dd1b2ee135"
-  integrity sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==
-  dependencies:
-    commander "^9.4.0"
-
-proc-log@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-2.0.1.tgz#8f3f69a1f608de27878f91f5c688b225391cb685"
-  integrity sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==
-
-proc-log@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-5.0.0.tgz#e6c93cf37aef33f835c53485f314f50ea906a9d8"
-  integrity sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==
-
-process-nextick-args@~2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
-  integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
-
-process-warning@^4.0.0:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-4.0.1.tgz#5c1db66007c67c756e4e09eb170cdece15da32fb"
-  integrity sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==
-
-process-warning@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-5.0.0.tgz#566e0bf79d1dff30a72d8bbbe9e8ecefe8d378d7"
-  integrity sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==
-
-progress@^2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
-  integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
-
-promise-inflight@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
-  integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==
-
-promise-retry@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22"
-  integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==
-  dependencies:
-    err-code "^2.0.2"
-    retry "^0.12.0"
-
-pump@^3.0.0:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.2.tgz#836f3edd6bc2ee599256c924ffe0d88573ddcbf8"
-  integrity sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==
-  dependencies:
-    end-of-stream "^1.1.0"
-    once "^1.3.1"
-
-punycode@^2.1.0:
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
-  integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
-
-pupa@^2.0.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62"
-  integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==
-  dependencies:
-    escape-goat "^2.0.0"
-
-queue-microtask@^1.2.2:
-  version "1.2.3"
-  resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
-  integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
-
-quick-format-unescaped@^4.0.3:
-  version "4.0.4"
-  resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7"
-  integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==
-
-quick-lru@^5.1.1:
-  version "5.1.1"
-  resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
-  integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
-
-random-path@^0.1.0:
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/random-path/-/random-path-0.1.2.tgz#78b7f1570e2a09f66a4e2e0113a98ed588e85da9"
-  integrity sha512-4jY0yoEaQ5v9StCl5kZbNIQlg1QheIDBrdkDn53EynpPb9FgO6//p3X/tgMnrC45XN6QZCzU1Xz/+pSSsJBpRw==
-  dependencies:
-    base32-encode "^0.1.0 || ^1.0.0"
-    murmur-32 "^0.1.0 || ^0.2.0"
-
-rcedit@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/rcedit/-/rcedit-4.0.1.tgz#892ac47a19204a380f49e00ea38ce070443343c2"
-  integrity sha512-bZdaQi34krFWhrDn+O53ccBDw0MkAT2Vhu75SqhtvhQu4OPyFM4RoVheyYiVQYdjhUi6EJMVWQ0tR6bCIYVkUg==
-  dependencies:
-    cross-spawn-windows-exe "^1.1.0"
-
-rcinfo@^0.1.3:
-  version "0.1.3"
-  resolved "https://registry.yarnpkg.com/rcinfo/-/rcinfo-0.1.3.tgz#ac36832d1f1e5970c6379e571480ea5826511fc6"
-  integrity sha512-c2XV2aYgY7x3BscO+/B/nCTtMvnclZ8w5D7R6zgK4sGOQnE0MjlXhOPynno7yp6Iw1RPNSXBwXwB1svZVRfcSw==
-
-read-binary-file-arch@^1.0.6:
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz#959c4637daa932280a9b911b1a6766a7e44288fc"
-  integrity sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==
-  dependencies:
-    debug "^4.3.4"
-
[email protected]:
-  version "6.3.2"
-  resolved "https://registry.yarnpkg.com/read-config-file/-/read-config-file-6.3.2.tgz#556891aa6ffabced916ed57457cb192e61880411"
-  integrity sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==
-  dependencies:
-    config-file-ts "^0.2.4"
-    dotenv "^9.0.2"
-    dotenv-expand "^5.1.0"
-    js-yaml "^4.1.0"
-    json5 "^2.2.0"
-    lazy-val "^1.0.4"
-
-read-pkg-up@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be"
-  integrity sha512-1orxQfbWGUiTn9XsPlChs6rLie/AV9jwZTGmu2NZw/CUDJQchXJFYE0Fq5j7+n558T1JhDWLdhyd1Zj+wLY//w==
-  dependencies:
-    find-up "^2.0.0"
-    read-pkg "^2.0.0"
-
-read-pkg@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8"
-  integrity sha512-eFIBOPW7FGjzBuk3hdXEuNSiTZS/xEMlH49HxMyzb0hyPfu4EhVjT2DH32K1hSSmVq4sebAWnZuuY5auISUTGA==
-  dependencies:
-    load-json-file "^2.0.0"
-    normalize-package-data "^2.3.2"
-    path-type "^2.0.0"
-
-readable-stream@^3.4.0:
-  version "3.6.2"
-  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
-  integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
-  dependencies:
-    inherits "^2.0.3"
-    string_decoder "^1.1.1"
-    util-deprecate "^1.0.1"
-
-readable-stream@~2.3.6:
-  version "2.3.8"
-  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
-  integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
-  dependencies:
-    core-util-is "~1.0.0"
-    inherits "~2.0.3"
-    isarray "~1.0.0"
-    process-nextick-args "~2.0.0"
-    safe-buffer "~5.1.1"
-    string_decoder "~1.1.1"
-    util-deprecate "~1.0.1"
-
-readdirp@~3.6.0:
-  version "3.6.0"
-  resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
-  integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
-  dependencies:
-    picomatch "^2.2.1"
-
-real-require@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78"
-  integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==
-
-rechoir@^0.8.0:
-  version "0.8.0"
-  resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22"
-  integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==
-  dependencies:
-    resolve "^1.20.0"
-
-repeat-string@^1.5.4:
-  version "1.6.1"
-  resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
-  integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==
-
-require-directory@^2.1.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
-  integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
-
-require-from-string@^2.0.2:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
-  integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
-
-resedit@^1.7.0:
-  version "1.7.2"
-  resolved "https://registry.yarnpkg.com/resedit/-/resedit-1.7.2.tgz#b1041170b99811710c13f949c7d225871de4cc78"
-  integrity sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==
-  dependencies:
-    pe-library "^0.4.1"
-
-resedit@^2.0.0:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/resedit/-/resedit-2.0.3.tgz#5145a9faabca44b917d5636dbe8e67ec7f62c6f2"
-  integrity sha512-oTeemxwoMuxxTYxXUwjkrOPfngTQehlv0/HoYFNkB4uzsP1Un1A9nI8JQKGOFkxpqkC7qkMs0lUsGrvUlbLNUA==
-  dependencies:
-    pe-library "^1.0.1"
-
-resolve-alpn@^1.0.0:
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9"
-  integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==
-
-resolve@^1.1.6, resolve@^1.10.0, resolve@^1.20.0:
-  version "1.22.10"
-  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39"
-  integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==
-  dependencies:
-    is-core-module "^2.16.0"
-    path-parse "^1.0.7"
-    supports-preserve-symlinks-flag "^1.0.0"
-
-responselike@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc"
-  integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==
-  dependencies:
-    lowercase-keys "^2.0.0"
-
-restore-cursor@^3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
-  integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
-  dependencies:
-    onetime "^5.1.0"
-    signal-exit "^3.0.2"
-
-restore-cursor@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9"
-  integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==
-  dependencies:
-    onetime "^5.1.0"
-    signal-exit "^3.0.2"
-
-ret@~0.5.0:
-  version "0.5.0"
-  resolved "https://registry.yarnpkg.com/ret/-/ret-0.5.0.tgz#30a4d38a7e704bd96dc5ffcbe7ce2a9274c41c95"
-  integrity sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==
-
-retry@^0.12.0:
-  version "0.12.0"
-  resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
-  integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==
-
-reusify@^1.0.4:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f"
-  integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==
-
-rfdc@^1.2.0, rfdc@^1.3.0, rfdc@^1.3.1:
-  version "1.4.1"
-  resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca"
-  integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==
-
-rimraf@^3.0.2:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
-  integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
-  dependencies:
-    glob "^7.1.3"
-
-rimraf@~2.6.2:
-  version "2.6.3"
-  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
-  integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
-  dependencies:
-    glob "^7.1.3"
-
-roarr@^2.15.3:
-  version "2.15.4"
-  resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.4.tgz#f5fe795b7b838ccfe35dc608e0282b9eba2e7afd"
-  integrity sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==
-  dependencies:
-    boolean "^3.0.1"
-    detect-node "^2.0.4"
-    globalthis "^1.0.1"
-    json-stringify-safe "^5.0.1"
-    semver-compare "^1.0.0"
-    sprintf-js "^1.1.2"
-
-run-parallel@^1.1.9:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
-  integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
-  dependencies:
-    queue-microtask "^1.2.2"
-
-safe-buffer@~5.1.0, safe-buffer@~5.1.1:
-  version "5.1.2"
-  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
-  integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-
-safe-buffer@~5.2.0:
-  version "5.2.1"
-  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
-  integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
-
-safe-regex2@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-5.0.0.tgz#762e4a4c328603427281d2b99662f2d04e4ae811"
-  integrity sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==
-  dependencies:
-    ret "~0.5.0"
-
-safe-stable-stringify@^2.3.1:
-  version "2.5.0"
-  resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd"
-  integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==
-
-"safer-buffer@>= 2.1.2 < 3.0.0":
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
-  integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-
-sanitize-filename@^1.6.3:
-  version "1.6.3"
-  resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378"
-  integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==
-  dependencies:
-    truncate-utf8-bytes "^1.0.0"
-
-sax@^1.2.4:
-  version "1.4.1"
-  resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f"
-  integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==
-
-secure-json-parse@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-4.0.0.tgz#2ee1b7581be38ab348bab5a3e49280ba80a89c85"
-  integrity sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA==
-
-semver-compare@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
-  integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==
-
-"semver@2 || 3 || 4 || 5", semver@^5.5.0:
-  version "5.7.2"
-  resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
-  integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
-
[email protected]:
-  version "7.5.2"
-  resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.2.tgz#5b851e66d1be07c1cdaf37dfc856f543325a2beb"
-  integrity sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==
-  dependencies:
-    lru-cache "^6.0.0"
-
-semver@^6.2.0:
-  version "6.3.1"
-  resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
-  integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
-
-semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.5, semver@^7.3.8, semver@^7.5.3, semver@^7.6.0:
-  version "7.7.1"
-  resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f"
-  integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
-
-serialize-error@^7.0.1:
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18"
-  integrity sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==
-  dependencies:
-    type-fest "^0.13.1"
-
-set-cookie-parser@^2.6.0:
-  version "2.7.1"
-  resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943"
-  integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==
-
-setimmediate@^1.0.5:
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
-  integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==
-
-shebang-command@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
-  integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==
-  dependencies:
-    shebang-regex "^1.0.0"
-
-shebang-command@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
-  integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
-  dependencies:
-    shebang-regex "^3.0.0"
-
-shebang-regex@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
-  integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==
-
-shebang-regex@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
-  integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
-
-signal-exit@^3.0.0, signal-exit@^3.0.2:
-  version "3.0.7"
-  resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
-  integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
-
-signal-exit@^4.0.1:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
-  integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
-
[email protected]:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb"
-  integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==
-  dependencies:
-    semver "^7.5.3"
-
-slice-ansi@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787"
-  integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==
-  dependencies:
-    ansi-styles "^4.0.0"
-    astral-regex "^2.0.0"
-    is-fullwidth-code-point "^3.0.0"
-
-slice-ansi@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a"
-  integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==
-  dependencies:
-    ansi-styles "^6.0.0"
-    is-fullwidth-code-point "^4.0.0"
-
-smart-buffer@^4.0.2, smart-buffer@^4.2.0:
-  version "4.2.0"
-  resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
-  integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
-
[email protected]:
-  version "8.0.2"
-  resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz#5acbd7be7baf18c46a3f293a840109a430a640ad"
-  integrity sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==
-  dependencies:
-    agent-base "^7.0.2"
-    debug "^4.3.4"
-    socks "^2.7.1"
-
-socks-proxy-agent@^7.0.0:
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz#dc069ecf34436621acb41e3efa66ca1b5fed15b6"
-  integrity sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==
-  dependencies:
-    agent-base "^6.0.2"
-    debug "^4.3.3"
-    socks "^2.6.2"
-
-socks-proxy-agent@^8.0.3:
-  version "8.0.4"
-  resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz#9071dca17af95f483300316f4b063578fa0db08c"
-  integrity sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==
-  dependencies:
-    agent-base "^7.1.1"
-    debug "^4.3.4"
-    socks "^2.8.3"
-
-socks@^2.6.2, socks@^2.7.1, socks@^2.8.3:
-  version "2.8.4"
-  resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.4.tgz#07109755cdd4da03269bda4725baa061ab56d5cc"
-  integrity sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==
-  dependencies:
-    ip-address "^9.0.5"
-    smart-buffer "^4.2.0"
-
-sonic-boom@^4.0.1:
-  version "4.2.0"
-  resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.0.tgz#e59a525f831210fa4ef1896428338641ac1c124d"
-  integrity sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==
-  dependencies:
-    atomic-sleep "^1.0.0"
-
-sort-keys-length@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188"
-  integrity sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==
-  dependencies:
-    sort-keys "^1.0.0"
-
-sort-keys@^1.0.0:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad"
-  integrity sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==
-  dependencies:
-    is-plain-obj "^1.0.0"
-
-source-map-support@^0.5.13, source-map-support@^0.5.19:
-  version "0.5.21"
-  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
-  integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
-  dependencies:
-    buffer-from "^1.0.0"
-    source-map "^0.6.0"
-
-source-map@^0.6.0:
-  version "0.6.1"
-  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
-  integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
-
-spdx-correct@^3.0.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c"
-  integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==
-  dependencies:
-    spdx-expression-parse "^3.0.0"
-    spdx-license-ids "^3.0.0"
-
-spdx-exceptions@^2.1.0:
-  version "2.5.0"
-  resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66"
-  integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==
-
-spdx-expression-parse@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
-  integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
-  dependencies:
-    spdx-exceptions "^2.1.0"
-    spdx-license-ids "^3.0.0"
-
-spdx-license-ids@^3.0.0:
-  version "3.0.21"
-  resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz#6d6e980c9df2b6fc905343a3b2d702a6239536c3"
-  integrity sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==
-
-split2@^4.0.0:
-  version "4.2.0"
-  resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
-  integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
-
-sprintf-js@^1.1.2, sprintf-js@^1.1.3:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a"
-  integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==
-
-ssri@^12.0.0:
-  version "12.0.0"
-  resolved "https://registry.yarnpkg.com/ssri/-/ssri-12.0.0.tgz#bcb4258417c702472f8191981d3c8a771fee6832"
-  integrity sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==
-  dependencies:
-    minipass "^7.0.3"
-
-ssri@^9.0.0:
-  version "9.0.1"
-  resolved "https://registry.yarnpkg.com/ssri/-/ssri-9.0.1.tgz#544d4c357a8d7b71a19700074b6883fcb4eae057"
-  integrity sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==
-  dependencies:
-    minipass "^3.1.1"
-
-stat-mode@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-1.0.0.tgz#68b55cb61ea639ff57136f36b216a291800d1465"
-  integrity sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==
-
-stream-buffers@~2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4"
-  integrity sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==
-
-"string-width-cjs@npm:string-width@^4.2.0":
-  version "4.2.3"
-  resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
-  integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
-  dependencies:
-    emoji-regex "^8.0.0"
-    is-fullwidth-code-point "^3.0.0"
-    strip-ansi "^6.0.1"
-
[email protected], string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3, string-width@^5.0.0, string-width@^5.1.2:
-  version "4.2.0"
-  resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
-  integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==
-  dependencies:
-    emoji-regex "^8.0.0"
-    is-fullwidth-code-point "^3.0.0"
-    strip-ansi "^6.0.0"
-
-string_decoder@^1.1.1:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
-  integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
-  dependencies:
-    safe-buffer "~5.2.0"
-
-string_decoder@~1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
-  integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
-  dependencies:
-    safe-buffer "~5.1.0"
-
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
-  version "6.0.1"
-  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
-  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
-  dependencies:
-    ansi-regex "^5.0.1"
-
-strip-ansi@^6.0.0, strip-ansi@^6.0.1, strip-ansi@^7.0.1:
-  version "6.0.1"
-  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
-  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
-  dependencies:
-    ansi-regex "^5.0.1"
-
-strip-bom@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
-  integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
-
-strip-eof@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
-  integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==
-
-strip-outer@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631"
-  integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==
-  dependencies:
-    escape-string-regexp "^1.0.2"
-
-sudo-prompt@^9.1.1:
-  version "9.2.1"
-  resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.2.1.tgz#77efb84309c9ca489527a4e749f287e6bdd52afd"
-  integrity sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==
-
-sumchecker@^3.0.1:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42"
-  integrity sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==
-  dependencies:
-    debug "^4.1.0"
-
-supports-color@^7.1.0:
-  version "7.2.0"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
-  integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
-  dependencies:
-    has-flag "^4.0.0"
-
-supports-preserve-symlinks-flag@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
-  integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
-
-tar@^6.0.5, tar@^6.1.11, tar@^6.1.12, tar@^6.2.1:
-  version "6.2.1"
-  resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a"
-  integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==
-  dependencies:
-    chownr "^2.0.0"
-    fs-minipass "^2.0.0"
-    minipass "^5.0.0"
-    minizlib "^2.1.1"
-    mkdirp "^1.0.3"
-    yallist "^4.0.0"
-
-tar@^7.4.3:
-  version "7.4.3"
-  resolved "https://registry.yarnpkg.com/tar/-/tar-7.4.3.tgz#88bbe9286a3fcd900e94592cda7a22b192e80571"
-  integrity sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==
-  dependencies:
-    "@isaacs/fs-minipass" "^4.0.0"
-    chownr "^3.0.0"
-    minipass "^7.1.2"
-    minizlib "^3.0.1"
-    mkdirp "^3.0.1"
-    yallist "^5.0.0"
-
-temp-file@^3.4.0:
-  version "3.4.0"
-  resolved "https://registry.yarnpkg.com/temp-file/-/temp-file-3.4.0.tgz#766ea28911c683996c248ef1a20eea04d51652c7"
-  integrity sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==
-  dependencies:
-    async-exit-hook "^2.0.1"
-    fs-extra "^10.0.0"
-
-temp@^0.9.0:
-  version "0.9.4"
-  resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.4.tgz#cd20a8580cb63635d0e4e9d4bd989d44286e7620"
-  integrity sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==
-  dependencies:
-    mkdirp "^0.5.1"
-    rimraf "~2.6.2"
-
-thread-stream@^3.0.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-3.1.0.tgz#4b2ef252a7c215064507d4ef70c05a5e2d34c4f1"
-  integrity sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==
-  dependencies:
-    real-require "^0.2.0"
-
[email protected]:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/tiny-async-pool/-/tiny-async-pool-1.3.0.tgz#c013e1b369095e7005db5595f95e646cca6ef8a5"
-  integrity sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==
-  dependencies:
-    semver "^5.5.0"
-
[email protected]:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/tiny-each-async/-/tiny-each-async-2.0.3.tgz#8ebbbfd6d6295f1370003fbb37162afe5a0a51d1"
-  integrity sha512-5ROII7nElnAirvFn8g7H7MtpfV1daMcyfTGQwsn/x2VtyV+VPiO5CjReCJtWLvoKTDEDmZocf3cNPraiMnBXLA==
-
-tmp-promise@^3.0.2:
-  version "3.0.3"
-  resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-3.0.3.tgz#60a1a1cc98c988674fcbfd23b6e3367bdeac4ce7"
-  integrity sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==
-  dependencies:
-    tmp "^0.2.0"
-
-tmp@^0.2.0:
-  version "0.2.3"
-  resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae"
-  integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==
-
-tn1150@^0.1.0:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/tn1150/-/tn1150-0.1.0.tgz#673503d24d56b87de8b8c77fee3fc0853d59a18d"
-  integrity sha512-DbplOfQFkqG5IHcDyyrs/lkvSr3mPUVsFf/RbDppOshs22yTPnSJWEe6FkYd1txAwU/zcnR905ar2fi4kwF29w==
-  dependencies:
-    unorm "^1.4.1"
-
-to-data-view@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/to-data-view/-/to-data-view-1.1.0.tgz#08d6492b0b8deb9b29bdf1f61c23eadfa8994d00"
-  integrity sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ==
-
-to-regex-range@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
-  integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
-  dependencies:
-    is-number "^7.0.0"
-
-toad-cache@^3.7.0:
-  version "3.7.0"
-  resolved "https://registry.yarnpkg.com/toad-cache/-/toad-cache-3.7.0.tgz#b9b63304ea7c45ec34d91f1d2fa513517025c441"
-  integrity sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==
-
-tr46@~0.0.3:
-  version "0.0.3"
-  resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
-  integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
-
-trim-repeated@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21"
-  integrity sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==
-  dependencies:
-    escape-string-regexp "^1.0.2"
-
-truncate-utf8-bytes@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b"
-  integrity sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==
-  dependencies:
-    utf8-byte-length "^1.0.1"
-
-tslib@^1.9.3:
-  version "1.14.1"
-  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
-  integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
-
-tslib@^2.1.0, tslib@^2.2.0:
-  version "2.8.1"
-  resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
-  integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
-
-type-fest@^0.13.1:
-  version "0.13.1"
-  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
-  integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==
-
-type-fest@^1.0.2:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1"
-  integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==
-
-typescript@^5.3.3, typescript@^5.4.3:
-  version "5.8.3"
-  resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
-  integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
-
-undici-types@~6.19.2:
-  version "6.19.8"
-  resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
-  integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
-
-undici-types@~6.21.0:
-  version "6.21.0"
-  resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
-  integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
-
-unique-filename@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-2.0.1.tgz#e785f8675a9a7589e0ac77e0b5c34d2eaeac6da2"
-  integrity sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==
-  dependencies:
-    unique-slug "^3.0.0"
-
-unique-filename@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-4.0.0.tgz#a06534d370e7c977a939cd1d11f7f0ab8f1fed13"
-  integrity sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==
-  dependencies:
-    unique-slug "^5.0.0"
-
-unique-slug@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-3.0.0.tgz#6d347cf57c8a7a7a6044aabd0e2d74e4d76dc7c9"
-  integrity sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==
-  dependencies:
-    imurmurhash "^0.1.4"
-
-unique-slug@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-5.0.0.tgz#ca72af03ad0dbab4dad8aa683f633878b1accda8"
-  integrity sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==
-  dependencies:
-    imurmurhash "^0.1.4"
-
-universalify@^0.1.0:
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
-  integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
-
-universalify@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d"
-  integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==
-
-unorm@^1.4.1:
-  version "1.6.0"
-  resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af"
-  integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==
-
-unused-filename@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/unused-filename/-/unused-filename-2.1.0.tgz#33719c4e8d9644f32d2dec1bc8525c6aaeb4ba51"
-  integrity sha512-BMiNwJbuWmqCpAM1FqxCTD7lXF97AvfQC8Kr/DIeA6VtvhJaMDupZ82+inbjl5yVP44PcxOuCSxye1QMS0wZyg==
-  dependencies:
-    modify-filename "^1.1.0"
-    path-exists "^4.0.0"
-
-unzip-crx-3@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/unzip-crx-3/-/unzip-crx-3-0.2.0.tgz#d5324147b104a8aed9ae8639c95521f6f7cda292"
-  integrity sha512-0+JiUq/z7faJ6oifVB5nSwt589v1KCduqIJupNVDoWSXZtWDmjDGO3RAEOvwJ07w90aoXoP4enKsR7ecMrJtWQ==
-  dependencies:
-    jszip "^3.1.0"
-    mkdirp "^0.5.1"
-    yaku "^0.16.6"
-
[email protected]:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/update-electron-app/-/update-electron-app-2.0.1.tgz#229dbeb4534f51ec949e6a46ae1ac32f68a17eed"
-  integrity sha512-e4xEner89UZZaBGYJbYlMdL1uUrC0VjOsTAL2N4opPjzFtn+j7mdsJJsnyXZzUVeLY+8tuCX4XEsUM98oBHmZg==
-  dependencies:
-    electron-is-dev "^0.3.0"
-    github-url-to-object "^4.0.4"
-    is-url "^1.2.4"
-    ms "^2.1.1"
-
-uri-js@^4.2.2:
-  version "4.4.1"
-  resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
-  integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
-  dependencies:
-    punycode "^2.1.0"
-
-username@^5.1.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/username/-/username-5.1.0.tgz#a7f9325adce2d0166448cdd55d4985b1360f2508"
-  integrity sha512-PCKbdWw85JsYMvmCv5GH3kXmM66rCd9m1hBEDutPNv94b/pqCMT4NtcKyeWYvLFiE8b+ha1Jdl8XAaUdPn5QTg==
-  dependencies:
-    execa "^1.0.0"
-    mem "^4.3.0"
-
-utf8-byte-length@^1.0.1:
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz#f9f63910d15536ee2b2d5dd4665389715eac5c1e"
-  integrity sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==
-
-util-deprecate@^1.0.1, util-deprecate@~1.0.1:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
-  integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
-
-validate-npm-package-license@^3.0.1:
-  version "3.0.4"
-  resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
-  integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
-  dependencies:
-    spdx-correct "^3.0.0"
-    spdx-expression-parse "^3.0.0"
-
-verror@^1.10.0:
-  version "1.10.1"
-  resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.1.tgz#4bf09eeccf4563b109ed4b3d458380c972b0cdeb"
-  integrity sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==
-  dependencies:
-    assert-plus "^1.0.0"
-    core-util-is "1.0.2"
-    extsprintf "^1.2.0"
-
-wcwidth@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
-  integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==
-  dependencies:
-    defaults "^1.0.3"
-
-webidl-conversions@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
-  integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
-
-whatwg-url@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
-  integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
-  dependencies:
-    tr46 "~0.0.3"
-    webidl-conversions "^3.0.0"
-
-which@^1.2.9:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
-  integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
-  dependencies:
-    isexe "^2.0.0"
-
-which@^2.0.1, which@^2.0.2:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
-  integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
-  dependencies:
-    isexe "^2.0.0"
-
-which@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/which/-/which-5.0.0.tgz#d93f2d93f79834d4363c7d0c23e00d07c466c8d6"
-  integrity sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==
-  dependencies:
-    isexe "^3.1.1"
-
-word-wrap@^1.2.3:
-  version "1.2.5"
-  resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
-  integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
-
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
-  integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
-  dependencies:
-    ansi-styles "^4.0.0"
-    string-width "^4.1.0"
-    strip-ansi "^6.0.0"
-
-wrap-ansi@^7.0.0, wrap-ansi@^8.0.1, wrap-ansi@^8.1.0:
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
-  integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
-  dependencies:
-    ansi-styles "^4.0.0"
-    string-width "^4.1.0"
-    strip-ansi "^6.0.0"
-
-wrappy@1:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
-  integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
-
-xmlbuilder@>=11.0.1, xmlbuilder@^15.1.1:
-  version "15.1.1"
-  resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5"
-  integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==
-
-xtend@^4.0.0:
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
-  integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
-
-y18n@^5.0.5:
-  version "5.0.8"
-  resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
-  integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
-
-yaku@^0.16.6:
-  version "0.16.7"
-  resolved "https://registry.yarnpkg.com/yaku/-/yaku-0.16.7.tgz#1d195c78aa9b5bf8479c895b9504fd4f0847984e"
-  integrity sha512-Syu3IB3rZvKvYk7yTiyl1bo/jiEFaaStrgv1V2TIJTqYPStSMQVO8EQjg/z+DRzLq/4LIIharNT3iH1hylEIRw==
-
-yallist@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
-  integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
-
-yallist@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533"
-  integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==
-
-yargs-parser@^20.2.2:
-  version "20.2.9"
-  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
-  integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
-
-yargs-parser@^21.1.1:
-  version "21.1.1"
-  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
-  integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
-
-yargs@^16.0.2:
-  version "16.2.0"
-  resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
-  integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
-  dependencies:
-    cliui "^7.0.2"
-    escalade "^3.1.1"
-    get-caller-file "^2.0.5"
-    require-directory "^2.1.1"
-    string-width "^4.2.0"
-    y18n "^5.0.5"
-    yargs-parser "^20.2.2"
-
-yargs@^17.0.1, yargs@^17.6.2:
-  version "17.7.2"
-  resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
-  integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
-  dependencies:
-    cliui "^8.0.1"
-    escalade "^3.1.1"
-    get-caller-file "^2.0.5"
-    require-directory "^2.1.1"
-    string-width "^4.2.3"
-    y18n "^5.0.5"
-    yargs-parser "^21.1.1"
-
-yauzl@^2.10.0:
-  version "2.10.0"
-  resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
-  integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==
-  dependencies:
-    buffer-crc32 "~0.2.3"
-    fd-slicer "~1.1.0"
-
-yocto-queue@^0.1.0:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
-  integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==

+ 1 - 1
typos.toml

@@ -18,4 +18,4 @@ fom = "fom"
 tne = "tne"
 Damon = "Damon"
 [files]
-extend-exclude = ["resources/*", "src/resources/*", "scripts/resources/*", "e2e-tests/plugin/lsplugin.user.js", "src/test/fixtures/*"]
+extend-exclude = ["resources/*", "src/resources/*", "scripts/resources/*", "src/test/fixtures/*"]

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä