diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn index d929c29d90d..f2c5de3d169 100644 --- a/.clj-kondo/config.edn +++ b/.clj-kondo/config.edn @@ -15,6 +15,8 @@ :aliased-namespace-symbol {:level :warning} ;; Disable until it doesn't trigger false positives on rum/defcontext :earmuffed-var-not-dynamic {:level :off} + ;; Disable until we decide to use conj! as recommended in docs + :unused-value {:level :off} :unresolved-symbol {:exclude [goog.DEBUG goog.string.unescapeEntities ;; TODO:lint: Fix when fixing all type hints @@ -39,6 +41,7 @@ electron.utils utils "/electron/utils" js-utils frontend.commands commands + frontend.components.block.macros block-macros frontend.components.query query frontend.components.query.result query-result frontend.config config diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index d68b009863b..3ec5eed74ec 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -7,6 +7,10 @@ body: Thank you very much for opening a bug report with Logseq. If you have a feature idea or need help, please go to [our Forum](https://discuss.logseq.com/) or [our Discord](https://discord.com/invite/KpN4eHY). + + Please make sure to provide a descriptive, deterministic, and reproducible report. It saves time for both the developers and users who are looking for solutions. Providing as much information as possible, including screenshots and logs, is highly appreciated. This will help us to better understand the issue and respond more effectively. + + Please DO NOT use this template to ask questions. There are other appropriate channels to ask questions. This template is strictly for reporting bugs. - type: checkboxes id: confirm-search attributes: diff --git a/.github/workflows/build-desktop-release.yml b/.github/workflows/build-desktop-release.yml index b856e1ef347..bf39aae1db4 100644 --- a/.github/workflows/build-desktop-release.yml +++ b/.github/workflows/build-desktop-release.yml @@ -122,7 +122,7 @@ jobs: run: | sed -i 's/defonce version ".*"/defonce version "${{ steps.ref.outputs.version }}"/g' src/main/frontend/version.cljs - - name: Set Build Environment Variables (only when workflow_dispath) + - name: Set Build Environment Variables (only when workflow_dispatch) if: ${{ github.event_name == 'workflow_dispatch' }} # if scheduled, use default settings run: | @@ -204,8 +204,19 @@ jobs: env: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: true + - 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: xvfb-run -- npx playwright test --reporter github --shard=${{ matrix.shard }}/3 + run: DISPLAY=:1.0 npx playwright test --reporter github --shard=${{ matrix.shard }}/3 env: LOGSEQ_CI: true DEBUG: "pw:api" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c9d15bd620a..632ae35ca41 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -182,15 +182,26 @@ jobs: - 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 - 1/2 - run: xvfb-run -- npx playwright test --reporter github --shard=1/2 + run: DISPLAY=:1.0 npx playwright test --reporter github --shard=1/2 env: LOGSEQ_CI: true DEBUG: "pw:api" RELEASE: true # skip dev only test - name: Run Playwright test - 2/2 - run: xvfb-run -- npx playwright test --reporter github --shard=2/2 + run: DISPLAY=:1.0 npx playwright test --reporter github --shard=2/2 env: LOGSEQ_CI: true DEBUG: "pw:api" diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index f3aa8eb3921..cf220e2c08e 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -137,8 +137,19 @@ jobs: - 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: xvfb-run -- npx playwright test --reporter github --shard=${{ matrix.shard }}/3 + run: DISPLAY=:1.0 npx playwright test --reporter github --shard=${{ matrix.shard }}/3 env: LOGSEQ_CI: true DEBUG: "pw:api" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8edee5e631b..f3dcb0e8088 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -133,6 +133,7 @@ When submitting a Pull Request (PR) or expecting a subsequent review, please fol * Unrelated refactoring or heavy refactoring * Code or doc formatting changes including whitespace changes * Dependency updates e.g. in package.json + * Changes that contain multiple unverified resources. This is risky for our users and is a lot of work to verify. A change with one resource that can be verified is acceptable. ### PR Additional Links diff --git a/android/app/build.gradle b/android/app/build.gradle index cec721ad49f..613adcc4e35 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -6,8 +6,8 @@ android { applicationId "com.logseq.app" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 61 - versionName "0.9.8" + versionCode 62 + versionName "0.9.9" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/bb.edn b/bb.edn index 0cb2c4dcdc2..1eba4c14006 100644 --- a/bb.edn +++ b/bb.edn @@ -5,13 +5,13 @@ logseq/bb-tasks #_{:local/root "../bb-tasks"} {:git/url "https://github.com/logseq/bb-tasks" - :git/sha "4295d5df0458cc06a09c5d506510ee49b785407d"} + :git/sha "70d3edeb287f5cec7192e642549a401f7d6d4263"} logseq/graph-parser {:local/root "deps/graph-parser"} org.clj-commons/digest {:mvn/version "1.4.100"}} :pods - {clj-kondo/clj-kondo {:version "2022.10.05"} + {clj-kondo/clj-kondo {:version "2023.05.26"} org.babashka/fswatcher {:version "0.0.3"} org.babashka/go-sqlite3 {:version "0.1.0"}} :tasks @@ -39,8 +39,8 @@ {:depends [dev:build-publishing] :doc "Build publishing spa app given graph and output dirs" :task (apply shell {:dir "scripts"} - "yarn -s nbb-logseq -cp src -m logseq.tasks.dev.publishing" - (into ["static"] *command-line-args*))} + "yarn -s nbb-logseq -cp src -m logseq.tasks.dev.publishing" + (into ["static"] *command-line-args*))} dev:npx-cap-run-ios logseq.tasks.dev.mobile/npx-cap-run-ios @@ -113,9 +113,6 @@ lang:missing logseq.tasks.lang/list-missing - lang:duplicates - logseq.tasks.lang/list-duplicates - lang:validate-translations logseq.tasks.lang/validate-translations diff --git a/deps.edn b/deps.edn index dd4948049d1..52e558d202f 100644 --- a/deps.edn +++ b/deps.edn @@ -1,4 +1,4 @@ -{:paths ["src/main" "src/electron" "templates" "src/resources"] +{:paths ["src/main" "src/electron" "src/resources"] :deps {org.clojure/clojure {:mvn/version "1.11.1"} rum/rum {:mvn/version "0.12.9"} @@ -55,5 +55,5 @@ :main-opts ["-m" "cljs-test-runner.main" "-d" "src/bench" "-n" "frontend.benchmark-test-runner"]} ;; Use :replace-deps for tools. See https://github.com/clj-kondo/clj-kondo/issues/1536#issuecomment-1013006889 - :clj-kondo {:replace-deps {clj-kondo/clj-kondo {:mvn/version "2022.12.08"}} + :clj-kondo {:replace-deps {clj-kondo/clj-kondo {:mvn/version "2023.05.26"}} :main-opts ["-m" "clj-kondo.main"]}}} diff --git a/deps/common/bb.edn b/deps/common/bb.edn index 4a681f504c5..31882225b4f 100644 --- a/deps/common/bb.edn +++ b/deps/common/bb.edn @@ -3,10 +3,10 @@ {logseq/bb-tasks #_{:local/root "../../../bb-tasks"} {:git/url "https://github.com/logseq/bb-tasks" - :git/sha "0d49051909bfa0c6b414e86606d82b4ea54f382c"}} + :git/sha "70d3edeb287f5cec7192e642549a401f7d6d4263"}} :pods - {clj-kondo/clj-kondo {:version "2023.03.17"}} + {clj-kondo/clj-kondo {:version "2023.05.26"}} :tasks {test:load-all-namespaces-with-nbb @@ -23,4 +23,4 @@ :tasks/config {:large-vars - {:max-lines-count 45}}} \ No newline at end of file + {:max-lines-count 45}}} diff --git a/deps/common/deps.edn b/deps/common/deps.edn index 8636da25970..cfe8fa52e2c 100644 --- a/deps/common/deps.edn +++ b/deps/common/deps.edn @@ -4,5 +4,5 @@ org.clojure/clojurescript {:mvn/version "1.11.54"}} :main-opts ["-m" "cljs-test-runner.main"]} :clj-kondo - {:replace-deps {clj-kondo/clj-kondo {:mvn/version "2022.12.08"}} + {:replace-deps {clj-kondo/clj-kondo {:mvn/version "2023.05.26"}} :main-opts ["-m" "clj-kondo.main"]}}} diff --git a/deps/db/bb.edn b/deps/db/bb.edn index f59c4281091..2bf0931d787 100644 --- a/deps/db/bb.edn +++ b/deps/db/bb.edn @@ -4,10 +4,10 @@ {logseq/bb-tasks #_{:local/root "../../../bb-tasks"} {:git/url "https://github.com/logseq/bb-tasks" - :git/sha "1815db538241082a01e95601e23e4290dd64d0c0"}} + :git/sha "70d3edeb287f5cec7192e642549a401f7d6d4263"}} :pods - {clj-kondo/clj-kondo {:version "2022.10.05"}} + {clj-kondo/clj-kondo {:version "2023.05.26"}} :tasks {test:load-all-namespaces-with-nbb diff --git a/deps/db/deps.edn b/deps/db/deps.edn index 5a60ce1b6f1..45816ef2793 100644 --- a/deps/db/deps.edn +++ b/deps/db/deps.edn @@ -3,5 +3,5 @@ {datascript/datascript {:mvn/version "1.3.8"}} :aliases {:clj-kondo - {:replace-deps {clj-kondo/clj-kondo {:mvn/version "2022.12.08"}} + {:replace-deps {clj-kondo/clj-kondo {:mvn/version "2023.05.26"}} :main-opts ["-m" "clj-kondo.main"]}}} diff --git a/deps/graph-parser/bb.edn b/deps/graph-parser/bb.edn index 4fd3f44662d..5093ff55f8f 100644 --- a/deps/graph-parser/bb.edn +++ b/deps/graph-parser/bb.edn @@ -3,10 +3,10 @@ {logseq/bb-tasks #_{:local/root "../../../bb-tasks"} {:git/url "https://github.com/logseq/bb-tasks" - :git/sha "1815db538241082a01e95601e23e4290dd64d0c0"}} + :git/sha "70d3edeb287f5cec7192e642549a401f7d6d4263"}} :pods - {clj-kondo/clj-kondo {:version "2022.10.05"}} + {clj-kondo/clj-kondo {:version "2023.05.26"}} :tasks {test:load-all-namespaces-with-nbb diff --git a/deps/graph-parser/deps.edn b/deps/graph-parser/deps.edn index c6b65464f61..4675c302c48 100644 --- a/deps/graph-parser/deps.edn +++ b/deps/graph-parser/deps.edn @@ -20,5 +20,5 @@ org.clojure/clojurescript {:mvn/version "1.11.54"}} :main-opts ["-m" "cljs-test-runner.main"]} - :clj-kondo {:replace-deps {clj-kondo/clj-kondo {:mvn/version "2022.12.08"}} + :clj-kondo {:replace-deps {clj-kondo/clj-kondo {:mvn/version "2023.05.26"}} :main-opts ["-m" "clj-kondo.main"]}}} diff --git a/deps/graph-parser/src/logseq/graph_parser/mldoc.cljc b/deps/graph-parser/src/logseq/graph_parser/mldoc.cljc index 221461a394b..7bc4bf05239 100644 --- a/deps/graph-parser/src/logseq/graph_parser/mldoc.cljc +++ b/deps/graph-parser/src/logseq/graph_parser/mldoc.cljc @@ -75,13 +75,26 @@ js/JSON.stringify)))) (defn remove-indentation-spaces + "Remove the indentation spaces from the content. Only for markdown. + level - ast level + 1 (2 for the first level, 3 for the second level, etc., as the non-first line of multi-line block has 2 more space + Ex. + - level 1 multiline block first line + level 1 multiline block second line + \t- level 2 multiline block first line + \t level 2 multiline block second line + remove-first-line? - apply the indentation removal to the first line or not" [s level remove-first-line?] (let [lines (string/split-lines s) [f & r] lines body (map (fn [line] + ;; Check if the indentation area only contains white spaces + ;; Level = ast level + 1, 1-based indentation level + ;; For markdown in Logseq, the indentation area for the non-first line of multi-line block is (ast level - 1) * "\t" + 2 * "(space)" (if (string/blank? (gp-util/safe-subs line 0 level)) + ;; If valid, then remove the indentation area spaces. Keep the rest of the line (might contain leading spaces) (gp-util/safe-subs line level) - line)) + ;; Otherwise, trim these invalid spaces + (string/triml line))) (if remove-first-line? lines r)) content (if remove-first-line? body (cons f body))] (string/join "\n" content))) diff --git a/deps/graph-parser/test/logseq/graph_parser/mldoc_test.cljs b/deps/graph-parser/test/logseq/graph_parser/mldoc_test.cljs index aef93a6369c..fe0819e86d2 100644 --- a/deps/graph-parser/test/logseq/graph_parser/mldoc_test.cljs +++ b/deps/graph-parser/test/logseq/graph_parser/mldoc_test.cljs @@ -119,6 +119,24 @@ body" (is ["@tag" "tag1" "tag2"] (sort (:filetags props))) (is ["@tag" "tag1" "tag2" "tag3"] (sort (:tags props)))))) +(deftest remove-indentation-spaces + (testing "Remove indentations for every line" + (is (= "block 1.1\n line 1\n line 2\nline 3\nline 4" + (let [s "block 1.1 + line 1 + line 2 + line 3 +line 4"] + (gp-mldoc/remove-indentation-spaces s 2 false)))) + (is (= "\t- block 1.1\n line 1\n line 2\nline 3\nline 4" + (let [s "\t- block 1.1 +\t line 1 +\t line 2 +\t line 3 +\tline 4"] + (gp-mldoc/remove-indentation-spaces s 3 false)))))) + + (deftest ^:integration test->edn (let [graph-dir "test/docs-0.9.2" _ (docs-graph-helper/clone-docs-repo-if-not-exists graph-dir "v0.9.2") diff --git a/deps/publishing/bb.edn b/deps/publishing/bb.edn index 234c14a0b4e..878757b9a47 100644 --- a/deps/publishing/bb.edn +++ b/deps/publishing/bb.edn @@ -3,10 +3,10 @@ {logseq/bb-tasks #_{:local/root "../../../bb-tasks"} {:git/url "https://github.com/logseq/bb-tasks" - :git/sha "0d49051909bfa0c6b414e86606d82b4ea54f382c"}} + :git/sha "70d3edeb287f5cec7192e642549a401f7d6d4263"}} :pods - {clj-kondo/clj-kondo {:version "2023.03.17"}} + {clj-kondo/clj-kondo {:version "2023.05.26"}} :tasks {test:load-all-namespaces-with-nbb diff --git a/deps/publishing/deps.edn b/deps/publishing/deps.edn index ca1078f3d2e..8893f828716 100644 --- a/deps/publishing/deps.edn +++ b/deps/publishing/deps.edn @@ -3,5 +3,5 @@ {logseq/db {:local/root "../db"}} :aliases - {:clj-kondo {:replace-deps {clj-kondo/clj-kondo {:mvn/version "2023.03.17"}} + {:clj-kondo {:replace-deps {clj-kondo/clj-kondo {:mvn/version "2023.05.26"}} :main-opts ["-m" "clj-kondo.main"]}}} diff --git a/deps/publishing/src/logseq/publishing/db.cljs b/deps/publishing/src/logseq/publishing/db.cljs index c17df0e3db3..2a71ebf5256 100644 --- a/deps/publishing/src/logseq/publishing/db.cljs +++ b/deps/publishing/src/logseq/publishing/db.cljs @@ -2,6 +2,8 @@ "Provides db fns and associated util fns for publishing" (:require [datascript.core :as d] [logseq.db.schema :as db-schema] + [logseq.db.rules :as rules] + [clojure.set :as set] [clojure.string :as string])) (defn ^:api get-area-block-asset-url @@ -92,6 +94,20 @@ flatten distinct))) +(defn- get-aliases-for-page-ids + [db page-ids] + (->> (d/q '[:find ?e + :in $ ?pages % + :where + [?page :block/name] + [(contains? ?pages ?page)] + (alias ?page ?e)] + db + (set page-ids) + (:alias rules/rules)) + (map first) + set)) + (defn clean-export! "Prepares a database assuming all pages are public unless a page has a 'public:: false'" [db] @@ -113,7 +129,8 @@ "Prepares a database assuming all pages are private unless a page has a 'public:: true'" [db] (when-let [public-pages* (seq (get-public-pages db))] - (let [public-pages (set public-pages*) + (let [public-pages (set/union (set public-pages*) + (get-aliases-for-page-ids db public-pages*)) exported-namespace? #(contains? #{"block" "recent"} %) filtered-db (d/filter db (fn [db datom] diff --git a/deps/publishing/test/logseq/publishing/db_test.cljs b/deps/publishing/test/logseq/publishing/db_test.cljs index e47c72ed255..b20439f1de6 100644 --- a/deps/publishing/test/logseq/publishing/db_test.cljs +++ b/deps/publishing/test/logseq/publishing/db_test.cljs @@ -36,7 +36,7 @@ (deftest filter-only-public-pages-and-blocks (let [conn (ldb/start-conn) _ (graph-parser/parse-file conn "page1.md" "- b11\n- b12\n- ![awesome.png](../assets/awesome_1648822509908_0.png)") - _ (graph-parser/parse-file conn "page2.md" "public:: true\n- b21\n- ![thumb-on-fire.PNG](../assets/thumb-on-fire_1648822523866_0.PNG)") + _ (graph-parser/parse-file conn "page2.md" "alias:: page2-alias\npublic:: true\n- b21\n- ![thumb-on-fire.PNG](../assets/thumb-on-fire_1648822523866_0.PNG)") _ (graph-parser/parse-file conn "page3.md" "public:: true\n- b31") [filtered-db assets] (publish-db/filter-only-public-pages-and-blocks @conn) exported-pages (->> (d/q '[:find (pull ?b [*]) @@ -56,6 +56,8 @@ "Contains all pages that have been marked public") (is (not (contains? exported-pages "page1")) "Doesn't contain private page") + (is (seq (d/entity filtered-db [:block/name "page2-alias"])) + "Alias of public page is exported") (is (= #{"page2" "page3"} exported-block-pages) "Only exports blocks from public pages") (is (= ["thumb-on-fire_1648822523866_0.PNG"] assets) diff --git a/docs/contributing-to-translations.md b/docs/contributing-to-translations.md index 2a0111d80e8..4982d52f594 100644 --- a/docs/contributing-to-translations.md +++ b/docs/contributing-to-translations.md @@ -80,27 +80,23 @@ $ bb lang:missing es --copy Almost all translations are small. The only exceptions to this are the keys `:tutorial/text` and `:tutorial/dummy-notes`. These translations are files that are part of the onboarding tutorial and can be found under [src/resources/tutorials/](https://github.com/logseq/logseq/blob/master/src/resources/tutorials/). -## Fix Untranslated - -There is a lot to translate and sometimes we forget to translate a string. To see what translation keys are still left for your language use : - -```shell -$ bb lang:duplicates LOCALE - -Keys with duplicate values found: - -| :translation-key | :duplicate-value | -|-----------------------------------+------------------| -| :general | General | -| :logseq | Logseq | -| :no | No | -``` +### Editing Tips +* Some translations may include punctuation like `:` or `!`. When translating them, please use the punctuation that makes the most sense for your language as you don't have to follow the English ones. +* Some translations may include arguments/interpolations e.g. `{1}`. If you see them in a translation, be sure to include them. These arguments are substituted in the string and are usually used something the app needs to calculate e.g. a number. See [these docs](https://github.com/tonsky/tongue#interpolation) for more examples. ## Fix Mistakes -Sometimes, we typo a translation key or forget to use it. If this happens, -the github CI step of `bb lang:validate-translations` will detect these errors -and tell you what's wrong. +There is a lint command to catch common translation mistakes - `bb +lang:validate-translations`. This runs for all contribution pull requests so +you'll need to ensure it doesn't fail. Mistakes that it catches: + +* Adding translation entries for nonexistent entries in English. + * Most common mistake is mistyping an entry name +* Adding English entries for translations that don't exist in the UI. +* Adding translation entries that are just duplicates of the English entry. + * This catches contributors copying entries from English and then forgetting to translate. Sometimes you do want to have the translation be the same. For this case, add an entry to `allowed-duplicates` in +[lang.clj](https://github.com/logseq/logseq/blob/master/scripts/src/logseq/tasks/lang.clj) for your language +with a list of duplicated entries e.g. `:nb-NO #{:port ...}`. ## Add a Language diff --git a/docs/dev-practices.md b/docs/dev-practices.md index 281f23fb513..2d0f35e4bc2 100644 --- a/docs/dev-practices.md +++ b/docs/dev-practices.md @@ -72,11 +72,14 @@ queries and rules. Our queries are linted through clj-kondo and [datalog-parser](https://github.com/lambdaforge/datalog-parser). clj-kondo will error if it detects an invalid query. -### Invalid translations +### Translations Our translations can be configured incorrectly. We can catch some of these mistakes [as noted here](./contributing-to-translations.md#fix-mistakes). +Punctuation and delimiting characters (e.g. `:`, `:`, `?`) should be part of the translatable string. +Those characters and their position may vary depending on the language. + ### Spell Checker We use [typos](https://github.com/crate-ci/typos) to spell check our source code. @@ -282,7 +285,7 @@ point out: * `dev:validate-repo-config-edn` - Validate a repo config.edn ```sh - bb dev:validate-repo-config-edn templates/config.edn + bb dev:validate-repo-config-edn src/resources/templates/config.edn ``` * `dev:publishing` - Build a publishing app for a given graph dir. If the diff --git a/e2e-tests/code-editing.spec.ts b/e2e-tests/code-editing.spec.ts index c46f3eecb1d..71335112c5a 100644 --- a/e2e-tests/code-editing.spec.ts +++ b/e2e-tests/code-editing.spec.ts @@ -9,7 +9,9 @@ import { createRandomPage, escapeToCodeEditor, escapeToBlockEditor } from './uti * For more information, see: https://codemirror.net/doc/manual.html */ -test('switch code editing mode', async ({ page }) => { +// 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 diff --git a/e2e-tests/editor.spec.ts b/e2e-tests/editor.spec.ts index a79d0cdd886..2181992f845 100644 --- a/e2e-tests/editor.spec.ts +++ b/e2e-tests/editor.spec.ts @@ -152,6 +152,7 @@ test( // 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 @@ -168,7 +169,7 @@ test( expect(await page.inputValue(':nth-match(textarea, 1)')).toBe(check_text + '[[]]') }; - // dont trigger RIME #3440 + // @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 diff --git a/e2e-tests/fixtures.ts b/e2e-tests/fixtures.ts index 16aea59a6b2..4ff9dc6efba 100644 --- a/e2e-tests/fixtures.ts +++ b/e2e-tests/fixtures.ts @@ -27,12 +27,13 @@ const consoleLogWatcher = (msg: ConsoleMessage) => { // List of error messages to ignore const ignoreErrors = [ - /net::ERR_CONNECTION_REFUSED/, + /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; } diff --git a/e2e-tests/history.spec.ts b/e2e-tests/history.spec.ts index 50d07e25cdf..fbf52911e46 100644 --- a/e2e-tests/history.spec.ts +++ b/e2e-tests/history.spec.ts @@ -43,6 +43,7 @@ test('undo/redo of a renamed page should be preserved', async ({ page, block }) await page.waitForTimeout(500) // Wait for 500ms autosave period to expire await renamePage(page, randomString(10)) + await page.click('.ui__confirm-modal button') await page.keyboard.press(modKey + '+z') await page.waitForTimeout(100) diff --git a/e2e-tests/hotkey.spec.ts b/e2e-tests/hotkey.spec.ts index ad1c07e852c..bfad8ffa989 100644 --- a/e2e-tests/hotkey.spec.ts +++ b/e2e-tests/hotkey.spec.ts @@ -1,9 +1,10 @@ import { expect } from '@playwright/test' import { test } from './fixtures' -import { createRandomPage, enterNextBlock, lastBlock, modKey, IsLinux } from './utils' +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="Search or create page"]') diff --git a/e2e-tests/logseq-api.spec.ts b/e2e-tests/logseq-api.spec.ts new file mode 100644 index 00000000000..69a533cdc33 --- /dev/null +++ b/e2e-tests/logseq-api.spec.ts @@ -0,0 +1,105 @@ +import { test } from './fixtures' +import { expect } from '@playwright/test' + +test('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 page.waitForSelector(`span[data-ref="${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) + await page.waitForTimeout(1000) + 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', 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() + }) + +/** + * @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]) +} diff --git a/e2e-tests/page-rename.spec.ts b/e2e-tests/page-rename.spec.ts index 783bacbf489..a498859acc7 100644 --- a/e2e-tests/page-rename.spec.ts +++ b/e2e-tests/page-rename.spec.ts @@ -1,6 +1,6 @@ import { expect, Page } from '@playwright/test' import { test } from './fixtures' -import { createPage, randomLowerString, randomString, renamePage } from './utils' +import { closeSearchBox, createPage, randomLowerString, randomString, renamePage, searchPage } from './utils' /*** * Test rename feature @@ -15,6 +15,7 @@ async function page_rename_test(page: Page, original_page_name: string, new_page // Rename page in UI await renamePage(page, new_name) + await page.click('.ui__confirm-modal button') expect(await page.innerText('.page-title .title')).toBe(new_name) @@ -45,6 +46,7 @@ async function homepage_rename_test(page: Page, original_page_name: string, new_ expect(await page.locator('.home-nav span.flex-1').innerText()).toBe(original_name); await renamePage(page, new_name) + await page.click('.ui__confirm-modal button') expect(await page.locator('.home-nav span.flex-1').innerText()).toBe(new_name); @@ -64,6 +66,16 @@ test('page rename test', async ({ page }) => { await page_rename_test(page, "abcd", "a.b.c.d") await page_rename_test(page, "abcd", "a/b/c/d") + // 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 thirdResultRow = await results[2].innerText() + expect(thirdResultRow).toContain("dCBA_"); + expect(thirdResultRow).not.toContain("DcBA_"); + await closeSearchBox(page) }) // TODO introduce more samples when #4722 is fixed diff --git a/e2e-tests/plugins.spec.ts b/e2e-tests/plugins.spec.ts index 30a47f9f692..8011ba55bab 100644 --- a/e2e-tests/plugins.spec.ts +++ b/e2e-tests/plugins.spec.ts @@ -1,5 +1,6 @@ import { expect } from '@playwright/test' import { test } from './fixtures' +import { callPageAPI } from './logseq-api.spec' test.skip('enabled plugin system default', async ({ page }) => { const callAPI = callPageAPI.bind(null, page) @@ -59,14 +60,3 @@ test.skip('play a plugin from the Marketplace', async await expect(page.locator('body[data-page="page"]')).toBeVisible() }) -/** - * @param page - * @param method - * @param args - */ -async function callPageAPI(page, method, ...args) { - return await page.evaluate(([method, args]) => { - // @ts-ignore - return window.logseq.api[method]?.(...args) - }, [method, args]) -} diff --git a/e2e-tests/util/page.ts b/e2e-tests/util/page.ts index 3e5e78caf72..8a4cfc86049 100644 --- a/e2e-tests/util/page.ts +++ b/e2e-tests/util/page.ts @@ -11,5 +11,4 @@ export async function renamePage(page: Page, new_name: string) { await page.fill('input[type="text"]', '') await page.type('.title input', new_name) await page.keyboard.press('Enter') - await page.click('.ui__confirm-modal button') } diff --git a/e2e-tests/util/search-modal.ts b/e2e-tests/util/search-modal.ts index d169f116655..3fa5c1f14a2 100644 --- a/e2e-tests/util/search-modal.ts +++ b/e2e-tests/util/search-modal.ts @@ -1,63 +1,66 @@ import { Page, Locator, ElementHandle } from '@playwright/test' import { randomString } from './basic' +export async function closeSearchBox(page: Page): Promise { + await page.keyboard.press("Escape") // escape (potential) search box typing + await page.waitForTimeout(500) + await page.keyboard.press("Escape") // 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="Search or create page"] await page.fill('[placeholder="Search or create page"]', randomTitle) // Click text=/.*New page: "new page".*/ - await page.click('text=/.*New page: ".*/') + await page.click('text=/.*New page:".*/') // 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 +} + +export async function createPage(page: Page, page_name: string) {// Click #search-button + await closeSearchBox(page) await page.click('#search-button') // Fill [placeholder="Search or create page"] await page.fill('[placeholder="Search or create page"]', page_name) // Click text=/.*New page: "new page".*/ - await page.click('text=/.*New page: ".*/') + await page.click('text=/.*New page:".*/') // 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) { + +export async function searchAndJumpToPage(page: Page, pageTitle: string) { + await closeSearchBox(page) await page.click('#search-button') await page.type('[placeholder="Search or create page"]', pageTitle) await page.waitForSelector(`[data-page-ref="${pageTitle}"]`, { state: 'visible' }) page.click(`[data-page-ref="${pageTitle}"]`) await page.waitForNavigation() 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[]>{ +} + +/** + * 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[]>{ + await closeSearchBox(page) await page.click('#search-button') await page.waitForSelector('[placeholder="Search or create page"]') await page.type('[placeholder="Search or create page"]', query, { delay: 10 }) await page.waitForTimeout(2000) // wait longer for search contents to render - + return page.$$('#ui__ac-inner>div'); - } - - export async function closeSearchBox(page: Page): Promise { - await page.keyboard.press("Escape") // escape (potential) search box typing - await page.waitForTimeout(500) - await page.keyboard.press("Escape") // escape modal - } +} diff --git a/e2e-tests/utils.ts b/e2e-tests/utils.ts index 22472a74b31..1cf13f84c88 100644 --- a/e2e-tests/utils.ts +++ b/e2e-tests/utils.ts @@ -2,6 +2,7 @@ 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 diff --git a/e2e-tests/whiteboards.spec.ts b/e2e-tests/whiteboards.spec.ts index fb10d871de0..60fdec1a623 100644 --- a/e2e-tests/whiteboards.spec.ts +++ b/e2e-tests/whiteboards.spec.ts @@ -1,6 +1,6 @@ import { expect } from '@playwright/test' import { test } from './fixtures' -import { modKey } from './utils' +import { modKey, renamePage } from './utils' test('enable whiteboards', async ({ page }) => { if (await page.$('.nav-header .whiteboard') === null) { @@ -85,10 +85,10 @@ test('draw a rectangle', async ({ page }) => { await page.keyboard.type('wr') - await page.mouse.move(bounds.x + 5, bounds.y + 5) + await page.mouse.move(bounds.x + 105, bounds.y + 105) await page.mouse.down() - await page.mouse.move(bounds.x + 50, bounds.y + 50 ) + await page.mouse.move(bounds.x + 150, bounds.y + 150 ) await page.mouse.up() await page.keyboard.press('Escape') @@ -114,12 +114,14 @@ test('clone the rectangle', async ({ page }) => { const canvas = await page.waitForSelector('.logseq-tldraw') const bounds = (await canvas.boundingBox())! - await page.mouse.move(bounds.x + 20, bounds.y + 20, {steps: 5}) + 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 + 100, bounds.y + 100, {steps: 5}) + await page.mouse.move(bounds.x + 200, bounds.y + 200, {steps: 5}) await page.mouse.up() await page.keyboard.up('Alt') @@ -163,10 +165,10 @@ test('connect rectangles with an arrow', async ({ page }) => { await page.keyboard.type('wc') - await page.mouse.move(bounds.x + 20, bounds.y + 20) + await page.mouse.move(bounds.x + 120, bounds.y + 120) await page.mouse.down() - await page.mouse.move(bounds.x + 100, bounds.y + 100, {steps: 5}) // will fail without steps + 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') @@ -191,10 +193,15 @@ test('undo the delete action', async ({ page }) => { }) 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.waitForTimeout(1000) - await page.click('.logseq-tldraw .tl-box-container:first-of-type') - await page.mouse.move(0, 0) // move mouse to trigger a rerender of the context bar + 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]') @@ -223,9 +230,14 @@ test('undo the shape conversion', async ({ page }) => { }) 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.waitForTimeout(1000) - await page.click('.logseq-tldraw .tl-box-container:first-of-type') + 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`) await page.keyboard.press('Delete') await page.keyboard.press(`${modKey}+Shift+l`) @@ -269,7 +281,7 @@ test('create a block', async ({ page }) => { const bounds = (await canvas.boundingBox())! await page.keyboard.type('ws') - await page.mouse.dblclick(bounds.x + 5, bounds.y + 5) + await page.mouse.dblclick(bounds.x + 105, bounds.y + 105) await page.waitForTimeout(100) await page.keyboard.type('a') @@ -279,15 +291,17 @@ test('create a block', async ({ page }) => { await expect(page.locator('.logseq-tldraw .tl-logseq-portal-container')).toHaveCount(1) }) -test('expand the block', async ({ page }) => { +// TODO: Fix the failing test +test.skip('expand the block', async ({ page }) => { await page.keyboard.press('Escape') - await page.click('.logseq-tldraw .tl-context-bar .tie-object-expanded ') + 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) }) -test('undo the expand action', async ({ page }) => { +// 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) @@ -304,7 +318,7 @@ test('copy/paste url to create an iFrame shape', async ({ page }) => { const bounds = (await canvas.boundingBox())! await page.keyboard.type('wt') - await page.mouse.move(bounds.x + 5, bounds.y + 5) + await page.mouse.move(bounds.x + 105, bounds.y + 105) await page.mouse.down() await page.waitForTimeout(100) @@ -323,7 +337,7 @@ test('copy/paste twitter status url to create a Tweet shape', async ({ page }) = const bounds = (await canvas.boundingBox())! await page.keyboard.type('wt') - await page.mouse.move(bounds.x + 5, bounds.y + 5) + await page.mouse.move(bounds.x + 105, bounds.y + 105) await page.mouse.down() await page.waitForTimeout(100) @@ -342,7 +356,7 @@ test('copy/paste youtube video url to create a Youtube shape', async ({ page }) const bounds = (await canvas.boundingBox())! await page.keyboard.type('wt') - await page.mouse.move(bounds.x + 5, bounds.y + 5) + await page.mouse.move(bounds.x + 105, bounds.y + 105) await page.mouse.down() await page.waitForTimeout(100) @@ -394,8 +408,8 @@ test('quick add another whiteboard', async ({ page }) => { const canvas = await page.waitForSelector('.logseq-tldraw') await canvas.dblclick({ position: { - x: 100, - y: 100, + x: 200, + y: 200, }, }) @@ -425,3 +439,65 @@ test('go to another board and check reference', async ({ page }) => { 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') +}) \ No newline at end of file diff --git a/e2e-tests/window.spec.ts b/e2e-tests/window.spec.ts new file mode 100644 index 00000000000..3e9adc3d647 --- /dev/null +++ b/e2e-tests/window.spec.ts @@ -0,0 +1,34 @@ +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) + }) +} diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index 9aab4404745..937b50ea545 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -519,7 +519,7 @@ INFOPLIST_FILE = App/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 0.9.8; + MARKETING_VERSION = 0.9.9; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -546,7 +546,7 @@ INFOPLIST_FILE = App/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 0.9.8; + MARKETING_VERSION = 0.9.9; PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; @@ -571,7 +571,7 @@ INFOPLIST_KEY_NSHumanReadableCopyright = ""; IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; - MARKETING_VERSION = 0.9.8; + MARKETING_VERSION = 0.9.9; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController; @@ -598,7 +598,7 @@ INFOPLIST_KEY_NSHumanReadableCopyright = ""; IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; - MARKETING_VERSION = 0.9.8; + MARKETING_VERSION = 0.9.9; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/ios/App/App/FsWatcher.swift b/ios/App/App/FsWatcher.swift index 50c9ebded79..ecebec013bd 100644 --- a/ios/App/App/FsWatcher.swift +++ b/ios/App/App/FsWatcher.swift @@ -56,7 +56,7 @@ public class FsWatcher: CAPPlugin, PollingWatcherDelegate { DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.notifyListeners("watcher", data: ["event": "unlink", "dir": baseUrl.description as Any, - "path": url.description + "path": url.relativePath(from: baseUrl)?.precomposedStringWithCanonicalMapping as Any ]) } case .Add, .Change: @@ -173,11 +173,11 @@ public class PollingWatcher { public init?(at: URL) { url = at } - + public func start() { - + self.tick(notify: false) - + let queue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".timer") timer = DispatchSource.makeTimerSource(queue: queue) timer!.setEventHandler(qos: .background, flags: []) { [weak self] in @@ -278,10 +278,18 @@ extension URL { return nil } + // NOTE: standardizedFileURL will remove `/private` prefix + // If the file is not exist, it won't remove the prefix. + // Remove/replace "." and "..", make paths absolute: - let destComponents = self.standardizedFileURL.pathComponents + var destComponents = self.standardizedFileURL.pathComponents let baseComponents = base.standardizedFileURL.pathComponents + // replace "private" when needed + if destComponents.count > 1 && destComponents[1] == "private" && baseComponents.count > 1 && baseComponents[1] != "private" { + destComponents.remove(at: 1) + } + // Find number of common path components: var i = 0 while i < destComponents.count && i < baseComponents.count diff --git a/libs/src/LSPlugin.core.ts b/libs/src/LSPlugin.core.ts index 498ab9a541b..ce1af87af71 100644 --- a/libs/src/LSPlugin.core.ts +++ b/libs/src/LSPlugin.core.ts @@ -233,7 +233,7 @@ function initMainUIHandlers(pluginLocal: PluginLocal) { pluginLocal.on(_('attrs'), (attrs: Partial) => { const el = pluginLocal.getMainUIContainer() Object.entries(attrs).forEach(([k, v]) => { - el?.setAttribute(k, v) + el?.setAttribute(k, String(v)) if (k === 'draggable' && v) { pluginLocal._dispose( pluginLocal._setupDraggableContainer(el, { diff --git a/libs/src/LSPlugin.ts b/libs/src/LSPlugin.ts index b110f9e7d59..f12334038f4 100644 --- a/libs/src/LSPlugin.ts +++ b/libs/src/LSPlugin.ts @@ -33,8 +33,6 @@ export type StyleOptions = { export type UIContainerAttrs = { draggable: boolean resizable: boolean - - [key: string]: any } export type UIBaseOptions = { @@ -75,20 +73,34 @@ export interface LSPluginPkgConfig { mode: 'shadow' | 'iframe' themes: Theme[] icon: string - - [key: string]: any + /** + * Alternative entrypoint for development. + */ + devEntry: unknown + /** + * For legacy themes, do not use. + */ + theme: unknown } export interface LSPluginBaseInfo { - id: string // should be unique + /** + * Must be unique. + */ + id: string mode: 'shadow' | 'iframe' - settings: { disabled: boolean - [key: string]: any - } - - [key: string]: any + } & Record + effect: boolean + /** + * For internal use only. Indicates if plugin is installed in dot root. + */ + iir: boolean + /** + * For internal use only. + */ + lsr: string } export type IHookEvent = { @@ -146,8 +158,6 @@ export interface AppUserConfigs { showBracket: boolean enabledFlashcards: boolean enabledJournals: boolean - - [key: string]: any } /** @@ -157,8 +167,6 @@ export interface AppGraphInfo { name: string url: string path: string - - [key: string]: any } /** @@ -184,8 +192,6 @@ export interface BlockEntity { level?: number meta?: { timestamps: any; properties: any; startPos: number; endPos: number } title?: Array - - [key: string]: any } /** @@ -205,8 +211,6 @@ export interface PageEntity { format?: 'markdown' | 'org' journalDay?: number updatedAt?: number - - [key: string]: any } export type BlockIdentity = BlockUUID | Pick @@ -1078,8 +1082,8 @@ export interface ILSPluginUser extends EventEmitter { resolveResourceFullUrl(filePath: string): string - App: IAppProxy & Record - Editor: IEditorProxy & Record + App: IAppProxy + Editor: IEditorProxy DB: IDBProxy Git: IGitProxy UI: IUIProxy diff --git a/package.json b/package.json index 21c0ffe44c7..a4cac0a3a4d 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,7 @@ "highlight.js": "10.4.1", "ignore": "5.1.8", "jszip": "3.8.0", - "mldoc": "^1.5.1", + "mldoc": "^1.5.5", "path": "0.12.7", "path-complete-extname": "1.0.0", "pixi-graph-fork": "0.2.0", @@ -158,4 +158,4 @@ "pixi-graph-fork/@pixi/mixin-get-child-by-name": "6.2.0", "pixi-graph-fork/@pixi/math": "6.2.0" } -} \ No newline at end of file +} diff --git a/playwright.config.ts b/playwright.config.ts index 53a869e1e32..0040571be05 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,12 +1,28 @@ 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, - workers: 1, // NOTE: must be 1 for now, otherwise tests will fail. + + // 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 diff --git a/resources/css/katex.min.css b/resources/css/katex.min.css index efef9610b1b..ef52517fcc3 100644 --- a/resources/css/katex.min.css +++ b/resources/css/katex.min.css @@ -1 +1 @@ -@font-face{font-family:KaTeX_AMS;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_AMS-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_AMS-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_AMS-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Caligraphic-Bold.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Caligraphic-Bold.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Caligraphic-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Caligraphic-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Caligraphic-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Caligraphic-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Fraktur-Bold.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Fraktur-Bold.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Fraktur-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Fraktur-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Fraktur-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Fraktur-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Main-Bold.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Main-Bold.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Main-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Main-BoldItalic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Main-BoldItalic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Main-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Main-Italic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Main-Italic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Main-Italic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Main-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Main-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Main-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Math-BoldItalic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Math-BoldItalic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Math-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Math-Italic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Math-Italic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Math-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_SansSerif-Bold.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_SansSerif-Bold.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_SansSerif-Bold.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:italic;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_SansSerif-Italic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_SansSerif-Italic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_SansSerif-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_SansSerif-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_SansSerif-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_SansSerif-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Script;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Script-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Script-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Script-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size1;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Size1-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Size1-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Size1-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size2;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Size2-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Size2-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Size2-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size3;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Size3-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Size3-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Size3-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size4;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Size4-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Size4-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Size4-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Typewriter;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Typewriter-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Typewriter-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.13.18/dist/fonts/KaTeX_Typewriter-Regular.ttf) format("truetype")}.katex{text-rendering:auto;font:normal 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;text-indent:0}.katex *{-ms-high-contrast-adjust:none!important;border-color:currentColor}.katex .katex-version:after{content:"0.13.18"}.katex .katex-mathml{clip:rect(1px,1px,1px,1px);border:0;height:1px;overflow:hidden;padding:0;position:absolute;width:1px}.katex .katex-html>.newline{display:block}.katex .base{position:relative;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .base,.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-style:italic;font-weight:700}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{border-collapse:collapse;display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;position:relative;vertical-align:bottom}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;font-size:1px;min-width:2px;vertical-align:bottom;width:2px}.katex .vbox{align-items:baseline;display:inline-flex;flex-direction:column}.katex .hbox{width:100%}.katex .hbox,.katex .thinbox{display:inline-flex;flex-direction:row}.katex .thinbox{max-width:0;width:0}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline,.katex .hline,.katex .mfrac .frac-line,.katex .overline .overline-line,.katex .rule,.katex .underline .underline-line{min-height:1px}.katex .mspace{display:inline-block}.katex .clap,.katex .llap,.katex .rlap{position:relative;width:0}.katex .clap>.inner,.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .clap>.fix,.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .clap>.inner,.katex .rlap>.inner{left:0}.katex .clap>.inner>span{margin-left:-50%;margin-right:50%}.katex .rule{border:0 solid;display:inline-block;position:relative}.katex .hline,.katex .overline .overline-line,.katex .underline .underline-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline{border-bottom-style:dashed;display:inline-block;width:100%}.katex .sqrt>.root{margin-left:.27777778em;margin-right:-.55555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.83333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.16666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.66666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.45666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11{font-size:4.14666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.71428571em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.85714286em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.14285714em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.28571429em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.42857143em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.71428571em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.05714286em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.46857143em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:2.96285714em}.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11{font-size:3.55428571em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.55555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.66666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.77777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.88888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.11111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.30444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11{font-size:2.76444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.41666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.58333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.66666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.83333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.72833333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11{font-size:2.07333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.34722222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.41666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.48611111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.55555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.69444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.83333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.44027778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11{font-size:1.72777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.28935185em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.34722222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.40509259em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.46296296em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.52083333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.5787037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.69444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.83333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.20023148em}.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11{font-size:1.43981481em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.24108004em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.28929605em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.33751205em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.38572806em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.43394407em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.48216008em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.57859209em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.69431051em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.83317261em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11{font-size:1.19961427em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.20096463em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.24115756em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.28135048em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.32154341em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.36173633em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.40192926em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.48231511em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.57877814em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.69453376em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.83360129em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist-t,.katex .op-limits>.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{fill:currentColor;stroke:currentColor;fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:block;height:inherit;position:absolute;width:100%}.katex svg path{stroke:none}.katex img{border-style:none;max-height:none;max-width:none;min-height:0;min-width:0}.katex .stretchy{display:block;overflow:hidden;position:relative;width:100%}.katex .stretchy:after,.katex .stretchy:before{content:""}.katex .hide-tail{overflow:hidden;position:relative;width:100%}.katex .halfarrow-left{left:0;overflow:hidden;position:absolute;width:50.2%}.katex .halfarrow-right{overflow:hidden;position:absolute;right:0;width:50.2%}.katex .brace-left{left:0;overflow:hidden;position:absolute;width:25.1%}.katex .brace-center{left:25%;overflow:hidden;position:absolute;width:50%}.katex .brace-right{overflow:hidden;position:absolute;right:0;width:25.1%}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{border:.04em solid;box-sizing:border-box}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{border-right:.049em solid;border-top:.049em solid;box-sizing:border-box;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .eqn-num:before{content:"(" counter(katexEqnNo) ")";counter-increment:katexEqnNo}.katex .mml-eqn-num:before{content:"(" counter(mmlEqnNo) ")";counter-increment:mmlEqnNo}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:inline-block;left:calc(50% + .3em);position:absolute;text-align:right}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:block;text-align:center;white-space:nowrap}.katex-display>.katex>.katex-html{display:block;position:relative}.katex-display>.katex>.katex-html>.tag{position:absolute;right:0}.katex-display.leqno>.katex>.katex-html>.tag{left:0;right:auto}.katex-display.fleqn>.katex{padding-left:2em;text-align:left}body{counter-reset:katexEqnNo mmlEqnNo} +@font-face{font-family:KaTeX_AMS;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_AMS-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_AMS-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_AMS-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Caligraphic-Bold.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Caligraphic-Bold.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Caligraphic-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Caligraphic-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Caligraphic-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Caligraphic-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Fraktur-Bold.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Fraktur-Bold.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Fraktur-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Fraktur-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Fraktur-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Fraktur-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Main-Bold.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Main-Bold.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Main-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Main-BoldItalic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Main-BoldItalic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Main-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Main-Italic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Main-Italic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Main-Italic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Main-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Main-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Main-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Math-BoldItalic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Math-BoldItalic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Math-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Math-Italic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Math-Italic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Math-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:700;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_SansSerif-Bold.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_SansSerif-Bold.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_SansSerif-Bold.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:italic;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_SansSerif-Italic.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_SansSerif-Italic.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_SansSerif-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_SansSerif-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_SansSerif-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_SansSerif-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Script;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Script-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Script-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Script-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size1;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Size1-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Size1-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Size1-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size2;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Size2-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Size2-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Size2-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size3;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Size3-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Size3-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Size3-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size4;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Size4-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Size4-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Size4-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Typewriter;font-style:normal;font-weight:400;src:url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Typewriter-Regular.woff2) format("woff2"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Typewriter-Regular.woff) format("woff"),url(https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/fonts/KaTeX_Typewriter-Regular.ttf) format("truetype")}.katex{text-rendering:auto;font:normal 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;text-indent:0}.katex *{-ms-high-contrast-adjust:none!important;border-color:currentColor}.katex .katex-version:after{content:"0.16.7"}.katex .katex-mathml{clip:rect(1px,1px,1px,1px);border:0;height:1px;overflow:hidden;padding:0;position:absolute;width:1px}.katex .katex-html>.newline{display:block}.katex .base{position:relative;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .base,.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-style:italic;font-weight:700}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{border-collapse:collapse;display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;position:relative;vertical-align:bottom}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;font-size:1px;min-width:2px;vertical-align:bottom;width:2px}.katex .vbox{align-items:baseline;display:inline-flex;flex-direction:column}.katex .hbox{width:100%}.katex .hbox,.katex .thinbox{display:inline-flex;flex-direction:row}.katex .thinbox{max-width:0;width:0}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline,.katex .hline,.katex .mfrac .frac-line,.katex .overline .overline-line,.katex .rule,.katex .underline .underline-line{min-height:1px}.katex .mspace{display:inline-block}.katex .clap,.katex .llap,.katex .rlap{position:relative;width:0}.katex .clap>.inner,.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .clap>.fix,.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .clap>.inner,.katex .rlap>.inner{left:0}.katex .clap>.inner>span{margin-left:-50%;margin-right:50%}.katex .rule{border:0 solid;display:inline-block;position:relative}.katex .hline,.katex .overline .overline-line,.katex .underline .underline-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline{border-bottom-style:dashed;display:inline-block;width:100%}.katex .sqrt>.root{margin-left:.27777778em;margin-right:-.55555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.83333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.16666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.66666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.45666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11{font-size:4.14666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.71428571em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.85714286em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.14285714em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.28571429em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.42857143em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.71428571em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.05714286em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.46857143em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:2.96285714em}.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11{font-size:3.55428571em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.55555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.66666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.77777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.88888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.11111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.30444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11{font-size:2.76444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.41666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.58333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.66666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.83333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.72833333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11{font-size:2.07333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.34722222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.41666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.48611111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.55555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.69444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.83333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.44027778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11{font-size:1.72777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.28935185em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.34722222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.40509259em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.46296296em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.52083333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.5787037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.69444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.83333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.20023148em}.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11{font-size:1.43981481em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.24108004em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.28929605em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.33751205em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.38572806em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.43394407em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.48216008em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.57859209em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.69431051em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.83317261em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11{font-size:1.19961427em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.20096463em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.24115756em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.28135048em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.32154341em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.36173633em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.40192926em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.48231511em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.57877814em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.69453376em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.83360129em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist-t,.katex .op-limits>.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{fill:currentColor;stroke:currentColor;fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:block;height:inherit;position:absolute;width:100%}.katex svg path{stroke:none}.katex img{border-style:none;max-height:none;max-width:none;min-height:0;min-width:0}.katex .stretchy{display:block;overflow:hidden;position:relative;width:100%}.katex .stretchy:after,.katex .stretchy:before{content:""}.katex .hide-tail{overflow:hidden;position:relative;width:100%}.katex .halfarrow-left{left:0;overflow:hidden;position:absolute;width:50.2%}.katex .halfarrow-right{overflow:hidden;position:absolute;right:0;width:50.2%}.katex .brace-left{left:0;overflow:hidden;position:absolute;width:25.1%}.katex .brace-center{left:25%;overflow:hidden;position:absolute;width:50%}.katex .brace-right{overflow:hidden;position:absolute;right:0;width:25.1%}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{border:.04em solid;box-sizing:border-box}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{border-right:.049em solid;border-top:.049em solid;box-sizing:border-box;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .eqn-num:before{content:"(" counter(katexEqnNo) ")";counter-increment:katexEqnNo}.katex .mml-eqn-num:before{content:"(" counter(mmlEqnNo) ")";counter-increment:mmlEqnNo}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:inline-block;left:calc(50% + .3em);position:absolute;text-align:right}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:block;text-align:center;white-space:nowrap}.katex-display>.katex>.katex-html{display:block;position:relative}.katex-display>.katex>.katex-html>.tag{position:absolute;right:0}.katex-display.leqno>.katex>.katex-html>.tag{left:0;right:auto}.katex-display.fleqn>.katex{padding-left:2em;text-align:left}body{counter-reset:katexEqnNo mmlEqnNo} diff --git a/resources/js/katex.min.js b/resources/js/katex.min.js index 26353bc9f17..4dd87faca79 100644 --- a/resources/js/katex.min.js +++ b/resources/js/katex.min.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.katex=t():e.katex=t()}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={d:function(t,r){for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}},t={};e.d(t,{default:function(){return Zn}});var r=function e(t,r){this.position=void 0;var n,a="KaTeX parse error: "+t,i=r&&r.loc;if(i&&i.start<=i.end){var o=i.lexer.input;n=i.start;var s=i.end;n===o.length?a+=" at end of input: ":a+=" at position "+(n+1)+": ";var l=o.slice(n,s).replace(/[^]/g,"$&\u0332");a+=(n>15?"\u2026"+o.slice(n-15,n):o.slice(0,n))+l+(s+15":">","<":"<",'"':""","'":"'"},o=/[&><"']/g;var s=function e(t){return"ordgroup"===t.type||"color"===t.type?1===t.body.length?e(t.body[0]):t:"font"===t.type?e(t.body):t},l={contains:function(e,t){return-1!==e.indexOf(t)},deflt:function(e,t){return void 0===e?t:e},escape:function(e){return String(e).replace(o,(function(e){return i[e]}))},hyphenate:function(e){return e.replace(a,"-$1").toLowerCase()},getBaseElem:s,isCharacterBox:function(e){var t=s(e);return"mathord"===t.type||"textord"===t.type||"atom"===t.type},protocolFromUrl:function(e){var t=/^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(e);return null!=t?t[1]:"_relative"}},h=function(){function e(e){this.displayMode=void 0,this.output=void 0,this.leqno=void 0,this.fleqn=void 0,this.throwOnError=void 0,this.errorColor=void 0,this.macros=void 0,this.minRuleThickness=void 0,this.colorIsTextColor=void 0,this.strict=void 0,this.trust=void 0,this.maxSize=void 0,this.maxExpand=void 0,this.globalGroup=void 0,e=e||{},this.displayMode=l.deflt(e.displayMode,!1),this.output=l.deflt(e.output,"htmlAndMathml"),this.leqno=l.deflt(e.leqno,!1),this.fleqn=l.deflt(e.fleqn,!1),this.throwOnError=l.deflt(e.throwOnError,!0),this.errorColor=l.deflt(e.errorColor,"#cc0000"),this.macros=e.macros||{},this.minRuleThickness=Math.max(0,l.deflt(e.minRuleThickness,0)),this.colorIsTextColor=l.deflt(e.colorIsTextColor,!1),this.strict=l.deflt(e.strict,"warn"),this.trust=l.deflt(e.trust,!1),this.maxSize=Math.max(0,l.deflt(e.maxSize,1/0)),this.maxExpand=Math.max(0,l.deflt(e.maxExpand,1e3)),this.globalGroup=l.deflt(e.globalGroup,!1)}var t=e.prototype;return t.reportNonstrict=function(e,t,r){var a=this.strict;if("function"==typeof a&&(a=a(e,t,r)),a&&"ignore"!==a){if(!0===a||"error"===a)throw new n("LaTeX-incompatible input and strict mode is set to 'error': "+t+" ["+e+"]",r);"warn"===a?"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"):"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+a+"': "+t+" ["+e+"]")}},t.useStrictBehavior=function(e,t,r){var n=this.strict;if("function"==typeof n)try{n=n(e,t,r)}catch(e){n="error"}return!(!n||"ignore"===n)&&(!0===n||"error"===n||("warn"===n?("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"),!1):("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+n+"': "+t+" ["+e+"]"),!1)))},t.isTrusted=function(e){e.url&&!e.protocol&&(e.protocol=l.protocolFromUrl(e.url));var t="function"==typeof this.trust?this.trust(e):this.trust;return Boolean(t)},e}(),m=function(){function e(e,t,r){this.id=void 0,this.size=void 0,this.cramped=void 0,this.id=e,this.size=t,this.cramped=r}var t=e.prototype;return t.sup=function(){return c[u[this.id]]},t.sub=function(){return c[p[this.id]]},t.fracNum=function(){return c[d[this.id]]},t.fracDen=function(){return c[f[this.id]]},t.cramp=function(){return c[g[this.id]]},t.text=function(){return c[v[this.id]]},t.isTight=function(){return this.size>=2},e}(),c=[new m(0,0,!1),new m(1,0,!0),new m(2,1,!1),new m(3,1,!0),new m(4,2,!1),new m(5,2,!0),new m(6,3,!1),new m(7,3,!0)],u=[4,5,4,5,6,7,6,7],p=[5,5,5,5,7,7,7,7],d=[2,3,4,5,6,7,6,7],f=[3,3,5,5,7,7,7,7],g=[1,1,3,3,5,5,7,7],v=[0,1,2,3,2,3,2,3],b={DISPLAY:c[0],TEXT:c[2],SCRIPT:c[4],SCRIPTSCRIPT:c[6]},y=[{name:"latin",blocks:[[256,591],[768,879]]},{name:"cyrillic",blocks:[[1024,1279]]},{name:"armenian",blocks:[[1328,1423]]},{name:"brahmic",blocks:[[2304,4255]]},{name:"georgian",blocks:[[4256,4351]]},{name:"cjk",blocks:[[12288,12543],[19968,40879],[65280,65376]]},{name:"hangul",blocks:[[44032,55215]]}];var x=[];function w(e){for(var t=0;t=x[t]&&e<=x[t+1])return!0;return!1}y.forEach((function(e){return e.blocks.forEach((function(e){return x.push.apply(x,e)}))}));var k=80,S={doubleleftarrow:"M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z",doublerightarrow:"M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z",leftarrow:"M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z",leftbrace:"M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z",leftbraceunder:"M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z",leftgroup:"M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z",leftgroupunder:"M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z",leftharpoon:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z",leftharpoonplus:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z",leftharpoondown:"M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z",leftharpoondownplus:"M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z",lefthook:"M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z",leftlinesegment:"M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z",leftmapsto:"M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z",leftToFrom:"M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z",longequal:"M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z",midbrace:"M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z",midbraceunder:"M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z",oiintSize1:"M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z",oiintSize2:"M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z",oiiintSize1:"M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z",oiiintSize2:"M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z",rightarrow:"M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z",rightbrace:"M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z",rightbraceunder:"M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z",rightgroup:"M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z",rightgroupunder:"M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z",rightharpoon:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z",rightharpoonplus:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z",rightharpoondown:"M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z",rightharpoondownplus:"M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z",righthook:"M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z",rightlinesegment:"M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z",rightToFrom:"M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z",twoheadleftarrow:"M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z",twoheadrightarrow:"M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z",tilde1:"M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z",tilde2:"M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z",tilde3:"M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z",tilde4:"M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z",vec:"M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z",widehat1:"M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z",widehat2:"M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat3:"M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat4:"M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widecheck1:"M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z",widecheck2:"M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck3:"M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck4:"M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",baraboveleftarrow:"M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z",rightarrowabovebar:"M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z",baraboveshortleftharpoon:"M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z",rightharpoonaboveshortbar:"M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z",shortbaraboveleftharpoon:"M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z",shortrightharpoonabovebar:"M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z"},M=function(){function e(e){this.children=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.children=e,this.classes=[],this.height=0,this.depth=0,this.maxFontSize=0,this.style={}}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){for(var e=document.createDocumentFragment(),t=0;t"},N=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.width=void 0,this.maxFontSize=void 0,this.style=void 0,A.call(this,e,r,n),this.children=t||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return T.call(this,"span")},t.toMarkup=function(){return B.call(this,"span")},e}(),q=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,A.call(this,t,n),this.children=r||[],this.setAttribute("href",e)}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return T.call(this,"a")},t.toMarkup=function(){return B.call(this,"a")},e}(),C=function(){function e(e,t,r){this.src=void 0,this.alt=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.alt=t,this.src=e,this.classes=["mord"],this.style=r}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createElement("img");for(var t in e.src=this.src,e.alt=this.alt,e.className="mord",this.style)this.style.hasOwnProperty(t)&&(e.style[t]=this.style[t]);return e},t.toMarkup=function(){var e=""+this.alt+"=a[0]&&e<=a[1])return r.name}return null}(this.text.charCodeAt(0));l&&this.classes.push(l+"_fallback"),/[\xee\xef\xed\xec]/.test(this.text)&&(this.text=I[this.text])}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createTextNode(this.text),t=null;for(var r in this.italic>0&&((t=document.createElement("span")).style.marginRight=this.italic+"em"),this.classes.length>0&&((t=t||document.createElement("span")).className=z(this.classes)),this.style)this.style.hasOwnProperty(r)&&((t=t||document.createElement("span")).style[r]=this.style[r]);return t?(t.appendChild(e),t):e},t.toMarkup=function(){var e=!1,t="0&&(r+="margin-right:"+this.italic+"em;"),this.style)this.style.hasOwnProperty(n)&&(r+=l.hyphenate(n)+":"+this.style[n]+";");r&&(e=!0,t+=' style="'+l.escape(r)+'"');var a=l.escape(this.text);return e?(t+=">",t+=a,t+=""):a},e}(),O=function(){function e(e,t){this.children=void 0,this.attributes=void 0,this.children=e||[],this.attributes=t||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","svg");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);for(var r=0;r":""},e}(),H=function(){function e(e){this.attributes=void 0,this.attributes=e||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","line");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);return e},t.toMarkup=function(){var e="","\\gt",!0),_(j,Z,oe,"\u2208","\\in",!0),_(j,Z,oe,"\ue020","\\@not"),_(j,Z,oe,"\u2282","\\subset",!0),_(j,Z,oe,"\u2283","\\supset",!0),_(j,Z,oe,"\u2286","\\subseteq",!0),_(j,Z,oe,"\u2287","\\supseteq",!0),_(j,K,oe,"\u2288","\\nsubseteq",!0),_(j,K,oe,"\u2289","\\nsupseteq",!0),_(j,Z,oe,"\u22a8","\\models"),_(j,Z,oe,"\u2190","\\leftarrow",!0),_(j,Z,oe,"\u2264","\\le"),_(j,Z,oe,"\u2264","\\leq",!0),_(j,Z,oe,"<","\\lt",!0),_(j,Z,oe,"\u2192","\\rightarrow",!0),_(j,Z,oe,"\u2192","\\to"),_(j,K,oe,"\u2271","\\ngeq",!0),_(j,K,oe,"\u2270","\\nleq",!0),_(j,Z,se,"\xa0","\\ "),_(j,Z,se,"\xa0","\\space"),_(j,Z,se,"\xa0","\\nobreakspace"),_($,Z,se,"\xa0","\\ "),_($,Z,se,"\xa0"," "),_($,Z,se,"\xa0","\\space"),_($,Z,se,"\xa0","\\nobreakspace"),_(j,Z,se,null,"\\nobreak"),_(j,Z,se,null,"\\allowbreak"),_(j,Z,ie,",",","),_(j,Z,ie,";",";"),_(j,K,Q,"\u22bc","\\barwedge",!0),_(j,K,Q,"\u22bb","\\veebar",!0),_(j,Z,Q,"\u2299","\\odot",!0),_(j,Z,Q,"\u2295","\\oplus",!0),_(j,Z,Q,"\u2297","\\otimes",!0),_(j,Z,le,"\u2202","\\partial",!0),_(j,Z,Q,"\u2298","\\oslash",!0),_(j,K,Q,"\u229a","\\circledcirc",!0),_(j,K,Q,"\u22a1","\\boxdot",!0),_(j,Z,Q,"\u25b3","\\bigtriangleup"),_(j,Z,Q,"\u25bd","\\bigtriangledown"),_(j,Z,Q,"\u2020","\\dagger"),_(j,Z,Q,"\u22c4","\\diamond"),_(j,Z,Q,"\u22c6","\\star"),_(j,Z,Q,"\u25c3","\\triangleleft"),_(j,Z,Q,"\u25b9","\\triangleright"),_(j,Z,ae,"{","\\{"),_($,Z,le,"{","\\{"),_($,Z,le,"{","\\textbraceleft"),_(j,Z,ee,"}","\\}"),_($,Z,le,"}","\\}"),_($,Z,le,"}","\\textbraceright"),_(j,Z,ae,"{","\\lbrace"),_(j,Z,ee,"}","\\rbrace"),_(j,Z,ae,"[","\\lbrack",!0),_($,Z,le,"[","\\lbrack",!0),_(j,Z,ee,"]","\\rbrack",!0),_($,Z,le,"]","\\rbrack",!0),_(j,Z,ae,"(","\\lparen",!0),_(j,Z,ee,")","\\rparen",!0),_($,Z,le,"<","\\textless",!0),_($,Z,le,">","\\textgreater",!0),_(j,Z,ae,"\u230a","\\lfloor",!0),_(j,Z,ee,"\u230b","\\rfloor",!0),_(j,Z,ae,"\u2308","\\lceil",!0),_(j,Z,ee,"\u2309","\\rceil",!0),_(j,Z,le,"\\","\\backslash"),_(j,Z,le,"\u2223","|"),_(j,Z,le,"\u2223","\\vert"),_($,Z,le,"|","\\textbar",!0),_(j,Z,le,"\u2225","\\|"),_(j,Z,le,"\u2225","\\Vert"),_($,Z,le,"\u2225","\\textbardbl"),_($,Z,le,"~","\\textasciitilde"),_($,Z,le,"\\","\\textbackslash"),_($,Z,le,"^","\\textasciicircum"),_(j,Z,oe,"\u2191","\\uparrow",!0),_(j,Z,oe,"\u21d1","\\Uparrow",!0),_(j,Z,oe,"\u2193","\\downarrow",!0),_(j,Z,oe,"\u21d3","\\Downarrow",!0),_(j,Z,oe,"\u2195","\\updownarrow",!0),_(j,Z,oe,"\u21d5","\\Updownarrow",!0),_(j,Z,ne,"\u2210","\\coprod"),_(j,Z,ne,"\u22c1","\\bigvee"),_(j,Z,ne,"\u22c0","\\bigwedge"),_(j,Z,ne,"\u2a04","\\biguplus"),_(j,Z,ne,"\u22c2","\\bigcap"),_(j,Z,ne,"\u22c3","\\bigcup"),_(j,Z,ne,"\u222b","\\int"),_(j,Z,ne,"\u222b","\\intop"),_(j,Z,ne,"\u222c","\\iint"),_(j,Z,ne,"\u222d","\\iiint"),_(j,Z,ne,"\u220f","\\prod"),_(j,Z,ne,"\u2211","\\sum"),_(j,Z,ne,"\u2a02","\\bigotimes"),_(j,Z,ne,"\u2a01","\\bigoplus"),_(j,Z,ne,"\u2a00","\\bigodot"),_(j,Z,ne,"\u222e","\\oint"),_(j,Z,ne,"\u222f","\\oiint"),_(j,Z,ne,"\u2230","\\oiiint"),_(j,Z,ne,"\u2a06","\\bigsqcup"),_(j,Z,ne,"\u222b","\\smallint"),_($,Z,te,"\u2026","\\textellipsis"),_(j,Z,te,"\u2026","\\mathellipsis"),_($,Z,te,"\u2026","\\ldots",!0),_(j,Z,te,"\u2026","\\ldots",!0),_(j,Z,te,"\u22ef","\\@cdots",!0),_(j,Z,te,"\u22f1","\\ddots",!0),_(j,Z,le,"\u22ee","\\varvdots"),_(j,Z,J,"\u02ca","\\acute"),_(j,Z,J,"\u02cb","\\grave"),_(j,Z,J,"\xa8","\\ddot"),_(j,Z,J,"~","\\tilde"),_(j,Z,J,"\u02c9","\\bar"),_(j,Z,J,"\u02d8","\\breve"),_(j,Z,J,"\u02c7","\\check"),_(j,Z,J,"^","\\hat"),_(j,Z,J,"\u20d7","\\vec"),_(j,Z,J,"\u02d9","\\dot"),_(j,Z,J,"\u02da","\\mathring"),_(j,Z,re,"\ue131","\\@imath"),_(j,Z,re,"\ue237","\\@jmath"),_(j,Z,le,"\u0131","\u0131"),_(j,Z,le,"\u0237","\u0237"),_($,Z,le,"\u0131","\\i",!0),_($,Z,le,"\u0237","\\j",!0),_($,Z,le,"\xdf","\\ss",!0),_($,Z,le,"\xe6","\\ae",!0),_($,Z,le,"\u0153","\\oe",!0),_($,Z,le,"\xf8","\\o",!0),_($,Z,le,"\xc6","\\AE",!0),_($,Z,le,"\u0152","\\OE",!0),_($,Z,le,"\xd8","\\O",!0),_($,Z,J,"\u02ca","\\'"),_($,Z,J,"\u02cb","\\`"),_($,Z,J,"\u02c6","\\^"),_($,Z,J,"\u02dc","\\~"),_($,Z,J,"\u02c9","\\="),_($,Z,J,"\u02d8","\\u"),_($,Z,J,"\u02d9","\\."),_($,Z,J,"\xb8","\\c"),_($,Z,J,"\u02da","\\r"),_($,Z,J,"\u02c7","\\v"),_($,Z,J,"\xa8",'\\"'),_($,Z,J,"\u02dd","\\H"),_($,Z,J,"\u25ef","\\textcircled");var he={"--":!0,"---":!0,"``":!0,"''":!0};_($,Z,le,"\u2013","--",!0),_($,Z,le,"\u2013","\\textendash"),_($,Z,le,"\u2014","---",!0),_($,Z,le,"\u2014","\\textemdash"),_($,Z,le,"\u2018","`",!0),_($,Z,le,"\u2018","\\textquoteleft"),_($,Z,le,"\u2019","'",!0),_($,Z,le,"\u2019","\\textquoteright"),_($,Z,le,"\u201c","``",!0),_($,Z,le,"\u201c","\\textquotedblleft"),_($,Z,le,"\u201d","''",!0),_($,Z,le,"\u201d","\\textquotedblright"),_(j,Z,le,"\xb0","\\degree",!0),_($,Z,le,"\xb0","\\degree"),_($,Z,le,"\xb0","\\textdegree",!0),_(j,Z,le,"\xa3","\\pounds"),_(j,Z,le,"\xa3","\\mathsterling",!0),_($,Z,le,"\xa3","\\pounds"),_($,Z,le,"\xa3","\\textsterling",!0),_(j,K,le,"\u2720","\\maltese"),_($,K,le,"\u2720","\\maltese");for(var me='0123456789/@."',ce=0;ce=5?0:e>=3?1:2]){var r=G[t]={cssEmPerMu:P.quad[t]/18};for(var n in P)P.hasOwnProperty(n)&&(r[n]=P[n][t])}return G[t]}(this.size)),this._fontMetrics},t.getColor=function(){return this.phantom?"transparent":this.color},e}();Ie.BASESIZE=6;var Re=Ie,Oe={pt:1,mm:7227/2540,cm:7227/254,in:72.27,bp:1.00375,pc:12,dd:1238/1157,cc:14856/1157,nd:685/642,nc:1370/107,sp:1/65536,px:1.00375},Ee={ex:!0,em:!0,mu:!0},He=function(e){return"string"!=typeof e&&(e=e.unit),e in Oe||e in Ee||"ex"===e},Le=function(e,t){var r;if(e.unit in Oe)r=Oe[e.unit]/t.fontMetrics().ptPerEm/t.sizeMultiplier;else if("mu"===e.unit)r=t.fontMetrics().cssEmPerMu;else{var a;if(a=t.style.isTight()?t.havingStyle(t.style.text()):t,"ex"===e.unit)r=a.fontMetrics().xHeight;else{if("em"!==e.unit)throw new n("Invalid unit: '"+e.unit+"'");r=a.fontMetrics().quad}a!==t&&(r*=a.sizeMultiplier/t.sizeMultiplier)}return Math.min(e.number*r,t.maxSize)},De=function(e,t,r){return X[r][e]&&X[r][e].replace&&(e=X[r][e].replace),{value:e,metrics:V(e,t,r)}},Pe=function(e,t,r,n,a){var i,o=De(e,t,r),s=o.metrics;if(e=o.value,s){var l=s.italic;("text"===r||n&&"mathit"===n.font)&&(l=0),i=new R(e,s.height,s.depth,l,s.skew,s.width,a)}else"undefined"!=typeof console&&console.warn("No character metrics for '"+e+"' in style '"+t+"' and mode '"+r+"'"),i=new R(e,0,0,0,0,0,a);if(n){i.maxFontSize=n.sizeMultiplier,n.style.isTight()&&i.classes.push("mtight");var h=n.getColor();h&&(i.style.color=h)}return i},Fe=function(e,t){if(z(e.classes)!==z(t.classes)||e.skew!==t.skew||e.maxFontSize!==t.maxFontSize)return!1;if(1===e.classes.length){var r=e.classes[0];if("mbin"===r||"mord"===r)return!1}for(var n in e.style)if(e.style.hasOwnProperty(n)&&e.style[n]!==t.style[n])return!1;for(var a in t.style)if(t.style.hasOwnProperty(a)&&e.style[a]!==t.style[a])return!1;return!0},Ve=function(e){for(var t=0,r=0,n=0,a=0;at&&(t=i.height),i.depth>r&&(r=i.depth),i.maxFontSize>n&&(n=i.maxFontSize)}e.height=t,e.depth=r,e.maxFontSize=n},Ge=function(e,t,r,n){var a=new N(e,t,r,n);return Ve(a),a},Ue=function(e,t,r,n){return new N(e,t,r,n)},Ye=function(e){var t=new M(e);return Ve(t),t},We=function(e,t,r){var n="";switch(e){case"amsrm":n="AMS";break;case"textrm":n="Main";break;case"textsf":n="SansSerif";break;case"texttt":n="Typewriter";break;default:n=e}return n+"-"+("textbf"===t&&"textit"===r?"BoldItalic":"textbf"===t?"Bold":"textit"===t?"Italic":"Regular")},Xe={mathbf:{variant:"bold",fontName:"Main-Bold"},mathrm:{variant:"normal",fontName:"Main-Regular"},textit:{variant:"italic",fontName:"Main-Italic"},mathit:{variant:"italic",fontName:"Main-Italic"},mathnormal:{variant:"italic",fontName:"Math-Italic"},mathbb:{variant:"double-struck",fontName:"AMS-Regular"},mathcal:{variant:"script",fontName:"Caligraphic-Regular"},mathfrak:{variant:"fraktur",fontName:"Fraktur-Regular"},mathscr:{variant:"script",fontName:"Script-Regular"},mathsf:{variant:"sans-serif",fontName:"SansSerif-Regular"},mathtt:{variant:"monospace",fontName:"Typewriter-Regular"}},_e={vec:["vec",.471,.714],oiintSize1:["oiintSize1",.957,.499],oiintSize2:["oiintSize2",1.472,.659],oiiintSize1:["oiiintSize1",1.304,.499],oiiintSize2:["oiiintSize2",1.98,.659]},je={fontMap:Xe,makeSymbol:Pe,mathsym:function(e,t,r,n){return void 0===n&&(n=[]),"boldsymbol"===r.font&&De(e,"Main-Bold",t).metrics?Pe(e,"Main-Bold",t,r,n.concat(["mathbf"])):"\\"===e||"main"===X[t][e].font?Pe(e,"Main-Regular",t,r,n):Pe(e,"AMS-Regular",t,r,n.concat(["amsrm"]))},makeSpan:Ge,makeSvgSpan:Ue,makeLineSpan:function(e,t,r){var n=Ge([e],[],t);return n.height=Math.max(r||t.fontMetrics().defaultRuleThickness,t.minRuleThickness),n.style.borderBottomWidth=n.height+"em",n.maxFontSize=1,n},makeAnchor:function(e,t,r,n){var a=new q(e,t,r,n);return Ve(a),a},makeFragment:Ye,wrapFragment:function(e,t){return e instanceof M?Ge([],[e],t):e},makeVList:function(e,t){for(var r=function(e){if("individualShift"===e.positionType){for(var t=e.children,r=[t[0]],n=-t[0].shift-t[0].elem.depth,a=n,i=1;i0&&(o.push(yt(s,t)),s=[]),o.push(a[l]));s.length>0&&o.push(yt(s,t)),r?((i=yt(ut(r,t,!0))).classes=["tag"],o.push(i)):n&&o.push(n);var m=st(["katex-html"],o);if(m.setAttribute("aria-hidden","true"),i){var c=i.children[0];c.style.height=m.height+m.depth+"em",c.style.verticalAlign=-m.depth+"em"}return m}function wt(e){return new M(e)}var kt=function(){function e(e,t,r){this.type=void 0,this.attributes=void 0,this.children=void 0,this.classes=void 0,this.type=e,this.attributes={},this.children=t||[],this.classes=r||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.getAttribute=function(e){return this.attributes[e]},t.toNode=function(){var e=document.createElementNS("http://www.w3.org/1998/Math/MathML",this.type);for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);this.classes.length>0&&(e.className=z(this.classes));for(var r=0;r0&&(e+=' class ="'+l.escape(z(this.classes))+'"'),e+=">";for(var r=0;r"},t.toText=function(){return this.children.map((function(e){return e.toText()})).join("")},e}(),St=function(){function e(e){this.text=void 0,this.text=e}var t=e.prototype;return t.toNode=function(){return document.createTextNode(this.text)},t.toMarkup=function(){return l.escape(this.toText())},t.toText=function(){return this.text},e}(),Mt={MathNode:kt,TextNode:St,SpaceNode:function(){function e(e){this.width=void 0,this.character=void 0,this.width=e,this.character=e>=.05555&&e<=.05556?"\u200a":e>=.1666&&e<=.1667?"\u2009":e>=.2222&&e<=.2223?"\u2005":e>=.2777&&e<=.2778?"\u2005\u200a":e>=-.05556&&e<=-.05555?"\u200a\u2063":e>=-.1667&&e<=-.1666?"\u2009\u2063":e>=-.2223&&e<=-.2222?"\u205f\u2063":e>=-.2778&&e<=-.2777?"\u2005\u2063":null}var t=e.prototype;return t.toNode=function(){if(this.character)return document.createTextNode(this.character);var e=document.createElementNS("http://www.w3.org/1998/Math/MathML","mspace");return e.setAttribute("width",this.width+"em"),e},t.toMarkup=function(){return this.character?""+this.character+"":''},t.toText=function(){return this.character?this.character:" "},e}(),newDocumentFragment:wt},zt=function(e,t,r){return!X[t][e]||!X[t][e].replace||55349===e.charCodeAt(0)||he.hasOwnProperty(e)&&r&&(r.fontFamily&&"tt"===r.fontFamily.substr(4,2)||r.font&&"tt"===r.font.substr(4,2))||(e=X[t][e].replace),new Mt.TextNode(e)},At=function(e){return 1===e.length?e[0]:new Mt.MathNode("mrow",e)},Tt=function(e,t){if("texttt"===t.fontFamily)return"monospace";if("textsf"===t.fontFamily)return"textit"===t.fontShape&&"textbf"===t.fontWeight?"sans-serif-bold-italic":"textit"===t.fontShape?"sans-serif-italic":"textbf"===t.fontWeight?"bold-sans-serif":"sans-serif";if("textit"===t.fontShape&&"textbf"===t.fontWeight)return"bold-italic";if("textit"===t.fontShape)return"italic";if("textbf"===t.fontWeight)return"bold";var r=t.font;if(!r||"mathnormal"===r)return null;var n=e.mode;if("mathit"===r)return"italic";if("boldsymbol"===r)return"textord"===e.type?"bold":"bold-italic";if("mathbf"===r)return"bold";if("mathbb"===r)return"double-struck";if("mathfrak"===r)return"fraktur";if("mathscr"===r||"mathcal"===r)return"script";if("mathsf"===r)return"sans-serif";if("mathtt"===r)return"monospace";var a=e.text;return l.contains(["\\imath","\\jmath"],a)?null:(X[n][a]&&X[n][a].replace&&(a=X[n][a].replace),V(a,je.fontMap[r].fontName,n)?je.fontMap[r].variant:null)},Bt=function(e,t,r){if(1===e.length){var n=qt(e[0],t);return r&&n instanceof kt&&"mo"===n.type&&(n.setAttribute("lspace","0em"),n.setAttribute("rspace","0em")),[n]}for(var a,i=[],o=0;o0&&(p.text=p.text.slice(0,1)+"\u0338"+p.text.slice(1),i.pop())}}}i.push(s),a=s}return i},Nt=function(e,t,r){return At(Bt(e,t,r))},qt=function(e,t){if(!e)return new Mt.MathNode("mrow");if(rt[e.type])return rt[e.type](e,t);throw new n("Got group of unknown type: '"+e.type+"'")};function Ct(e,t,r,n,a){var i,o=Bt(e,r);i=1===o.length&&o[0]instanceof kt&&l.contains(["mrow","mtable"],o[0].type)?o[0]:new Mt.MathNode("mrow",o);var s=new Mt.MathNode("annotation",[new Mt.TextNode(t)]);s.setAttribute("encoding","application/x-tex");var h=new Mt.MathNode("semantics",[i,s]),m=new Mt.MathNode("math",[h]);m.setAttribute("xmlns","http://www.w3.org/1998/Math/MathML"),n&&m.setAttribute("display","block");var c=a?"katex":"katex-mathml";return je.makeSpan([c],[m])}var It=function(e){return new Re({style:e.displayMode?b.DISPLAY:b.TEXT,maxSize:e.maxSize,minRuleThickness:e.minRuleThickness})},Rt=function(e,t){if(t.displayMode){var r=["katex-display"];t.leqno&&r.push("leqno"),t.fleqn&&r.push("fleqn"),e=je.makeSpan(r,[e])}return e},Ot=function(e,t,r){var n,a=It(r);if("mathml"===r.output)return Ct(e,t,a,r.displayMode,!0);if("html"===r.output){var i=xt(e,a);n=je.makeSpan(["katex"],[i])}else{var o=Ct(e,t,a,r.displayMode,!1),s=xt(e,a);n=je.makeSpan(["katex"],[o,s])}return Rt(n,r)},Et={widehat:"^",widecheck:"\u02c7",widetilde:"~",utilde:"~",overleftarrow:"\u2190",underleftarrow:"\u2190",xleftarrow:"\u2190",overrightarrow:"\u2192",underrightarrow:"\u2192",xrightarrow:"\u2192",underbrace:"\u23df",overbrace:"\u23de",overgroup:"\u23e0",undergroup:"\u23e1",overleftrightarrow:"\u2194",underleftrightarrow:"\u2194",xleftrightarrow:"\u2194",Overrightarrow:"\u21d2",xRightarrow:"\u21d2",overleftharpoon:"\u21bc",xleftharpoonup:"\u21bc",overrightharpoon:"\u21c0",xrightharpoonup:"\u21c0",xLeftarrow:"\u21d0",xLeftrightarrow:"\u21d4",xhookleftarrow:"\u21a9",xhookrightarrow:"\u21aa",xmapsto:"\u21a6",xrightharpoondown:"\u21c1",xleftharpoondown:"\u21bd",xrightleftharpoons:"\u21cc",xleftrightharpoons:"\u21cb",xtwoheadleftarrow:"\u219e",xtwoheadrightarrow:"\u21a0",xlongequal:"=",xtofrom:"\u21c4",xrightleftarrows:"\u21c4",xrightequilibrium:"\u21cc",xleftequilibrium:"\u21cb","\\cdrightarrow":"\u2192","\\cdleftarrow":"\u2190","\\cdlongequal":"="},Ht={overrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],overleftarrow:[["leftarrow"],.888,522,"xMinYMin"],underrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],underleftarrow:[["leftarrow"],.888,522,"xMinYMin"],xrightarrow:[["rightarrow"],1.469,522,"xMaxYMin"],"\\cdrightarrow":[["rightarrow"],3,522,"xMaxYMin"],xleftarrow:[["leftarrow"],1.469,522,"xMinYMin"],"\\cdleftarrow":[["leftarrow"],3,522,"xMinYMin"],Overrightarrow:[["doublerightarrow"],.888,560,"xMaxYMin"],xRightarrow:[["doublerightarrow"],1.526,560,"xMaxYMin"],xLeftarrow:[["doubleleftarrow"],1.526,560,"xMinYMin"],overleftharpoon:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoonup:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoondown:[["leftharpoondown"],.888,522,"xMinYMin"],overrightharpoon:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoonup:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoondown:[["rightharpoondown"],.888,522,"xMaxYMin"],xlongequal:[["longequal"],.888,334,"xMinYMin"],"\\cdlongequal":[["longequal"],3,334,"xMinYMin"],xtwoheadleftarrow:[["twoheadleftarrow"],.888,334,"xMinYMin"],xtwoheadrightarrow:[["twoheadrightarrow"],.888,334,"xMaxYMin"],overleftrightarrow:[["leftarrow","rightarrow"],.888,522],overbrace:[["leftbrace","midbrace","rightbrace"],1.6,548],underbrace:[["leftbraceunder","midbraceunder","rightbraceunder"],1.6,548],underleftrightarrow:[["leftarrow","rightarrow"],.888,522],xleftrightarrow:[["leftarrow","rightarrow"],1.75,522],xLeftrightarrow:[["doubleleftarrow","doublerightarrow"],1.75,560],xrightleftharpoons:[["leftharpoondownplus","rightharpoonplus"],1.75,716],xleftrightharpoons:[["leftharpoonplus","rightharpoondownplus"],1.75,716],xhookleftarrow:[["leftarrow","righthook"],1.08,522],xhookrightarrow:[["lefthook","rightarrow"],1.08,522],overlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],underlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],overgroup:[["leftgroup","rightgroup"],.888,342],undergroup:[["leftgroupunder","rightgroupunder"],.888,342],xmapsto:[["leftmapsto","rightarrow"],1.5,522],xtofrom:[["leftToFrom","rightToFrom"],1.75,528],xrightleftarrows:[["baraboveleftarrow","rightarrowabovebar"],1.75,901],xrightequilibrium:[["baraboveshortleftharpoon","rightharpoonaboveshortbar"],1.75,716],xleftequilibrium:[["shortbaraboveleftharpoon","shortrightharpoonabovebar"],1.75,716]},Lt=function(e,t,r,n,a){var i,o=e.height+e.depth+r+n;if(/fbox|color|angl/.test(t)){if(i=je.makeSpan(["stretchy",t],[],a),"fbox"===t){var s=a.color&&a.getColor();s&&(i.style.borderColor=s)}}else{var l=[];/^[bx]cancel$/.test(t)&&l.push(new H({x1:"0",y1:"0",x2:"100%",y2:"100%","stroke-width":"0.046em"})),/^x?cancel$/.test(t)&&l.push(new H({x1:"0",y1:"100%",x2:"100%",y2:"0","stroke-width":"0.046em"}));var h=new O(l,{width:"100%",height:o+"em"});i=je.makeSvgSpan([],[h],a)}return i.height=o,i.style.height=o+"em",i},Dt=function(e){var t=new Mt.MathNode("mo",[new Mt.TextNode(Et[e.replace(/^\\/,"")])]);return t.setAttribute("stretchy","true"),t},Pt=function(e,t){var r=function(){var r=4e5,n=e.label.substr(1);if(l.contains(["widehat","widecheck","widetilde","utilde"],n)){var a,i,o,s="ordgroup"===(d=e.base).type?d.body.length:1;if(s>5)"widehat"===n||"widecheck"===n?(a=420,r=2364,o=.42,i=n+"4"):(a=312,r=2340,o=.34,i="tilde4");else{var h=[1,1,2,2,3,3][s];"widehat"===n||"widecheck"===n?(r=[0,1062,2364,2364,2364][h],a=[0,239,300,360,420][h],o=[0,.24,.3,.3,.36,.42][h],i=n+h):(r=[0,600,1033,2339,2340][h],a=[0,260,286,306,312][h],o=[0,.26,.286,.3,.306,.34][h],i="tilde"+h)}var m=new E(i),c=new O([m],{width:"100%",height:o+"em",viewBox:"0 0 "+r+" "+a,preserveAspectRatio:"none"});return{span:je.makeSvgSpan([],[c],t),minWidth:0,height:o}}var u,p,d,f=[],g=Ht[n],v=g[0],b=g[1],y=g[2],x=y/1e3,w=v.length;if(1===w)u=["hide-tail"],p=[g[3]];else if(2===w)u=["halfarrow-left","halfarrow-right"],p=["xMinYMin","xMaxYMin"];else{if(3!==w)throw new Error("Correct katexImagesData or update code here to support\n "+w+" children.");u=["brace-left","brace-center","brace-right"],p=["xMinYMin","xMidYMin","xMaxYMin"]}for(var k=0;k0&&(n.style.minWidth=a+"em"),n};function Ft(e,t){if(!e||e.type!==t)throw new Error("Expected node of type "+t+", but got "+(e?"node of type "+e.type:String(e)));return e}function Vt(e){var t=Gt(e);if(!t)throw new Error("Expected node of symbol group type, but got "+(e?"node of type "+e.type:String(e)));return t}function Gt(e){return e&&("atom"===e.type||Y.hasOwnProperty(e.type))?e:null}var Ut=function(e,t){var r,n,a;e&&"supsub"===e.type?(r=(n=Ft(e.base,"accent")).base,e.base=r,a=function(e){if(e instanceof N)return e;throw new Error("Expected span but got "+String(e)+".")}(bt(e,t)),e.base=n):r=(n=Ft(e,"accent")).base;var i=bt(r,t.havingCrampedStyle()),o=0;if(n.isShifty&&l.isCharacterBox(r)){var s=l.getBaseElem(r);o=L(bt(s,t.havingCrampedStyle())).skew}var h,m="\\c"===n.label,c=m?i.height+i.depth:Math.min(i.height,t.fontMetrics().xHeight);if(n.isStretchy)h=Pt(n,t),h=je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"elem",elem:h,wrapperClasses:["svg-align"],wrapperStyle:o>0?{width:"calc(100% - "+2*o+"em)",marginLeft:2*o+"em"}:void 0}]},t);else{var u,p;"\\vec"===n.label?(u=je.staticSvg("vec",t),p=je.svgData.vec[1]):((u=L(u=je.makeOrd({mode:n.mode,text:n.label},t,"textord"))).italic=0,p=u.width,m&&(c+=u.depth)),h=je.makeSpan(["accent-body"],[u]);var d="\\textcircled"===n.label;d&&(h.classes.push("accent-full"),c=i.height);var f=o;d||(f-=p/2),h.style.left=f+"em","\\textcircled"===n.label&&(h.style.top=".2em"),h=je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"kern",size:-c},{type:"elem",elem:h}]},t)}var g=je.makeSpan(["mord","accent"],[h],t);return a?(a.children[0]=g,a.height=Math.max(g.height,a.height),a.classes[0]="mord",a):g},Yt=function(e,t){var r=e.isStretchy?Dt(e.label):new Mt.MathNode("mo",[zt(e.label,e.mode)]),n=new Mt.MathNode("mover",[qt(e.base,t),r]);return n.setAttribute("accent","true"),n},Wt=new RegExp(["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring"].map((function(e){return"\\"+e})).join("|"));nt({type:"accent",names:["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring","\\widecheck","\\widehat","\\widetilde","\\overrightarrow","\\overleftarrow","\\Overrightarrow","\\overleftrightarrow","\\overgroup","\\overlinesegment","\\overleftharpoon","\\overrightharpoon"],props:{numArgs:1},handler:function(e,t){var r=it(t[0]),n=!Wt.test(e.funcName),a=!n||"\\widehat"===e.funcName||"\\widetilde"===e.funcName||"\\widecheck"===e.funcName;return{type:"accent",mode:e.parser.mode,label:e.funcName,isStretchy:n,isShifty:a,base:r}},htmlBuilder:Ut,mathmlBuilder:Yt}),nt({type:"accent",names:["\\'","\\`","\\^","\\~","\\=","\\u","\\.",'\\"',"\\c","\\r","\\H","\\v","\\textcircled"],props:{numArgs:1,allowedInText:!0,allowedInMath:!0,argTypes:["primitive"]},handler:function(e,t){var r=t[0],n=e.parser.mode;return"math"===n&&(e.parser.settings.reportNonstrict("mathVsTextAccents","LaTeX's accent "+e.funcName+" works only in text mode"),n="text"),{type:"accent",mode:n,label:e.funcName,isStretchy:!1,isShifty:!0,base:r}},htmlBuilder:Ut,mathmlBuilder:Yt}),nt({type:"accentUnder",names:["\\underleftarrow","\\underrightarrow","\\underleftrightarrow","\\undergroup","\\underlinesegment","\\utilde"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"accentUnder",mode:r.mode,label:n,base:a}},htmlBuilder:function(e,t){var r=bt(e.base,t),n=Pt(e,t),a="\\utilde"===e.label?.12:0,i=je.makeVList({positionType:"top",positionData:r.height,children:[{type:"elem",elem:n,wrapperClasses:["svg-align"]},{type:"kern",size:a},{type:"elem",elem:r}]},t);return je.makeSpan(["mord","accentunder"],[i],t)},mathmlBuilder:function(e,t){var r=Dt(e.label),n=new Mt.MathNode("munder",[qt(e.base,t),r]);return n.setAttribute("accentunder","true"),n}});var Xt=function(e){var t=new Mt.MathNode("mpadded",e?[e]:[]);return t.setAttribute("width","+0.6em"),t.setAttribute("lspace","0.3em"),t};nt({type:"xArrow",names:["\\xleftarrow","\\xrightarrow","\\xLeftarrow","\\xRightarrow","\\xleftrightarrow","\\xLeftrightarrow","\\xhookleftarrow","\\xhookrightarrow","\\xmapsto","\\xrightharpoondown","\\xrightharpoonup","\\xleftharpoondown","\\xleftharpoonup","\\xrightleftharpoons","\\xleftrightharpoons","\\xlongequal","\\xtwoheadrightarrow","\\xtwoheadleftarrow","\\xtofrom","\\xrightleftarrows","\\xrightequilibrium","\\xleftequilibrium","\\\\cdrightarrow","\\\\cdleftarrow","\\\\cdlongequal"],props:{numArgs:1,numOptionalArgs:1},handler:function(e,t,r){var n=e.parser,a=e.funcName;return{type:"xArrow",mode:n.mode,label:a,body:t[0],below:r[0]}},htmlBuilder:function(e,t){var r,n=t.style,a=t.havingStyle(n.sup()),i=je.wrapFragment(bt(e.body,a,t),t),o="\\x"===e.label.slice(0,2)?"x":"cd";i.classes.push(o+"-arrow-pad"),e.below&&(a=t.havingStyle(n.sub()),(r=je.wrapFragment(bt(e.below,a,t),t)).classes.push(o+"-arrow-pad"));var s,l=Pt(e,t),h=-t.fontMetrics().axisHeight+.5*l.height,m=-t.fontMetrics().axisHeight-.5*l.height-.111;if((i.depth>.25||"\\xleftequilibrium"===e.label)&&(m-=i.depth),r){var c=-t.fontMetrics().axisHeight+r.height+.5*l.height+.111;s=je.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:m},{type:"elem",elem:l,shift:h},{type:"elem",elem:r,shift:c}]},t)}else s=je.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:m},{type:"elem",elem:l,shift:h}]},t);return s.children[0].children[0].children[1].classes.push("svg-align"),je.makeSpan(["mrel","x-arrow"],[s],t)},mathmlBuilder:function(e,t){var r,n=Dt(e.label);if(n.setAttribute("minsize","x"===e.label.charAt(0)?"1.75em":"3.0em"),e.body){var a=Xt(qt(e.body,t));if(e.below){var i=Xt(qt(e.below,t));r=new Mt.MathNode("munderover",[n,i,a])}else r=new Mt.MathNode("mover",[n,a])}else if(e.below){var o=Xt(qt(e.below,t));r=new Mt.MathNode("munder",[n,o])}else r=Xt(),r=new Mt.MathNode("mover",[n,r]);return r}});var _t={">":"\\\\cdrightarrow","<":"\\\\cdleftarrow","=":"\\\\cdlongequal",A:"\\uparrow",V:"\\downarrow","|":"\\Vert",".":"no arrow"},jt=function(e){return"textord"===e.type&&"@"===e.text};function $t(e,t,r){var n=_t[e];switch(n){case"\\\\cdrightarrow":case"\\\\cdleftarrow":return r.callFunction(n,[t[0]],[t[1]]);case"\\uparrow":case"\\downarrow":var a={type:"atom",text:n,mode:"math",family:"rel"},i={type:"ordgroup",mode:"math",body:[r.callFunction("\\\\cdleft",[t[0]],[]),r.callFunction("\\Big",[a],[]),r.callFunction("\\\\cdright",[t[1]],[])]};return r.callFunction("\\\\cdparent",[i],[]);case"\\\\cdlongequal":return r.callFunction("\\\\cdlongequal",[],[]);case"\\Vert":return r.callFunction("\\Big",[{type:"textord",text:"\\Vert",mode:"math"}],[]);default:return{type:"textord",text:" ",mode:"math"}}}nt({type:"cdlabel",names:["\\\\cdleft","\\\\cdright"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"cdlabel",mode:r.mode,side:n.slice(4),label:t[0]}},htmlBuilder:function(e,t){var r=t.havingStyle(t.style.sup()),n=je.wrapFragment(bt(e.label,r,t),t);return n.classes.push("cd-label-"+e.side),n.style.bottom=.8-n.depth+"em",n.height=0,n.depth=0,n},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mrow",[qt(e.label,t)]);return(r=new Mt.MathNode("mpadded",[r])).setAttribute("width","0"),"left"===e.side&&r.setAttribute("lspace","-1width"),r.setAttribute("voffset","0.7em"),(r=new Mt.MathNode("mstyle",[r])).setAttribute("displaystyle","false"),r.setAttribute("scriptlevel","1"),r}}),nt({type:"cdlabelparent",names:["\\\\cdparent"],props:{numArgs:1},handler:function(e,t){return{type:"cdlabelparent",mode:e.parser.mode,fragment:t[0]}},htmlBuilder:function(e,t){var r=je.wrapFragment(bt(e.fragment,t),t);return r.classes.push("cd-vert-arrow"),r},mathmlBuilder:function(e,t){return new Mt.MathNode("mrow",[qt(e.fragment,t)])}}),nt({type:"textord",names:["\\@char"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){for(var r=e.parser,a=Ft(t[0],"ordgroup").body,i="",o=0;o=1114111)throw new n("\\@char with invalid code point "+i);return l<=65535?s=String.fromCharCode(l):(l-=65536,s=String.fromCharCode(55296+(l>>10),56320+(1023&l))),{type:"textord",mode:r.mode,text:s}}});var Zt=function(e,t){var r=ut(e.body,t.withColor(e.color),!1);return je.makeFragment(r)},Kt=function(e,t){var r=Bt(e.body,t.withColor(e.color)),n=new Mt.MathNode("mstyle",r);return n.setAttribute("mathcolor",e.color),n};nt({type:"color",names:["\\textcolor"],props:{numArgs:2,allowedInText:!0,argTypes:["color","original"]},handler:function(e,t){var r=e.parser,n=Ft(t[0],"color-token").color,a=t[1];return{type:"color",mode:r.mode,color:n,body:ot(a)}},htmlBuilder:Zt,mathmlBuilder:Kt}),nt({type:"color",names:["\\color"],props:{numArgs:1,allowedInText:!0,argTypes:["color"]},handler:function(e,t){var r=e.parser,n=e.breakOnTokenText,a=Ft(t[0],"color-token").color;r.gullet.macros.set("\\current@color",a);var i=r.parseExpression(!0,n);return{type:"color",mode:r.mode,color:a,body:i}},htmlBuilder:Zt,mathmlBuilder:Kt}),nt({type:"cr",names:["\\\\"],props:{numArgs:0,numOptionalArgs:1,argTypes:["size"],allowedInText:!0},handler:function(e,t,r){var n=e.parser,a=r[0],i=!n.settings.displayMode||!n.settings.useStrictBehavior("newLineInDisplayMode","In LaTeX, \\\\ or \\newline does nothing in display mode");return{type:"cr",mode:n.mode,newLine:i,size:a&&Ft(a,"size").value}},htmlBuilder:function(e,t){var r=je.makeSpan(["mspace"],[],t);return e.newLine&&(r.classes.push("newline"),e.size&&(r.style.marginTop=Le(e.size,t)+"em")),r},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mspace");return e.newLine&&(r.setAttribute("linebreak","newline"),e.size&&r.setAttribute("height",Le(e.size,t)+"em")),r}});var Jt={"\\global":"\\global","\\long":"\\\\globallong","\\\\globallong":"\\\\globallong","\\def":"\\gdef","\\gdef":"\\gdef","\\edef":"\\xdef","\\xdef":"\\xdef","\\let":"\\\\globallet","\\futurelet":"\\\\globalfuture"},Qt=function(e){var t=e.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(t))throw new n("Expected a control sequence",e);return t},er=function(e,t,r,n){var a=e.gullet.macros.get(r.text);null==a&&(r.noexpand=!0,a={tokens:[r],numArgs:0,unexpandable:!e.gullet.isExpandable(r.text)}),e.gullet.macros.set(t,a,n)};nt({type:"internal",names:["\\global","\\long","\\\\globallong"],props:{numArgs:0,allowedInText:!0},handler:function(e){var t=e.parser,r=e.funcName;t.consumeSpaces();var a=t.fetch();if(Jt[a.text])return"\\global"!==r&&"\\\\globallong"!==r||(a.text=Jt[a.text]),Ft(t.parseFunction(),"internal");throw new n("Invalid token after macro prefix",a)}}),nt({type:"internal",names:["\\def","\\gdef","\\edef","\\xdef"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,a=t.gullet.popToken(),i=a.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(i))throw new n("Expected a control sequence",a);for(var o,s=0,l=[[]];"{"!==t.gullet.future().text;)if("#"===(a=t.gullet.popToken()).text){if("{"===t.gullet.future().text){o=t.gullet.future(),l[s].push("{");break}if(a=t.gullet.popToken(),!/^[1-9]$/.test(a.text))throw new n('Invalid argument number "'+a.text+'"');if(parseInt(a.text)!==s+1)throw new n('Argument number "'+a.text+'" out of order');s++,l.push([])}else{if("EOF"===a.text)throw new n("Expected a macro definition");l[s].push(a.text)}var h=t.gullet.consumeArg().tokens;return o&&h.unshift(o),"\\edef"!==r&&"\\xdef"!==r||(h=t.gullet.expandTokens(h)).reverse(),t.gullet.macros.set(i,{tokens:h,numArgs:s,delimiters:l},r===Jt[r]),{type:"internal",mode:t.mode}}}),nt({type:"internal",names:["\\let","\\\\globallet"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,n=Qt(t.gullet.popToken());t.gullet.consumeSpaces();var a=function(e){var t=e.gullet.popToken();return"="===t.text&&" "===(t=e.gullet.popToken()).text&&(t=e.gullet.popToken()),t}(t);return er(t,n,a,"\\\\globallet"===r),{type:"internal",mode:t.mode}}}),nt({type:"internal",names:["\\futurelet","\\\\globalfuture"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,n=Qt(t.gullet.popToken()),a=t.gullet.popToken(),i=t.gullet.popToken();return er(t,n,i,"\\\\globalfuture"===r),t.gullet.pushToken(i),t.gullet.pushToken(a),{type:"internal",mode:t.mode}}});var tr=function(e,t,r){var n=V(X.math[e]&&X.math[e].replace||e,t,r);if(!n)throw new Error("Unsupported symbol "+e+" and font size "+t+".");return n},rr=function(e,t,r,n){var a=r.havingBaseStyle(t),i=je.makeSpan(n.concat(a.sizingClasses(r)),[e],r),o=a.sizeMultiplier/r.sizeMultiplier;return i.height*=o,i.depth*=o,i.maxFontSize=a.sizeMultiplier,i},nr=function(e,t,r){var n=t.havingBaseStyle(r),a=(1-t.sizeMultiplier/n.sizeMultiplier)*t.fontMetrics().axisHeight;e.classes.push("delimcenter"),e.style.top=a+"em",e.height-=a,e.depth+=a},ar=function(e,t,r,n,a,i){var o=function(e,t,r,n){return je.makeSymbol(e,"Size"+t+"-Regular",r,n)}(e,t,a,n),s=rr(je.makeSpan(["delimsizing","size"+t],[o],n),b.TEXT,n,i);return r&&nr(s,n,b.TEXT),s},ir=function(e,t,r){var n;return n="Size1-Regular"===t?"delim-size1":"delim-size4",{type:"elem",elem:je.makeSpan(["delimsizinginner",n],[je.makeSpan([],[je.makeSymbol(e,t,r)])])}},or=function(e,t,r){var n=D["Size4-Regular"][e.charCodeAt(0)]?D["Size4-Regular"][e.charCodeAt(0)][4].toFixed(3):D["Size1-Regular"][e.charCodeAt(0)][4].toFixed(3),a=new E("inner",function(e,t){switch(e){case"\u239c":return"M291 0 H417 V"+t+" H291z M291 0 H417 V"+t+" H291z";case"\u2223":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145z";case"\u2225":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145zM367 0 H410 V"+t+" H367z M367 0 H410 V"+t+" H367z";case"\u239f":return"M457 0 H583 V"+t+" H457z M457 0 H583 V"+t+" H457z";case"\u23a2":return"M319 0 H403 V"+t+" H319z M319 0 H403 V"+t+" H319z";case"\u23a5":return"M263 0 H347 V"+t+" H263z M263 0 H347 V"+t+" H263z";case"\u23aa":return"M384 0 H504 V"+t+" H384z M384 0 H504 V"+t+" H384z";case"\u23d0":return"M312 0 H355 V"+t+" H312z M312 0 H355 V"+t+" H312z";case"\u2016":return"M257 0 H300 V"+t+" H257z M257 0 H300 V"+t+" H257zM478 0 H521 V"+t+" H478z M478 0 H521 V"+t+" H478z";default:return""}}(e,Math.round(1e3*t))),i=new O([a],{width:n+"em",height:t+"em",style:"width:"+n+"em",viewBox:"0 0 "+1e3*n+" "+Math.round(1e3*t),preserveAspectRatio:"xMinYMin"}),o=je.makeSvgSpan([],[i],r);return o.height=t,o.style.height=t+"em",o.style.width=n+"em",{type:"elem",elem:o}},sr={type:"kern",size:-.008},lr=["|","\\lvert","\\rvert","\\vert"],hr=["\\|","\\lVert","\\rVert","\\Vert"],mr=function(e,t,r,n,a,i){var o,s,h,m;o=h=m=e,s=null;var c="Size1-Regular";"\\uparrow"===e?h=m="\u23d0":"\\Uparrow"===e?h=m="\u2016":"\\downarrow"===e?o=h="\u23d0":"\\Downarrow"===e?o=h="\u2016":"\\updownarrow"===e?(o="\\uparrow",h="\u23d0",m="\\downarrow"):"\\Updownarrow"===e?(o="\\Uparrow",h="\u2016",m="\\Downarrow"):l.contains(lr,e)?h="\u2223":l.contains(hr,e)?h="\u2225":"["===e||"\\lbrack"===e?(o="\u23a1",h="\u23a2",m="\u23a3",c="Size4-Regular"):"]"===e||"\\rbrack"===e?(o="\u23a4",h="\u23a5",m="\u23a6",c="Size4-Regular"):"\\lfloor"===e||"\u230a"===e?(h=o="\u23a2",m="\u23a3",c="Size4-Regular"):"\\lceil"===e||"\u2308"===e?(o="\u23a1",h=m="\u23a2",c="Size4-Regular"):"\\rfloor"===e||"\u230b"===e?(h=o="\u23a5",m="\u23a6",c="Size4-Regular"):"\\rceil"===e||"\u2309"===e?(o="\u23a4",h=m="\u23a5",c="Size4-Regular"):"("===e||"\\lparen"===e?(o="\u239b",h="\u239c",m="\u239d",c="Size4-Regular"):")"===e||"\\rparen"===e?(o="\u239e",h="\u239f",m="\u23a0",c="Size4-Regular"):"\\{"===e||"\\lbrace"===e?(o="\u23a7",s="\u23a8",m="\u23a9",h="\u23aa",c="Size4-Regular"):"\\}"===e||"\\rbrace"===e?(o="\u23ab",s="\u23ac",m="\u23ad",h="\u23aa",c="Size4-Regular"):"\\lgroup"===e||"\u27ee"===e?(o="\u23a7",m="\u23a9",h="\u23aa",c="Size4-Regular"):"\\rgroup"===e||"\u27ef"===e?(o="\u23ab",m="\u23ad",h="\u23aa",c="Size4-Regular"):"\\lmoustache"===e||"\u23b0"===e?(o="\u23a7",m="\u23ad",h="\u23aa",c="Size4-Regular"):"\\rmoustache"!==e&&"\u23b1"!==e||(o="\u23ab",m="\u23a9",h="\u23aa",c="Size4-Regular");var u=tr(o,c,a),p=u.height+u.depth,d=tr(h,c,a),f=d.height+d.depth,g=tr(m,c,a),v=g.height+g.depth,y=0,x=1;if(null!==s){var w=tr(s,c,a);y=w.height+w.depth,x=2}var k=p+v+y,S=k+Math.max(0,Math.ceil((t-k)/(x*f)))*x*f,M=n.fontMetrics().axisHeight;r&&(M*=n.sizeMultiplier);var z=S/2-M,A=[];if(A.push(ir(m,c,a)),A.push(sr),null===s){var T=S-p-v+.016;A.push(or(h,T,n))}else{var B=(S-p-v-y)/2+.016;A.push(or(h,B,n)),A.push(sr),A.push(ir(s,c,a)),A.push(sr),A.push(or(h,B,n))}A.push(sr),A.push(ir(o,c,a));var N=n.havingBaseStyle(b.TEXT),q=je.makeVList({positionType:"bottom",positionData:z,children:A},N);return rr(je.makeSpan(["delimsizing","mult"],[q],N),b.TEXT,n,i)},cr=.08,ur=function(e,t,r,n,a){var i=function(e,t,r){t*=1e3;var n="";switch(e){case"sqrtMain":n=function(e,t){return"M95,"+(622+e+t)+"\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl"+e/2.075+" -"+e+"\nc5.3,-9.3,12,-14,20,-14\nH400000v"+(40+e)+"H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM"+(834+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,k);break;case"sqrtSize1":n=function(e,t){return"M263,"+(601+e+t)+"c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl"+e/2.084+" -"+e+"\nc4.7,-7.3,11,-11,19,-11\nH40000v"+(40+e)+"H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM"+(1001+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,k);break;case"sqrtSize2":n=function(e,t){return"M983 "+(10+e+t)+"\nl"+e/3.13+" -"+e+"\nc4,-6.7,10,-10,18,-10 H400000v"+(40+e)+"\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM"+(1001+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,k);break;case"sqrtSize3":n=function(e,t){return"M424,"+(2398+e+t)+"\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl"+e/4.223+" -"+e+"c4,-6.7,10,-10,18,-10 H400000\nv"+(40+e)+"H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M"+(1001+e)+" "+t+"\nh400000v"+(40+e)+"h-400000z"}(t,k);break;case"sqrtSize4":n=function(e,t){return"M473,"+(2713+e+t)+"\nc339.3,-1799.3,509.3,-2700,510,-2702 l"+e/5.298+" -"+e+"\nc3.3,-7.3,9.3,-11,18,-11 H400000v"+(40+e)+"H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM"+(1001+e)+" "+t+"h400000v"+(40+e)+"H1017.7z"}(t,k);break;case"sqrtTall":n=function(e,t,r){return"M702 "+(e+t)+"H400000"+(40+e)+"\nH742v"+(r-54-t-e)+"l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 "+t+"H400000v"+(40+e)+"H742z"}(t,k,r)}return n}(e,n,r),o=new E(e,i),s=new O([o],{width:"400em",height:t+"em",viewBox:"0 0 400000 "+r,preserveAspectRatio:"xMinYMin slice"});return je.makeSvgSpan(["hide-tail"],[s],a)},pr=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\u230a","\u230b","\\lceil","\\rceil","\u2308","\u2309","\\surd"],dr=["\\uparrow","\\downarrow","\\updownarrow","\\Uparrow","\\Downarrow","\\Updownarrow","|","\\|","\\vert","\\Vert","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\u27ee","\u27ef","\\lmoustache","\\rmoustache","\u23b0","\u23b1"],fr=["<",">","\\langle","\\rangle","/","\\backslash","\\lt","\\gt"],gr=[0,1.2,1.8,2.4,3],vr=[{type:"small",style:b.SCRIPTSCRIPT},{type:"small",style:b.SCRIPT},{type:"small",style:b.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4}],br=[{type:"small",style:b.SCRIPTSCRIPT},{type:"small",style:b.SCRIPT},{type:"small",style:b.TEXT},{type:"stack"}],yr=[{type:"small",style:b.SCRIPTSCRIPT},{type:"small",style:b.SCRIPT},{type:"small",style:b.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4},{type:"stack"}],xr=function(e){if("small"===e.type)return"Main-Regular";if("large"===e.type)return"Size"+e.size+"-Regular";if("stack"===e.type)return"Size4-Regular";throw new Error("Add support for delim type '"+e.type+"' here.")},wr=function(e,t,r,n){for(var a=Math.min(2,3-n.style.size);at)return r[a]}return r[r.length-1]},kr=function(e,t,r,n,a,i){var o;"<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),o=l.contains(fr,e)?vr:l.contains(pr,e)?yr:br;var s=wr(e,t,o,n);return"small"===s.type?function(e,t,r,n,a,i){var o=je.makeSymbol(e,"Main-Regular",a,n),s=rr(o,t,n,i);return r&&nr(s,n,t),s}(e,s.style,r,n,a,i):"large"===s.type?ar(e,s.size,r,n,a,i):mr(e,t,r,n,a,i)},Sr=function(e,t){var r,n,a=t.havingBaseSizing(),i=wr("\\surd",e*a.sizeMultiplier,yr,a),o=a.sizeMultiplier,s=Math.max(0,t.minRuleThickness-t.fontMetrics().sqrtRuleThickness),l=0,h=0,m=0;return"small"===i.type?(e<1?o=1:e<1.4&&(o=.7),h=(1+s)/o,(r=ur("sqrtMain",l=(1+s+cr)/o,m=1e3+1e3*s+80,s,t)).style.minWidth="0.853em",n=.833/o):"large"===i.type?(m=1080*gr[i.size],h=(gr[i.size]+s)/o,l=(gr[i.size]+s+cr)/o,(r=ur("sqrtSize"+i.size,l,m,s,t)).style.minWidth="1.02em",n=1/o):(l=e+s+cr,h=e+s,m=Math.floor(1e3*e+s)+80,(r=ur("sqrtTall",l,m,s,t)).style.minWidth="0.742em",n=1.056),r.height=h,r.style.height=l+"em",{span:r,advanceWidth:n,ruleWidth:(t.fontMetrics().sqrtRuleThickness+s)*o}},Mr=function(e,t,r,a,i){if("<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),l.contains(pr,e)||l.contains(fr,e))return ar(e,t,!1,r,a,i);if(l.contains(dr,e))return mr(e,gr[t],!1,r,a,i);throw new n("Illegal delimiter: '"+e+"'")},zr=gr,Ar=kr,Tr=function(e,t,r,n,a,i){var o=n.fontMetrics().axisHeight*n.sizeMultiplier,s=5/n.fontMetrics().ptPerEm,l=Math.max(t-o,r+o),h=Math.max(l/500*901,2*l-s);return kr(e,h,!0,n,a,i)},Br={"\\bigl":{mclass:"mopen",size:1},"\\Bigl":{mclass:"mopen",size:2},"\\biggl":{mclass:"mopen",size:3},"\\Biggl":{mclass:"mopen",size:4},"\\bigr":{mclass:"mclose",size:1},"\\Bigr":{mclass:"mclose",size:2},"\\biggr":{mclass:"mclose",size:3},"\\Biggr":{mclass:"mclose",size:4},"\\bigm":{mclass:"mrel",size:1},"\\Bigm":{mclass:"mrel",size:2},"\\biggm":{mclass:"mrel",size:3},"\\Biggm":{mclass:"mrel",size:4},"\\big":{mclass:"mord",size:1},"\\Big":{mclass:"mord",size:2},"\\bigg":{mclass:"mord",size:3},"\\Bigg":{mclass:"mord",size:4}},Nr=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\u230a","\u230b","\\lceil","\\rceil","\u2308","\u2309","<",">","\\langle","\u27e8","\\rangle","\u27e9","\\lt","\\gt","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\u27ee","\u27ef","\\lmoustache","\\rmoustache","\u23b0","\u23b1","/","\\backslash","|","\\vert","\\|","\\Vert","\\uparrow","\\Uparrow","\\downarrow","\\Downarrow","\\updownarrow","\\Updownarrow","."];function qr(e,t){var r=Gt(e);if(r&&l.contains(Nr,r.text))return r;throw new n(r?"Invalid delimiter '"+r.text+"' after '"+t.funcName+"'":"Invalid delimiter type '"+e.type+"'",e)}function Cr(e){if(!e.body)throw new Error("Bug: The leftright ParseNode wasn't fully parsed.")}nt({type:"delimsizing",names:["\\bigl","\\Bigl","\\biggl","\\Biggl","\\bigr","\\Bigr","\\biggr","\\Biggr","\\bigm","\\Bigm","\\biggm","\\Biggm","\\big","\\Big","\\bigg","\\Bigg"],props:{numArgs:1,argTypes:["primitive"]},handler:function(e,t){var r=qr(t[0],e);return{type:"delimsizing",mode:e.parser.mode,size:Br[e.funcName].size,mclass:Br[e.funcName].mclass,delim:r.text}},htmlBuilder:function(e,t){return"."===e.delim?je.makeSpan([e.mclass]):Mr(e.delim,e.size,t,e.mode,[e.mclass])},mathmlBuilder:function(e){var t=[];"."!==e.delim&&t.push(zt(e.delim,e.mode));var r=new Mt.MathNode("mo",t);return"mopen"===e.mclass||"mclose"===e.mclass?r.setAttribute("fence","true"):r.setAttribute("fence","false"),r.setAttribute("stretchy","true"),r.setAttribute("minsize",zr[e.size]+"em"),r.setAttribute("maxsize",zr[e.size]+"em"),r}}),nt({type:"leftright-right",names:["\\right"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=e.parser.gullet.macros.get("\\current@color");if(r&&"string"!=typeof r)throw new n("\\current@color set to non-string in \\right");return{type:"leftright-right",mode:e.parser.mode,delim:qr(t[0],e).text,color:r}}}),nt({type:"leftright",names:["\\left"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=qr(t[0],e),n=e.parser;++n.leftrightDepth;var a=n.parseExpression(!1);--n.leftrightDepth,n.expect("\\right",!1);var i=Ft(n.parseFunction(),"leftright-right");return{type:"leftright",mode:n.mode,body:a,left:r.text,right:i.delim,rightColor:i.color}},htmlBuilder:function(e,t){Cr(e);for(var r,n,a=ut(e.body,t,!0,["mopen","mclose"]),i=0,o=0,s=!1,l=0;l-1?"mpadded":"menclose",[qt(e.body,t)]);switch(e.label){case"\\cancel":n.setAttribute("notation","updiagonalstrike");break;case"\\bcancel":n.setAttribute("notation","downdiagonalstrike");break;case"\\phase":n.setAttribute("notation","phasorangle");break;case"\\sout":n.setAttribute("notation","horizontalstrike");break;case"\\fbox":n.setAttribute("notation","box");break;case"\\angl":n.setAttribute("notation","actuarial");break;case"\\fcolorbox":case"\\colorbox":if(r=t.fontMetrics().fboxsep*t.fontMetrics().ptPerEm,n.setAttribute("width","+"+2*r+"pt"),n.setAttribute("height","+"+2*r+"pt"),n.setAttribute("lspace",r+"pt"),n.setAttribute("voffset",r+"pt"),"\\fcolorbox"===e.label){var a=Math.max(t.fontMetrics().fboxrule,t.minRuleThickness);n.setAttribute("style","border: "+a+"em solid "+String(e.borderColor))}break;case"\\xcancel":n.setAttribute("notation","updiagonalstrike downdiagonalstrike")}return e.backgroundColor&&n.setAttribute("mathbackground",e.backgroundColor),n};nt({type:"enclose",names:["\\colorbox"],props:{numArgs:2,allowedInText:!0,argTypes:["color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ft(t[0],"color-token").color,o=t[1];return{type:"enclose",mode:n.mode,label:a,backgroundColor:i,body:o}},htmlBuilder:Ir,mathmlBuilder:Rr}),nt({type:"enclose",names:["\\fcolorbox"],props:{numArgs:3,allowedInText:!0,argTypes:["color","color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ft(t[0],"color-token").color,o=Ft(t[1],"color-token").color,s=t[2];return{type:"enclose",mode:n.mode,label:a,backgroundColor:o,borderColor:i,body:s}},htmlBuilder:Ir,mathmlBuilder:Rr}),nt({type:"enclose",names:["\\fbox"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!0},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\fbox",body:t[0]}}}),nt({type:"enclose",names:["\\cancel","\\bcancel","\\xcancel","\\sout","\\phase"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"enclose",mode:r.mode,label:n,body:a}},htmlBuilder:Ir,mathmlBuilder:Rr}),nt({type:"enclose",names:["\\angl"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!1},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\angl",body:t[0]}}});var Or={};function Er(e){for(var t=e.type,r=e.names,n=e.props,a=e.handler,i=e.htmlBuilder,o=e.mathmlBuilder,s={type:t,numArgs:n.numArgs||0,allowedInText:!1,numOptionalArgs:0,handler:a},l=0;l1||!c)&&g.pop(),b.length0&&(x+=.25),m.push({pos:x,isDashed:e[t]})}for(w(o[0]),r=0;r0&&(M<(B+=y)&&(M=B),B=0),e.addJot&&(M+=f),z.height=S,z.depth=M,x+=S,z.pos=x,x+=M+B,h[r]=z,w(o[r+1])}var N,q,C=x/2+t.fontMetrics().axisHeight,I=e.cols||[],R=[],O=[];if(e.addEqnNum)for(r=0;r=s)){var G=void 0;(a>0||e.hskipBeforeAndAfter)&&0!==(G=l.deflt(D.pregap,p))&&((N=je.makeSpan(["arraycolsep"],[])).style.width=G+"em",R.push(N));var U=[];for(r=0;r0){for(var _=je.makeLineSpan("hline",t,c),j=je.makeLineSpan("hdashline",t,c),$=[{type:"elem",elem:h,shift:0}];m.length>0;){var Z=m.pop(),K=Z.pos-C;Z.isDashed?$.push({type:"elem",elem:j,shift:K}):$.push({type:"elem",elem:_,shift:K})}h=je.makeVList({positionType:"individualShift",children:$},t)}if(e.addEqnNum){var J=je.makeVList({positionType:"individualShift",children:O},t);return J=je.makeSpan(["tag"],[J],t),je.makeFragment([h,J])}return je.makeSpan(["mord"],[h],t)},Vr={c:"center ",l:"left ",r:"right "},Gr=function(e,t){for(var r=[],n=new Mt.MathNode("mtd",[],["mtr-glue"]),a=new Mt.MathNode("mtd",[],["mml-eqn-num"]),i=0;i0){var p=e.cols,d="",f=!1,g=0,v=p.length;"separator"===p[0].type&&(c+="top ",g=1),"separator"===p[p.length-1].type&&(c+="bottom ",v-=1);for(var b=g;b0?"left ":"",c+=S[S.length-1].length>0?"right ":"";for(var M=1;M-1?"alignat":"align",o=Dr(e.parser,{cols:a,addJot:!0,addEqnNum:"align"===e.envName||"alignat"===e.envName,emptySingleRow:!0,colSeparationType:i,maxNumCols:"split"===e.envName?2:void 0,leqno:e.parser.settings.leqno},"display"),s=0,l={type:"ordgroup",mode:e.mode,body:[]};if(t[0]&&"ordgroup"===t[0].type){for(var h="",m=0;m0&&c&&(d=1),a[u]={type:"align",align:p,pregap:d,postgap:0}}return o.colSeparationType=c?"align":"alignat",o};Er({type:"array",names:["array","darray"],props:{numArgs:1},handler:function(e,t){var r=(Gt(t[0])?[t[0]]:Ft(t[0],"ordgroup").body).map((function(e){var t=Vt(e).text;if(-1!=="lcr".indexOf(t))return{type:"align",align:t};if("|"===t)return{type:"separator",separator:"|"};if(":"===t)return{type:"separator",separator:":"};throw new n("Unknown column alignment: "+t,e)})),a={cols:r,hskipBeforeAndAfter:!0,maxNumCols:r.length};return Dr(e.parser,a,Pr(e.envName))},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix","matrix*","pmatrix*","bmatrix*","Bmatrix*","vmatrix*","Vmatrix*"],props:{numArgs:0},handler:function(e){var t={matrix:null,pmatrix:["(",")"],bmatrix:["[","]"],Bmatrix:["\\{","\\}"],vmatrix:["|","|"],Vmatrix:["\\Vert","\\Vert"]}[e.envName.replace("*","")],r="c",a={hskipBeforeAndAfter:!1,cols:[{type:"align",align:r}]};if("*"===e.envName.charAt(e.envName.length-1)){var i=e.parser;if(i.consumeSpaces(),"["===i.fetch().text){if(i.consume(),i.consumeSpaces(),r=i.fetch().text,-1==="lcr".indexOf(r))throw new n("Expected l or c or r",i.nextToken);i.consume(),i.consumeSpaces(),i.expect("]"),i.consume(),a.cols=[{type:"align",align:r}]}}var o=Dr(e.parser,a,Pr(e.envName)),s=Math.max.apply(Math,[0].concat(o.body.map((function(e){return e.length}))));return o.cols=new Array(s).fill({type:"align",align:r}),t?{type:"leftright",mode:e.mode,body:[o],left:t[0],right:t[1],rightColor:void 0}:o},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["smallmatrix"],props:{numArgs:0},handler:function(e){var t=Dr(e.parser,{arraystretch:.5},"script");return t.colSeparationType="small",t},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["subarray"],props:{numArgs:1},handler:function(e,t){var r=(Gt(t[0])?[t[0]]:Ft(t[0],"ordgroup").body).map((function(e){var t=Vt(e).text;if(-1!=="lc".indexOf(t))return{type:"align",align:t};throw new n("Unknown column alignment: "+t,e)}));if(r.length>1)throw new n("{subarray} can contain only one column");var a={cols:r,hskipBeforeAndAfter:!1,arraystretch:.5};if((a=Dr(e.parser,a,"script")).body.length>0&&a.body[0].length>1)throw new n("{subarray} can contain only one column");return a},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["cases","dcases","rcases","drcases"],props:{numArgs:0},handler:function(e){var t=Dr(e.parser,{arraystretch:1.2,cols:[{type:"align",align:"l",pregap:0,postgap:1},{type:"align",align:"l",pregap:0,postgap:0}]},Pr(e.envName));return{type:"leftright",mode:e.mode,body:[t],left:e.envName.indexOf("r")>-1?".":"\\{",right:e.envName.indexOf("r")>-1?"\\}":".",rightColor:void 0}},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["align","align*","aligned","split"],props:{numArgs:0},handler:Ur,htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["gathered","gather","gather*"],props:{numArgs:0},handler:function(e){l.contains(["gather","gather*"],e.envName)&&Lr(e);var t={cols:[{type:"align",align:"c"}],addJot:!0,colSeparationType:"gather",addEqnNum:"gather"===e.envName,emptySingleRow:!0,leqno:e.parser.settings.leqno};return Dr(e.parser,t,"display")},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["alignat","alignat*","alignedat"],props:{numArgs:1},handler:Ur,htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["equation","equation*"],props:{numArgs:0},handler:function(e){Lr(e);var t={addEqnNum:"equation"===e.envName,emptySingleRow:!0,singleRow:!0,maxNumCols:1,leqno:e.parser.settings.leqno};return Dr(e.parser,t,"display")},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["CD"],props:{numArgs:0},handler:function(e){return Lr(e),function(e){var t=[];for(e.gullet.beginGroup(),e.gullet.macros.set("\\cr","\\\\\\relax"),e.gullet.beginGroup();;){t.push(e.parseExpression(!1,"\\\\")),e.gullet.endGroup(),e.gullet.beginGroup();var r=e.fetch().text;if("&"!==r&&"\\\\"!==r){if("\\end"===r){0===t[t.length-1].length&&t.pop();break}throw new n("Expected \\\\ or \\cr or \\end",e.nextToken)}e.consume()}for(var a,i,o=[],s=[o],l=0;l-1);else{if(!("<>AV".indexOf(u)>-1))throw new n('Expected one of "<>AV=|." after @',h[c]);for(var d=0;d<2;d++){for(var f=!0,g=c+1;g=b.SCRIPT.id?r.text():b.DISPLAY:"text"===e&&r.size===b.DISPLAY.size?r=b.TEXT:"script"===e?r=b.SCRIPT:"scriptscript"===e&&(r=b.SCRIPTSCRIPT),r},Qr=function(e,t){var r,n=Jr(e.size,t.style),a=n.fracNum(),i=n.fracDen();r=t.havingStyle(a);var o=bt(e.numer,r,t);if(e.continued){var s=8.5/t.fontMetrics().ptPerEm,l=3.5/t.fontMetrics().ptPerEm;o.height=o.height0?3*c:7*c,d=t.fontMetrics().denom1):(m>0?(u=t.fontMetrics().num2,p=c):(u=t.fontMetrics().num3,p=3*c),d=t.fontMetrics().denom2),h){var w=t.fontMetrics().axisHeight;u-o.depth-(w+.5*m)0&&(t="."===(t=e)?null:t),t};nt({type:"genfrac",names:["\\genfrac"],props:{numArgs:6,allowedInArgument:!0,argTypes:["math","math","size","text","math","math"]},handler:function(e,t){var r,n=e.parser,a=t[4],i=t[5],o=it(t[0]),s="atom"===o.type&&"open"===o.family?rn(o.text):null,l=it(t[1]),h="atom"===l.type&&"close"===l.family?rn(l.text):null,m=Ft(t[2],"size"),c=null;r=!!m.isBlank||(c=m.value).number>0;var u="auto",p=t[3];if("ordgroup"===p.type){if(p.body.length>0){var d=Ft(p.body[0],"textord");u=tn[Number(d.text)]}}else p=Ft(p,"textord"),u=tn[Number(p.text)];return{type:"genfrac",mode:n.mode,numer:a,denom:i,continued:!1,hasBarLine:r,barSize:c,leftDelim:s,rightDelim:h,size:u}},htmlBuilder:Qr,mathmlBuilder:en}),nt({type:"infix",names:["\\above"],props:{numArgs:1,argTypes:["size"],infix:!0},handler:function(e,t){var r=e.parser,n=(e.funcName,e.token);return{type:"infix",mode:r.mode,replaceWith:"\\\\abovefrac",size:Ft(t[0],"size").value,token:n}}}),nt({type:"genfrac",names:["\\\\abovefrac"],props:{numArgs:3,argTypes:["math","size","math"]},handler:function(e,t){var r=e.parser,n=(e.funcName,t[0]),a=function(e){if(!e)throw new Error("Expected non-null, but got "+String(e));return e}(Ft(t[1],"infix").size),i=t[2],o=a.number>0;return{type:"genfrac",mode:r.mode,numer:n,denom:i,continued:!1,hasBarLine:o,barSize:a,leftDelim:null,rightDelim:null,size:"auto"}},htmlBuilder:Qr,mathmlBuilder:en});var nn=function(e,t){var r,n,a=t.style;"supsub"===e.type?(r=e.sup?bt(e.sup,t.havingStyle(a.sup()),t):bt(e.sub,t.havingStyle(a.sub()),t),n=Ft(e.base,"horizBrace")):n=Ft(e,"horizBrace");var i,o=bt(n.base,t.havingBaseStyle(b.DISPLAY)),s=Pt(n,t);if(n.isOver?(i=je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:o},{type:"kern",size:.1},{type:"elem",elem:s}]},t)).children[0].children[0].children[1].classes.push("svg-align"):(i=je.makeVList({positionType:"bottom",positionData:o.depth+.1+s.height,children:[{type:"elem",elem:s},{type:"kern",size:.1},{type:"elem",elem:o}]},t)).children[0].children[0].children[0].classes.push("svg-align"),r){var l=je.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t);i=n.isOver?je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:l},{type:"kern",size:.2},{type:"elem",elem:r}]},t):je.makeVList({positionType:"bottom",positionData:l.depth+.2+r.height+r.depth,children:[{type:"elem",elem:r},{type:"kern",size:.2},{type:"elem",elem:l}]},t)}return je.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t)};nt({type:"horizBrace",names:["\\overbrace","\\underbrace"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"horizBrace",mode:r.mode,label:n,isOver:/^\\over/.test(n),base:t[0]}},htmlBuilder:nn,mathmlBuilder:function(e,t){var r=Dt(e.label);return new Mt.MathNode(e.isOver?"mover":"munder",[qt(e.base,t),r])}}),nt({type:"href",names:["\\href"],props:{numArgs:2,argTypes:["url","original"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=t[1],a=Ft(t[0],"url").url;return r.settings.isTrusted({command:"\\href",url:a})?{type:"href",mode:r.mode,href:a,body:ot(n)}:r.formatUnsupportedCmd("\\href")},htmlBuilder:function(e,t){var r=ut(e.body,t,!1);return je.makeAnchor(e.href,[],r,t)},mathmlBuilder:function(e,t){var r=Nt(e.body,t);return r instanceof kt||(r=new kt("mrow",[r])),r.setAttribute("href",e.href),r}}),nt({type:"href",names:["\\url"],props:{numArgs:1,argTypes:["url"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=Ft(t[0],"url").url;if(!r.settings.isTrusted({command:"\\url",url:n}))return r.formatUnsupportedCmd("\\url");for(var a=[],i=0;i0&&(n=Le(e.totalheight,t)-r,n=Number(n.toFixed(2)));var a=0;e.width.number>0&&(a=Le(e.width,t));var i={height:r+n+"em"};a>0&&(i.width=a+"em"),n>0&&(i.verticalAlign=-n+"em");var o=new C(e.src,e.alt,i);return o.height=r,o.depth=n,o},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mglyph",[]);r.setAttribute("alt",e.alt);var n=Le(e.height,t),a=0;if(e.totalheight.number>0&&(a=(a=Le(e.totalheight,t)-n).toFixed(2),r.setAttribute("valign","-"+a+"em")),r.setAttribute("height",n+a+"em"),e.width.number>0){var i=Le(e.width,t);r.setAttribute("width",i+"em")}return r.setAttribute("src",e.src),r}}),nt({type:"kern",names:["\\kern","\\mkern","\\hskip","\\mskip"],props:{numArgs:1,argTypes:["size"],primitive:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=Ft(t[0],"size");if(r.settings.strict){var i="m"===n[1],o="mu"===a.value.unit;i?(o||r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" supports only mu units, not "+a.value.unit+" units"),"math"!==r.mode&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" works only in math mode")):o&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" doesn't support mu units")}return{type:"kern",mode:r.mode,dimension:a.value}},htmlBuilder:function(e,t){return je.makeGlue(e.dimension,t)},mathmlBuilder:function(e,t){var r=Le(e.dimension,t);return new Mt.SpaceNode(r)}}),nt({type:"lap",names:["\\mathllap","\\mathrlap","\\mathclap"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"lap",mode:r.mode,alignment:n.slice(5),body:a}},htmlBuilder:function(e,t){var r;"clap"===e.alignment?(r=je.makeSpan([],[bt(e.body,t)]),r=je.makeSpan(["inner"],[r],t)):r=je.makeSpan(["inner"],[bt(e.body,t)]);var n=je.makeSpan(["fix"],[]),a=je.makeSpan([e.alignment],[r,n],t),i=je.makeSpan(["strut"]);return i.style.height=a.height+a.depth+"em",i.style.verticalAlign=-a.depth+"em",a.children.unshift(i),a=je.makeSpan(["thinbox"],[a],t),je.makeSpan(["mord","vbox"],[a],t)},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mpadded",[qt(e.body,t)]);if("rlap"!==e.alignment){var n="llap"===e.alignment?"-1":"-0.5";r.setAttribute("lspace",n+"width")}return r.setAttribute("width","0px"),r}}),nt({type:"styling",names:["\\(","$"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){var r=e.funcName,n=e.parser,a=n.mode;n.switchMode("math");var i="\\("===r?"\\)":"$",o=n.parseExpression(!1,i);return n.expect(i),n.switchMode(a),{type:"styling",mode:n.mode,style:"text",body:o}}}),nt({type:"text",names:["\\)","\\]"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){throw new n("Mismatched "+e.funcName)}});var on=function(e,t){switch(t.style.size){case b.DISPLAY.size:return e.display;case b.TEXT.size:return e.text;case b.SCRIPT.size:return e.script;case b.SCRIPTSCRIPT.size:return e.scriptscript;default:return e.text}};nt({type:"mathchoice",names:["\\mathchoice"],props:{numArgs:4,primitive:!0},handler:function(e,t){return{type:"mathchoice",mode:e.parser.mode,display:ot(t[0]),text:ot(t[1]),script:ot(t[2]),scriptscript:ot(t[3])}},htmlBuilder:function(e,t){var r=on(e,t),n=ut(r,t,!1);return je.makeFragment(n)},mathmlBuilder:function(e,t){var r=on(e,t);return Nt(r,t)}});var sn=function(e,t,r,n,a,i,o){e=je.makeSpan([],[e]);var s,h,m,c=r&&l.isCharacterBox(r);if(t){var u=bt(t,n.havingStyle(a.sup()),n);h={elem:u,kern:Math.max(n.fontMetrics().bigOpSpacing1,n.fontMetrics().bigOpSpacing3-u.depth)}}if(r){var p=bt(r,n.havingStyle(a.sub()),n);s={elem:p,kern:Math.max(n.fontMetrics().bigOpSpacing2,n.fontMetrics().bigOpSpacing4-p.height)}}if(h&&s){var d=n.fontMetrics().bigOpSpacing5+s.elem.height+s.elem.depth+s.kern+e.depth+o;m=je.makeVList({positionType:"bottom",positionData:d,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:-i+"em"},{type:"kern",size:s.kern},{type:"elem",elem:e},{type:"kern",size:h.kern},{type:"elem",elem:h.elem,marginLeft:i+"em"},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}else if(s){var f=e.height-o;m=je.makeVList({positionType:"top",positionData:f,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:-i+"em"},{type:"kern",size:s.kern},{type:"elem",elem:e}]},n)}else{if(!h)return e;var g=e.depth+o;m=je.makeVList({positionType:"bottom",positionData:g,children:[{type:"elem",elem:e},{type:"kern",size:h.kern},{type:"elem",elem:h.elem,marginLeft:i+"em"},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}var v=[m];if(s&&0!==i&&!c){var b=je.makeSpan(["mspace"],[],n);b.style.marginRight=i+"em",v.unshift(b)}return je.makeSpan(["mop","op-limits"],v,n)},ln=["\\smallint"],hn=function(e,t){var r,n,a,i=!1;"supsub"===e.type?(r=e.sup,n=e.sub,a=Ft(e.base,"op"),i=!0):a=Ft(e,"op");var o,s=t.style,h=!1;if(s.size===b.DISPLAY.size&&a.symbol&&!l.contains(ln,a.name)&&(h=!0),a.symbol){var m=h?"Size2-Regular":"Size1-Regular",c="";if("\\oiint"!==a.name&&"\\oiiint"!==a.name||(c=a.name.substr(1),a.name="oiint"===c?"\\iint":"\\iiint"),o=je.makeSymbol(a.name,m,"math",t,["mop","op-symbol",h?"large-op":"small-op"]),c.length>0){var u=o.italic,p=je.staticSvg(c+"Size"+(h?"2":"1"),t);o=je.makeVList({positionType:"individualShift",children:[{type:"elem",elem:o,shift:0},{type:"elem",elem:p,shift:h?.08:0}]},t),a.name="\\"+c,o.classes.unshift("mop"),o.italic=u}}else if(a.body){var d=ut(a.body,t,!0);1===d.length&&d[0]instanceof R?(o=d[0]).classes[0]="mop":o=je.makeSpan(["mop"],d,t)}else{for(var f=[],g=1;g0){for(var s=a.body.map((function(e){var t=e.text;return"string"==typeof t?{type:"textord",mode:e.mode,text:t}:e})),l=ut(s,t.withFont("mathrm"),!0),h=0;h=0?s.setAttribute("height","+"+a+"em"):(s.setAttribute("height",a+"em"),s.setAttribute("depth","+"+-a+"em")),s.setAttribute("voffset",a+"em"),s}});var vn=["\\tiny","\\sixptsize","\\scriptsize","\\footnotesize","\\small","\\normalsize","\\large","\\Large","\\LARGE","\\huge","\\Huge"];nt({type:"sizing",names:vn,props:{numArgs:0,allowedInText:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!1,r);return{type:"sizing",mode:a.mode,size:vn.indexOf(n)+1,body:i}},htmlBuilder:function(e,t){var r=t.havingSize(e.size);return gn(e.body,r,t)},mathmlBuilder:function(e,t){var r=t.havingSize(e.size),n=Bt(e.body,r),a=new Mt.MathNode("mstyle",n);return a.setAttribute("mathsize",r.sizeMultiplier+"em"),a}}),nt({type:"smash",names:["\\smash"],props:{numArgs:1,numOptionalArgs:1,allowedInText:!0},handler:function(e,t,r){var n=e.parser,a=!1,i=!1,o=r[0]&&Ft(r[0],"ordgroup");if(o)for(var s="",l=0;lr.height+r.depth+i&&(i=(i+c-r.height-r.depth)/2);var u=l.height-r.height-i-h;r.style.paddingLeft=m+"em";var p=je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:r,wrapperClasses:["svg-align"]},{type:"kern",size:-(r.height+u)},{type:"elem",elem:l},{type:"kern",size:h}]},t);if(e.index){var d=t.havingStyle(b.SCRIPTSCRIPT),f=bt(e.index,d,t),g=.6*(p.height-p.depth),v=je.makeVList({positionType:"shift",positionData:-g,children:[{type:"elem",elem:f}]},t),y=je.makeSpan(["root"],[v]);return je.makeSpan(["mord","sqrt"],[y,p],t)}return je.makeSpan(["mord","sqrt"],[p],t)},mathmlBuilder:function(e,t){var r=e.body,n=e.index;return n?new Mt.MathNode("mroot",[qt(r,t),qt(n,t)]):new Mt.MathNode("msqrt",[qt(r,t)])}});var bn={display:b.DISPLAY,text:b.TEXT,script:b.SCRIPT,scriptscript:b.SCRIPTSCRIPT};nt({type:"styling",names:["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!0,r),o=n.slice(1,n.length-5);return{type:"styling",mode:a.mode,style:o,body:i}},htmlBuilder:function(e,t){var r=bn[e.style],n=t.havingStyle(r).withFont("");return gn(e.body,n,t)},mathmlBuilder:function(e,t){var r=bn[e.style],n=t.havingStyle(r),a=Bt(e.body,n),i=new Mt.MathNode("mstyle",a),o={display:["0","true"],text:["0","false"],script:["1","false"],scriptscript:["2","false"]}[e.style];return i.setAttribute("scriptlevel",o[0]),i.setAttribute("displaystyle",o[1]),i}});var yn=function(e,t){var r=e.base;return r?"op"===r.type?r.limits&&(t.style.size===b.DISPLAY.size||r.alwaysHandleSupSub)?hn:null:"operatorname"===r.type?r.alwaysHandleSupSub&&(t.style.size===b.DISPLAY.size||r.limits)?fn:null:"accent"===r.type?l.isCharacterBox(r.base)?Ut:null:"horizBrace"===r.type&&!e.sub===r.isOver?nn:null:null};at({type:"supsub",htmlBuilder:function(e,t){var r=yn(e,t);if(r)return r(e,t);var n,a,i,o=e.base,s=e.sup,h=e.sub,m=bt(o,t),c=t.fontMetrics(),u=0,p=0,d=o&&l.isCharacterBox(o);if(s){var f=t.havingStyle(t.style.sup());n=bt(s,f,t),d||(u=m.height-f.fontMetrics().supDrop*f.sizeMultiplier/t.sizeMultiplier)}if(h){var g=t.havingStyle(t.style.sub());a=bt(h,g,t),d||(p=m.depth+g.fontMetrics().subDrop*g.sizeMultiplier/t.sizeMultiplier)}i=t.style===b.DISPLAY?c.sup1:t.style.cramped?c.sup3:c.sup2;var v,y=t.sizeMultiplier,x=.5/c.ptPerEm/y+"em",w=null;if(a){var k=e.base&&"op"===e.base.type&&e.base.name&&("\\oiint"===e.base.name||"\\oiiint"===e.base.name);(m instanceof R||k)&&(w=-m.italic+"em")}if(n&&a){u=Math.max(u,i,n.depth+.25*c.xHeight),p=Math.max(p,c.sub2);var S=4*c.defaultRuleThickness;if(u-n.depth-(a.height-p)0&&(u+=M,p-=M)}var z=[{type:"elem",elem:a,shift:p,marginRight:x,marginLeft:w},{type:"elem",elem:n,shift:-u,marginRight:x}];v=je.makeVList({positionType:"individualShift",children:z},t)}else if(a){p=Math.max(p,c.sub1,a.height-.8*c.xHeight);var A=[{type:"elem",elem:a,marginLeft:w,marginRight:x}];v=je.makeVList({positionType:"shift",positionData:p,children:A},t)}else{if(!n)throw new Error("supsub must have either sup or sub.");u=Math.max(u,i,n.depth+.25*c.xHeight),v=je.makeVList({positionType:"shift",positionData:-u,children:[{type:"elem",elem:n,marginRight:x}]},t)}var T=gt(m,"right")||"mord";return je.makeSpan([T],[m,je.makeSpan(["msupsub"],[v])],t)},mathmlBuilder:function(e,t){var r,n=!1;e.base&&"horizBrace"===e.base.type&&!!e.sup===e.base.isOver&&(n=!0,r=e.base.isOver),!e.base||"op"!==e.base.type&&"operatorname"!==e.base.type||(e.base.parentIsSupSub=!0);var a,i=[qt(e.base,t)];if(e.sub&&i.push(qt(e.sub,t)),e.sup&&i.push(qt(e.sup,t)),n)a=r?"mover":"munder";else if(e.sub)if(e.sup){var o=e.base;a=o&&"op"===o.type&&o.limits&&t.style===b.DISPLAY||o&&"operatorname"===o.type&&o.alwaysHandleSupSub&&(t.style===b.DISPLAY||o.limits)?"munderover":"msubsup"}else{var s=e.base;a=s&&"op"===s.type&&s.limits&&(t.style===b.DISPLAY||s.alwaysHandleSupSub)||s&&"operatorname"===s.type&&s.alwaysHandleSupSub&&(s.limits||t.style===b.DISPLAY)?"munder":"msub"}else{var l=e.base;a=l&&"op"===l.type&&l.limits&&(t.style===b.DISPLAY||l.alwaysHandleSupSub)||l&&"operatorname"===l.type&&l.alwaysHandleSupSub&&(l.limits||t.style===b.DISPLAY)?"mover":"msup"}return new Mt.MathNode(a,i)}}),at({type:"atom",htmlBuilder:function(e,t){return je.mathsym(e.text,e.mode,t,["m"+e.family])},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mo",[zt(e.text,e.mode)]);if("bin"===e.family){var n=Tt(e,t);"bold-italic"===n&&r.setAttribute("mathvariant",n)}else"punct"===e.family?r.setAttribute("separator","true"):"open"!==e.family&&"close"!==e.family||r.setAttribute("stretchy","false");return r}});var xn={mi:"italic",mn:"normal",mtext:"normal"};at({type:"mathord",htmlBuilder:function(e,t){return je.makeOrd(e,t,"mathord")},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mi",[zt(e.text,e.mode,t)]),n=Tt(e,t)||"italic";return n!==xn[r.type]&&r.setAttribute("mathvariant",n),r}}),at({type:"textord",htmlBuilder:function(e,t){return je.makeOrd(e,t,"textord")},mathmlBuilder:function(e,t){var r,n=zt(e.text,e.mode,t),a=Tt(e,t)||"normal";return r="text"===e.mode?new Mt.MathNode("mtext",[n]):/[0-9]/.test(e.text)?new Mt.MathNode("mn",[n]):"\\prime"===e.text?new Mt.MathNode("mo",[n]):new Mt.MathNode("mi",[n]),a!==xn[r.type]&&r.setAttribute("mathvariant",a),r}});var wn={"\\nobreak":"nobreak","\\allowbreak":"allowbreak"},kn={" ":{},"\\ ":{},"~":{className:"nobreak"},"\\space":{},"\\nobreakspace":{className:"nobreak"}};at({type:"spacing",htmlBuilder:function(e,t){if(kn.hasOwnProperty(e.text)){var r=kn[e.text].className||"";if("text"===e.mode){var a=je.makeOrd(e,t,"textord");return a.classes.push(r),a}return je.makeSpan(["mspace",r],[je.mathsym(e.text,e.mode,t)],t)}if(wn.hasOwnProperty(e.text))return je.makeSpan(["mspace",wn[e.text]],[],t);throw new n('Unknown type of space "'+e.text+'"')},mathmlBuilder:function(e,t){if(!kn.hasOwnProperty(e.text)){if(wn.hasOwnProperty(e.text))return new Mt.MathNode("mspace");throw new n('Unknown type of space "'+e.text+'"')}return new Mt.MathNode("mtext",[new Mt.TextNode("\xa0")])}});var Sn=function(){var e=new Mt.MathNode("mtd",[]);return e.setAttribute("width","50%"),e};at({type:"tag",mathmlBuilder:function(e,t){var r=new Mt.MathNode("mtable",[new Mt.MathNode("mtr",[Sn(),new Mt.MathNode("mtd",[Nt(e.body,t)]),Sn(),new Mt.MathNode("mtd",[Nt(e.tag,t)])])]);return r.setAttribute("width","100%"),r}});var Mn={"\\text":void 0,"\\textrm":"textrm","\\textsf":"textsf","\\texttt":"texttt","\\textnormal":"textrm"},zn={"\\textbf":"textbf","\\textmd":"textmd"},An={"\\textit":"textit","\\textup":"textup"},Tn=function(e,t){var r=e.font;return r?Mn[r]?t.withTextFontFamily(Mn[r]):zn[r]?t.withTextFontWeight(zn[r]):t.withTextFontShape(An[r]):t};nt({type:"text",names:["\\text","\\textrm","\\textsf","\\texttt","\\textnormal","\\textbf","\\textmd","\\textit","\\textup"],props:{numArgs:1,argTypes:["text"],allowedInArgument:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"text",mode:r.mode,body:ot(a),font:n}},htmlBuilder:function(e,t){var r=Tn(e,t),n=ut(e.body,r,!0);return je.makeSpan(["mord","text"],n,r)},mathmlBuilder:function(e,t){var r=Tn(e,t);return Nt(e.body,r)}}),nt({type:"underline",names:["\\underline"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){return{type:"underline",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=bt(e.body,t),n=je.makeLineSpan("underline-line",t),a=t.fontMetrics().defaultRuleThickness,i=je.makeVList({positionType:"top",positionData:r.height,children:[{type:"kern",size:a},{type:"elem",elem:n},{type:"kern",size:3*a},{type:"elem",elem:r}]},t);return je.makeSpan(["mord","underline"],[i],t)},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mo",[new Mt.TextNode("\u203e")]);r.setAttribute("stretchy","true");var n=new Mt.MathNode("munder",[qt(e.body,t),r]);return n.setAttribute("accentunder","true"),n}}),nt({type:"vcenter",names:["\\vcenter"],props:{numArgs:1,argTypes:["original"],allowedInText:!1},handler:function(e,t){return{type:"vcenter",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=bt(e.body,t),n=t.fontMetrics().axisHeight,a=.5*(r.height-n-(r.depth+n));return je.makeVList({positionType:"shift",positionData:a,children:[{type:"elem",elem:r}]},t)},mathmlBuilder:function(e,t){return new Mt.MathNode("mpadded",[qt(e.body,t)],["vcenter"])}}),nt({type:"verb",names:["\\verb"],props:{numArgs:0,allowedInText:!0},handler:function(e,t,r){throw new n("\\verb ended by end of line instead of matching delimiter")},htmlBuilder:function(e,t){for(var r=Bn(e),n=[],a=t.havingStyle(t.style.text()),i=0;i0;)this.endGroup()},t.has=function(e){return this.current.hasOwnProperty(e)||this.builtins.hasOwnProperty(e)},t.get=function(e){return this.current.hasOwnProperty(e)?this.current[e]:this.builtins[e]},t.set=function(e,t,r){if(void 0===r&&(r=!1),r){for(var n=0;n0&&(this.undefStack[this.undefStack.length-1][e]=t)}else{var a=this.undefStack[this.undefStack.length-1];a&&!a.hasOwnProperty(e)&&(a[e]=this.current[e])}this.current[e]=t},e}(),En=pn;dn("\\noexpand",(function(e){var t=e.popToken();return e.isExpandable(t.text)&&(t.noexpand=!0,t.treatAsRelax=!0),{tokens:[t],numArgs:0}})),dn("\\expandafter",(function(e){var t=e.popToken();return e.expandOnce(!0),{tokens:[t],numArgs:0}})),dn("\\@firstoftwo",(function(e){return{tokens:e.consumeArgs(2)[0],numArgs:0}})),dn("\\@secondoftwo",(function(e){return{tokens:e.consumeArgs(2)[1],numArgs:0}})),dn("\\@ifnextchar",(function(e){var t=e.consumeArgs(3);e.consumeSpaces();var r=e.future();return 1===t[0].length&&t[0][0].text===r.text?{tokens:t[1],numArgs:0}:{tokens:t[2],numArgs:0}})),dn("\\@ifstar","\\@ifnextchar *{\\@firstoftwo{#1}}"),dn("\\TextOrMath",(function(e){var t=e.consumeArgs(2);return"text"===e.mode?{tokens:t[0],numArgs:0}:{tokens:t[1],numArgs:0}}));var Hn={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,a:10,A:10,b:11,B:11,c:12,C:12,d:13,D:13,e:14,E:14,f:15,F:15};dn("\\char",(function(e){var t,r=e.popToken(),a="";if("'"===r.text)t=8,r=e.popToken();else if('"'===r.text)t=16,r=e.popToken();else if("`"===r.text)if("\\"===(r=e.popToken()).text[0])a=r.text.charCodeAt(1);else{if("EOF"===r.text)throw new n("\\char` missing argument");a=r.text.charCodeAt(0)}else t=10;if(t){if(null==(a=Hn[r.text])||a>=t)throw new n("Invalid base-"+t+" digit "+r.text);for(var i;null!=(i=Hn[e.future().text])&&i":"\\dotsb","-":"\\dotsb","*":"\\dotsb",":":"\\dotsb","\\DOTSB":"\\dotsb","\\coprod":"\\dotsb","\\bigvee":"\\dotsb","\\bigwedge":"\\dotsb","\\biguplus":"\\dotsb","\\bigcap":"\\dotsb","\\bigcup":"\\dotsb","\\prod":"\\dotsb","\\sum":"\\dotsb","\\bigotimes":"\\dotsb","\\bigoplus":"\\dotsb","\\bigodot":"\\dotsb","\\bigsqcup":"\\dotsb","\\And":"\\dotsb","\\longrightarrow":"\\dotsb","\\Longrightarrow":"\\dotsb","\\longleftarrow":"\\dotsb","\\Longleftarrow":"\\dotsb","\\longleftrightarrow":"\\dotsb","\\Longleftrightarrow":"\\dotsb","\\mapsto":"\\dotsb","\\longmapsto":"\\dotsb","\\hookrightarrow":"\\dotsb","\\doteq":"\\dotsb","\\mathbin":"\\dotsb","\\mathrel":"\\dotsb","\\relbar":"\\dotsb","\\Relbar":"\\dotsb","\\xrightarrow":"\\dotsb","\\xleftarrow":"\\dotsb","\\DOTSI":"\\dotsi","\\int":"\\dotsi","\\oint":"\\dotsi","\\iint":"\\dotsi","\\iiint":"\\dotsi","\\iiiint":"\\dotsi","\\idotsint":"\\dotsi","\\DOTSX":"\\dotsx"};dn("\\dots",(function(e){var t="\\dotso",r=e.expandAfterFuture().text;return r in Dn?t=Dn[r]:("\\not"===r.substr(0,4)||r in X.math&&l.contains(["bin","rel"],X.math[r].group))&&(t="\\dotsb"),t}));var Pn={")":!0,"]":!0,"\\rbrack":!0,"\\}":!0,"\\rbrace":!0,"\\rangle":!0,"\\rceil":!0,"\\rfloor":!0,"\\rgroup":!0,"\\rmoustache":!0,"\\right":!0,"\\bigr":!0,"\\biggr":!0,"\\Bigr":!0,"\\Biggr":!0,$:!0,";":!0,".":!0,",":!0};dn("\\dotso",(function(e){return e.future().text in Pn?"\\ldots\\,":"\\ldots"})),dn("\\dotsc",(function(e){var t=e.future().text;return t in Pn&&","!==t?"\\ldots\\,":"\\ldots"})),dn("\\cdots",(function(e){return e.future().text in Pn?"\\@cdots\\,":"\\@cdots"})),dn("\\dotsb","\\cdots"),dn("\\dotsm","\\cdots"),dn("\\dotsi","\\!\\cdots"),dn("\\dotsx","\\ldots\\,"),dn("\\DOTSI","\\relax"),dn("\\DOTSB","\\relax"),dn("\\DOTSX","\\relax"),dn("\\tmspace","\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"),dn("\\,","\\tmspace+{3mu}{.1667em}"),dn("\\thinspace","\\,"),dn("\\>","\\mskip{4mu}"),dn("\\:","\\tmspace+{4mu}{.2222em}"),dn("\\medspace","\\:"),dn("\\;","\\tmspace+{5mu}{.2777em}"),dn("\\thickspace","\\;"),dn("\\!","\\tmspace-{3mu}{.1667em}"),dn("\\negthinspace","\\!"),dn("\\negmedspace","\\tmspace-{4mu}{.2222em}"),dn("\\negthickspace","\\tmspace-{5mu}{.277em}"),dn("\\enspace","\\kern.5em "),dn("\\enskip","\\hskip.5em\\relax"),dn("\\quad","\\hskip1em\\relax"),dn("\\qquad","\\hskip2em\\relax"),dn("\\tag","\\@ifstar\\tag@literal\\tag@paren"),dn("\\tag@paren","\\tag@literal{({#1})}"),dn("\\tag@literal",(function(e){if(e.macros.get("\\df@tag"))throw new n("Multiple \\tag");return"\\gdef\\df@tag{\\text{#1}}"})),dn("\\bmod","\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}\\mathbin{\\rm mod}\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"),dn("\\pod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"),dn("\\pmod","\\pod{{\\rm mod}\\mkern6mu#1}"),dn("\\mod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1"),dn("\\pmb","\\html@mathml{\\@binrel{#1}{\\mathrlap{#1}\\kern0.5px#1}}{\\mathbf{#1}}"),dn("\\newline","\\\\\\relax"),dn("\\TeX","\\textrm{\\html@mathml{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}{TeX}}");var Fn=D["Main-Regular"]["T".charCodeAt(0)][1]-.7*D["Main-Regular"]["A".charCodeAt(0)][1]+"em";dn("\\LaTeX","\\textrm{\\html@mathml{L\\kern-.36em\\raisebox{"+Fn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{LaTeX}}"),dn("\\KaTeX","\\textrm{\\html@mathml{K\\kern-.17em\\raisebox{"+Fn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{KaTeX}}"),dn("\\hspace","\\@ifstar\\@hspacer\\@hspace"),dn("\\@hspace","\\hskip #1\\relax"),dn("\\@hspacer","\\rule{0pt}{0pt}\\hskip #1\\relax"),dn("\\ordinarycolon",":"),dn("\\vcentcolon","\\mathrel{\\mathop\\ordinarycolon}"),dn("\\dblcolon",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}{\\mathop{\\char"2237}}'),dn("\\coloneqq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2254}}'),dn("\\Coloneqq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2237\\char"3d}}'),dn("\\coloneq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"3a\\char"2212}}'),dn("\\Coloneq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"2237\\char"2212}}'),dn("\\eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2255}}'),dn("\\Eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"3d\\char"2237}}'),dn("\\eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2239}}'),dn("\\Eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"2212\\char"2237}}'),dn("\\colonapprox",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"3a\\char"2248}}'),dn("\\Colonapprox",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"2237\\char"2248}}'),dn("\\colonsim",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"3a\\char"223c}}'),dn("\\Colonsim",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"2237\\char"223c}}'),dn("\u2237","\\dblcolon"),dn("\u2239","\\eqcolon"),dn("\u2254","\\coloneqq"),dn("\u2255","\\eqqcolon"),dn("\u2a74","\\Coloneqq"),dn("\\ratio","\\vcentcolon"),dn("\\coloncolon","\\dblcolon"),dn("\\colonequals","\\coloneqq"),dn("\\coloncolonequals","\\Coloneqq"),dn("\\equalscolon","\\eqqcolon"),dn("\\equalscoloncolon","\\Eqqcolon"),dn("\\colonminus","\\coloneq"),dn("\\coloncolonminus","\\Coloneq"),dn("\\minuscolon","\\eqcolon"),dn("\\minuscoloncolon","\\Eqcolon"),dn("\\coloncolonapprox","\\Colonapprox"),dn("\\coloncolonsim","\\Colonsim"),dn("\\simcolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),dn("\\simcoloncolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"),dn("\\approxcolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),dn("\\approxcoloncolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"),dn("\\notni","\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220c}}"),dn("\\limsup","\\DOTSB\\operatorname*{lim\\,sup}"),dn("\\liminf","\\DOTSB\\operatorname*{lim\\,inf}"),dn("\\injlim","\\DOTSB\\operatorname*{inj\\,lim}"),dn("\\projlim","\\DOTSB\\operatorname*{proj\\,lim}"),dn("\\varlimsup","\\DOTSB\\operatorname*{\\overline{lim}}"),dn("\\varliminf","\\DOTSB\\operatorname*{\\underline{lim}}"),dn("\\varinjlim","\\DOTSB\\operatorname*{\\underrightarrow{lim}}"),dn("\\varprojlim","\\DOTSB\\operatorname*{\\underleftarrow{lim}}"),dn("\\gvertneqq","\\html@mathml{\\@gvertneqq}{\u2269}"),dn("\\lvertneqq","\\html@mathml{\\@lvertneqq}{\u2268}"),dn("\\ngeqq","\\html@mathml{\\@ngeqq}{\u2271}"),dn("\\ngeqslant","\\html@mathml{\\@ngeqslant}{\u2271}"),dn("\\nleqq","\\html@mathml{\\@nleqq}{\u2270}"),dn("\\nleqslant","\\html@mathml{\\@nleqslant}{\u2270}"),dn("\\nshortmid","\\html@mathml{\\@nshortmid}{\u2224}"),dn("\\nshortparallel","\\html@mathml{\\@nshortparallel}{\u2226}"),dn("\\nsubseteqq","\\html@mathml{\\@nsubseteqq}{\u2288}"),dn("\\nsupseteqq","\\html@mathml{\\@nsupseteqq}{\u2289}"),dn("\\varsubsetneq","\\html@mathml{\\@varsubsetneq}{\u228a}"),dn("\\varsubsetneqq","\\html@mathml{\\@varsubsetneqq}{\u2acb}"),dn("\\varsupsetneq","\\html@mathml{\\@varsupsetneq}{\u228b}"),dn("\\varsupsetneqq","\\html@mathml{\\@varsupsetneqq}{\u2acc}"),dn("\\imath","\\html@mathml{\\@imath}{\u0131}"),dn("\\jmath","\\html@mathml{\\@jmath}{\u0237}"),dn("\\llbracket","\\html@mathml{\\mathopen{[\\mkern-3.2mu[}}{\\mathopen{\\char`\u27e6}}"),dn("\\rrbracket","\\html@mathml{\\mathclose{]\\mkern-3.2mu]}}{\\mathclose{\\char`\u27e7}}"),dn("\u27e6","\\llbracket"),dn("\u27e7","\\rrbracket"),dn("\\lBrace","\\html@mathml{\\mathopen{\\{\\mkern-3.2mu[}}{\\mathopen{\\char`\u2983}}"),dn("\\rBrace","\\html@mathml{\\mathclose{]\\mkern-3.2mu\\}}}{\\mathclose{\\char`\u2984}}"),dn("\u2983","\\lBrace"),dn("\u2984","\\rBrace"),dn("\\minuso","\\mathbin{\\html@mathml{{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}{\\char`\u29b5}}"),dn("\u29b5","\\minuso"),dn("\\darr","\\downarrow"),dn("\\dArr","\\Downarrow"),dn("\\Darr","\\Downarrow"),dn("\\lang","\\langle"),dn("\\rang","\\rangle"),dn("\\uarr","\\uparrow"),dn("\\uArr","\\Uparrow"),dn("\\Uarr","\\Uparrow"),dn("\\N","\\mathbb{N}"),dn("\\R","\\mathbb{R}"),dn("\\Z","\\mathbb{Z}"),dn("\\alef","\\aleph"),dn("\\alefsym","\\aleph"),dn("\\Alpha","\\mathrm{A}"),dn("\\Beta","\\mathrm{B}"),dn("\\bull","\\bullet"),dn("\\Chi","\\mathrm{X}"),dn("\\clubs","\\clubsuit"),dn("\\cnums","\\mathbb{C}"),dn("\\Complex","\\mathbb{C}"),dn("\\Dagger","\\ddagger"),dn("\\diamonds","\\diamondsuit"),dn("\\empty","\\emptyset"),dn("\\Epsilon","\\mathrm{E}"),dn("\\Eta","\\mathrm{H}"),dn("\\exist","\\exists"),dn("\\harr","\\leftrightarrow"),dn("\\hArr","\\Leftrightarrow"),dn("\\Harr","\\Leftrightarrow"),dn("\\hearts","\\heartsuit"),dn("\\image","\\Im"),dn("\\infin","\\infty"),dn("\\Iota","\\mathrm{I}"),dn("\\isin","\\in"),dn("\\Kappa","\\mathrm{K}"),dn("\\larr","\\leftarrow"),dn("\\lArr","\\Leftarrow"),dn("\\Larr","\\Leftarrow"),dn("\\lrarr","\\leftrightarrow"),dn("\\lrArr","\\Leftrightarrow"),dn("\\Lrarr","\\Leftrightarrow"),dn("\\Mu","\\mathrm{M}"),dn("\\natnums","\\mathbb{N}"),dn("\\Nu","\\mathrm{N}"),dn("\\Omicron","\\mathrm{O}"),dn("\\plusmn","\\pm"),dn("\\rarr","\\rightarrow"),dn("\\rArr","\\Rightarrow"),dn("\\Rarr","\\Rightarrow"),dn("\\real","\\Re"),dn("\\reals","\\mathbb{R}"),dn("\\Reals","\\mathbb{R}"),dn("\\Rho","\\mathrm{P}"),dn("\\sdot","\\cdot"),dn("\\sect","\\S"),dn("\\spades","\\spadesuit"),dn("\\sub","\\subset"),dn("\\sube","\\subseteq"),dn("\\supe","\\supseteq"),dn("\\Tau","\\mathrm{T}"),dn("\\thetasym","\\vartheta"),dn("\\weierp","\\wp"),dn("\\Zeta","\\mathrm{Z}"),dn("\\argmin","\\DOTSB\\operatorname*{arg\\,min}"),dn("\\argmax","\\DOTSB\\operatorname*{arg\\,max}"),dn("\\plim","\\DOTSB\\mathop{\\operatorname{plim}}\\limits"),dn("\\bra","\\mathinner{\\langle{#1}|}"),dn("\\ket","\\mathinner{|{#1}\\rangle}"),dn("\\braket","\\mathinner{\\langle{#1}\\rangle}"),dn("\\Bra","\\left\\langle#1\\right|"),dn("\\Ket","\\left|#1\\right\\rangle"),dn("\\angln","{\\angl n}"),dn("\\blue","\\textcolor{##6495ed}{#1}"),dn("\\orange","\\textcolor{##ffa500}{#1}"),dn("\\pink","\\textcolor{##ff00af}{#1}"),dn("\\red","\\textcolor{##df0030}{#1}"),dn("\\green","\\textcolor{##28ae7b}{#1}"),dn("\\gray","\\textcolor{gray}{#1}"),dn("\\purple","\\textcolor{##9d38bd}{#1}"),dn("\\blueA","\\textcolor{##ccfaff}{#1}"),dn("\\blueB","\\textcolor{##80f6ff}{#1}"),dn("\\blueC","\\textcolor{##63d9ea}{#1}"),dn("\\blueD","\\textcolor{##11accd}{#1}"),dn("\\blueE","\\textcolor{##0c7f99}{#1}"),dn("\\tealA","\\textcolor{##94fff5}{#1}"),dn("\\tealB","\\textcolor{##26edd5}{#1}"),dn("\\tealC","\\textcolor{##01d1c1}{#1}"),dn("\\tealD","\\textcolor{##01a995}{#1}"),dn("\\tealE","\\textcolor{##208170}{#1}"),dn("\\greenA","\\textcolor{##b6ffb0}{#1}"),dn("\\greenB","\\textcolor{##8af281}{#1}"),dn("\\greenC","\\textcolor{##74cf70}{#1}"),dn("\\greenD","\\textcolor{##1fab54}{#1}"),dn("\\greenE","\\textcolor{##0d923f}{#1}"),dn("\\goldA","\\textcolor{##ffd0a9}{#1}"),dn("\\goldB","\\textcolor{##ffbb71}{#1}"),dn("\\goldC","\\textcolor{##ff9c39}{#1}"),dn("\\goldD","\\textcolor{##e07d10}{#1}"),dn("\\goldE","\\textcolor{##a75a05}{#1}"),dn("\\redA","\\textcolor{##fca9a9}{#1}"),dn("\\redB","\\textcolor{##ff8482}{#1}"),dn("\\redC","\\textcolor{##f9685d}{#1}"),dn("\\redD","\\textcolor{##e84d39}{#1}"),dn("\\redE","\\textcolor{##bc2612}{#1}"),dn("\\maroonA","\\textcolor{##ffbde0}{#1}"),dn("\\maroonB","\\textcolor{##ff92c6}{#1}"),dn("\\maroonC","\\textcolor{##ed5fa6}{#1}"),dn("\\maroonD","\\textcolor{##ca337c}{#1}"),dn("\\maroonE","\\textcolor{##9e034e}{#1}"),dn("\\purpleA","\\textcolor{##ddd7ff}{#1}"),dn("\\purpleB","\\textcolor{##c6b9fc}{#1}"),dn("\\purpleC","\\textcolor{##aa87ff}{#1}"),dn("\\purpleD","\\textcolor{##7854ab}{#1}"),dn("\\purpleE","\\textcolor{##543b78}{#1}"),dn("\\mintA","\\textcolor{##f5f9e8}{#1}"),dn("\\mintB","\\textcolor{##edf2df}{#1}"),dn("\\mintC","\\textcolor{##e0e5cc}{#1}"),dn("\\grayA","\\textcolor{##f6f7f7}{#1}"),dn("\\grayB","\\textcolor{##f0f1f2}{#1}"),dn("\\grayC","\\textcolor{##e3e5e6}{#1}"),dn("\\grayD","\\textcolor{##d6d8da}{#1}"),dn("\\grayE","\\textcolor{##babec2}{#1}"),dn("\\grayF","\\textcolor{##888d93}{#1}"),dn("\\grayG","\\textcolor{##626569}{#1}"),dn("\\grayH","\\textcolor{##3b3e40}{#1}"),dn("\\grayI","\\textcolor{##21242c}{#1}"),dn("\\kaBlue","\\textcolor{##314453}{#1}"),dn("\\kaGreen","\\textcolor{##71B307}{#1}");var Vn={"\\relax":!0,"^":!0,_:!0,"\\limits":!0,"\\nolimits":!0},Gn=function(){function e(e,t,r){this.settings=void 0,this.expansionCount=void 0,this.lexer=void 0,this.macros=void 0,this.stack=void 0,this.mode=void 0,this.settings=t,this.expansionCount=0,this.feed(e),this.macros=new On(En,t.macros),this.mode=r,this.stack=[]}var t=e.prototype;return t.feed=function(e){this.lexer=new Rn(e,this.settings)},t.switchMode=function(e){this.mode=e},t.beginGroup=function(){this.macros.beginGroup()},t.endGroup=function(){this.macros.endGroup()},t.endGroups=function(){this.macros.endGroups()},t.future=function(){return 0===this.stack.length&&this.pushToken(this.lexer.lex()),this.stack[this.stack.length-1]},t.popToken=function(){return this.future(),this.stack.pop()},t.pushToken=function(e){this.stack.push(e)},t.pushTokens=function(e){var t;(t=this.stack).push.apply(t,e)},t.scanArgument=function(e){var t,r,n;if(e){if(this.consumeSpaces(),"["!==this.future().text)return null;t=this.popToken();var a=this.consumeArg(["]"]);n=a.tokens,r=a.end}else{var i=this.consumeArg();n=i.tokens,t=i.start,r=i.end}return this.pushToken(new Cn("EOF",r.loc)),this.pushTokens(n),t.range(r,"")},t.consumeSpaces=function(){for(;;){if(" "!==this.future().text)break;this.stack.pop()}},t.consumeArg=function(e){var t=[],r=e&&e.length>0;r||this.consumeSpaces();var a,i=this.future(),o=0,s=0;do{if(a=this.popToken(),t.push(a),"{"===a.text)++o;else if("}"===a.text){if(-1===--o)throw new n("Extra }",a)}else if("EOF"===a.text)throw new n("Unexpected end of input in a macro argument, expected '"+(e&&r?e[s]:"}")+"'",a);if(e&&r)if((0===o||1===o&&"{"===e[s])&&a.text===e[s]){if(++s===e.length){t.splice(-s,s);break}}else s=0}while(0!==o||r);return"{"===i.text&&"}"===t[t.length-1].text&&(t.pop(),t.shift()),t.reverse(),{tokens:t,start:i,end:a}},t.consumeArgs=function(e,t){if(t){if(t.length!==e+1)throw new n("The length of delimiters doesn't match the number of args!");for(var r=t[0],a=0;athis.settings.maxExpand)throw new n("Too many expansions: infinite loop or need to increase maxExpand setting");var i=a.tokens,o=this.consumeArgs(a.numArgs,a.delimiters);if(a.numArgs)for(var s=(i=i.slice()).length-1;s>=0;--s){var l=i[s];if("#"===l.text){if(0===s)throw new n("Incomplete placeholder at end of macro body",l);if("#"===(l=i[--s]).text)i.splice(s+1,1);else{if(!/^[1-9]$/.test(l.text))throw new n("Not a valid argument number",l);var h;(h=i).splice.apply(h,[s,2].concat(o[+l.text-1]))}}}return this.pushTokens(i),i},t.expandAfterFuture=function(){return this.expandOnce(),this.future()},t.expandNextToken=function(){for(;;){var e=this.expandOnce();if(e instanceof Cn){if("\\relax"!==e.text&&!e.treatAsRelax)return this.stack.pop();this.stack.pop()}}throw new Error},t.expandMacro=function(e){return this.macros.has(e)?this.expandTokens([new Cn(e)]):void 0},t.expandTokens=function(e){var t=[],r=this.stack.length;for(this.pushTokens(e);this.stack.length>r;){var n=this.expandOnce(!0);n instanceof Cn&&(n.treatAsRelax&&(n.noexpand=!1,n.treatAsRelax=!1),t.push(this.stack.pop()))}return t},t.expandMacroAsText=function(e){var t=this.expandMacro(e);return t?t.map((function(e){return e.text})).join(""):t},t._getExpansion=function(e){var t=this.macros.get(e);if(null==t)return t;if(1===e.length){var r=this.lexer.catcodes[e];if(null!=r&&13!==r)return}var n="function"==typeof t?t(this):t;if("string"==typeof n){var a=0;if(-1!==n.indexOf("#"))for(var i=n.replace(/##/g,"");-1!==i.indexOf("#"+(a+1));)++a;for(var o=new Rn(n,this.settings),s=[],l=o.lex();"EOF"!==l.text;)s.push(l),l=o.lex();return s.reverse(),{tokens:s,numArgs:a}}return n},t.isDefined=function(e){return this.macros.has(e)||Nn.hasOwnProperty(e)||X.math.hasOwnProperty(e)||X.text.hasOwnProperty(e)||Vn.hasOwnProperty(e)},t.isExpandable=function(e){var t=this.macros.get(e);return null!=t?"string"==typeof t||"function"==typeof t||!t.unexpandable:Nn.hasOwnProperty(e)&&!Nn[e].primitive},e}(),Un={"\u0301":{text:"\\'",math:"\\acute"},"\u0300":{text:"\\`",math:"\\grave"},"\u0308":{text:'\\"',math:"\\ddot"},"\u0303":{text:"\\~",math:"\\tilde"},"\u0304":{text:"\\=",math:"\\bar"},"\u0306":{text:"\\u",math:"\\breve"},"\u030c":{text:"\\v",math:"\\check"},"\u0302":{text:"\\^",math:"\\hat"},"\u0307":{text:"\\.",math:"\\dot"},"\u030a":{text:"\\r",math:"\\mathring"},"\u030b":{text:"\\H"},"\u0327":{text:"\\c"}},Yn={"\xe1":"a\u0301","\xe0":"a\u0300","\xe4":"a\u0308","\u01df":"a\u0308\u0304","\xe3":"a\u0303","\u0101":"a\u0304","\u0103":"a\u0306","\u1eaf":"a\u0306\u0301","\u1eb1":"a\u0306\u0300","\u1eb5":"a\u0306\u0303","\u01ce":"a\u030c","\xe2":"a\u0302","\u1ea5":"a\u0302\u0301","\u1ea7":"a\u0302\u0300","\u1eab":"a\u0302\u0303","\u0227":"a\u0307","\u01e1":"a\u0307\u0304","\xe5":"a\u030a","\u01fb":"a\u030a\u0301","\u1e03":"b\u0307","\u0107":"c\u0301","\u1e09":"c\u0327\u0301","\u010d":"c\u030c","\u0109":"c\u0302","\u010b":"c\u0307","\xe7":"c\u0327","\u010f":"d\u030c","\u1e0b":"d\u0307","\u1e11":"d\u0327","\xe9":"e\u0301","\xe8":"e\u0300","\xeb":"e\u0308","\u1ebd":"e\u0303","\u0113":"e\u0304","\u1e17":"e\u0304\u0301","\u1e15":"e\u0304\u0300","\u0115":"e\u0306","\u1e1d":"e\u0327\u0306","\u011b":"e\u030c","\xea":"e\u0302","\u1ebf":"e\u0302\u0301","\u1ec1":"e\u0302\u0300","\u1ec5":"e\u0302\u0303","\u0117":"e\u0307","\u0229":"e\u0327","\u1e1f":"f\u0307","\u01f5":"g\u0301","\u1e21":"g\u0304","\u011f":"g\u0306","\u01e7":"g\u030c","\u011d":"g\u0302","\u0121":"g\u0307","\u0123":"g\u0327","\u1e27":"h\u0308","\u021f":"h\u030c","\u0125":"h\u0302","\u1e23":"h\u0307","\u1e29":"h\u0327","\xed":"i\u0301","\xec":"i\u0300","\xef":"i\u0308","\u1e2f":"i\u0308\u0301","\u0129":"i\u0303","\u012b":"i\u0304","\u012d":"i\u0306","\u01d0":"i\u030c","\xee":"i\u0302","\u01f0":"j\u030c","\u0135":"j\u0302","\u1e31":"k\u0301","\u01e9":"k\u030c","\u0137":"k\u0327","\u013a":"l\u0301","\u013e":"l\u030c","\u013c":"l\u0327","\u1e3f":"m\u0301","\u1e41":"m\u0307","\u0144":"n\u0301","\u01f9":"n\u0300","\xf1":"n\u0303","\u0148":"n\u030c","\u1e45":"n\u0307","\u0146":"n\u0327","\xf3":"o\u0301","\xf2":"o\u0300","\xf6":"o\u0308","\u022b":"o\u0308\u0304","\xf5":"o\u0303","\u1e4d":"o\u0303\u0301","\u1e4f":"o\u0303\u0308","\u022d":"o\u0303\u0304","\u014d":"o\u0304","\u1e53":"o\u0304\u0301","\u1e51":"o\u0304\u0300","\u014f":"o\u0306","\u01d2":"o\u030c","\xf4":"o\u0302","\u1ed1":"o\u0302\u0301","\u1ed3":"o\u0302\u0300","\u1ed7":"o\u0302\u0303","\u022f":"o\u0307","\u0231":"o\u0307\u0304","\u0151":"o\u030b","\u1e55":"p\u0301","\u1e57":"p\u0307","\u0155":"r\u0301","\u0159":"r\u030c","\u1e59":"r\u0307","\u0157":"r\u0327","\u015b":"s\u0301","\u1e65":"s\u0301\u0307","\u0161":"s\u030c","\u1e67":"s\u030c\u0307","\u015d":"s\u0302","\u1e61":"s\u0307","\u015f":"s\u0327","\u1e97":"t\u0308","\u0165":"t\u030c","\u1e6b":"t\u0307","\u0163":"t\u0327","\xfa":"u\u0301","\xf9":"u\u0300","\xfc":"u\u0308","\u01d8":"u\u0308\u0301","\u01dc":"u\u0308\u0300","\u01d6":"u\u0308\u0304","\u01da":"u\u0308\u030c","\u0169":"u\u0303","\u1e79":"u\u0303\u0301","\u016b":"u\u0304","\u1e7b":"u\u0304\u0308","\u016d":"u\u0306","\u01d4":"u\u030c","\xfb":"u\u0302","\u016f":"u\u030a","\u0171":"u\u030b","\u1e7d":"v\u0303","\u1e83":"w\u0301","\u1e81":"w\u0300","\u1e85":"w\u0308","\u0175":"w\u0302","\u1e87":"w\u0307","\u1e98":"w\u030a","\u1e8d":"x\u0308","\u1e8b":"x\u0307","\xfd":"y\u0301","\u1ef3":"y\u0300","\xff":"y\u0308","\u1ef9":"y\u0303","\u0233":"y\u0304","\u0177":"y\u0302","\u1e8f":"y\u0307","\u1e99":"y\u030a","\u017a":"z\u0301","\u017e":"z\u030c","\u1e91":"z\u0302","\u017c":"z\u0307","\xc1":"A\u0301","\xc0":"A\u0300","\xc4":"A\u0308","\u01de":"A\u0308\u0304","\xc3":"A\u0303","\u0100":"A\u0304","\u0102":"A\u0306","\u1eae":"A\u0306\u0301","\u1eb0":"A\u0306\u0300","\u1eb4":"A\u0306\u0303","\u01cd":"A\u030c","\xc2":"A\u0302","\u1ea4":"A\u0302\u0301","\u1ea6":"A\u0302\u0300","\u1eaa":"A\u0302\u0303","\u0226":"A\u0307","\u01e0":"A\u0307\u0304","\xc5":"A\u030a","\u01fa":"A\u030a\u0301","\u1e02":"B\u0307","\u0106":"C\u0301","\u1e08":"C\u0327\u0301","\u010c":"C\u030c","\u0108":"C\u0302","\u010a":"C\u0307","\xc7":"C\u0327","\u010e":"D\u030c","\u1e0a":"D\u0307","\u1e10":"D\u0327","\xc9":"E\u0301","\xc8":"E\u0300","\xcb":"E\u0308","\u1ebc":"E\u0303","\u0112":"E\u0304","\u1e16":"E\u0304\u0301","\u1e14":"E\u0304\u0300","\u0114":"E\u0306","\u1e1c":"E\u0327\u0306","\u011a":"E\u030c","\xca":"E\u0302","\u1ebe":"E\u0302\u0301","\u1ec0":"E\u0302\u0300","\u1ec4":"E\u0302\u0303","\u0116":"E\u0307","\u0228":"E\u0327","\u1e1e":"F\u0307","\u01f4":"G\u0301","\u1e20":"G\u0304","\u011e":"G\u0306","\u01e6":"G\u030c","\u011c":"G\u0302","\u0120":"G\u0307","\u0122":"G\u0327","\u1e26":"H\u0308","\u021e":"H\u030c","\u0124":"H\u0302","\u1e22":"H\u0307","\u1e28":"H\u0327","\xcd":"I\u0301","\xcc":"I\u0300","\xcf":"I\u0308","\u1e2e":"I\u0308\u0301","\u0128":"I\u0303","\u012a":"I\u0304","\u012c":"I\u0306","\u01cf":"I\u030c","\xce":"I\u0302","\u0130":"I\u0307","\u0134":"J\u0302","\u1e30":"K\u0301","\u01e8":"K\u030c","\u0136":"K\u0327","\u0139":"L\u0301","\u013d":"L\u030c","\u013b":"L\u0327","\u1e3e":"M\u0301","\u1e40":"M\u0307","\u0143":"N\u0301","\u01f8":"N\u0300","\xd1":"N\u0303","\u0147":"N\u030c","\u1e44":"N\u0307","\u0145":"N\u0327","\xd3":"O\u0301","\xd2":"O\u0300","\xd6":"O\u0308","\u022a":"O\u0308\u0304","\xd5":"O\u0303","\u1e4c":"O\u0303\u0301","\u1e4e":"O\u0303\u0308","\u022c":"O\u0303\u0304","\u014c":"O\u0304","\u1e52":"O\u0304\u0301","\u1e50":"O\u0304\u0300","\u014e":"O\u0306","\u01d1":"O\u030c","\xd4":"O\u0302","\u1ed0":"O\u0302\u0301","\u1ed2":"O\u0302\u0300","\u1ed6":"O\u0302\u0303","\u022e":"O\u0307","\u0230":"O\u0307\u0304","\u0150":"O\u030b","\u1e54":"P\u0301","\u1e56":"P\u0307","\u0154":"R\u0301","\u0158":"R\u030c","\u1e58":"R\u0307","\u0156":"R\u0327","\u015a":"S\u0301","\u1e64":"S\u0301\u0307","\u0160":"S\u030c","\u1e66":"S\u030c\u0307","\u015c":"S\u0302","\u1e60":"S\u0307","\u015e":"S\u0327","\u0164":"T\u030c","\u1e6a":"T\u0307","\u0162":"T\u0327","\xda":"U\u0301","\xd9":"U\u0300","\xdc":"U\u0308","\u01d7":"U\u0308\u0301","\u01db":"U\u0308\u0300","\u01d5":"U\u0308\u0304","\u01d9":"U\u0308\u030c","\u0168":"U\u0303","\u1e78":"U\u0303\u0301","\u016a":"U\u0304","\u1e7a":"U\u0304\u0308","\u016c":"U\u0306","\u01d3":"U\u030c","\xdb":"U\u0302","\u016e":"U\u030a","\u0170":"U\u030b","\u1e7c":"V\u0303","\u1e82":"W\u0301","\u1e80":"W\u0300","\u1e84":"W\u0308","\u0174":"W\u0302","\u1e86":"W\u0307","\u1e8c":"X\u0308","\u1e8a":"X\u0307","\xdd":"Y\u0301","\u1ef2":"Y\u0300","\u0178":"Y\u0308","\u1ef8":"Y\u0303","\u0232":"Y\u0304","\u0176":"Y\u0302","\u1e8e":"Y\u0307","\u0179":"Z\u0301","\u017d":"Z\u030c","\u1e90":"Z\u0302","\u017b":"Z\u0307","\u03ac":"\u03b1\u0301","\u1f70":"\u03b1\u0300","\u1fb1":"\u03b1\u0304","\u1fb0":"\u03b1\u0306","\u03ad":"\u03b5\u0301","\u1f72":"\u03b5\u0300","\u03ae":"\u03b7\u0301","\u1f74":"\u03b7\u0300","\u03af":"\u03b9\u0301","\u1f76":"\u03b9\u0300","\u03ca":"\u03b9\u0308","\u0390":"\u03b9\u0308\u0301","\u1fd2":"\u03b9\u0308\u0300","\u1fd1":"\u03b9\u0304","\u1fd0":"\u03b9\u0306","\u03cc":"\u03bf\u0301","\u1f78":"\u03bf\u0300","\u03cd":"\u03c5\u0301","\u1f7a":"\u03c5\u0300","\u03cb":"\u03c5\u0308","\u03b0":"\u03c5\u0308\u0301","\u1fe2":"\u03c5\u0308\u0300","\u1fe1":"\u03c5\u0304","\u1fe0":"\u03c5\u0306","\u03ce":"\u03c9\u0301","\u1f7c":"\u03c9\u0300","\u038e":"\u03a5\u0301","\u1fea":"\u03a5\u0300","\u03ab":"\u03a5\u0308","\u1fe9":"\u03a5\u0304","\u1fe8":"\u03a5\u0306","\u038f":"\u03a9\u0301","\u1ffa":"\u03a9\u0300"},Wn=function(){function e(e,t){this.mode=void 0,this.gullet=void 0,this.settings=void 0,this.leftrightDepth=void 0,this.nextToken=void 0,this.mode="math",this.gullet=new Gn(e,t,this.mode),this.settings=t,this.leftrightDepth=0}var t=e.prototype;return t.expect=function(e,t){if(void 0===t&&(t=!0),this.fetch().text!==e)throw new n("Expected '"+e+"', got '"+this.fetch().text+"'",this.fetch());t&&this.consume()},t.consume=function(){this.nextToken=null},t.fetch=function(){return null==this.nextToken&&(this.nextToken=this.gullet.expandNextToken()),this.nextToken},t.switchMode=function(e){this.mode=e,this.gullet.switchMode(e)},t.parse=function(){this.settings.globalGroup||this.gullet.beginGroup(),this.settings.colorIsTextColor&&this.gullet.macros.set("\\color","\\textcolor");try{var e=this.parseExpression(!1);return this.expect("EOF"),this.settings.globalGroup||this.gullet.endGroup(),e}finally{this.gullet.endGroups()}},t.parseExpression=function(t,r){for(var n=[];;){"math"===this.mode&&this.consumeSpaces();var a=this.fetch();if(-1!==e.endOfExpression.indexOf(a.text))break;if(r&&a.text===r)break;if(t&&Nn[a.text]&&Nn[a.text].infix)break;var i=this.parseAtom(r);if(!i)break;"internal"!==i.type&&n.push(i)}return"text"===this.mode&&this.formLigatures(n),this.handleInfixNodes(n)},t.handleInfixNodes=function(e){for(var t,r=-1,a=0;a=0&&this.settings.reportNonstrict("unicodeTextInMathMode",'Latin-1/Unicode text character "'+t[0]+'" used in math mode',e);var s,l=X[this.mode][t].group,h=qn.range(e);if(U.hasOwnProperty(l)){var m=l;s={type:"atom",mode:this.mode,family:m,loc:h,text:t}}else s={type:l,mode:this.mode,loc:h,text:t};i=s}else{if(!(t.charCodeAt(0)>=128))return null;this.settings.strict&&(w(t.charCodeAt(0))?"math"===this.mode&&this.settings.reportNonstrict("unicodeTextInMathMode",'Unicode text character "'+t[0]+'" used in math mode',e):this.settings.reportNonstrict("unknownSymbol",'Unrecognized Unicode character "'+t[0]+'" ('+t.charCodeAt(0)+")",e)),i={type:"textord",mode:"text",loc:qn.range(e),text:t}}if(this.consume(),o)for(var c=0;c15?"\u2026"+o.slice(n-15,n):o.slice(0,n))+l+(s+15":">","<":"<",'"':""","'":"'"},o=/[&><"']/g;var s=function e(t){return"ordgroup"===t.type||"color"===t.type?1===t.body.length?e(t.body[0]):t:"font"===t.type?e(t.body):t},l={contains:function(e,t){return-1!==e.indexOf(t)},deflt:function(e,t){return void 0===e?t:e},escape:function(e){return String(e).replace(o,(function(e){return i[e]}))},hyphenate:function(e){return e.replace(a,"-$1").toLowerCase()},getBaseElem:s,isCharacterBox:function(e){var t=s(e);return"mathord"===t.type||"textord"===t.type||"atom"===t.type},protocolFromUrl:function(e){var t=/^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(e);return null!=t?t[1]:"_relative"}},h={displayMode:{type:"boolean",description:"Render math in display mode, which puts the math in display style (so \\int and \\sum are large, for example), and centers the math on the page on its own line.",cli:"-d, --display-mode"},output:{type:{enum:["htmlAndMathml","html","mathml"]},description:"Determines the markup language of the output.",cli:"-F, --format "},leqno:{type:"boolean",description:"Render display math in leqno style (left-justified tags)."},fleqn:{type:"boolean",description:"Render display math flush left."},throwOnError:{type:"boolean",default:!0,cli:"-t, --no-throw-on-error",cliDescription:"Render errors (in the color given by --error-color) instead of throwing a ParseError exception when encountering an error."},errorColor:{type:"string",default:"#cc0000",cli:"-c, --error-color ",cliDescription:"A color string given in the format 'rgb' or 'rrggbb' (no #). This option determines the color of errors rendered by the -t option.",cliProcessor:function(e){return"#"+e}},macros:{type:"object",cli:"-m, --macro ",cliDescription:"Define custom macro of the form '\\foo:expansion' (use multiple -m arguments for multiple macros).",cliDefault:[],cliProcessor:function(e,t){return t.push(e),t}},minRuleThickness:{type:"number",description:"Specifies a minimum thickness, in ems, for fraction lines, `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, `\\hdashline`, `\\underline`, `\\overline`, and the borders of `\\fbox`, `\\boxed`, and `\\fcolorbox`.",processor:function(e){return Math.max(0,e)},cli:"--min-rule-thickness ",cliProcessor:parseFloat},colorIsTextColor:{type:"boolean",description:"Makes \\color behave like LaTeX's 2-argument \\textcolor, instead of LaTeX's one-argument \\color mode change.",cli:"-b, --color-is-text-color"},strict:{type:[{enum:["warn","ignore","error"]},"boolean","function"],description:"Turn on strict / LaTeX faithfulness mode, which throws an error if the input uses features that are not supported by LaTeX.",cli:"-S, --strict",cliDefault:!1},trust:{type:["boolean","function"],description:"Trust the input, enabling all HTML features such as \\url.",cli:"-T, --trust"},maxSize:{type:"number",default:1/0,description:"If non-zero, all user-specified sizes, e.g. in \\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, elements and spaces can be arbitrarily large",processor:function(e){return Math.max(0,e)},cli:"-s, --max-size ",cliProcessor:parseInt},maxExpand:{type:"number",default:1e3,description:"Limit the number of macro expansions to the specified number, to prevent e.g. infinite macro loops. If set to Infinity, the macro expander will try to fully expand as in LaTeX.",processor:function(e){return Math.max(0,e)},cli:"-e, --max-expand ",cliProcessor:function(e){return"Infinity"===e?1/0:parseInt(e)}},globalGroup:{type:"boolean",cli:!1}};function c(e){if(e.default)return e.default;var t=e.type,r=Array.isArray(t)?t[0]:t;if("string"!=typeof r)return r.enum[0];switch(r){case"boolean":return!1;case"string":return"";case"number":return 0;case"object":return{}}}var m=function(){function e(e){for(var t in this.displayMode=void 0,this.output=void 0,this.leqno=void 0,this.fleqn=void 0,this.throwOnError=void 0,this.errorColor=void 0,this.macros=void 0,this.minRuleThickness=void 0,this.colorIsTextColor=void 0,this.strict=void 0,this.trust=void 0,this.maxSize=void 0,this.maxExpand=void 0,this.globalGroup=void 0,e=e||{},h)if(h.hasOwnProperty(t)){var r=h[t];this[t]=void 0!==e[t]?r.processor?r.processor(e[t]):e[t]:c(r)}}var t=e.prototype;return t.reportNonstrict=function(e,t,r){var a=this.strict;if("function"==typeof a&&(a=a(e,t,r)),a&&"ignore"!==a){if(!0===a||"error"===a)throw new n("LaTeX-incompatible input and strict mode is set to 'error': "+t+" ["+e+"]",r);"warn"===a?"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"):"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+a+"': "+t+" ["+e+"]")}},t.useStrictBehavior=function(e,t,r){var n=this.strict;if("function"==typeof n)try{n=n(e,t,r)}catch(e){n="error"}return!(!n||"ignore"===n)&&(!0===n||"error"===n||("warn"===n?("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"),!1):("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+n+"': "+t+" ["+e+"]"),!1)))},t.isTrusted=function(e){e.url&&!e.protocol&&(e.protocol=l.protocolFromUrl(e.url));var t="function"==typeof this.trust?this.trust(e):this.trust;return Boolean(t)},e}(),u=function(){function e(e,t,r){this.id=void 0,this.size=void 0,this.cramped=void 0,this.id=e,this.size=t,this.cramped=r}var t=e.prototype;return t.sup=function(){return p[d[this.id]]},t.sub=function(){return p[f[this.id]]},t.fracNum=function(){return p[g[this.id]]},t.fracDen=function(){return p[v[this.id]]},t.cramp=function(){return p[b[this.id]]},t.text=function(){return p[y[this.id]]},t.isTight=function(){return this.size>=2},e}(),p=[new u(0,0,!1),new u(1,0,!0),new u(2,1,!1),new u(3,1,!0),new u(4,2,!1),new u(5,2,!0),new u(6,3,!1),new u(7,3,!0)],d=[4,5,4,5,6,7,6,7],f=[5,5,5,5,7,7,7,7],g=[2,3,4,5,6,7,6,7],v=[3,3,5,5,7,7,7,7],b=[1,1,3,3,5,5,7,7],y=[0,1,2,3,2,3,2,3],x={DISPLAY:p[0],TEXT:p[2],SCRIPT:p[4],SCRIPTSCRIPT:p[6]},w=[{name:"latin",blocks:[[256,591],[768,879]]},{name:"cyrillic",blocks:[[1024,1279]]},{name:"armenian",blocks:[[1328,1423]]},{name:"brahmic",blocks:[[2304,4255]]},{name:"georgian",blocks:[[4256,4351]]},{name:"cjk",blocks:[[12288,12543],[19968,40879],[65280,65376]]},{name:"hangul",blocks:[[44032,55215]]}];var k=[];function S(e){for(var t=0;t=k[t]&&e<=k[t+1])return!0;return!1}w.forEach((function(e){return e.blocks.forEach((function(e){return k.push.apply(k,e)}))}));var M=80,z={doubleleftarrow:"M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z",doublerightarrow:"M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z",leftarrow:"M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z",leftbrace:"M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z",leftbraceunder:"M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z",leftgroup:"M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z",leftgroupunder:"M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z",leftharpoon:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z",leftharpoonplus:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z",leftharpoondown:"M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z",leftharpoondownplus:"M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z",lefthook:"M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z",leftlinesegment:"M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z",leftmapsto:"M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z",leftToFrom:"M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z",longequal:"M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z",midbrace:"M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z",midbraceunder:"M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z",oiintSize1:"M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z",oiintSize2:"M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z",oiiintSize1:"M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z",oiiintSize2:"M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z",rightarrow:"M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z",rightbrace:"M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z",rightbraceunder:"M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z",rightgroup:"M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z",rightgroupunder:"M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z",rightharpoon:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z",rightharpoonplus:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z",rightharpoondown:"M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z",rightharpoondownplus:"M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z",righthook:"M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z",rightlinesegment:"M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z",rightToFrom:"M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z",twoheadleftarrow:"M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z",twoheadrightarrow:"M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z",tilde1:"M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z",tilde2:"M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z",tilde3:"M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z",tilde4:"M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z",vec:"M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z",widehat1:"M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z",widehat2:"M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat3:"M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat4:"M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widecheck1:"M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z",widecheck2:"M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck3:"M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck4:"M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",baraboveleftarrow:"M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z",rightarrowabovebar:"M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z",baraboveshortleftharpoon:"M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z",rightharpoonaboveshortbar:"M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z",shortbaraboveleftharpoon:"M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z",shortrightharpoonabovebar:"M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z"},A=function(){function e(e){this.children=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.children=e,this.classes=[],this.height=0,this.depth=0,this.maxFontSize=0,this.style={}}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){for(var e=document.createDocumentFragment(),t=0;t=5?0:e>=3?1:2]){var r=q[t]={cssEmPerMu:B.quad[t]/18};for(var n in B)B.hasOwnProperty(n)&&(r[n]=B[n][t])}return q[t]}(this.size)),this._fontMetrics},t.getColor=function(){return this.phantom?"transparent":this.color},e}();O.BASESIZE=6;var E=O,L={pt:1,mm:7227/2540,cm:7227/254,in:72.27,bp:1.00375,pc:12,dd:1238/1157,cc:14856/1157,nd:685/642,nc:1370/107,sp:1/65536,px:1.00375},D={ex:!0,em:!0,mu:!0},V=function(e){return"string"!=typeof e&&(e=e.unit),e in L||e in D||"ex"===e},P=function(e,t){var r;if(e.unit in L)r=L[e.unit]/t.fontMetrics().ptPerEm/t.sizeMultiplier;else if("mu"===e.unit)r=t.fontMetrics().cssEmPerMu;else{var a;if(a=t.style.isTight()?t.havingStyle(t.style.text()):t,"ex"===e.unit)r=a.fontMetrics().xHeight;else{if("em"!==e.unit)throw new n("Invalid unit: '"+e.unit+"'");r=a.fontMetrics().quad}a!==t&&(r*=a.sizeMultiplier/t.sizeMultiplier)}return Math.min(e.number*r,t.maxSize)},F=function(e){return+e.toFixed(4)+"em"},G=function(e){return e.filter((function(e){return e})).join(" ")},U=function(e,t,r){if(this.classes=e||[],this.attributes={},this.height=0,this.depth=0,this.maxFontSize=0,this.style=r||{},t){t.style.isTight()&&this.classes.push("mtight");var n=t.getColor();n&&(this.style.color=n)}},Y=function(e){var t=document.createElement(e);for(var r in t.className=G(this.classes),this.style)this.style.hasOwnProperty(r)&&(t.style[r]=this.style[r]);for(var n in this.attributes)this.attributes.hasOwnProperty(n)&&t.setAttribute(n,this.attributes[n]);for(var a=0;a"},W=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.width=void 0,this.maxFontSize=void 0,this.style=void 0,U.call(this,e,r,n),this.children=t||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return Y.call(this,"span")},t.toMarkup=function(){return X.call(this,"span")},e}(),_=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,U.call(this,t,n),this.children=r||[],this.setAttribute("href",e)}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return Y.call(this,"a")},t.toMarkup=function(){return X.call(this,"a")},e}(),j=function(){function e(e,t,r){this.src=void 0,this.alt=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.alt=t,this.src=e,this.classes=["mord"],this.style=r}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createElement("img");for(var t in e.src=this.src,e.alt=this.alt,e.className="mord",this.style)this.style.hasOwnProperty(t)&&(e.style[t]=this.style[t]);return e},t.toMarkup=function(){var e=""+this.alt+"=a[0]&&e<=a[1])return r.name}return null}(this.text.charCodeAt(0));l&&this.classes.push(l+"_fallback"),/[\xee\xef\xed\xec]/.test(this.text)&&(this.text=$[this.text])}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createTextNode(this.text),t=null;for(var r in this.italic>0&&((t=document.createElement("span")).style.marginRight=F(this.italic)),this.classes.length>0&&((t=t||document.createElement("span")).className=G(this.classes)),this.style)this.style.hasOwnProperty(r)&&((t=t||document.createElement("span")).style[r]=this.style[r]);return t?(t.appendChild(e),t):e},t.toMarkup=function(){var e=!1,t="0&&(r+="margin-right:"+this.italic+"em;"),this.style)this.style.hasOwnProperty(n)&&(r+=l.hyphenate(n)+":"+this.style[n]+";");r&&(e=!0,t+=' style="'+l.escape(r)+'"');var a=l.escape(this.text);return e?(t+=">",t+=a,t+=""):a},e}(),K=function(){function e(e,t){this.children=void 0,this.attributes=void 0,this.children=e||[],this.attributes=t||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","svg");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);for(var r=0;r":""},e}(),Q=function(){function e(e){this.attributes=void 0,this.attributes=e||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","line");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);return e},t.toMarkup=function(){var e="","\\gt",!0),ie(oe,le,be,"\u2208","\\in",!0),ie(oe,le,be,"\ue020","\\@not"),ie(oe,le,be,"\u2282","\\subset",!0),ie(oe,le,be,"\u2283","\\supset",!0),ie(oe,le,be,"\u2286","\\subseteq",!0),ie(oe,le,be,"\u2287","\\supseteq",!0),ie(oe,he,be,"\u2288","\\nsubseteq",!0),ie(oe,he,be,"\u2289","\\nsupseteq",!0),ie(oe,le,be,"\u22a8","\\models"),ie(oe,le,be,"\u2190","\\leftarrow",!0),ie(oe,le,be,"\u2264","\\le"),ie(oe,le,be,"\u2264","\\leq",!0),ie(oe,le,be,"<","\\lt",!0),ie(oe,le,be,"\u2192","\\rightarrow",!0),ie(oe,le,be,"\u2192","\\to"),ie(oe,he,be,"\u2271","\\ngeq",!0),ie(oe,he,be,"\u2270","\\nleq",!0),ie(oe,le,ye,"\xa0","\\ "),ie(oe,le,ye,"\xa0","\\space"),ie(oe,le,ye,"\xa0","\\nobreakspace"),ie(se,le,ye,"\xa0","\\ "),ie(se,le,ye,"\xa0"," "),ie(se,le,ye,"\xa0","\\space"),ie(se,le,ye,"\xa0","\\nobreakspace"),ie(oe,le,ye,null,"\\nobreak"),ie(oe,le,ye,null,"\\allowbreak"),ie(oe,le,ve,",",","),ie(oe,le,ve,";",";"),ie(oe,he,me,"\u22bc","\\barwedge",!0),ie(oe,he,me,"\u22bb","\\veebar",!0),ie(oe,le,me,"\u2299","\\odot",!0),ie(oe,le,me,"\u2295","\\oplus",!0),ie(oe,le,me,"\u2297","\\otimes",!0),ie(oe,le,xe,"\u2202","\\partial",!0),ie(oe,le,me,"\u2298","\\oslash",!0),ie(oe,he,me,"\u229a","\\circledcirc",!0),ie(oe,he,me,"\u22a1","\\boxdot",!0),ie(oe,le,me,"\u25b3","\\bigtriangleup"),ie(oe,le,me,"\u25bd","\\bigtriangledown"),ie(oe,le,me,"\u2020","\\dagger"),ie(oe,le,me,"\u22c4","\\diamond"),ie(oe,le,me,"\u22c6","\\star"),ie(oe,le,me,"\u25c3","\\triangleleft"),ie(oe,le,me,"\u25b9","\\triangleright"),ie(oe,le,ge,"{","\\{"),ie(se,le,xe,"{","\\{"),ie(se,le,xe,"{","\\textbraceleft"),ie(oe,le,ue,"}","\\}"),ie(se,le,xe,"}","\\}"),ie(se,le,xe,"}","\\textbraceright"),ie(oe,le,ge,"{","\\lbrace"),ie(oe,le,ue,"}","\\rbrace"),ie(oe,le,ge,"[","\\lbrack",!0),ie(se,le,xe,"[","\\lbrack",!0),ie(oe,le,ue,"]","\\rbrack",!0),ie(se,le,xe,"]","\\rbrack",!0),ie(oe,le,ge,"(","\\lparen",!0),ie(oe,le,ue,")","\\rparen",!0),ie(se,le,xe,"<","\\textless",!0),ie(se,le,xe,">","\\textgreater",!0),ie(oe,le,ge,"\u230a","\\lfloor",!0),ie(oe,le,ue,"\u230b","\\rfloor",!0),ie(oe,le,ge,"\u2308","\\lceil",!0),ie(oe,le,ue,"\u2309","\\rceil",!0),ie(oe,le,xe,"\\","\\backslash"),ie(oe,le,xe,"\u2223","|"),ie(oe,le,xe,"\u2223","\\vert"),ie(se,le,xe,"|","\\textbar",!0),ie(oe,le,xe,"\u2225","\\|"),ie(oe,le,xe,"\u2225","\\Vert"),ie(se,le,xe,"\u2225","\\textbardbl"),ie(se,le,xe,"~","\\textasciitilde"),ie(se,le,xe,"\\","\\textbackslash"),ie(se,le,xe,"^","\\textasciicircum"),ie(oe,le,be,"\u2191","\\uparrow",!0),ie(oe,le,be,"\u21d1","\\Uparrow",!0),ie(oe,le,be,"\u2193","\\downarrow",!0),ie(oe,le,be,"\u21d3","\\Downarrow",!0),ie(oe,le,be,"\u2195","\\updownarrow",!0),ie(oe,le,be,"\u21d5","\\Updownarrow",!0),ie(oe,le,fe,"\u2210","\\coprod"),ie(oe,le,fe,"\u22c1","\\bigvee"),ie(oe,le,fe,"\u22c0","\\bigwedge"),ie(oe,le,fe,"\u2a04","\\biguplus"),ie(oe,le,fe,"\u22c2","\\bigcap"),ie(oe,le,fe,"\u22c3","\\bigcup"),ie(oe,le,fe,"\u222b","\\int"),ie(oe,le,fe,"\u222b","\\intop"),ie(oe,le,fe,"\u222c","\\iint"),ie(oe,le,fe,"\u222d","\\iiint"),ie(oe,le,fe,"\u220f","\\prod"),ie(oe,le,fe,"\u2211","\\sum"),ie(oe,le,fe,"\u2a02","\\bigotimes"),ie(oe,le,fe,"\u2a01","\\bigoplus"),ie(oe,le,fe,"\u2a00","\\bigodot"),ie(oe,le,fe,"\u222e","\\oint"),ie(oe,le,fe,"\u222f","\\oiint"),ie(oe,le,fe,"\u2230","\\oiiint"),ie(oe,le,fe,"\u2a06","\\bigsqcup"),ie(oe,le,fe,"\u222b","\\smallint"),ie(se,le,pe,"\u2026","\\textellipsis"),ie(oe,le,pe,"\u2026","\\mathellipsis"),ie(se,le,pe,"\u2026","\\ldots",!0),ie(oe,le,pe,"\u2026","\\ldots",!0),ie(oe,le,pe,"\u22ef","\\@cdots",!0),ie(oe,le,pe,"\u22f1","\\ddots",!0),ie(oe,le,xe,"\u22ee","\\varvdots"),ie(oe,le,ce,"\u02ca","\\acute"),ie(oe,le,ce,"\u02cb","\\grave"),ie(oe,le,ce,"\xa8","\\ddot"),ie(oe,le,ce,"~","\\tilde"),ie(oe,le,ce,"\u02c9","\\bar"),ie(oe,le,ce,"\u02d8","\\breve"),ie(oe,le,ce,"\u02c7","\\check"),ie(oe,le,ce,"^","\\hat"),ie(oe,le,ce,"\u20d7","\\vec"),ie(oe,le,ce,"\u02d9","\\dot"),ie(oe,le,ce,"\u02da","\\mathring"),ie(oe,le,de,"\ue131","\\@imath"),ie(oe,le,de,"\ue237","\\@jmath"),ie(oe,le,xe,"\u0131","\u0131"),ie(oe,le,xe,"\u0237","\u0237"),ie(se,le,xe,"\u0131","\\i",!0),ie(se,le,xe,"\u0237","\\j",!0),ie(se,le,xe,"\xdf","\\ss",!0),ie(se,le,xe,"\xe6","\\ae",!0),ie(se,le,xe,"\u0153","\\oe",!0),ie(se,le,xe,"\xf8","\\o",!0),ie(se,le,xe,"\xc6","\\AE",!0),ie(se,le,xe,"\u0152","\\OE",!0),ie(se,le,xe,"\xd8","\\O",!0),ie(se,le,ce,"\u02ca","\\'"),ie(se,le,ce,"\u02cb","\\`"),ie(se,le,ce,"\u02c6","\\^"),ie(se,le,ce,"\u02dc","\\~"),ie(se,le,ce,"\u02c9","\\="),ie(se,le,ce,"\u02d8","\\u"),ie(se,le,ce,"\u02d9","\\."),ie(se,le,ce,"\xb8","\\c"),ie(se,le,ce,"\u02da","\\r"),ie(se,le,ce,"\u02c7","\\v"),ie(se,le,ce,"\xa8",'\\"'),ie(se,le,ce,"\u02dd","\\H"),ie(se,le,ce,"\u25ef","\\textcircled");var we={"--":!0,"---":!0,"``":!0,"''":!0};ie(se,le,xe,"\u2013","--",!0),ie(se,le,xe,"\u2013","\\textendash"),ie(se,le,xe,"\u2014","---",!0),ie(se,le,xe,"\u2014","\\textemdash"),ie(se,le,xe,"\u2018","`",!0),ie(se,le,xe,"\u2018","\\textquoteleft"),ie(se,le,xe,"\u2019","'",!0),ie(se,le,xe,"\u2019","\\textquoteright"),ie(se,le,xe,"\u201c","``",!0),ie(se,le,xe,"\u201c","\\textquotedblleft"),ie(se,le,xe,"\u201d","''",!0),ie(se,le,xe,"\u201d","\\textquotedblright"),ie(oe,le,xe,"\xb0","\\degree",!0),ie(se,le,xe,"\xb0","\\degree"),ie(se,le,xe,"\xb0","\\textdegree",!0),ie(oe,le,xe,"\xa3","\\pounds"),ie(oe,le,xe,"\xa3","\\mathsterling",!0),ie(se,le,xe,"\xa3","\\pounds"),ie(se,le,xe,"\xa3","\\textsterling",!0),ie(oe,he,xe,"\u2720","\\maltese"),ie(se,he,xe,"\u2720","\\maltese");for(var ke='0123456789/@."',Se=0;Set&&(t=i.height),i.depth>r&&(r=i.depth),i.maxFontSize>n&&(n=i.maxFontSize)}e.height=t,e.depth=r,e.maxFontSize=n},Xe=function(e,t,r,n){var a=new W(e,t,r,n);return Ye(a),a},We=function(e,t,r,n){return new W(e,t,r,n)},_e=function(e){var t=new A(e);return Ye(t),t},je=function(e,t,r){var n="";switch(e){case"amsrm":n="AMS";break;case"textrm":n="Main";break;case"textsf":n="SansSerif";break;case"texttt":n="Typewriter";break;default:n=e}return n+"-"+("textbf"===t&&"textit"===r?"BoldItalic":"textbf"===t?"Bold":"textit"===t?"Italic":"Regular")},$e={mathbf:{variant:"bold",fontName:"Main-Bold"},mathrm:{variant:"normal",fontName:"Main-Regular"},textit:{variant:"italic",fontName:"Main-Italic"},mathit:{variant:"italic",fontName:"Main-Italic"},mathnormal:{variant:"italic",fontName:"Math-Italic"},mathbb:{variant:"double-struck",fontName:"AMS-Regular"},mathcal:{variant:"script",fontName:"Caligraphic-Regular"},mathfrak:{variant:"fraktur",fontName:"Fraktur-Regular"},mathscr:{variant:"script",fontName:"Script-Regular"},mathsf:{variant:"sans-serif",fontName:"SansSerif-Regular"},mathtt:{variant:"monospace",fontName:"Typewriter-Regular"}},Ze={vec:["vec",.471,.714],oiintSize1:["oiintSize1",.957,.499],oiintSize2:["oiintSize2",1.472,.659],oiiintSize1:["oiiintSize1",1.304,.499],oiiintSize2:["oiiintSize2",1.98,.659]},Ke={fontMap:$e,makeSymbol:Ge,mathsym:function(e,t,r,n){return void 0===n&&(n=[]),"boldsymbol"===r.font&&Fe(e,"Main-Bold",t).metrics?Ge(e,"Main-Bold",t,r,n.concat(["mathbf"])):"\\"===e||"main"===ae[t][e].font?Ge(e,"Main-Regular",t,r,n):Ge(e,"AMS-Regular",t,r,n.concat(["amsrm"]))},makeSpan:Xe,makeSvgSpan:We,makeLineSpan:function(e,t,r){var n=Xe([e],[],t);return n.height=Math.max(r||t.fontMetrics().defaultRuleThickness,t.minRuleThickness),n.style.borderBottomWidth=F(n.height),n.maxFontSize=1,n},makeAnchor:function(e,t,r,n){var a=new _(e,t,r,n);return Ye(a),a},makeFragment:_e,wrapFragment:function(e,t){return e instanceof A?Xe([],[e],t):e},makeVList:function(e,t){for(var r=function(e){if("individualShift"===e.positionType){for(var t=e.children,r=[t[0]],n=-t[0].shift-t[0].elem.depth,a=n,i=1;i0&&(o.push(kt(s,t)),s=[]),o.push(a[l]));s.length>0&&o.push(kt(s,t)),r?((i=kt(ft(r,t,!0))).classes=["tag"],o.push(i)):n&&o.push(n);var c=ct(["katex-html"],o);if(c.setAttribute("aria-hidden","true"),i){var m=i.children[0];m.style.height=F(c.height+c.depth),c.depth&&(m.style.verticalAlign=F(-c.depth))}return c}function Mt(e){return new A(e)}var zt=function(){function e(e,t,r){this.type=void 0,this.attributes=void 0,this.children=void 0,this.classes=void 0,this.type=e,this.attributes={},this.children=t||[],this.classes=r||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.getAttribute=function(e){return this.attributes[e]},t.toNode=function(){var e=document.createElementNS("http://www.w3.org/1998/Math/MathML",this.type);for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);this.classes.length>0&&(e.className=G(this.classes));for(var r=0;r0&&(e+=' class ="'+l.escape(G(this.classes))+'"'),e+=">";for(var r=0;r"},t.toText=function(){return this.children.map((function(e){return e.toText()})).join("")},e}(),At=function(){function e(e){this.text=void 0,this.text=e}var t=e.prototype;return t.toNode=function(){return document.createTextNode(this.text)},t.toMarkup=function(){return l.escape(this.toText())},t.toText=function(){return this.text},e}(),Tt={MathNode:zt,TextNode:At,SpaceNode:function(){function e(e){this.width=void 0,this.character=void 0,this.width=e,this.character=e>=.05555&&e<=.05556?"\u200a":e>=.1666&&e<=.1667?"\u2009":e>=.2222&&e<=.2223?"\u2005":e>=.2777&&e<=.2778?"\u2005\u200a":e>=-.05556&&e<=-.05555?"\u200a\u2063":e>=-.1667&&e<=-.1666?"\u2009\u2063":e>=-.2223&&e<=-.2222?"\u205f\u2063":e>=-.2778&&e<=-.2777?"\u2005\u2063":null}var t=e.prototype;return t.toNode=function(){if(this.character)return document.createTextNode(this.character);var e=document.createElementNS("http://www.w3.org/1998/Math/MathML","mspace");return e.setAttribute("width",F(this.width)),e},t.toMarkup=function(){return this.character?""+this.character+"":''},t.toText=function(){return this.character?this.character:" "},e}(),newDocumentFragment:Mt},Bt=function(e,t,r){return!ae[t][e]||!ae[t][e].replace||55349===e.charCodeAt(0)||we.hasOwnProperty(e)&&r&&(r.fontFamily&&"tt"===r.fontFamily.slice(4,6)||r.font&&"tt"===r.font.slice(4,6))||(e=ae[t][e].replace),new Tt.TextNode(e)},Ct=function(e){return 1===e.length?e[0]:new Tt.MathNode("mrow",e)},Nt=function(e,t){if("texttt"===t.fontFamily)return"monospace";if("textsf"===t.fontFamily)return"textit"===t.fontShape&&"textbf"===t.fontWeight?"sans-serif-bold-italic":"textit"===t.fontShape?"sans-serif-italic":"textbf"===t.fontWeight?"bold-sans-serif":"sans-serif";if("textit"===t.fontShape&&"textbf"===t.fontWeight)return"bold-italic";if("textit"===t.fontShape)return"italic";if("textbf"===t.fontWeight)return"bold";var r=t.font;if(!r||"mathnormal"===r)return null;var n=e.mode;if("mathit"===r)return"italic";if("boldsymbol"===r)return"textord"===e.type?"bold":"bold-italic";if("mathbf"===r)return"bold";if("mathbb"===r)return"double-struck";if("mathfrak"===r)return"fraktur";if("mathscr"===r||"mathcal"===r)return"script";if("mathsf"===r)return"sans-serif";if("mathtt"===r)return"monospace";var a=e.text;return l.contains(["\\imath","\\jmath"],a)?null:(ae[n][a]&&ae[n][a].replace&&(a=ae[n][a].replace),N(a,Ke.fontMap[r].fontName,n)?Ke.fontMap[r].variant:null)},qt=function(e,t,r){if(1===e.length){var n=Rt(e[0],t);return r&&n instanceof zt&&"mo"===n.type&&(n.setAttribute("lspace","0em"),n.setAttribute("rspace","0em")),[n]}for(var a,i=[],o=0;o0&&(p.text=p.text.slice(0,1)+"\u0338"+p.text.slice(1),i.pop())}}}i.push(s),a=s}return i},It=function(e,t,r){return Ct(qt(e,t,r))},Rt=function(e,t){if(!e)return new Tt.MathNode("mrow");if(it[e.type])return it[e.type](e,t);throw new n("Got group of unknown type: '"+e.type+"'")};function Ht(e,t,r,n,a){var i,o=qt(e,r);i=1===o.length&&o[0]instanceof zt&&l.contains(["mrow","mtable"],o[0].type)?o[0]:new Tt.MathNode("mrow",o);var s=new Tt.MathNode("annotation",[new Tt.TextNode(t)]);s.setAttribute("encoding","application/x-tex");var h=new Tt.MathNode("semantics",[i,s]),c=new Tt.MathNode("math",[h]);c.setAttribute("xmlns","http://www.w3.org/1998/Math/MathML"),n&&c.setAttribute("display","block");var m=a?"katex":"katex-mathml";return Ke.makeSpan([m],[c])}var Ot=function(e){return new E({style:e.displayMode?x.DISPLAY:x.TEXT,maxSize:e.maxSize,minRuleThickness:e.minRuleThickness})},Et=function(e,t){if(t.displayMode){var r=["katex-display"];t.leqno&&r.push("leqno"),t.fleqn&&r.push("fleqn"),e=Ke.makeSpan(r,[e])}return e},Lt=function(e,t,r){var n,a=Ot(r);if("mathml"===r.output)return Ht(e,t,a,r.displayMode,!0);if("html"===r.output){var i=St(e,a);n=Ke.makeSpan(["katex"],[i])}else{var o=Ht(e,t,a,r.displayMode,!1),s=St(e,a);n=Ke.makeSpan(["katex"],[o,s])}return Et(n,r)},Dt={widehat:"^",widecheck:"\u02c7",widetilde:"~",utilde:"~",overleftarrow:"\u2190",underleftarrow:"\u2190",xleftarrow:"\u2190",overrightarrow:"\u2192",underrightarrow:"\u2192",xrightarrow:"\u2192",underbrace:"\u23df",overbrace:"\u23de",overgroup:"\u23e0",undergroup:"\u23e1",overleftrightarrow:"\u2194",underleftrightarrow:"\u2194",xleftrightarrow:"\u2194",Overrightarrow:"\u21d2",xRightarrow:"\u21d2",overleftharpoon:"\u21bc",xleftharpoonup:"\u21bc",overrightharpoon:"\u21c0",xrightharpoonup:"\u21c0",xLeftarrow:"\u21d0",xLeftrightarrow:"\u21d4",xhookleftarrow:"\u21a9",xhookrightarrow:"\u21aa",xmapsto:"\u21a6",xrightharpoondown:"\u21c1",xleftharpoondown:"\u21bd",xrightleftharpoons:"\u21cc",xleftrightharpoons:"\u21cb",xtwoheadleftarrow:"\u219e",xtwoheadrightarrow:"\u21a0",xlongequal:"=",xtofrom:"\u21c4",xrightleftarrows:"\u21c4",xrightequilibrium:"\u21cc",xleftequilibrium:"\u21cb","\\cdrightarrow":"\u2192","\\cdleftarrow":"\u2190","\\cdlongequal":"="},Vt={overrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],overleftarrow:[["leftarrow"],.888,522,"xMinYMin"],underrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],underleftarrow:[["leftarrow"],.888,522,"xMinYMin"],xrightarrow:[["rightarrow"],1.469,522,"xMaxYMin"],"\\cdrightarrow":[["rightarrow"],3,522,"xMaxYMin"],xleftarrow:[["leftarrow"],1.469,522,"xMinYMin"],"\\cdleftarrow":[["leftarrow"],3,522,"xMinYMin"],Overrightarrow:[["doublerightarrow"],.888,560,"xMaxYMin"],xRightarrow:[["doublerightarrow"],1.526,560,"xMaxYMin"],xLeftarrow:[["doubleleftarrow"],1.526,560,"xMinYMin"],overleftharpoon:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoonup:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoondown:[["leftharpoondown"],.888,522,"xMinYMin"],overrightharpoon:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoonup:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoondown:[["rightharpoondown"],.888,522,"xMaxYMin"],xlongequal:[["longequal"],.888,334,"xMinYMin"],"\\cdlongequal":[["longequal"],3,334,"xMinYMin"],xtwoheadleftarrow:[["twoheadleftarrow"],.888,334,"xMinYMin"],xtwoheadrightarrow:[["twoheadrightarrow"],.888,334,"xMaxYMin"],overleftrightarrow:[["leftarrow","rightarrow"],.888,522],overbrace:[["leftbrace","midbrace","rightbrace"],1.6,548],underbrace:[["leftbraceunder","midbraceunder","rightbraceunder"],1.6,548],underleftrightarrow:[["leftarrow","rightarrow"],.888,522],xleftrightarrow:[["leftarrow","rightarrow"],1.75,522],xLeftrightarrow:[["doubleleftarrow","doublerightarrow"],1.75,560],xrightleftharpoons:[["leftharpoondownplus","rightharpoonplus"],1.75,716],xleftrightharpoons:[["leftharpoonplus","rightharpoondownplus"],1.75,716],xhookleftarrow:[["leftarrow","righthook"],1.08,522],xhookrightarrow:[["lefthook","rightarrow"],1.08,522],overlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],underlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],overgroup:[["leftgroup","rightgroup"],.888,342],undergroup:[["leftgroupunder","rightgroupunder"],.888,342],xmapsto:[["leftmapsto","rightarrow"],1.5,522],xtofrom:[["leftToFrom","rightToFrom"],1.75,528],xrightleftarrows:[["baraboveleftarrow","rightarrowabovebar"],1.75,901],xrightequilibrium:[["baraboveshortleftharpoon","rightharpoonaboveshortbar"],1.75,716],xleftequilibrium:[["shortbaraboveleftharpoon","shortrightharpoonabovebar"],1.75,716]},Pt=function(e,t,r,n,a){var i,o=e.height+e.depth+r+n;if(/fbox|color|angl/.test(t)){if(i=Ke.makeSpan(["stretchy",t],[],a),"fbox"===t){var s=a.color&&a.getColor();s&&(i.style.borderColor=s)}}else{var l=[];/^[bx]cancel$/.test(t)&&l.push(new Q({x1:"0",y1:"0",x2:"100%",y2:"100%","stroke-width":"0.046em"})),/^x?cancel$/.test(t)&&l.push(new Q({x1:"0",y1:"100%",x2:"100%",y2:"0","stroke-width":"0.046em"}));var h=new K(l,{width:"100%",height:F(o)});i=Ke.makeSvgSpan([],[h],a)}return i.height=o,i.style.height=F(o),i},Ft=function(e){var t=new Tt.MathNode("mo",[new Tt.TextNode(Dt[e.replace(/^\\/,"")])]);return t.setAttribute("stretchy","true"),t},Gt=function(e,t){var r=function(){var r=4e5,n=e.label.slice(1);if(l.contains(["widehat","widecheck","widetilde","utilde"],n)){var a,i,o,s="ordgroup"===(d=e.base).type?d.body.length:1;if(s>5)"widehat"===n||"widecheck"===n?(a=420,r=2364,o=.42,i=n+"4"):(a=312,r=2340,o=.34,i="tilde4");else{var h=[1,1,2,2,3,3][s];"widehat"===n||"widecheck"===n?(r=[0,1062,2364,2364,2364][h],a=[0,239,300,360,420][h],o=[0,.24,.3,.3,.36,.42][h],i=n+h):(r=[0,600,1033,2339,2340][h],a=[0,260,286,306,312][h],o=[0,.26,.286,.3,.306,.34][h],i="tilde"+h)}var c=new J(i),m=new K([c],{width:"100%",height:F(o),viewBox:"0 0 "+r+" "+a,preserveAspectRatio:"none"});return{span:Ke.makeSvgSpan([],[m],t),minWidth:0,height:o}}var u,p,d,f=[],g=Vt[n],v=g[0],b=g[1],y=g[2],x=y/1e3,w=v.length;if(1===w)u=["hide-tail"],p=[g[3]];else if(2===w)u=["halfarrow-left","halfarrow-right"],p=["xMinYMin","xMaxYMin"];else{if(3!==w)throw new Error("Correct katexImagesData or update code here to support\n "+w+" children.");u=["brace-left","brace-center","brace-right"],p=["xMinYMin","xMidYMin","xMaxYMin"]}for(var k=0;k0&&(n.style.minWidth=F(a)),n};function Ut(e,t){if(!e||e.type!==t)throw new Error("Expected node of type "+t+", but got "+(e?"node of type "+e.type:String(e)));return e}function Yt(e){var t=Xt(e);if(!t)throw new Error("Expected node of symbol group type, but got "+(e?"node of type "+e.type:String(e)));return t}function Xt(e){return e&&("atom"===e.type||re.hasOwnProperty(e.type))?e:null}var Wt=function(e,t){var r,n,a;e&&"supsub"===e.type?(r=(n=Ut(e.base,"accent")).base,e.base=r,a=function(e){if(e instanceof W)return e;throw new Error("Expected span but got "+String(e)+".")}(wt(e,t)),e.base=n):r=(n=Ut(e,"accent")).base;var i=wt(r,t.havingCrampedStyle()),o=0;if(n.isShifty&&l.isCharacterBox(r)){var s=l.getBaseElem(r);o=ee(wt(s,t.havingCrampedStyle())).skew}var h,c="\\c"===n.label,m=c?i.height+i.depth:Math.min(i.height,t.fontMetrics().xHeight);if(n.isStretchy)h=Gt(n,t),h=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"elem",elem:h,wrapperClasses:["svg-align"],wrapperStyle:o>0?{width:"calc(100% - "+F(2*o)+")",marginLeft:F(2*o)}:void 0}]},t);else{var u,p;"\\vec"===n.label?(u=Ke.staticSvg("vec",t),p=Ke.svgData.vec[1]):((u=ee(u=Ke.makeOrd({mode:n.mode,text:n.label},t,"textord"))).italic=0,p=u.width,c&&(m+=u.depth)),h=Ke.makeSpan(["accent-body"],[u]);var d="\\textcircled"===n.label;d&&(h.classes.push("accent-full"),m=i.height);var f=o;d||(f-=p/2),h.style.left=F(f),"\\textcircled"===n.label&&(h.style.top=".2em"),h=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"kern",size:-m},{type:"elem",elem:h}]},t)}var g=Ke.makeSpan(["mord","accent"],[h],t);return a?(a.children[0]=g,a.height=Math.max(g.height,a.height),a.classes[0]="mord",a):g},_t=function(e,t){var r=e.isStretchy?Ft(e.label):new Tt.MathNode("mo",[Bt(e.label,e.mode)]),n=new Tt.MathNode("mover",[Rt(e.base,t),r]);return n.setAttribute("accent","true"),n},jt=new RegExp(["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring"].map((function(e){return"\\"+e})).join("|"));ot({type:"accent",names:["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring","\\widecheck","\\widehat","\\widetilde","\\overrightarrow","\\overleftarrow","\\Overrightarrow","\\overleftrightarrow","\\overgroup","\\overlinesegment","\\overleftharpoon","\\overrightharpoon"],props:{numArgs:1},handler:function(e,t){var r=lt(t[0]),n=!jt.test(e.funcName),a=!n||"\\widehat"===e.funcName||"\\widetilde"===e.funcName||"\\widecheck"===e.funcName;return{type:"accent",mode:e.parser.mode,label:e.funcName,isStretchy:n,isShifty:a,base:r}},htmlBuilder:Wt,mathmlBuilder:_t}),ot({type:"accent",names:["\\'","\\`","\\^","\\~","\\=","\\u","\\.",'\\"',"\\c","\\r","\\H","\\v","\\textcircled"],props:{numArgs:1,allowedInText:!0,allowedInMath:!0,argTypes:["primitive"]},handler:function(e,t){var r=t[0],n=e.parser.mode;return"math"===n&&(e.parser.settings.reportNonstrict("mathVsTextAccents","LaTeX's accent "+e.funcName+" works only in text mode"),n="text"),{type:"accent",mode:n,label:e.funcName,isStretchy:!1,isShifty:!0,base:r}},htmlBuilder:Wt,mathmlBuilder:_t}),ot({type:"accentUnder",names:["\\underleftarrow","\\underrightarrow","\\underleftrightarrow","\\undergroup","\\underlinesegment","\\utilde"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"accentUnder",mode:r.mode,label:n,base:a}},htmlBuilder:function(e,t){var r=wt(e.base,t),n=Gt(e,t),a="\\utilde"===e.label?.12:0,i=Ke.makeVList({positionType:"top",positionData:r.height,children:[{type:"elem",elem:n,wrapperClasses:["svg-align"]},{type:"kern",size:a},{type:"elem",elem:r}]},t);return Ke.makeSpan(["mord","accentunder"],[i],t)},mathmlBuilder:function(e,t){var r=Ft(e.label),n=new Tt.MathNode("munder",[Rt(e.base,t),r]);return n.setAttribute("accentunder","true"),n}});var $t=function(e){var t=new Tt.MathNode("mpadded",e?[e]:[]);return t.setAttribute("width","+0.6em"),t.setAttribute("lspace","0.3em"),t};ot({type:"xArrow",names:["\\xleftarrow","\\xrightarrow","\\xLeftarrow","\\xRightarrow","\\xleftrightarrow","\\xLeftrightarrow","\\xhookleftarrow","\\xhookrightarrow","\\xmapsto","\\xrightharpoondown","\\xrightharpoonup","\\xleftharpoondown","\\xleftharpoonup","\\xrightleftharpoons","\\xleftrightharpoons","\\xlongequal","\\xtwoheadrightarrow","\\xtwoheadleftarrow","\\xtofrom","\\xrightleftarrows","\\xrightequilibrium","\\xleftequilibrium","\\\\cdrightarrow","\\\\cdleftarrow","\\\\cdlongequal"],props:{numArgs:1,numOptionalArgs:1},handler:function(e,t,r){var n=e.parser,a=e.funcName;return{type:"xArrow",mode:n.mode,label:a,body:t[0],below:r[0]}},htmlBuilder:function(e,t){var r,n=t.style,a=t.havingStyle(n.sup()),i=Ke.wrapFragment(wt(e.body,a,t),t),o="\\x"===e.label.slice(0,2)?"x":"cd";i.classes.push(o+"-arrow-pad"),e.below&&(a=t.havingStyle(n.sub()),(r=Ke.wrapFragment(wt(e.below,a,t),t)).classes.push(o+"-arrow-pad"));var s,l=Gt(e,t),h=-t.fontMetrics().axisHeight+.5*l.height,c=-t.fontMetrics().axisHeight-.5*l.height-.111;if((i.depth>.25||"\\xleftequilibrium"===e.label)&&(c-=i.depth),r){var m=-t.fontMetrics().axisHeight+r.height+.5*l.height+.111;s=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:c},{type:"elem",elem:l,shift:h},{type:"elem",elem:r,shift:m}]},t)}else s=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:c},{type:"elem",elem:l,shift:h}]},t);return s.children[0].children[0].children[1].classes.push("svg-align"),Ke.makeSpan(["mrel","x-arrow"],[s],t)},mathmlBuilder:function(e,t){var r,n=Ft(e.label);if(n.setAttribute("minsize","x"===e.label.charAt(0)?"1.75em":"3.0em"),e.body){var a=$t(Rt(e.body,t));if(e.below){var i=$t(Rt(e.below,t));r=new Tt.MathNode("munderover",[n,i,a])}else r=new Tt.MathNode("mover",[n,a])}else if(e.below){var o=$t(Rt(e.below,t));r=new Tt.MathNode("munder",[n,o])}else r=$t(),r=new Tt.MathNode("mover",[n,r]);return r}});var Zt=Ke.makeSpan;function Kt(e,t){var r=ft(e.body,t,!0);return Zt([e.mclass],r,t)}function Jt(e,t){var r,n=qt(e.body,t);return"minner"===e.mclass?r=new Tt.MathNode("mpadded",n):"mord"===e.mclass?e.isCharacterBox?(r=n[0]).type="mi":r=new Tt.MathNode("mi",n):(e.isCharacterBox?(r=n[0]).type="mo":r=new Tt.MathNode("mo",n),"mbin"===e.mclass?(r.attributes.lspace="0.22em",r.attributes.rspace="0.22em"):"mpunct"===e.mclass?(r.attributes.lspace="0em",r.attributes.rspace="0.17em"):"mopen"===e.mclass||"mclose"===e.mclass?(r.attributes.lspace="0em",r.attributes.rspace="0em"):"minner"===e.mclass&&(r.attributes.lspace="0.0556em",r.attributes.width="+0.1111em")),r}ot({type:"mclass",names:["\\mathord","\\mathbin","\\mathrel","\\mathopen","\\mathclose","\\mathpunct","\\mathinner"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"mclass",mode:r.mode,mclass:"m"+n.slice(5),body:ht(a),isCharacterBox:l.isCharacterBox(a)}},htmlBuilder:Kt,mathmlBuilder:Jt});var Qt=function(e){var t="ordgroup"===e.type&&e.body.length?e.body[0]:e;return"atom"!==t.type||"bin"!==t.family&&"rel"!==t.family?"mord":"m"+t.family};ot({type:"mclass",names:["\\@binrel"],props:{numArgs:2},handler:function(e,t){return{type:"mclass",mode:e.parser.mode,mclass:Qt(t[0]),body:ht(t[1]),isCharacterBox:l.isCharacterBox(t[1])}}}),ot({type:"mclass",names:["\\stackrel","\\overset","\\underset"],props:{numArgs:2},handler:function(e,t){var r,n=e.parser,a=e.funcName,i=t[1],o=t[0];r="\\stackrel"!==a?Qt(i):"mrel";var s={type:"op",mode:i.mode,limits:!0,alwaysHandleSupSub:!0,parentIsSupSub:!1,symbol:!1,suppressBaseShift:"\\stackrel"!==a,body:ht(i)},h={type:"supsub",mode:o.mode,base:s,sup:"\\underset"===a?null:o,sub:"\\underset"===a?o:null};return{type:"mclass",mode:n.mode,mclass:r,body:[h],isCharacterBox:l.isCharacterBox(h)}},htmlBuilder:Kt,mathmlBuilder:Jt}),ot({type:"pmb",names:["\\pmb"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){return{type:"pmb",mode:e.parser.mode,mclass:Qt(t[0]),body:ht(t[0])}},htmlBuilder:function(e,t){var r=ft(e.body,t,!0),n=Ke.makeSpan([e.mclass],r,t);return n.style.textShadow="0.02em 0.01em 0.04px",n},mathmlBuilder:function(e,t){var r=qt(e.body,t),n=new Tt.MathNode("mstyle",r);return n.setAttribute("style","text-shadow: 0.02em 0.01em 0.04px"),n}});var er={">":"\\\\cdrightarrow","<":"\\\\cdleftarrow","=":"\\\\cdlongequal",A:"\\uparrow",V:"\\downarrow","|":"\\Vert",".":"no arrow"},tr=function(e){return"textord"===e.type&&"@"===e.text};function rr(e,t,r){var n=er[e];switch(n){case"\\\\cdrightarrow":case"\\\\cdleftarrow":return r.callFunction(n,[t[0]],[t[1]]);case"\\uparrow":case"\\downarrow":var a={type:"atom",text:n,mode:"math",family:"rel"},i={type:"ordgroup",mode:"math",body:[r.callFunction("\\\\cdleft",[t[0]],[]),r.callFunction("\\Big",[a],[]),r.callFunction("\\\\cdright",[t[1]],[])]};return r.callFunction("\\\\cdparent",[i],[]);case"\\\\cdlongequal":return r.callFunction("\\\\cdlongequal",[],[]);case"\\Vert":return r.callFunction("\\Big",[{type:"textord",text:"\\Vert",mode:"math"}],[]);default:return{type:"textord",text:" ",mode:"math"}}}ot({type:"cdlabel",names:["\\\\cdleft","\\\\cdright"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"cdlabel",mode:r.mode,side:n.slice(4),label:t[0]}},htmlBuilder:function(e,t){var r=t.havingStyle(t.style.sup()),n=Ke.wrapFragment(wt(e.label,r,t),t);return n.classes.push("cd-label-"+e.side),n.style.bottom=F(.8-n.depth),n.height=0,n.depth=0,n},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mrow",[Rt(e.label,t)]);return(r=new Tt.MathNode("mpadded",[r])).setAttribute("width","0"),"left"===e.side&&r.setAttribute("lspace","-1width"),r.setAttribute("voffset","0.7em"),(r=new Tt.MathNode("mstyle",[r])).setAttribute("displaystyle","false"),r.setAttribute("scriptlevel","1"),r}}),ot({type:"cdlabelparent",names:["\\\\cdparent"],props:{numArgs:1},handler:function(e,t){return{type:"cdlabelparent",mode:e.parser.mode,fragment:t[0]}},htmlBuilder:function(e,t){var r=Ke.wrapFragment(wt(e.fragment,t),t);return r.classes.push("cd-vert-arrow"),r},mathmlBuilder:function(e,t){return new Tt.MathNode("mrow",[Rt(e.fragment,t)])}}),ot({type:"textord",names:["\\@char"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){for(var r=e.parser,a=Ut(t[0],"ordgroup").body,i="",o=0;o=1114111)throw new n("\\@char with invalid code point "+i);return l<=65535?s=String.fromCharCode(l):(l-=65536,s=String.fromCharCode(55296+(l>>10),56320+(1023&l))),{type:"textord",mode:r.mode,text:s}}});var nr=function(e,t){var r=ft(e.body,t.withColor(e.color),!1);return Ke.makeFragment(r)},ar=function(e,t){var r=qt(e.body,t.withColor(e.color)),n=new Tt.MathNode("mstyle",r);return n.setAttribute("mathcolor",e.color),n};ot({type:"color",names:["\\textcolor"],props:{numArgs:2,allowedInText:!0,argTypes:["color","original"]},handler:function(e,t){var r=e.parser,n=Ut(t[0],"color-token").color,a=t[1];return{type:"color",mode:r.mode,color:n,body:ht(a)}},htmlBuilder:nr,mathmlBuilder:ar}),ot({type:"color",names:["\\color"],props:{numArgs:1,allowedInText:!0,argTypes:["color"]},handler:function(e,t){var r=e.parser,n=e.breakOnTokenText,a=Ut(t[0],"color-token").color;r.gullet.macros.set("\\current@color",a);var i=r.parseExpression(!0,n);return{type:"color",mode:r.mode,color:a,body:i}},htmlBuilder:nr,mathmlBuilder:ar}),ot({type:"cr",names:["\\\\"],props:{numArgs:0,numOptionalArgs:0,allowedInText:!0},handler:function(e,t,r){var n=e.parser,a="["===n.gullet.future().text?n.parseSizeGroup(!0):null,i=!n.settings.displayMode||!n.settings.useStrictBehavior("newLineInDisplayMode","In LaTeX, \\\\ or \\newline does nothing in display mode");return{type:"cr",mode:n.mode,newLine:i,size:a&&Ut(a,"size").value}},htmlBuilder:function(e,t){var r=Ke.makeSpan(["mspace"],[],t);return e.newLine&&(r.classes.push("newline"),e.size&&(r.style.marginTop=F(P(e.size,t)))),r},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mspace");return e.newLine&&(r.setAttribute("linebreak","newline"),e.size&&r.setAttribute("height",F(P(e.size,t)))),r}});var ir={"\\global":"\\global","\\long":"\\\\globallong","\\\\globallong":"\\\\globallong","\\def":"\\gdef","\\gdef":"\\gdef","\\edef":"\\xdef","\\xdef":"\\xdef","\\let":"\\\\globallet","\\futurelet":"\\\\globalfuture"},or=function(e){var t=e.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(t))throw new n("Expected a control sequence",e);return t},sr=function(e,t,r,n){var a=e.gullet.macros.get(r.text);null==a&&(r.noexpand=!0,a={tokens:[r],numArgs:0,unexpandable:!e.gullet.isExpandable(r.text)}),e.gullet.macros.set(t,a,n)};ot({type:"internal",names:["\\global","\\long","\\\\globallong"],props:{numArgs:0,allowedInText:!0},handler:function(e){var t=e.parser,r=e.funcName;t.consumeSpaces();var a=t.fetch();if(ir[a.text])return"\\global"!==r&&"\\\\globallong"!==r||(a.text=ir[a.text]),Ut(t.parseFunction(),"internal");throw new n("Invalid token after macro prefix",a)}}),ot({type:"internal",names:["\\def","\\gdef","\\edef","\\xdef"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,a=t.gullet.popToken(),i=a.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(i))throw new n("Expected a control sequence",a);for(var o,s=0,l=[[]];"{"!==t.gullet.future().text;)if("#"===(a=t.gullet.popToken()).text){if("{"===t.gullet.future().text){o=t.gullet.future(),l[s].push("{");break}if(a=t.gullet.popToken(),!/^[1-9]$/.test(a.text))throw new n('Invalid argument number "'+a.text+'"');if(parseInt(a.text)!==s+1)throw new n('Argument number "'+a.text+'" out of order');s++,l.push([])}else{if("EOF"===a.text)throw new n("Expected a macro definition");l[s].push(a.text)}var h=t.gullet.consumeArg().tokens;return o&&h.unshift(o),"\\edef"!==r&&"\\xdef"!==r||(h=t.gullet.expandTokens(h)).reverse(),t.gullet.macros.set(i,{tokens:h,numArgs:s,delimiters:l},r===ir[r]),{type:"internal",mode:t.mode}}}),ot({type:"internal",names:["\\let","\\\\globallet"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,n=or(t.gullet.popToken());t.gullet.consumeSpaces();var a=function(e){var t=e.gullet.popToken();return"="===t.text&&" "===(t=e.gullet.popToken()).text&&(t=e.gullet.popToken()),t}(t);return sr(t,n,a,"\\\\globallet"===r),{type:"internal",mode:t.mode}}}),ot({type:"internal",names:["\\futurelet","\\\\globalfuture"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,n=or(t.gullet.popToken()),a=t.gullet.popToken(),i=t.gullet.popToken();return sr(t,n,i,"\\\\globalfuture"===r),t.gullet.pushToken(i),t.gullet.pushToken(a),{type:"internal",mode:t.mode}}});var lr=function(e,t,r){var n=N(ae.math[e]&&ae.math[e].replace||e,t,r);if(!n)throw new Error("Unsupported symbol "+e+" and font size "+t+".");return n},hr=function(e,t,r,n){var a=r.havingBaseStyle(t),i=Ke.makeSpan(n.concat(a.sizingClasses(r)),[e],r),o=a.sizeMultiplier/r.sizeMultiplier;return i.height*=o,i.depth*=o,i.maxFontSize=a.sizeMultiplier,i},cr=function(e,t,r){var n=t.havingBaseStyle(r),a=(1-t.sizeMultiplier/n.sizeMultiplier)*t.fontMetrics().axisHeight;e.classes.push("delimcenter"),e.style.top=F(a),e.height-=a,e.depth+=a},mr=function(e,t,r,n,a,i){var o=function(e,t,r,n){return Ke.makeSymbol(e,"Size"+t+"-Regular",r,n)}(e,t,a,n),s=hr(Ke.makeSpan(["delimsizing","size"+t],[o],n),x.TEXT,n,i);return r&&cr(s,n,x.TEXT),s},ur=function(e,t,r){var n;return n="Size1-Regular"===t?"delim-size1":"delim-size4",{type:"elem",elem:Ke.makeSpan(["delimsizinginner",n],[Ke.makeSpan([],[Ke.makeSymbol(e,t,r)])])}},pr=function(e,t,r){var n=T["Size4-Regular"][e.charCodeAt(0)]?T["Size4-Regular"][e.charCodeAt(0)][4]:T["Size1-Regular"][e.charCodeAt(0)][4],a=new J("inner",function(e,t){switch(e){case"\u239c":return"M291 0 H417 V"+t+" H291z M291 0 H417 V"+t+" H291z";case"\u2223":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145z";case"\u2225":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145zM367 0 H410 V"+t+" H367z M367 0 H410 V"+t+" H367z";case"\u239f":return"M457 0 H583 V"+t+" H457z M457 0 H583 V"+t+" H457z";case"\u23a2":return"M319 0 H403 V"+t+" H319z M319 0 H403 V"+t+" H319z";case"\u23a5":return"M263 0 H347 V"+t+" H263z M263 0 H347 V"+t+" H263z";case"\u23aa":return"M384 0 H504 V"+t+" H384z M384 0 H504 V"+t+" H384z";case"\u23d0":return"M312 0 H355 V"+t+" H312z M312 0 H355 V"+t+" H312z";case"\u2016":return"M257 0 H300 V"+t+" H257z M257 0 H300 V"+t+" H257zM478 0 H521 V"+t+" H478z M478 0 H521 V"+t+" H478z";default:return""}}(e,Math.round(1e3*t))),i=new K([a],{width:F(n),height:F(t),style:"width:"+F(n),viewBox:"0 0 "+1e3*n+" "+Math.round(1e3*t),preserveAspectRatio:"xMinYMin"}),o=Ke.makeSvgSpan([],[i],r);return o.height=t,o.style.height=F(t),o.style.width=F(n),{type:"elem",elem:o}},dr={type:"kern",size:-.008},fr=["|","\\lvert","\\rvert","\\vert"],gr=["\\|","\\lVert","\\rVert","\\Vert"],vr=function(e,t,r,n,a,i){var o,s,h,c,m="",u=0;o=h=c=e,s=null;var p="Size1-Regular";"\\uparrow"===e?h=c="\u23d0":"\\Uparrow"===e?h=c="\u2016":"\\downarrow"===e?o=h="\u23d0":"\\Downarrow"===e?o=h="\u2016":"\\updownarrow"===e?(o="\\uparrow",h="\u23d0",c="\\downarrow"):"\\Updownarrow"===e?(o="\\Uparrow",h="\u2016",c="\\Downarrow"):l.contains(fr,e)?(h="\u2223",m="vert",u=333):l.contains(gr,e)?(h="\u2225",m="doublevert",u=556):"["===e||"\\lbrack"===e?(o="\u23a1",h="\u23a2",c="\u23a3",p="Size4-Regular",m="lbrack",u=667):"]"===e||"\\rbrack"===e?(o="\u23a4",h="\u23a5",c="\u23a6",p="Size4-Regular",m="rbrack",u=667):"\\lfloor"===e||"\u230a"===e?(h=o="\u23a2",c="\u23a3",p="Size4-Regular",m="lfloor",u=667):"\\lceil"===e||"\u2308"===e?(o="\u23a1",h=c="\u23a2",p="Size4-Regular",m="lceil",u=667):"\\rfloor"===e||"\u230b"===e?(h=o="\u23a5",c="\u23a6",p="Size4-Regular",m="rfloor",u=667):"\\rceil"===e||"\u2309"===e?(o="\u23a4",h=c="\u23a5",p="Size4-Regular",m="rceil",u=667):"("===e||"\\lparen"===e?(o="\u239b",h="\u239c",c="\u239d",p="Size4-Regular",m="lparen",u=875):")"===e||"\\rparen"===e?(o="\u239e",h="\u239f",c="\u23a0",p="Size4-Regular",m="rparen",u=875):"\\{"===e||"\\lbrace"===e?(o="\u23a7",s="\u23a8",c="\u23a9",h="\u23aa",p="Size4-Regular"):"\\}"===e||"\\rbrace"===e?(o="\u23ab",s="\u23ac",c="\u23ad",h="\u23aa",p="Size4-Regular"):"\\lgroup"===e||"\u27ee"===e?(o="\u23a7",c="\u23a9",h="\u23aa",p="Size4-Regular"):"\\rgroup"===e||"\u27ef"===e?(o="\u23ab",c="\u23ad",h="\u23aa",p="Size4-Regular"):"\\lmoustache"===e||"\u23b0"===e?(o="\u23a7",c="\u23ad",h="\u23aa",p="Size4-Regular"):"\\rmoustache"!==e&&"\u23b1"!==e||(o="\u23ab",c="\u23a9",h="\u23aa",p="Size4-Regular");var d=lr(o,p,a),f=d.height+d.depth,g=lr(h,p,a),v=g.height+g.depth,b=lr(c,p,a),y=b.height+b.depth,w=0,k=1;if(null!==s){var S=lr(s,p,a);w=S.height+S.depth,k=2}var M=f+y+w,z=M+Math.max(0,Math.ceil((t-M)/(k*v)))*k*v,A=n.fontMetrics().axisHeight;r&&(A*=n.sizeMultiplier);var T=z/2-A,B=[];if(m.length>0){var C=z-f-y,N=Math.round(1e3*z),q=function(e,t){switch(e){case"lbrack":return"M403 1759 V84 H666 V0 H319 V1759 v"+t+" v1759 h347 v-84\nH403z M403 1759 V0 H319 V1759 v"+t+" v1759 h84z";case"rbrack":return"M347 1759 V0 H0 V84 H263 V1759 v"+t+" v1759 H0 v84 H347z\nM347 1759 V0 H263 V1759 v"+t+" v1759 h84z";case"vert":return"M145 15 v585 v"+t+" v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v"+-t+" v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v"+t+" v585 h43z";case"doublevert":return"M145 15 v585 v"+t+" v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v"+-t+" v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M188 15 H145 v585 v"+t+" v585 h43z\nM367 15 v585 v"+t+" v585 c2.667,10,9.667,15,21,15\nc10,0,16.667,-5,20,-15 v-585 v"+-t+" v-585 c-2.667,-10,-9.667,-15,-21,-15\nc-10,0,-16.667,5,-20,15z M410 15 H367 v585 v"+t+" v585 h43z";case"lfloor":return"M319 602 V0 H403 V602 v"+t+" v1715 h263 v84 H319z\nMM319 602 V0 H403 V602 v"+t+" v1715 H319z";case"rfloor":return"M319 602 V0 H403 V602 v"+t+" v1799 H0 v-84 H319z\nMM319 602 V0 H403 V602 v"+t+" v1715 H319z";case"lceil":return"M403 1759 V84 H666 V0 H319 V1759 v"+t+" v602 h84z\nM403 1759 V0 H319 V1759 v"+t+" v602 h84z";case"rceil":return"M347 1759 V0 H0 V84 H263 V1759 v"+t+" v602 h84z\nM347 1759 V0 h-84 V1759 v"+t+" v602 h84z";case"lparen":return"M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1\nc-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349,\n-36,557 l0,"+(t+84)+"c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210,\n949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9\nc0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5,\n-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189\nl0,-"+(t+92)+"c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3,\n-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z";case"rparen":return"M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3,\n63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5\nc11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0,"+(t+9)+"\nc-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664\nc-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11\nc0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17\nc242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558\nl0,-"+(t+144)+"c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7,\n-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z";default:throw new Error("Unknown stretchy delimiter.")}}(m,Math.round(1e3*C)),I=new J(m,q),R=(u/1e3).toFixed(3)+"em",H=(N/1e3).toFixed(3)+"em",O=new K([I],{width:R,height:H,viewBox:"0 0 "+u+" "+N}),E=Ke.makeSvgSpan([],[O],n);E.height=N/1e3,E.style.width=R,E.style.height=H,B.push({type:"elem",elem:E})}else{if(B.push(ur(c,p,a)),B.push(dr),null===s){var L=z-f-y+.016;B.push(pr(h,L,n))}else{var D=(z-f-y-w)/2+.016;B.push(pr(h,D,n)),B.push(dr),B.push(ur(s,p,a)),B.push(dr),B.push(pr(h,D,n))}B.push(dr),B.push(ur(o,p,a))}var V=n.havingBaseStyle(x.TEXT),P=Ke.makeVList({positionType:"bottom",positionData:T,children:B},V);return hr(Ke.makeSpan(["delimsizing","mult"],[P],V),x.TEXT,n,i)},br=.08,yr=function(e,t,r,n,a){var i=function(e,t,r){t*=1e3;var n="";switch(e){case"sqrtMain":n=function(e,t){return"M95,"+(622+e+t)+"\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl"+e/2.075+" -"+e+"\nc5.3,-9.3,12,-14,20,-14\nH400000v"+(40+e)+"H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM"+(834+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize1":n=function(e,t){return"M263,"+(601+e+t)+"c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl"+e/2.084+" -"+e+"\nc4.7,-7.3,11,-11,19,-11\nH40000v"+(40+e)+"H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM"+(1001+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize2":n=function(e,t){return"M983 "+(10+e+t)+"\nl"+e/3.13+" -"+e+"\nc4,-6.7,10,-10,18,-10 H400000v"+(40+e)+"\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM"+(1001+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize3":n=function(e,t){return"M424,"+(2398+e+t)+"\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl"+e/4.223+" -"+e+"c4,-6.7,10,-10,18,-10 H400000\nv"+(40+e)+"H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M"+(1001+e)+" "+t+"\nh400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize4":n=function(e,t){return"M473,"+(2713+e+t)+"\nc339.3,-1799.3,509.3,-2700,510,-2702 l"+e/5.298+" -"+e+"\nc3.3,-7.3,9.3,-11,18,-11 H400000v"+(40+e)+"H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM"+(1001+e)+" "+t+"h400000v"+(40+e)+"H1017.7z"}(t,M);break;case"sqrtTall":n=function(e,t,r){return"M702 "+(e+t)+"H400000"+(40+e)+"\nH742v"+(r-54-t-e)+"l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 "+t+"H400000v"+(40+e)+"H742z"}(t,M,r)}return n}(e,n,r),o=new J(e,i),s=new K([o],{width:"400em",height:F(t),viewBox:"0 0 400000 "+r,preserveAspectRatio:"xMinYMin slice"});return Ke.makeSvgSpan(["hide-tail"],[s],a)},xr=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\u230a","\u230b","\\lceil","\\rceil","\u2308","\u2309","\\surd"],wr=["\\uparrow","\\downarrow","\\updownarrow","\\Uparrow","\\Downarrow","\\Updownarrow","|","\\|","\\vert","\\Vert","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\u27ee","\u27ef","\\lmoustache","\\rmoustache","\u23b0","\u23b1"],kr=["<",">","\\langle","\\rangle","/","\\backslash","\\lt","\\gt"],Sr=[0,1.2,1.8,2.4,3],Mr=[{type:"small",style:x.SCRIPTSCRIPT},{type:"small",style:x.SCRIPT},{type:"small",style:x.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4}],zr=[{type:"small",style:x.SCRIPTSCRIPT},{type:"small",style:x.SCRIPT},{type:"small",style:x.TEXT},{type:"stack"}],Ar=[{type:"small",style:x.SCRIPTSCRIPT},{type:"small",style:x.SCRIPT},{type:"small",style:x.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4},{type:"stack"}],Tr=function(e){if("small"===e.type)return"Main-Regular";if("large"===e.type)return"Size"+e.size+"-Regular";if("stack"===e.type)return"Size4-Regular";throw new Error("Add support for delim type '"+e.type+"' here.")},Br=function(e,t,r,n){for(var a=Math.min(2,3-n.style.size);at)return r[a]}return r[r.length-1]},Cr=function(e,t,r,n,a,i){var o;"<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),o=l.contains(kr,e)?Mr:l.contains(xr,e)?Ar:zr;var s=Br(e,t,o,n);return"small"===s.type?function(e,t,r,n,a,i){var o=Ke.makeSymbol(e,"Main-Regular",a,n),s=hr(o,t,n,i);return r&&cr(s,n,t),s}(e,s.style,r,n,a,i):"large"===s.type?mr(e,s.size,r,n,a,i):vr(e,t,r,n,a,i)},Nr={sqrtImage:function(e,t){var r,n,a=t.havingBaseSizing(),i=Br("\\surd",e*a.sizeMultiplier,Ar,a),o=a.sizeMultiplier,s=Math.max(0,t.minRuleThickness-t.fontMetrics().sqrtRuleThickness),l=0,h=0,c=0;return"small"===i.type?(e<1?o=1:e<1.4&&(o=.7),h=(1+s)/o,(r=yr("sqrtMain",l=(1+s+br)/o,c=1e3+1e3*s+80,s,t)).style.minWidth="0.853em",n=.833/o):"large"===i.type?(c=1080*Sr[i.size],h=(Sr[i.size]+s)/o,l=(Sr[i.size]+s+br)/o,(r=yr("sqrtSize"+i.size,l,c,s,t)).style.minWidth="1.02em",n=1/o):(l=e+s+br,h=e+s,c=Math.floor(1e3*e+s)+80,(r=yr("sqrtTall",l,c,s,t)).style.minWidth="0.742em",n=1.056),r.height=h,r.style.height=F(l),{span:r,advanceWidth:n,ruleWidth:(t.fontMetrics().sqrtRuleThickness+s)*o}},sizedDelim:function(e,t,r,a,i){if("<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),l.contains(xr,e)||l.contains(kr,e))return mr(e,t,!1,r,a,i);if(l.contains(wr,e))return vr(e,Sr[t],!1,r,a,i);throw new n("Illegal delimiter: '"+e+"'")},sizeToMaxHeight:Sr,customSizedDelim:Cr,leftRightDelim:function(e,t,r,n,a,i){var o=n.fontMetrics().axisHeight*n.sizeMultiplier,s=5/n.fontMetrics().ptPerEm,l=Math.max(t-o,r+o),h=Math.max(l/500*901,2*l-s);return Cr(e,h,!0,n,a,i)}},qr={"\\bigl":{mclass:"mopen",size:1},"\\Bigl":{mclass:"mopen",size:2},"\\biggl":{mclass:"mopen",size:3},"\\Biggl":{mclass:"mopen",size:4},"\\bigr":{mclass:"mclose",size:1},"\\Bigr":{mclass:"mclose",size:2},"\\biggr":{mclass:"mclose",size:3},"\\Biggr":{mclass:"mclose",size:4},"\\bigm":{mclass:"mrel",size:1},"\\Bigm":{mclass:"mrel",size:2},"\\biggm":{mclass:"mrel",size:3},"\\Biggm":{mclass:"mrel",size:4},"\\big":{mclass:"mord",size:1},"\\Big":{mclass:"mord",size:2},"\\bigg":{mclass:"mord",size:3},"\\Bigg":{mclass:"mord",size:4}},Ir=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\u230a","\u230b","\\lceil","\\rceil","\u2308","\u2309","<",">","\\langle","\u27e8","\\rangle","\u27e9","\\lt","\\gt","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\u27ee","\u27ef","\\lmoustache","\\rmoustache","\u23b0","\u23b1","/","\\backslash","|","\\vert","\\|","\\Vert","\\uparrow","\\Uparrow","\\downarrow","\\Downarrow","\\updownarrow","\\Updownarrow","."];function Rr(e,t){var r=Xt(e);if(r&&l.contains(Ir,r.text))return r;throw new n(r?"Invalid delimiter '"+r.text+"' after '"+t.funcName+"'":"Invalid delimiter type '"+e.type+"'",e)}function Hr(e){if(!e.body)throw new Error("Bug: The leftright ParseNode wasn't fully parsed.")}ot({type:"delimsizing",names:["\\bigl","\\Bigl","\\biggl","\\Biggl","\\bigr","\\Bigr","\\biggr","\\Biggr","\\bigm","\\Bigm","\\biggm","\\Biggm","\\big","\\Big","\\bigg","\\Bigg"],props:{numArgs:1,argTypes:["primitive"]},handler:function(e,t){var r=Rr(t[0],e);return{type:"delimsizing",mode:e.parser.mode,size:qr[e.funcName].size,mclass:qr[e.funcName].mclass,delim:r.text}},htmlBuilder:function(e,t){return"."===e.delim?Ke.makeSpan([e.mclass]):Nr.sizedDelim(e.delim,e.size,t,e.mode,[e.mclass])},mathmlBuilder:function(e){var t=[];"."!==e.delim&&t.push(Bt(e.delim,e.mode));var r=new Tt.MathNode("mo",t);"mopen"===e.mclass||"mclose"===e.mclass?r.setAttribute("fence","true"):r.setAttribute("fence","false"),r.setAttribute("stretchy","true");var n=F(Nr.sizeToMaxHeight[e.size]);return r.setAttribute("minsize",n),r.setAttribute("maxsize",n),r}}),ot({type:"leftright-right",names:["\\right"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=e.parser.gullet.macros.get("\\current@color");if(r&&"string"!=typeof r)throw new n("\\current@color set to non-string in \\right");return{type:"leftright-right",mode:e.parser.mode,delim:Rr(t[0],e).text,color:r}}}),ot({type:"leftright",names:["\\left"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=Rr(t[0],e),n=e.parser;++n.leftrightDepth;var a=n.parseExpression(!1);--n.leftrightDepth,n.expect("\\right",!1);var i=Ut(n.parseFunction(),"leftright-right");return{type:"leftright",mode:n.mode,body:a,left:r.text,right:i.delim,rightColor:i.color}},htmlBuilder:function(e,t){Hr(e);for(var r,n,a=ft(e.body,t,!0,["mopen","mclose"]),i=0,o=0,s=!1,l=0;l-1?"mpadded":"menclose",[Rt(e.body,t)]);switch(e.label){case"\\cancel":n.setAttribute("notation","updiagonalstrike");break;case"\\bcancel":n.setAttribute("notation","downdiagonalstrike");break;case"\\phase":n.setAttribute("notation","phasorangle");break;case"\\sout":n.setAttribute("notation","horizontalstrike");break;case"\\fbox":n.setAttribute("notation","box");break;case"\\angl":n.setAttribute("notation","actuarial");break;case"\\fcolorbox":case"\\colorbox":if(r=t.fontMetrics().fboxsep*t.fontMetrics().ptPerEm,n.setAttribute("width","+"+2*r+"pt"),n.setAttribute("height","+"+2*r+"pt"),n.setAttribute("lspace",r+"pt"),n.setAttribute("voffset",r+"pt"),"\\fcolorbox"===e.label){var a=Math.max(t.fontMetrics().fboxrule,t.minRuleThickness);n.setAttribute("style","border: "+a+"em solid "+String(e.borderColor))}break;case"\\xcancel":n.setAttribute("notation","updiagonalstrike downdiagonalstrike")}return e.backgroundColor&&n.setAttribute("mathbackground",e.backgroundColor),n};ot({type:"enclose",names:["\\colorbox"],props:{numArgs:2,allowedInText:!0,argTypes:["color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ut(t[0],"color-token").color,o=t[1];return{type:"enclose",mode:n.mode,label:a,backgroundColor:i,body:o}},htmlBuilder:Or,mathmlBuilder:Er}),ot({type:"enclose",names:["\\fcolorbox"],props:{numArgs:3,allowedInText:!0,argTypes:["color","color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ut(t[0],"color-token").color,o=Ut(t[1],"color-token").color,s=t[2];return{type:"enclose",mode:n.mode,label:a,backgroundColor:o,borderColor:i,body:s}},htmlBuilder:Or,mathmlBuilder:Er}),ot({type:"enclose",names:["\\fbox"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!0},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\fbox",body:t[0]}}}),ot({type:"enclose",names:["\\cancel","\\bcancel","\\xcancel","\\sout","\\phase"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"enclose",mode:r.mode,label:n,body:a}},htmlBuilder:Or,mathmlBuilder:Er}),ot({type:"enclose",names:["\\angl"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!1},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\angl",body:t[0]}}});var Lr={};function Dr(e){for(var t=e.type,r=e.names,n=e.props,a=e.handler,i=e.htmlBuilder,o=e.mathmlBuilder,s={type:t,numArgs:n.numArgs||0,allowedInText:!1,numOptionalArgs:0,handler:a},l=0;l1||!m)&&g.pop(),b.length0&&(y+=.25),c.push({pos:y,isDashed:e[t]})}for(w(o[0]),r=0;r0&&(M<(B+=b)&&(M=B),B=0),e.addJot&&(M+=f),z.height=S,z.depth=M,y+=S,z.pos=y,y+=M+B,h[r]=z,w(o[r+1])}var C,N,q=y/2+t.fontMetrics().axisHeight,I=e.cols||[],R=[],H=[];if(e.tags&&e.tags.some((function(e){return e})))for(r=0;r=s)){var W=void 0;(a>0||e.hskipBeforeAndAfter)&&0!==(W=l.deflt(V.pregap,p))&&((C=Ke.makeSpan(["arraycolsep"],[])).style.width=F(W),R.push(C));var _=[];for(r=0;r0){for(var K=Ke.makeLineSpan("hline",t,m),J=Ke.makeLineSpan("hdashline",t,m),Q=[{type:"elem",elem:h,shift:0}];c.length>0;){var ee=c.pop(),te=ee.pos-q;ee.isDashed?Q.push({type:"elem",elem:J,shift:te}):Q.push({type:"elem",elem:K,shift:te})}h=Ke.makeVList({positionType:"individualShift",children:Q},t)}if(0===H.length)return Ke.makeSpan(["mord"],[h],t);var re=Ke.makeVList({positionType:"individualShift",children:H},t);return re=Ke.makeSpan(["tag"],[re],t),Ke.makeFragment([h,re])},$r={c:"center ",l:"left ",r:"right "},Zr=function(e,t){for(var r=[],n=new Tt.MathNode("mtd",[],["mtr-glue"]),a=new Tt.MathNode("mtd",[],["mml-eqn-num"]),i=0;i0){var p=e.cols,d="",f=!1,g=0,v=p.length;"separator"===p[0].type&&(m+="top ",g=1),"separator"===p[p.length-1].type&&(m+="bottom ",v-=1);for(var b=g;b0?"left ":"",m+=S[S.length-1].length>0?"right ":"";for(var M=1;M-1?"alignat":"align",o="split"===e.envName,s=Wr(e.parser,{cols:a,addJot:!0,autoTag:o?void 0:Xr(e.envName),emptySingleRow:!0,colSeparationType:i,maxNumCols:o?2:void 0,leqno:e.parser.settings.leqno},"display"),l=0,h={type:"ordgroup",mode:e.mode,body:[]};if(t[0]&&"ordgroup"===t[0].type){for(var c="",m=0;m0&&u&&(f=1),a[p]={type:"align",align:d,pregap:f,postgap:0}}return s.colSeparationType=u?"align":"alignat",s};Dr({type:"array",names:["array","darray"],props:{numArgs:1},handler:function(e,t){var r=(Xt(t[0])?[t[0]]:Ut(t[0],"ordgroup").body).map((function(e){var t=Yt(e).text;if(-1!=="lcr".indexOf(t))return{type:"align",align:t};if("|"===t)return{type:"separator",separator:"|"};if(":"===t)return{type:"separator",separator:":"};throw new n("Unknown column alignment: "+t,e)})),a={cols:r,hskipBeforeAndAfter:!0,maxNumCols:r.length};return Wr(e.parser,a,_r(e.envName))},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix","matrix*","pmatrix*","bmatrix*","Bmatrix*","vmatrix*","Vmatrix*"],props:{numArgs:0},handler:function(e){var t={matrix:null,pmatrix:["(",")"],bmatrix:["[","]"],Bmatrix:["\\{","\\}"],vmatrix:["|","|"],Vmatrix:["\\Vert","\\Vert"]}[e.envName.replace("*","")],r="c",a={hskipBeforeAndAfter:!1,cols:[{type:"align",align:r}]};if("*"===e.envName.charAt(e.envName.length-1)){var i=e.parser;if(i.consumeSpaces(),"["===i.fetch().text){if(i.consume(),i.consumeSpaces(),r=i.fetch().text,-1==="lcr".indexOf(r))throw new n("Expected l or c or r",i.nextToken);i.consume(),i.consumeSpaces(),i.expect("]"),i.consume(),a.cols=[{type:"align",align:r}]}}var o=Wr(e.parser,a,_r(e.envName)),s=Math.max.apply(Math,[0].concat(o.body.map((function(e){return e.length}))));return o.cols=new Array(s).fill({type:"align",align:r}),t?{type:"leftright",mode:e.mode,body:[o],left:t[0],right:t[1],rightColor:void 0}:o},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["smallmatrix"],props:{numArgs:0},handler:function(e){var t=Wr(e.parser,{arraystretch:.5},"script");return t.colSeparationType="small",t},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["subarray"],props:{numArgs:1},handler:function(e,t){var r=(Xt(t[0])?[t[0]]:Ut(t[0],"ordgroup").body).map((function(e){var t=Yt(e).text;if(-1!=="lc".indexOf(t))return{type:"align",align:t};throw new n("Unknown column alignment: "+t,e)}));if(r.length>1)throw new n("{subarray} can contain only one column");var a={cols:r,hskipBeforeAndAfter:!1,arraystretch:.5};if((a=Wr(e.parser,a,"script")).body.length>0&&a.body[0].length>1)throw new n("{subarray} can contain only one column");return a},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["cases","dcases","rcases","drcases"],props:{numArgs:0},handler:function(e){var t=Wr(e.parser,{arraystretch:1.2,cols:[{type:"align",align:"l",pregap:0,postgap:1},{type:"align",align:"l",pregap:0,postgap:0}]},_r(e.envName));return{type:"leftright",mode:e.mode,body:[t],left:e.envName.indexOf("r")>-1?".":"\\{",right:e.envName.indexOf("r")>-1?"\\}":".",rightColor:void 0}},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["align","align*","aligned","split"],props:{numArgs:0},handler:Kr,htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["gathered","gather","gather*"],props:{numArgs:0},handler:function(e){l.contains(["gather","gather*"],e.envName)&&Yr(e);var t={cols:[{type:"align",align:"c"}],addJot:!0,colSeparationType:"gather",autoTag:Xr(e.envName),emptySingleRow:!0,leqno:e.parser.settings.leqno};return Wr(e.parser,t,"display")},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["alignat","alignat*","alignedat"],props:{numArgs:1},handler:Kr,htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["equation","equation*"],props:{numArgs:0},handler:function(e){Yr(e);var t={autoTag:Xr(e.envName),emptySingleRow:!0,singleRow:!0,maxNumCols:1,leqno:e.parser.settings.leqno};return Wr(e.parser,t,"display")},htmlBuilder:jr,mathmlBuilder:Zr}),Dr({type:"array",names:["CD"],props:{numArgs:0},handler:function(e){return Yr(e),function(e){var t=[];for(e.gullet.beginGroup(),e.gullet.macros.set("\\cr","\\\\\\relax"),e.gullet.beginGroup();;){t.push(e.parseExpression(!1,"\\\\")),e.gullet.endGroup(),e.gullet.beginGroup();var r=e.fetch().text;if("&"!==r&&"\\\\"!==r){if("\\end"===r){0===t[t.length-1].length&&t.pop();break}throw new n("Expected \\\\ or \\cr or \\end",e.nextToken)}e.consume()}for(var a,i,o=[],s=[o],l=0;l-1);else{if(!("<>AV".indexOf(u)>-1))throw new n('Expected one of "<>AV=|." after @',h[m]);for(var d=0;d<2;d++){for(var f=!0,g=m+1;g=x.SCRIPT.id?r.text():x.DISPLAY:"text"===e&&r.size===x.DISPLAY.size?r=x.TEXT:"script"===e?r=x.SCRIPT:"scriptscript"===e&&(r=x.SCRIPTSCRIPT),r},nn=function(e,t){var r,n=rn(e.size,t.style),a=n.fracNum(),i=n.fracDen();r=t.havingStyle(a);var o=wt(e.numer,r,t);if(e.continued){var s=8.5/t.fontMetrics().ptPerEm,l=3.5/t.fontMetrics().ptPerEm;o.height=o.height0?3*m:7*m,d=t.fontMetrics().denom1):(c>0?(u=t.fontMetrics().num2,p=m):(u=t.fontMetrics().num3,p=3*m),d=t.fontMetrics().denom2),h){var w=t.fontMetrics().axisHeight;u-o.depth-(w+.5*c)0&&(t="."===(t=e)?null:t),t};ot({type:"genfrac",names:["\\genfrac"],props:{numArgs:6,allowedInArgument:!0,argTypes:["math","math","size","text","math","math"]},handler:function(e,t){var r,n=e.parser,a=t[4],i=t[5],o=lt(t[0]),s="atom"===o.type&&"open"===o.family?sn(o.text):null,l=lt(t[1]),h="atom"===l.type&&"close"===l.family?sn(l.text):null,c=Ut(t[2],"size"),m=null;r=!!c.isBlank||(m=c.value).number>0;var u="auto",p=t[3];if("ordgroup"===p.type){if(p.body.length>0){var d=Ut(p.body[0],"textord");u=on[Number(d.text)]}}else p=Ut(p,"textord"),u=on[Number(p.text)];return{type:"genfrac",mode:n.mode,numer:a,denom:i,continued:!1,hasBarLine:r,barSize:m,leftDelim:s,rightDelim:h,size:u}},htmlBuilder:nn,mathmlBuilder:an}),ot({type:"infix",names:["\\above"],props:{numArgs:1,argTypes:["size"],infix:!0},handler:function(e,t){var r=e.parser,n=(e.funcName,e.token);return{type:"infix",mode:r.mode,replaceWith:"\\\\abovefrac",size:Ut(t[0],"size").value,token:n}}}),ot({type:"genfrac",names:["\\\\abovefrac"],props:{numArgs:3,argTypes:["math","size","math"]},handler:function(e,t){var r=e.parser,n=(e.funcName,t[0]),a=function(e){if(!e)throw new Error("Expected non-null, but got "+String(e));return e}(Ut(t[1],"infix").size),i=t[2],o=a.number>0;return{type:"genfrac",mode:r.mode,numer:n,denom:i,continued:!1,hasBarLine:o,barSize:a,leftDelim:null,rightDelim:null,size:"auto"}},htmlBuilder:nn,mathmlBuilder:an});var ln=function(e,t){var r,n,a=t.style;"supsub"===e.type?(r=e.sup?wt(e.sup,t.havingStyle(a.sup()),t):wt(e.sub,t.havingStyle(a.sub()),t),n=Ut(e.base,"horizBrace")):n=Ut(e,"horizBrace");var i,o=wt(n.base,t.havingBaseStyle(x.DISPLAY)),s=Gt(n,t);if(n.isOver?(i=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:o},{type:"kern",size:.1},{type:"elem",elem:s}]},t)).children[0].children[0].children[1].classes.push("svg-align"):(i=Ke.makeVList({positionType:"bottom",positionData:o.depth+.1+s.height,children:[{type:"elem",elem:s},{type:"kern",size:.1},{type:"elem",elem:o}]},t)).children[0].children[0].children[0].classes.push("svg-align"),r){var l=Ke.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t);i=n.isOver?Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:l},{type:"kern",size:.2},{type:"elem",elem:r}]},t):Ke.makeVList({positionType:"bottom",positionData:l.depth+.2+r.height+r.depth,children:[{type:"elem",elem:r},{type:"kern",size:.2},{type:"elem",elem:l}]},t)}return Ke.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t)};ot({type:"horizBrace",names:["\\overbrace","\\underbrace"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"horizBrace",mode:r.mode,label:n,isOver:/^\\over/.test(n),base:t[0]}},htmlBuilder:ln,mathmlBuilder:function(e,t){var r=Ft(e.label);return new Tt.MathNode(e.isOver?"mover":"munder",[Rt(e.base,t),r])}}),ot({type:"href",names:["\\href"],props:{numArgs:2,argTypes:["url","original"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=t[1],a=Ut(t[0],"url").url;return r.settings.isTrusted({command:"\\href",url:a})?{type:"href",mode:r.mode,href:a,body:ht(n)}:r.formatUnsupportedCmd("\\href")},htmlBuilder:function(e,t){var r=ft(e.body,t,!1);return Ke.makeAnchor(e.href,[],r,t)},mathmlBuilder:function(e,t){var r=It(e.body,t);return r instanceof zt||(r=new zt("mrow",[r])),r.setAttribute("href",e.href),r}}),ot({type:"href",names:["\\url"],props:{numArgs:1,argTypes:["url"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=Ut(t[0],"url").url;if(!r.settings.isTrusted({command:"\\url",url:n}))return r.formatUnsupportedCmd("\\url");for(var a=[],i=0;i0&&(n=P(e.totalheight,t)-r);var a=0;e.width.number>0&&(a=P(e.width,t));var i={height:F(r+n)};a>0&&(i.width=F(a)),n>0&&(i.verticalAlign=F(-n));var o=new j(e.src,e.alt,i);return o.height=r,o.depth=n,o},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mglyph",[]);r.setAttribute("alt",e.alt);var n=P(e.height,t),a=0;if(e.totalheight.number>0&&(a=P(e.totalheight,t)-n,r.setAttribute("valign",F(-a))),r.setAttribute("height",F(n+a)),e.width.number>0){var i=P(e.width,t);r.setAttribute("width",F(i))}return r.setAttribute("src",e.src),r}}),ot({type:"kern",names:["\\kern","\\mkern","\\hskip","\\mskip"],props:{numArgs:1,argTypes:["size"],primitive:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=Ut(t[0],"size");if(r.settings.strict){var i="m"===n[1],o="mu"===a.value.unit;i?(o||r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" supports only mu units, not "+a.value.unit+" units"),"math"!==r.mode&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" works only in math mode")):o&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" doesn't support mu units")}return{type:"kern",mode:r.mode,dimension:a.value}},htmlBuilder:function(e,t){return Ke.makeGlue(e.dimension,t)},mathmlBuilder:function(e,t){var r=P(e.dimension,t);return new Tt.SpaceNode(r)}}),ot({type:"lap",names:["\\mathllap","\\mathrlap","\\mathclap"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"lap",mode:r.mode,alignment:n.slice(5),body:a}},htmlBuilder:function(e,t){var r;"clap"===e.alignment?(r=Ke.makeSpan([],[wt(e.body,t)]),r=Ke.makeSpan(["inner"],[r],t)):r=Ke.makeSpan(["inner"],[wt(e.body,t)]);var n=Ke.makeSpan(["fix"],[]),a=Ke.makeSpan([e.alignment],[r,n],t),i=Ke.makeSpan(["strut"]);return i.style.height=F(a.height+a.depth),a.depth&&(i.style.verticalAlign=F(-a.depth)),a.children.unshift(i),a=Ke.makeSpan(["thinbox"],[a],t),Ke.makeSpan(["mord","vbox"],[a],t)},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mpadded",[Rt(e.body,t)]);if("rlap"!==e.alignment){var n="llap"===e.alignment?"-1":"-0.5";r.setAttribute("lspace",n+"width")}return r.setAttribute("width","0px"),r}}),ot({type:"styling",names:["\\(","$"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){var r=e.funcName,n=e.parser,a=n.mode;n.switchMode("math");var i="\\("===r?"\\)":"$",o=n.parseExpression(!1,i);return n.expect(i),n.switchMode(a),{type:"styling",mode:n.mode,style:"text",body:o}}}),ot({type:"text",names:["\\)","\\]"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){throw new n("Mismatched "+e.funcName)}});var cn=function(e,t){switch(t.style.size){case x.DISPLAY.size:return e.display;case x.TEXT.size:return e.text;case x.SCRIPT.size:return e.script;case x.SCRIPTSCRIPT.size:return e.scriptscript;default:return e.text}};ot({type:"mathchoice",names:["\\mathchoice"],props:{numArgs:4,primitive:!0},handler:function(e,t){return{type:"mathchoice",mode:e.parser.mode,display:ht(t[0]),text:ht(t[1]),script:ht(t[2]),scriptscript:ht(t[3])}},htmlBuilder:function(e,t){var r=cn(e,t),n=ft(r,t,!1);return Ke.makeFragment(n)},mathmlBuilder:function(e,t){var r=cn(e,t);return It(r,t)}});var mn=function(e,t,r,n,a,i,o){e=Ke.makeSpan([],[e]);var s,h,c,m=r&&l.isCharacterBox(r);if(t){var u=wt(t,n.havingStyle(a.sup()),n);h={elem:u,kern:Math.max(n.fontMetrics().bigOpSpacing1,n.fontMetrics().bigOpSpacing3-u.depth)}}if(r){var p=wt(r,n.havingStyle(a.sub()),n);s={elem:p,kern:Math.max(n.fontMetrics().bigOpSpacing2,n.fontMetrics().bigOpSpacing4-p.height)}}if(h&&s){var d=n.fontMetrics().bigOpSpacing5+s.elem.height+s.elem.depth+s.kern+e.depth+o;c=Ke.makeVList({positionType:"bottom",positionData:d,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:F(-i)},{type:"kern",size:s.kern},{type:"elem",elem:e},{type:"kern",size:h.kern},{type:"elem",elem:h.elem,marginLeft:F(i)},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}else if(s){var f=e.height-o;c=Ke.makeVList({positionType:"top",positionData:f,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:F(-i)},{type:"kern",size:s.kern},{type:"elem",elem:e}]},n)}else{if(!h)return e;var g=e.depth+o;c=Ke.makeVList({positionType:"bottom",positionData:g,children:[{type:"elem",elem:e},{type:"kern",size:h.kern},{type:"elem",elem:h.elem,marginLeft:F(i)},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}var v=[c];if(s&&0!==i&&!m){var b=Ke.makeSpan(["mspace"],[],n);b.style.marginRight=F(i),v.unshift(b)}return Ke.makeSpan(["mop","op-limits"],v,n)},un=["\\smallint"],pn=function(e,t){var r,n,a,i=!1;"supsub"===e.type?(r=e.sup,n=e.sub,a=Ut(e.base,"op"),i=!0):a=Ut(e,"op");var o,s=t.style,h=!1;if(s.size===x.DISPLAY.size&&a.symbol&&!l.contains(un,a.name)&&(h=!0),a.symbol){var c=h?"Size2-Regular":"Size1-Regular",m="";if("\\oiint"!==a.name&&"\\oiiint"!==a.name||(m=a.name.slice(1),a.name="oiint"===m?"\\iint":"\\iiint"),o=Ke.makeSymbol(a.name,c,"math",t,["mop","op-symbol",h?"large-op":"small-op"]),m.length>0){var u=o.italic,p=Ke.staticSvg(m+"Size"+(h?"2":"1"),t);o=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:o,shift:0},{type:"elem",elem:p,shift:h?.08:0}]},t),a.name="\\"+m,o.classes.unshift("mop"),o.italic=u}}else if(a.body){var d=ft(a.body,t,!0);1===d.length&&d[0]instanceof Z?(o=d[0]).classes[0]="mop":o=Ke.makeSpan(["mop"],d,t)}else{for(var f=[],g=1;g0){for(var s=a.body.map((function(e){var t=e.text;return"string"==typeof t?{type:"textord",mode:e.mode,text:t}:e})),l=ft(s,t.withFont("mathrm"),!0),h=0;h=0?s.setAttribute("height",F(a)):(s.setAttribute("height",F(a)),s.setAttribute("depth",F(-a))),s.setAttribute("voffset",F(a)),s}});var yn=["\\tiny","\\sixptsize","\\scriptsize","\\footnotesize","\\small","\\normalsize","\\large","\\Large","\\LARGE","\\huge","\\Huge"];ot({type:"sizing",names:yn,props:{numArgs:0,allowedInText:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!1,r);return{type:"sizing",mode:a.mode,size:yn.indexOf(n)+1,body:i}},htmlBuilder:function(e,t){var r=t.havingSize(e.size);return bn(e.body,r,t)},mathmlBuilder:function(e,t){var r=t.havingSize(e.size),n=qt(e.body,r),a=new Tt.MathNode("mstyle",n);return a.setAttribute("mathsize",F(r.sizeMultiplier)),a}}),ot({type:"smash",names:["\\smash"],props:{numArgs:1,numOptionalArgs:1,allowedInText:!0},handler:function(e,t,r){var n=e.parser,a=!1,i=!1,o=r[0]&&Ut(r[0],"ordgroup");if(o)for(var s="",l=0;lr.height+r.depth+i&&(i=(i+m-r.height-r.depth)/2);var u=l.height-r.height-i-h;r.style.paddingLeft=F(c);var p=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:r,wrapperClasses:["svg-align"]},{type:"kern",size:-(r.height+u)},{type:"elem",elem:l},{type:"kern",size:h}]},t);if(e.index){var d=t.havingStyle(x.SCRIPTSCRIPT),f=wt(e.index,d,t),g=.6*(p.height-p.depth),v=Ke.makeVList({positionType:"shift",positionData:-g,children:[{type:"elem",elem:f}]},t),b=Ke.makeSpan(["root"],[v]);return Ke.makeSpan(["mord","sqrt"],[b,p],t)}return Ke.makeSpan(["mord","sqrt"],[p],t)},mathmlBuilder:function(e,t){var r=e.body,n=e.index;return n?new Tt.MathNode("mroot",[Rt(r,t),Rt(n,t)]):new Tt.MathNode("msqrt",[Rt(r,t)])}});var xn={display:x.DISPLAY,text:x.TEXT,script:x.SCRIPT,scriptscript:x.SCRIPTSCRIPT};ot({type:"styling",names:["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!0,r),o=n.slice(1,n.length-5);return{type:"styling",mode:a.mode,style:o,body:i}},htmlBuilder:function(e,t){var r=xn[e.style],n=t.havingStyle(r).withFont("");return bn(e.body,n,t)},mathmlBuilder:function(e,t){var r=xn[e.style],n=t.havingStyle(r),a=qt(e.body,n),i=new Tt.MathNode("mstyle",a),o={display:["0","true"],text:["0","false"],script:["1","false"],scriptscript:["2","false"]}[e.style];return i.setAttribute("scriptlevel",o[0]),i.setAttribute("displaystyle",o[1]),i}});var wn=function(e,t){var r=e.base;return r?"op"===r.type?r.limits&&(t.style.size===x.DISPLAY.size||r.alwaysHandleSupSub)?pn:null:"operatorname"===r.type?r.alwaysHandleSupSub&&(t.style.size===x.DISPLAY.size||r.limits)?vn:null:"accent"===r.type?l.isCharacterBox(r.base)?Wt:null:"horizBrace"===r.type&&!e.sub===r.isOver?ln:null:null};st({type:"supsub",htmlBuilder:function(e,t){var r=wn(e,t);if(r)return r(e,t);var n,a,i,o=e.base,s=e.sup,h=e.sub,c=wt(o,t),m=t.fontMetrics(),u=0,p=0,d=o&&l.isCharacterBox(o);if(s){var f=t.havingStyle(t.style.sup());n=wt(s,f,t),d||(u=c.height-f.fontMetrics().supDrop*f.sizeMultiplier/t.sizeMultiplier)}if(h){var g=t.havingStyle(t.style.sub());a=wt(h,g,t),d||(p=c.depth+g.fontMetrics().subDrop*g.sizeMultiplier/t.sizeMultiplier)}i=t.style===x.DISPLAY?m.sup1:t.style.cramped?m.sup3:m.sup2;var v,b=t.sizeMultiplier,y=F(.5/m.ptPerEm/b),w=null;if(a){var k=e.base&&"op"===e.base.type&&e.base.name&&("\\oiint"===e.base.name||"\\oiiint"===e.base.name);(c instanceof Z||k)&&(w=F(-c.italic))}if(n&&a){u=Math.max(u,i,n.depth+.25*m.xHeight),p=Math.max(p,m.sub2);var S=4*m.defaultRuleThickness;if(u-n.depth-(a.height-p)0&&(u+=M,p-=M)}var z=[{type:"elem",elem:a,shift:p,marginRight:y,marginLeft:w},{type:"elem",elem:n,shift:-u,marginRight:y}];v=Ke.makeVList({positionType:"individualShift",children:z},t)}else if(a){p=Math.max(p,m.sub1,a.height-.8*m.xHeight);var A=[{type:"elem",elem:a,marginLeft:w,marginRight:y}];v=Ke.makeVList({positionType:"shift",positionData:p,children:A},t)}else{if(!n)throw new Error("supsub must have either sup or sub.");u=Math.max(u,i,n.depth+.25*m.xHeight),v=Ke.makeVList({positionType:"shift",positionData:-u,children:[{type:"elem",elem:n,marginRight:y}]},t)}var T=yt(c,"right")||"mord";return Ke.makeSpan([T],[c,Ke.makeSpan(["msupsub"],[v])],t)},mathmlBuilder:function(e,t){var r,n=!1;e.base&&"horizBrace"===e.base.type&&!!e.sup===e.base.isOver&&(n=!0,r=e.base.isOver),!e.base||"op"!==e.base.type&&"operatorname"!==e.base.type||(e.base.parentIsSupSub=!0);var a,i=[Rt(e.base,t)];if(e.sub&&i.push(Rt(e.sub,t)),e.sup&&i.push(Rt(e.sup,t)),n)a=r?"mover":"munder";else if(e.sub)if(e.sup){var o=e.base;a=o&&"op"===o.type&&o.limits&&t.style===x.DISPLAY||o&&"operatorname"===o.type&&o.alwaysHandleSupSub&&(t.style===x.DISPLAY||o.limits)?"munderover":"msubsup"}else{var s=e.base;a=s&&"op"===s.type&&s.limits&&(t.style===x.DISPLAY||s.alwaysHandleSupSub)||s&&"operatorname"===s.type&&s.alwaysHandleSupSub&&(s.limits||t.style===x.DISPLAY)?"munder":"msub"}else{var l=e.base;a=l&&"op"===l.type&&l.limits&&(t.style===x.DISPLAY||l.alwaysHandleSupSub)||l&&"operatorname"===l.type&&l.alwaysHandleSupSub&&(l.limits||t.style===x.DISPLAY)?"mover":"msup"}return new Tt.MathNode(a,i)}}),st({type:"atom",htmlBuilder:function(e,t){return Ke.mathsym(e.text,e.mode,t,["m"+e.family])},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mo",[Bt(e.text,e.mode)]);if("bin"===e.family){var n=Nt(e,t);"bold-italic"===n&&r.setAttribute("mathvariant",n)}else"punct"===e.family?r.setAttribute("separator","true"):"open"!==e.family&&"close"!==e.family||r.setAttribute("stretchy","false");return r}});var kn={mi:"italic",mn:"normal",mtext:"normal"};st({type:"mathord",htmlBuilder:function(e,t){return Ke.makeOrd(e,t,"mathord")},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mi",[Bt(e.text,e.mode,t)]),n=Nt(e,t)||"italic";return n!==kn[r.type]&&r.setAttribute("mathvariant",n),r}}),st({type:"textord",htmlBuilder:function(e,t){return Ke.makeOrd(e,t,"textord")},mathmlBuilder:function(e,t){var r,n=Bt(e.text,e.mode,t),a=Nt(e,t)||"normal";return r="text"===e.mode?new Tt.MathNode("mtext",[n]):/[0-9]/.test(e.text)?new Tt.MathNode("mn",[n]):"\\prime"===e.text?new Tt.MathNode("mo",[n]):new Tt.MathNode("mi",[n]),a!==kn[r.type]&&r.setAttribute("mathvariant",a),r}});var Sn={"\\nobreak":"nobreak","\\allowbreak":"allowbreak"},Mn={" ":{},"\\ ":{},"~":{className:"nobreak"},"\\space":{},"\\nobreakspace":{className:"nobreak"}};st({type:"spacing",htmlBuilder:function(e,t){if(Mn.hasOwnProperty(e.text)){var r=Mn[e.text].className||"";if("text"===e.mode){var a=Ke.makeOrd(e,t,"textord");return a.classes.push(r),a}return Ke.makeSpan(["mspace",r],[Ke.mathsym(e.text,e.mode,t)],t)}if(Sn.hasOwnProperty(e.text))return Ke.makeSpan(["mspace",Sn[e.text]],[],t);throw new n('Unknown type of space "'+e.text+'"')},mathmlBuilder:function(e,t){if(!Mn.hasOwnProperty(e.text)){if(Sn.hasOwnProperty(e.text))return new Tt.MathNode("mspace");throw new n('Unknown type of space "'+e.text+'"')}return new Tt.MathNode("mtext",[new Tt.TextNode("\xa0")])}});var zn=function(){var e=new Tt.MathNode("mtd",[]);return e.setAttribute("width","50%"),e};st({type:"tag",mathmlBuilder:function(e,t){var r=new Tt.MathNode("mtable",[new Tt.MathNode("mtr",[zn(),new Tt.MathNode("mtd",[It(e.body,t)]),zn(),new Tt.MathNode("mtd",[It(e.tag,t)])])]);return r.setAttribute("width","100%"),r}});var An={"\\text":void 0,"\\textrm":"textrm","\\textsf":"textsf","\\texttt":"texttt","\\textnormal":"textrm"},Tn={"\\textbf":"textbf","\\textmd":"textmd"},Bn={"\\textit":"textit","\\textup":"textup"},Cn=function(e,t){var r=e.font;return r?An[r]?t.withTextFontFamily(An[r]):Tn[r]?t.withTextFontWeight(Tn[r]):t.withTextFontShape(Bn[r]):t};ot({type:"text",names:["\\text","\\textrm","\\textsf","\\texttt","\\textnormal","\\textbf","\\textmd","\\textit","\\textup"],props:{numArgs:1,argTypes:["text"],allowedInArgument:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"text",mode:r.mode,body:ht(a),font:n}},htmlBuilder:function(e,t){var r=Cn(e,t),n=ft(e.body,r,!0);return Ke.makeSpan(["mord","text"],n,r)},mathmlBuilder:function(e,t){var r=Cn(e,t);return It(e.body,r)}}),ot({type:"underline",names:["\\underline"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){return{type:"underline",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=wt(e.body,t),n=Ke.makeLineSpan("underline-line",t),a=t.fontMetrics().defaultRuleThickness,i=Ke.makeVList({positionType:"top",positionData:r.height,children:[{type:"kern",size:a},{type:"elem",elem:n},{type:"kern",size:3*a},{type:"elem",elem:r}]},t);return Ke.makeSpan(["mord","underline"],[i],t)},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mo",[new Tt.TextNode("\u203e")]);r.setAttribute("stretchy","true");var n=new Tt.MathNode("munder",[Rt(e.body,t),r]);return n.setAttribute("accentunder","true"),n}}),ot({type:"vcenter",names:["\\vcenter"],props:{numArgs:1,argTypes:["original"],allowedInText:!1},handler:function(e,t){return{type:"vcenter",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=wt(e.body,t),n=t.fontMetrics().axisHeight,a=.5*(r.height-n-(r.depth+n));return Ke.makeVList({positionType:"shift",positionData:a,children:[{type:"elem",elem:r}]},t)},mathmlBuilder:function(e,t){return new Tt.MathNode("mpadded",[Rt(e.body,t)],["vcenter"])}}),ot({type:"verb",names:["\\verb"],props:{numArgs:0,allowedInText:!0},handler:function(e,t,r){throw new n("\\verb ended by end of line instead of matching delimiter")},htmlBuilder:function(e,t){for(var r=Nn(e),n=[],a=t.havingStyle(t.style.text()),i=0;i0;)this.endGroup()},t.has=function(e){return this.current.hasOwnProperty(e)||this.builtins.hasOwnProperty(e)},t.get=function(e){return this.current.hasOwnProperty(e)?this.current[e]:this.builtins[e]},t.set=function(e,t,r){if(void 0===r&&(r=!1),r){for(var n=0;n0&&(this.undefStack[this.undefStack.length-1][e]=t)}else{var a=this.undefStack[this.undefStack.length-1];a&&!a.hasOwnProperty(e)&&(a[e]=this.current[e])}null==t?delete this.current[e]:this.current[e]=t},e}(),Vn=Vr;Pr("\\noexpand",(function(e){var t=e.popToken();return e.isExpandable(t.text)&&(t.noexpand=!0,t.treatAsRelax=!0),{tokens:[t],numArgs:0}})),Pr("\\expandafter",(function(e){var t=e.popToken();return e.expandOnce(!0),{tokens:[t],numArgs:0}})),Pr("\\@firstoftwo",(function(e){return{tokens:e.consumeArgs(2)[0],numArgs:0}})),Pr("\\@secondoftwo",(function(e){return{tokens:e.consumeArgs(2)[1],numArgs:0}})),Pr("\\@ifnextchar",(function(e){var t=e.consumeArgs(3);e.consumeSpaces();var r=e.future();return 1===t[0].length&&t[0][0].text===r.text?{tokens:t[1],numArgs:0}:{tokens:t[2],numArgs:0}})),Pr("\\@ifstar","\\@ifnextchar *{\\@firstoftwo{#1}}"),Pr("\\TextOrMath",(function(e){var t=e.consumeArgs(2);return"text"===e.mode?{tokens:t[0],numArgs:0}:{tokens:t[1],numArgs:0}}));var Pn={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,a:10,A:10,b:11,B:11,c:12,C:12,d:13,D:13,e:14,E:14,f:15,F:15};Pr("\\char",(function(e){var t,r=e.popToken(),a="";if("'"===r.text)t=8,r=e.popToken();else if('"'===r.text)t=16,r=e.popToken();else if("`"===r.text)if("\\"===(r=e.popToken()).text[0])a=r.text.charCodeAt(1);else{if("EOF"===r.text)throw new n("\\char` missing argument");a=r.text.charCodeAt(0)}else t=10;if(t){if(null==(a=Pn[r.text])||a>=t)throw new n("Invalid base-"+t+" digit "+r.text);for(var i;null!=(i=Pn[e.future().text])&&i":"\\dotsb","-":"\\dotsb","*":"\\dotsb",":":"\\dotsb","\\DOTSB":"\\dotsb","\\coprod":"\\dotsb","\\bigvee":"\\dotsb","\\bigwedge":"\\dotsb","\\biguplus":"\\dotsb","\\bigcap":"\\dotsb","\\bigcup":"\\dotsb","\\prod":"\\dotsb","\\sum":"\\dotsb","\\bigotimes":"\\dotsb","\\bigoplus":"\\dotsb","\\bigodot":"\\dotsb","\\bigsqcup":"\\dotsb","\\And":"\\dotsb","\\longrightarrow":"\\dotsb","\\Longrightarrow":"\\dotsb","\\longleftarrow":"\\dotsb","\\Longleftarrow":"\\dotsb","\\longleftrightarrow":"\\dotsb","\\Longleftrightarrow":"\\dotsb","\\mapsto":"\\dotsb","\\longmapsto":"\\dotsb","\\hookrightarrow":"\\dotsb","\\doteq":"\\dotsb","\\mathbin":"\\dotsb","\\mathrel":"\\dotsb","\\relbar":"\\dotsb","\\Relbar":"\\dotsb","\\xrightarrow":"\\dotsb","\\xleftarrow":"\\dotsb","\\DOTSI":"\\dotsi","\\int":"\\dotsi","\\oint":"\\dotsi","\\iint":"\\dotsi","\\iiint":"\\dotsi","\\iiiint":"\\dotsi","\\idotsint":"\\dotsi","\\DOTSX":"\\dotsx"};Pr("\\dots",(function(e){var t="\\dotso",r=e.expandAfterFuture().text;return r in Gn?t=Gn[r]:("\\not"===r.slice(0,4)||r in ae.math&&l.contains(["bin","rel"],ae.math[r].group))&&(t="\\dotsb"),t}));var Un={")":!0,"]":!0,"\\rbrack":!0,"\\}":!0,"\\rbrace":!0,"\\rangle":!0,"\\rceil":!0,"\\rfloor":!0,"\\rgroup":!0,"\\rmoustache":!0,"\\right":!0,"\\bigr":!0,"\\biggr":!0,"\\Bigr":!0,"\\Biggr":!0,$:!0,";":!0,".":!0,",":!0};Pr("\\dotso",(function(e){return e.future().text in Un?"\\ldots\\,":"\\ldots"})),Pr("\\dotsc",(function(e){var t=e.future().text;return t in Un&&","!==t?"\\ldots\\,":"\\ldots"})),Pr("\\cdots",(function(e){return e.future().text in Un?"\\@cdots\\,":"\\@cdots"})),Pr("\\dotsb","\\cdots"),Pr("\\dotsm","\\cdots"),Pr("\\dotsi","\\!\\cdots"),Pr("\\dotsx","\\ldots\\,"),Pr("\\DOTSI","\\relax"),Pr("\\DOTSB","\\relax"),Pr("\\DOTSX","\\relax"),Pr("\\tmspace","\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"),Pr("\\,","\\tmspace+{3mu}{.1667em}"),Pr("\\thinspace","\\,"),Pr("\\>","\\mskip{4mu}"),Pr("\\:","\\tmspace+{4mu}{.2222em}"),Pr("\\medspace","\\:"),Pr("\\;","\\tmspace+{5mu}{.2777em}"),Pr("\\thickspace","\\;"),Pr("\\!","\\tmspace-{3mu}{.1667em}"),Pr("\\negthinspace","\\!"),Pr("\\negmedspace","\\tmspace-{4mu}{.2222em}"),Pr("\\negthickspace","\\tmspace-{5mu}{.277em}"),Pr("\\enspace","\\kern.5em "),Pr("\\enskip","\\hskip.5em\\relax"),Pr("\\quad","\\hskip1em\\relax"),Pr("\\qquad","\\hskip2em\\relax"),Pr("\\tag","\\@ifstar\\tag@literal\\tag@paren"),Pr("\\tag@paren","\\tag@literal{({#1})}"),Pr("\\tag@literal",(function(e){if(e.macros.get("\\df@tag"))throw new n("Multiple \\tag");return"\\gdef\\df@tag{\\text{#1}}"})),Pr("\\bmod","\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}\\mathbin{\\rm mod}\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"),Pr("\\pod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"),Pr("\\pmod","\\pod{{\\rm mod}\\mkern6mu#1}"),Pr("\\mod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1"),Pr("\\newline","\\\\\\relax"),Pr("\\TeX","\\textrm{\\html@mathml{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}{TeX}}");var Yn=F(T["Main-Regular"]["T".charCodeAt(0)][1]-.7*T["Main-Regular"]["A".charCodeAt(0)][1]);Pr("\\LaTeX","\\textrm{\\html@mathml{L\\kern-.36em\\raisebox{"+Yn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{LaTeX}}"),Pr("\\KaTeX","\\textrm{\\html@mathml{K\\kern-.17em\\raisebox{"+Yn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{KaTeX}}"),Pr("\\hspace","\\@ifstar\\@hspacer\\@hspace"),Pr("\\@hspace","\\hskip #1\\relax"),Pr("\\@hspacer","\\rule{0pt}{0pt}\\hskip #1\\relax"),Pr("\\ordinarycolon",":"),Pr("\\vcentcolon","\\mathrel{\\mathop\\ordinarycolon}"),Pr("\\dblcolon",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}{\\mathop{\\char"2237}}'),Pr("\\coloneqq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2254}}'),Pr("\\Coloneqq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2237\\char"3d}}'),Pr("\\coloneq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"3a\\char"2212}}'),Pr("\\Coloneq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"2237\\char"2212}}'),Pr("\\eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2255}}'),Pr("\\Eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"3d\\char"2237}}'),Pr("\\eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2239}}'),Pr("\\Eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"2212\\char"2237}}'),Pr("\\colonapprox",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"3a\\char"2248}}'),Pr("\\Colonapprox",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"2237\\char"2248}}'),Pr("\\colonsim",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"3a\\char"223c}}'),Pr("\\Colonsim",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"2237\\char"223c}}'),Pr("\u2237","\\dblcolon"),Pr("\u2239","\\eqcolon"),Pr("\u2254","\\coloneqq"),Pr("\u2255","\\eqqcolon"),Pr("\u2a74","\\Coloneqq"),Pr("\\ratio","\\vcentcolon"),Pr("\\coloncolon","\\dblcolon"),Pr("\\colonequals","\\coloneqq"),Pr("\\coloncolonequals","\\Coloneqq"),Pr("\\equalscolon","\\eqqcolon"),Pr("\\equalscoloncolon","\\Eqqcolon"),Pr("\\colonminus","\\coloneq"),Pr("\\coloncolonminus","\\Coloneq"),Pr("\\minuscolon","\\eqcolon"),Pr("\\minuscoloncolon","\\Eqcolon"),Pr("\\coloncolonapprox","\\Colonapprox"),Pr("\\coloncolonsim","\\Colonsim"),Pr("\\simcolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),Pr("\\simcoloncolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"),Pr("\\approxcolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),Pr("\\approxcoloncolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"),Pr("\\notni","\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220c}}"),Pr("\\limsup","\\DOTSB\\operatorname*{lim\\,sup}"),Pr("\\liminf","\\DOTSB\\operatorname*{lim\\,inf}"),Pr("\\injlim","\\DOTSB\\operatorname*{inj\\,lim}"),Pr("\\projlim","\\DOTSB\\operatorname*{proj\\,lim}"),Pr("\\varlimsup","\\DOTSB\\operatorname*{\\overline{lim}}"),Pr("\\varliminf","\\DOTSB\\operatorname*{\\underline{lim}}"),Pr("\\varinjlim","\\DOTSB\\operatorname*{\\underrightarrow{lim}}"),Pr("\\varprojlim","\\DOTSB\\operatorname*{\\underleftarrow{lim}}"),Pr("\\gvertneqq","\\html@mathml{\\@gvertneqq}{\u2269}"),Pr("\\lvertneqq","\\html@mathml{\\@lvertneqq}{\u2268}"),Pr("\\ngeqq","\\html@mathml{\\@ngeqq}{\u2271}"),Pr("\\ngeqslant","\\html@mathml{\\@ngeqslant}{\u2271}"),Pr("\\nleqq","\\html@mathml{\\@nleqq}{\u2270}"),Pr("\\nleqslant","\\html@mathml{\\@nleqslant}{\u2270}"),Pr("\\nshortmid","\\html@mathml{\\@nshortmid}{\u2224}"),Pr("\\nshortparallel","\\html@mathml{\\@nshortparallel}{\u2226}"),Pr("\\nsubseteqq","\\html@mathml{\\@nsubseteqq}{\u2288}"),Pr("\\nsupseteqq","\\html@mathml{\\@nsupseteqq}{\u2289}"),Pr("\\varsubsetneq","\\html@mathml{\\@varsubsetneq}{\u228a}"),Pr("\\varsubsetneqq","\\html@mathml{\\@varsubsetneqq}{\u2acb}"),Pr("\\varsupsetneq","\\html@mathml{\\@varsupsetneq}{\u228b}"),Pr("\\varsupsetneqq","\\html@mathml{\\@varsupsetneqq}{\u2acc}"),Pr("\\imath","\\html@mathml{\\@imath}{\u0131}"),Pr("\\jmath","\\html@mathml{\\@jmath}{\u0237}"),Pr("\\llbracket","\\html@mathml{\\mathopen{[\\mkern-3.2mu[}}{\\mathopen{\\char`\u27e6}}"),Pr("\\rrbracket","\\html@mathml{\\mathclose{]\\mkern-3.2mu]}}{\\mathclose{\\char`\u27e7}}"),Pr("\u27e6","\\llbracket"),Pr("\u27e7","\\rrbracket"),Pr("\\lBrace","\\html@mathml{\\mathopen{\\{\\mkern-3.2mu[}}{\\mathopen{\\char`\u2983}}"),Pr("\\rBrace","\\html@mathml{\\mathclose{]\\mkern-3.2mu\\}}}{\\mathclose{\\char`\u2984}}"),Pr("\u2983","\\lBrace"),Pr("\u2984","\\rBrace"),Pr("\\minuso","\\mathbin{\\html@mathml{{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}{\\char`\u29b5}}"),Pr("\u29b5","\\minuso"),Pr("\\darr","\\downarrow"),Pr("\\dArr","\\Downarrow"),Pr("\\Darr","\\Downarrow"),Pr("\\lang","\\langle"),Pr("\\rang","\\rangle"),Pr("\\uarr","\\uparrow"),Pr("\\uArr","\\Uparrow"),Pr("\\Uarr","\\Uparrow"),Pr("\\N","\\mathbb{N}"),Pr("\\R","\\mathbb{R}"),Pr("\\Z","\\mathbb{Z}"),Pr("\\alef","\\aleph"),Pr("\\alefsym","\\aleph"),Pr("\\Alpha","\\mathrm{A}"),Pr("\\Beta","\\mathrm{B}"),Pr("\\bull","\\bullet"),Pr("\\Chi","\\mathrm{X}"),Pr("\\clubs","\\clubsuit"),Pr("\\cnums","\\mathbb{C}"),Pr("\\Complex","\\mathbb{C}"),Pr("\\Dagger","\\ddagger"),Pr("\\diamonds","\\diamondsuit"),Pr("\\empty","\\emptyset"),Pr("\\Epsilon","\\mathrm{E}"),Pr("\\Eta","\\mathrm{H}"),Pr("\\exist","\\exists"),Pr("\\harr","\\leftrightarrow"),Pr("\\hArr","\\Leftrightarrow"),Pr("\\Harr","\\Leftrightarrow"),Pr("\\hearts","\\heartsuit"),Pr("\\image","\\Im"),Pr("\\infin","\\infty"),Pr("\\Iota","\\mathrm{I}"),Pr("\\isin","\\in"),Pr("\\Kappa","\\mathrm{K}"),Pr("\\larr","\\leftarrow"),Pr("\\lArr","\\Leftarrow"),Pr("\\Larr","\\Leftarrow"),Pr("\\lrarr","\\leftrightarrow"),Pr("\\lrArr","\\Leftrightarrow"),Pr("\\Lrarr","\\Leftrightarrow"),Pr("\\Mu","\\mathrm{M}"),Pr("\\natnums","\\mathbb{N}"),Pr("\\Nu","\\mathrm{N}"),Pr("\\Omicron","\\mathrm{O}"),Pr("\\plusmn","\\pm"),Pr("\\rarr","\\rightarrow"),Pr("\\rArr","\\Rightarrow"),Pr("\\Rarr","\\Rightarrow"),Pr("\\real","\\Re"),Pr("\\reals","\\mathbb{R}"),Pr("\\Reals","\\mathbb{R}"),Pr("\\Rho","\\mathrm{P}"),Pr("\\sdot","\\cdot"),Pr("\\sect","\\S"),Pr("\\spades","\\spadesuit"),Pr("\\sub","\\subset"),Pr("\\sube","\\subseteq"),Pr("\\supe","\\supseteq"),Pr("\\Tau","\\mathrm{T}"),Pr("\\thetasym","\\vartheta"),Pr("\\weierp","\\wp"),Pr("\\Zeta","\\mathrm{Z}"),Pr("\\argmin","\\DOTSB\\operatorname*{arg\\,min}"),Pr("\\argmax","\\DOTSB\\operatorname*{arg\\,max}"),Pr("\\plim","\\DOTSB\\mathop{\\operatorname{plim}}\\limits"),Pr("\\bra","\\mathinner{\\langle{#1}|}"),Pr("\\ket","\\mathinner{|{#1}\\rangle}"),Pr("\\braket","\\mathinner{\\langle{#1}\\rangle}"),Pr("\\Bra","\\left\\langle#1\\right|"),Pr("\\Ket","\\left|#1\\right\\rangle");var Xn=function(e){return function(t){var r=t.consumeArg().tokens,n=t.consumeArg().tokens,a=t.consumeArg().tokens,i=t.consumeArg().tokens,o=t.macros.get("|"),s=t.macros.get("\\|");t.macros.beginGroup();var l=function(t){return function(r){e&&(r.macros.set("|",o),a.length&&r.macros.set("\\|",s));var i=t;!t&&a.length&&("|"===r.future().text&&(r.popToken(),i=!0));return{tokens:i?a:n,numArgs:0}}};t.macros.set("|",l(!1)),a.length&&t.macros.set("\\|",l(!0));var h=t.consumeArg().tokens,c=t.expandTokens([].concat(i,h,r));return t.macros.endGroup(),{tokens:c.reverse(),numArgs:0}}};Pr("\\bra@ket",Xn(!1)),Pr("\\bra@set",Xn(!0)),Pr("\\Braket","\\bra@ket{\\left\\langle}{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"),Pr("\\Set","\\bra@set{\\left\\{\\:}{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"),Pr("\\set","\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"),Pr("\\angln","{\\angl n}"),Pr("\\blue","\\textcolor{##6495ed}{#1}"),Pr("\\orange","\\textcolor{##ffa500}{#1}"),Pr("\\pink","\\textcolor{##ff00af}{#1}"),Pr("\\red","\\textcolor{##df0030}{#1}"),Pr("\\green","\\textcolor{##28ae7b}{#1}"),Pr("\\gray","\\textcolor{gray}{#1}"),Pr("\\purple","\\textcolor{##9d38bd}{#1}"),Pr("\\blueA","\\textcolor{##ccfaff}{#1}"),Pr("\\blueB","\\textcolor{##80f6ff}{#1}"),Pr("\\blueC","\\textcolor{##63d9ea}{#1}"),Pr("\\blueD","\\textcolor{##11accd}{#1}"),Pr("\\blueE","\\textcolor{##0c7f99}{#1}"),Pr("\\tealA","\\textcolor{##94fff5}{#1}"),Pr("\\tealB","\\textcolor{##26edd5}{#1}"),Pr("\\tealC","\\textcolor{##01d1c1}{#1}"),Pr("\\tealD","\\textcolor{##01a995}{#1}"),Pr("\\tealE","\\textcolor{##208170}{#1}"),Pr("\\greenA","\\textcolor{##b6ffb0}{#1}"),Pr("\\greenB","\\textcolor{##8af281}{#1}"),Pr("\\greenC","\\textcolor{##74cf70}{#1}"),Pr("\\greenD","\\textcolor{##1fab54}{#1}"),Pr("\\greenE","\\textcolor{##0d923f}{#1}"),Pr("\\goldA","\\textcolor{##ffd0a9}{#1}"),Pr("\\goldB","\\textcolor{##ffbb71}{#1}"),Pr("\\goldC","\\textcolor{##ff9c39}{#1}"),Pr("\\goldD","\\textcolor{##e07d10}{#1}"),Pr("\\goldE","\\textcolor{##a75a05}{#1}"),Pr("\\redA","\\textcolor{##fca9a9}{#1}"),Pr("\\redB","\\textcolor{##ff8482}{#1}"),Pr("\\redC","\\textcolor{##f9685d}{#1}"),Pr("\\redD","\\textcolor{##e84d39}{#1}"),Pr("\\redE","\\textcolor{##bc2612}{#1}"),Pr("\\maroonA","\\textcolor{##ffbde0}{#1}"),Pr("\\maroonB","\\textcolor{##ff92c6}{#1}"),Pr("\\maroonC","\\textcolor{##ed5fa6}{#1}"),Pr("\\maroonD","\\textcolor{##ca337c}{#1}"),Pr("\\maroonE","\\textcolor{##9e034e}{#1}"),Pr("\\purpleA","\\textcolor{##ddd7ff}{#1}"),Pr("\\purpleB","\\textcolor{##c6b9fc}{#1}"),Pr("\\purpleC","\\textcolor{##aa87ff}{#1}"),Pr("\\purpleD","\\textcolor{##7854ab}{#1}"),Pr("\\purpleE","\\textcolor{##543b78}{#1}"),Pr("\\mintA","\\textcolor{##f5f9e8}{#1}"),Pr("\\mintB","\\textcolor{##edf2df}{#1}"),Pr("\\mintC","\\textcolor{##e0e5cc}{#1}"),Pr("\\grayA","\\textcolor{##f6f7f7}{#1}"),Pr("\\grayB","\\textcolor{##f0f1f2}{#1}"),Pr("\\grayC","\\textcolor{##e3e5e6}{#1}"),Pr("\\grayD","\\textcolor{##d6d8da}{#1}"),Pr("\\grayE","\\textcolor{##babec2}{#1}"),Pr("\\grayF","\\textcolor{##888d93}{#1}"),Pr("\\grayG","\\textcolor{##626569}{#1}"),Pr("\\grayH","\\textcolor{##3b3e40}{#1}"),Pr("\\grayI","\\textcolor{##21242c}{#1}"),Pr("\\kaBlue","\\textcolor{##314453}{#1}"),Pr("\\kaGreen","\\textcolor{##71B307}{#1}");var Wn={"^":!0,_:!0,"\\limits":!0,"\\nolimits":!0},_n=function(){function e(e,t,r){this.settings=void 0,this.expansionCount=void 0,this.lexer=void 0,this.macros=void 0,this.stack=void 0,this.mode=void 0,this.settings=t,this.expansionCount=0,this.feed(e),this.macros=new Dn(Vn,t.macros),this.mode=r,this.stack=[]}var t=e.prototype;return t.feed=function(e){this.lexer=new Ln(e,this.settings)},t.switchMode=function(e){this.mode=e},t.beginGroup=function(){this.macros.beginGroup()},t.endGroup=function(){this.macros.endGroup()},t.endGroups=function(){this.macros.endGroups()},t.future=function(){return 0===this.stack.length&&this.pushToken(this.lexer.lex()),this.stack[this.stack.length-1]},t.popToken=function(){return this.future(),this.stack.pop()},t.pushToken=function(e){this.stack.push(e)},t.pushTokens=function(e){var t;(t=this.stack).push.apply(t,e)},t.scanArgument=function(e){var t,r,n;if(e){if(this.consumeSpaces(),"["!==this.future().text)return null;t=this.popToken();var a=this.consumeArg(["]"]);n=a.tokens,r=a.end}else{var i=this.consumeArg();n=i.tokens,t=i.start,r=i.end}return this.pushToken(new Gr("EOF",r.loc)),this.pushTokens(n),t.range(r,"")},t.consumeSpaces=function(){for(;;){if(" "!==this.future().text)break;this.stack.pop()}},t.consumeArg=function(e){var t=[],r=e&&e.length>0;r||this.consumeSpaces();var a,i=this.future(),o=0,s=0;do{if(a=this.popToken(),t.push(a),"{"===a.text)++o;else if("}"===a.text){if(-1===--o)throw new n("Extra }",a)}else if("EOF"===a.text)throw new n("Unexpected end of input in a macro argument, expected '"+(e&&r?e[s]:"}")+"'",a);if(e&&r)if((0===o||1===o&&"{"===e[s])&&a.text===e[s]){if(++s===e.length){t.splice(-s,s);break}}else s=0}while(0!==o||r);return"{"===i.text&&"}"===t[t.length-1].text&&(t.pop(),t.shift()),t.reverse(),{tokens:t,start:i,end:a}},t.consumeArgs=function(e,t){if(t){if(t.length!==e+1)throw new n("The length of delimiters doesn't match the number of args!");for(var r=t[0],a=0;athis.settings.maxExpand)throw new n("Too many expansions: infinite loop or need to increase maxExpand setting");var i=a.tokens,o=this.consumeArgs(a.numArgs,a.delimiters);if(a.numArgs)for(var s=(i=i.slice()).length-1;s>=0;--s){var l=i[s];if("#"===l.text){if(0===s)throw new n("Incomplete placeholder at end of macro body",l);if("#"===(l=i[--s]).text)i.splice(s+1,1);else{if(!/^[1-9]$/.test(l.text))throw new n("Not a valid argument number",l);var h;(h=i).splice.apply(h,[s,2].concat(o[+l.text-1]))}}}return this.pushTokens(i),i.length},t.expandAfterFuture=function(){return this.expandOnce(),this.future()},t.expandNextToken=function(){for(;;)if(!1===this.expandOnce()){var e=this.stack.pop();return e.treatAsRelax&&(e.text="\\relax"),e}throw new Error},t.expandMacro=function(e){return this.macros.has(e)?this.expandTokens([new Gr(e)]):void 0},t.expandTokens=function(e){var t=[],r=this.stack.length;for(this.pushTokens(e);this.stack.length>r;)if(!1===this.expandOnce(!0)){var n=this.stack.pop();n.treatAsRelax&&(n.noexpand=!1,n.treatAsRelax=!1),t.push(n)}return t},t.expandMacroAsText=function(e){var t=this.expandMacro(e);return t?t.map((function(e){return e.text})).join(""):t},t._getExpansion=function(e){var t=this.macros.get(e);if(null==t)return t;if(1===e.length){var r=this.lexer.catcodes[e];if(null!=r&&13!==r)return}var n="function"==typeof t?t(this):t;if("string"==typeof n){var a=0;if(-1!==n.indexOf("#"))for(var i=n.replace(/##/g,"");-1!==i.indexOf("#"+(a+1));)++a;for(var o=new Ln(n,this.settings),s=[],l=o.lex();"EOF"!==l.text;)s.push(l),l=o.lex();return s.reverse(),{tokens:s,numArgs:a}}return n},t.isDefined=function(e){return this.macros.has(e)||qn.hasOwnProperty(e)||ae.math.hasOwnProperty(e)||ae.text.hasOwnProperty(e)||Wn.hasOwnProperty(e)},t.isExpandable=function(e){var t=this.macros.get(e);return null!=t?"string"==typeof t||"function"==typeof t||!t.unexpandable:qn.hasOwnProperty(e)&&!qn[e].primitive},e}(),jn=/^[\u208a\u208b\u208c\u208d\u208e\u2080\u2081\u2082\u2083\u2084\u2085\u2086\u2087\u2088\u2089\u2090\u2091\u2095\u1d62\u2c7c\u2096\u2097\u2098\u2099\u2092\u209a\u1d63\u209b\u209c\u1d64\u1d65\u2093\u1d66\u1d67\u1d68\u1d69\u1d6a]/,$n=Object.freeze({"\u208a":"+","\u208b":"-","\u208c":"=","\u208d":"(","\u208e":")","\u2080":"0","\u2081":"1","\u2082":"2","\u2083":"3","\u2084":"4","\u2085":"5","\u2086":"6","\u2087":"7","\u2088":"8","\u2089":"9","\u2090":"a","\u2091":"e","\u2095":"h","\u1d62":"i","\u2c7c":"j","\u2096":"k","\u2097":"l","\u2098":"m","\u2099":"n","\u2092":"o","\u209a":"p","\u1d63":"r","\u209b":"s","\u209c":"t","\u1d64":"u","\u1d65":"v","\u2093":"x","\u1d66":"\u03b2","\u1d67":"\u03b3","\u1d68":"\u03c1","\u1d69":"\u03d5","\u1d6a":"\u03c7","\u207a":"+","\u207b":"-","\u207c":"=","\u207d":"(","\u207e":")","\u2070":"0","\xb9":"1","\xb2":"2","\xb3":"3","\u2074":"4","\u2075":"5","\u2076":"6","\u2077":"7","\u2078":"8","\u2079":"9","\u1d2c":"A","\u1d2e":"B","\u1d30":"D","\u1d31":"E","\u1d33":"G","\u1d34":"H","\u1d35":"I","\u1d36":"J","\u1d37":"K","\u1d38":"L","\u1d39":"M","\u1d3a":"N","\u1d3c":"O","\u1d3e":"P","\u1d3f":"R","\u1d40":"T","\u1d41":"U","\u2c7d":"V","\u1d42":"W","\u1d43":"a","\u1d47":"b","\u1d9c":"c","\u1d48":"d","\u1d49":"e","\u1da0":"f","\u1d4d":"g","\u02b0":"h","\u2071":"i","\u02b2":"j","\u1d4f":"k","\u02e1":"l","\u1d50":"m","\u207f":"n","\u1d52":"o","\u1d56":"p","\u02b3":"r","\u02e2":"s","\u1d57":"t","\u1d58":"u","\u1d5b":"v","\u02b7":"w","\u02e3":"x","\u02b8":"y","\u1dbb":"z","\u1d5d":"\u03b2","\u1d5e":"\u03b3","\u1d5f":"\u03b4","\u1d60":"\u03d5","\u1d61":"\u03c7","\u1dbf":"\u03b8"}),Zn={"\u0301":{text:"\\'",math:"\\acute"},"\u0300":{text:"\\`",math:"\\grave"},"\u0308":{text:'\\"',math:"\\ddot"},"\u0303":{text:"\\~",math:"\\tilde"},"\u0304":{text:"\\=",math:"\\bar"},"\u0306":{text:"\\u",math:"\\breve"},"\u030c":{text:"\\v",math:"\\check"},"\u0302":{text:"\\^",math:"\\hat"},"\u0307":{text:"\\.",math:"\\dot"},"\u030a":{text:"\\r",math:"\\mathring"},"\u030b":{text:"\\H"},"\u0327":{text:"\\c"}},Kn={"\xe1":"a\u0301","\xe0":"a\u0300","\xe4":"a\u0308","\u01df":"a\u0308\u0304","\xe3":"a\u0303","\u0101":"a\u0304","\u0103":"a\u0306","\u1eaf":"a\u0306\u0301","\u1eb1":"a\u0306\u0300","\u1eb5":"a\u0306\u0303","\u01ce":"a\u030c","\xe2":"a\u0302","\u1ea5":"a\u0302\u0301","\u1ea7":"a\u0302\u0300","\u1eab":"a\u0302\u0303","\u0227":"a\u0307","\u01e1":"a\u0307\u0304","\xe5":"a\u030a","\u01fb":"a\u030a\u0301","\u1e03":"b\u0307","\u0107":"c\u0301","\u1e09":"c\u0327\u0301","\u010d":"c\u030c","\u0109":"c\u0302","\u010b":"c\u0307","\xe7":"c\u0327","\u010f":"d\u030c","\u1e0b":"d\u0307","\u1e11":"d\u0327","\xe9":"e\u0301","\xe8":"e\u0300","\xeb":"e\u0308","\u1ebd":"e\u0303","\u0113":"e\u0304","\u1e17":"e\u0304\u0301","\u1e15":"e\u0304\u0300","\u0115":"e\u0306","\u1e1d":"e\u0327\u0306","\u011b":"e\u030c","\xea":"e\u0302","\u1ebf":"e\u0302\u0301","\u1ec1":"e\u0302\u0300","\u1ec5":"e\u0302\u0303","\u0117":"e\u0307","\u0229":"e\u0327","\u1e1f":"f\u0307","\u01f5":"g\u0301","\u1e21":"g\u0304","\u011f":"g\u0306","\u01e7":"g\u030c","\u011d":"g\u0302","\u0121":"g\u0307","\u0123":"g\u0327","\u1e27":"h\u0308","\u021f":"h\u030c","\u0125":"h\u0302","\u1e23":"h\u0307","\u1e29":"h\u0327","\xed":"i\u0301","\xec":"i\u0300","\xef":"i\u0308","\u1e2f":"i\u0308\u0301","\u0129":"i\u0303","\u012b":"i\u0304","\u012d":"i\u0306","\u01d0":"i\u030c","\xee":"i\u0302","\u01f0":"j\u030c","\u0135":"j\u0302","\u1e31":"k\u0301","\u01e9":"k\u030c","\u0137":"k\u0327","\u013a":"l\u0301","\u013e":"l\u030c","\u013c":"l\u0327","\u1e3f":"m\u0301","\u1e41":"m\u0307","\u0144":"n\u0301","\u01f9":"n\u0300","\xf1":"n\u0303","\u0148":"n\u030c","\u1e45":"n\u0307","\u0146":"n\u0327","\xf3":"o\u0301","\xf2":"o\u0300","\xf6":"o\u0308","\u022b":"o\u0308\u0304","\xf5":"o\u0303","\u1e4d":"o\u0303\u0301","\u1e4f":"o\u0303\u0308","\u022d":"o\u0303\u0304","\u014d":"o\u0304","\u1e53":"o\u0304\u0301","\u1e51":"o\u0304\u0300","\u014f":"o\u0306","\u01d2":"o\u030c","\xf4":"o\u0302","\u1ed1":"o\u0302\u0301","\u1ed3":"o\u0302\u0300","\u1ed7":"o\u0302\u0303","\u022f":"o\u0307","\u0231":"o\u0307\u0304","\u0151":"o\u030b","\u1e55":"p\u0301","\u1e57":"p\u0307","\u0155":"r\u0301","\u0159":"r\u030c","\u1e59":"r\u0307","\u0157":"r\u0327","\u015b":"s\u0301","\u1e65":"s\u0301\u0307","\u0161":"s\u030c","\u1e67":"s\u030c\u0307","\u015d":"s\u0302","\u1e61":"s\u0307","\u015f":"s\u0327","\u1e97":"t\u0308","\u0165":"t\u030c","\u1e6b":"t\u0307","\u0163":"t\u0327","\xfa":"u\u0301","\xf9":"u\u0300","\xfc":"u\u0308","\u01d8":"u\u0308\u0301","\u01dc":"u\u0308\u0300","\u01d6":"u\u0308\u0304","\u01da":"u\u0308\u030c","\u0169":"u\u0303","\u1e79":"u\u0303\u0301","\u016b":"u\u0304","\u1e7b":"u\u0304\u0308","\u016d":"u\u0306","\u01d4":"u\u030c","\xfb":"u\u0302","\u016f":"u\u030a","\u0171":"u\u030b","\u1e7d":"v\u0303","\u1e83":"w\u0301","\u1e81":"w\u0300","\u1e85":"w\u0308","\u0175":"w\u0302","\u1e87":"w\u0307","\u1e98":"w\u030a","\u1e8d":"x\u0308","\u1e8b":"x\u0307","\xfd":"y\u0301","\u1ef3":"y\u0300","\xff":"y\u0308","\u1ef9":"y\u0303","\u0233":"y\u0304","\u0177":"y\u0302","\u1e8f":"y\u0307","\u1e99":"y\u030a","\u017a":"z\u0301","\u017e":"z\u030c","\u1e91":"z\u0302","\u017c":"z\u0307","\xc1":"A\u0301","\xc0":"A\u0300","\xc4":"A\u0308","\u01de":"A\u0308\u0304","\xc3":"A\u0303","\u0100":"A\u0304","\u0102":"A\u0306","\u1eae":"A\u0306\u0301","\u1eb0":"A\u0306\u0300","\u1eb4":"A\u0306\u0303","\u01cd":"A\u030c","\xc2":"A\u0302","\u1ea4":"A\u0302\u0301","\u1ea6":"A\u0302\u0300","\u1eaa":"A\u0302\u0303","\u0226":"A\u0307","\u01e0":"A\u0307\u0304","\xc5":"A\u030a","\u01fa":"A\u030a\u0301","\u1e02":"B\u0307","\u0106":"C\u0301","\u1e08":"C\u0327\u0301","\u010c":"C\u030c","\u0108":"C\u0302","\u010a":"C\u0307","\xc7":"C\u0327","\u010e":"D\u030c","\u1e0a":"D\u0307","\u1e10":"D\u0327","\xc9":"E\u0301","\xc8":"E\u0300","\xcb":"E\u0308","\u1ebc":"E\u0303","\u0112":"E\u0304","\u1e16":"E\u0304\u0301","\u1e14":"E\u0304\u0300","\u0114":"E\u0306","\u1e1c":"E\u0327\u0306","\u011a":"E\u030c","\xca":"E\u0302","\u1ebe":"E\u0302\u0301","\u1ec0":"E\u0302\u0300","\u1ec4":"E\u0302\u0303","\u0116":"E\u0307","\u0228":"E\u0327","\u1e1e":"F\u0307","\u01f4":"G\u0301","\u1e20":"G\u0304","\u011e":"G\u0306","\u01e6":"G\u030c","\u011c":"G\u0302","\u0120":"G\u0307","\u0122":"G\u0327","\u1e26":"H\u0308","\u021e":"H\u030c","\u0124":"H\u0302","\u1e22":"H\u0307","\u1e28":"H\u0327","\xcd":"I\u0301","\xcc":"I\u0300","\xcf":"I\u0308","\u1e2e":"I\u0308\u0301","\u0128":"I\u0303","\u012a":"I\u0304","\u012c":"I\u0306","\u01cf":"I\u030c","\xce":"I\u0302","\u0130":"I\u0307","\u0134":"J\u0302","\u1e30":"K\u0301","\u01e8":"K\u030c","\u0136":"K\u0327","\u0139":"L\u0301","\u013d":"L\u030c","\u013b":"L\u0327","\u1e3e":"M\u0301","\u1e40":"M\u0307","\u0143":"N\u0301","\u01f8":"N\u0300","\xd1":"N\u0303","\u0147":"N\u030c","\u1e44":"N\u0307","\u0145":"N\u0327","\xd3":"O\u0301","\xd2":"O\u0300","\xd6":"O\u0308","\u022a":"O\u0308\u0304","\xd5":"O\u0303","\u1e4c":"O\u0303\u0301","\u1e4e":"O\u0303\u0308","\u022c":"O\u0303\u0304","\u014c":"O\u0304","\u1e52":"O\u0304\u0301","\u1e50":"O\u0304\u0300","\u014e":"O\u0306","\u01d1":"O\u030c","\xd4":"O\u0302","\u1ed0":"O\u0302\u0301","\u1ed2":"O\u0302\u0300","\u1ed6":"O\u0302\u0303","\u022e":"O\u0307","\u0230":"O\u0307\u0304","\u0150":"O\u030b","\u1e54":"P\u0301","\u1e56":"P\u0307","\u0154":"R\u0301","\u0158":"R\u030c","\u1e58":"R\u0307","\u0156":"R\u0327","\u015a":"S\u0301","\u1e64":"S\u0301\u0307","\u0160":"S\u030c","\u1e66":"S\u030c\u0307","\u015c":"S\u0302","\u1e60":"S\u0307","\u015e":"S\u0327","\u0164":"T\u030c","\u1e6a":"T\u0307","\u0162":"T\u0327","\xda":"U\u0301","\xd9":"U\u0300","\xdc":"U\u0308","\u01d7":"U\u0308\u0301","\u01db":"U\u0308\u0300","\u01d5":"U\u0308\u0304","\u01d9":"U\u0308\u030c","\u0168":"U\u0303","\u1e78":"U\u0303\u0301","\u016a":"U\u0304","\u1e7a":"U\u0304\u0308","\u016c":"U\u0306","\u01d3":"U\u030c","\xdb":"U\u0302","\u016e":"U\u030a","\u0170":"U\u030b","\u1e7c":"V\u0303","\u1e82":"W\u0301","\u1e80":"W\u0300","\u1e84":"W\u0308","\u0174":"W\u0302","\u1e86":"W\u0307","\u1e8c":"X\u0308","\u1e8a":"X\u0307","\xdd":"Y\u0301","\u1ef2":"Y\u0300","\u0178":"Y\u0308","\u1ef8":"Y\u0303","\u0232":"Y\u0304","\u0176":"Y\u0302","\u1e8e":"Y\u0307","\u0179":"Z\u0301","\u017d":"Z\u030c","\u1e90":"Z\u0302","\u017b":"Z\u0307","\u03ac":"\u03b1\u0301","\u1f70":"\u03b1\u0300","\u1fb1":"\u03b1\u0304","\u1fb0":"\u03b1\u0306","\u03ad":"\u03b5\u0301","\u1f72":"\u03b5\u0300","\u03ae":"\u03b7\u0301","\u1f74":"\u03b7\u0300","\u03af":"\u03b9\u0301","\u1f76":"\u03b9\u0300","\u03ca":"\u03b9\u0308","\u0390":"\u03b9\u0308\u0301","\u1fd2":"\u03b9\u0308\u0300","\u1fd1":"\u03b9\u0304","\u1fd0":"\u03b9\u0306","\u03cc":"\u03bf\u0301","\u1f78":"\u03bf\u0300","\u03cd":"\u03c5\u0301","\u1f7a":"\u03c5\u0300","\u03cb":"\u03c5\u0308","\u03b0":"\u03c5\u0308\u0301","\u1fe2":"\u03c5\u0308\u0300","\u1fe1":"\u03c5\u0304","\u1fe0":"\u03c5\u0306","\u03ce":"\u03c9\u0301","\u1f7c":"\u03c9\u0300","\u038e":"\u03a5\u0301","\u1fea":"\u03a5\u0300","\u03ab":"\u03a5\u0308","\u1fe9":"\u03a5\u0304","\u1fe8":"\u03a5\u0306","\u038f":"\u03a9\u0301","\u1ffa":"\u03a9\u0300"},Jn=function(){function e(e,t){this.mode=void 0,this.gullet=void 0,this.settings=void 0,this.leftrightDepth=void 0,this.nextToken=void 0,this.mode="math",this.gullet=new _n(e,t,this.mode),this.settings=t,this.leftrightDepth=0}var t=e.prototype;return t.expect=function(e,t){if(void 0===t&&(t=!0),this.fetch().text!==e)throw new n("Expected '"+e+"', got '"+this.fetch().text+"'",this.fetch());t&&this.consume()},t.consume=function(){this.nextToken=null},t.fetch=function(){return null==this.nextToken&&(this.nextToken=this.gullet.expandNextToken()),this.nextToken},t.switchMode=function(e){this.mode=e,this.gullet.switchMode(e)},t.parse=function(){this.settings.globalGroup||this.gullet.beginGroup(),this.settings.colorIsTextColor&&this.gullet.macros.set("\\color","\\textcolor");try{var e=this.parseExpression(!1);return this.expect("EOF"),this.settings.globalGroup||this.gullet.endGroup(),e}finally{this.gullet.endGroups()}},t.subparse=function(e){var t=this.nextToken;this.consume(),this.gullet.pushToken(new Gr("}")),this.gullet.pushTokens(e);var r=this.parseExpression(!1);return this.expect("}"),this.nextToken=t,r},t.parseExpression=function(t,r){for(var n=[];;){"math"===this.mode&&this.consumeSpaces();var a=this.fetch();if(-1!==e.endOfExpression.indexOf(a.text))break;if(r&&a.text===r)break;if(t&&qn[a.text]&&qn[a.text].infix)break;var i=this.parseAtom(r);if(!i)break;"internal"!==i.type&&n.push(i)}return"text"===this.mode&&this.formLigatures(n),this.handleInfixNodes(n)},t.handleInfixNodes=function(e){for(var t,r=-1,a=0;a=0&&this.settings.reportNonstrict("unicodeTextInMathMode",'Latin-1/Unicode text character "'+t[0]+'" used in math mode',e);var s,l=ae[this.mode][t].group,h=Fr.range(e);if(te.hasOwnProperty(l)){var c=l;s={type:"atom",mode:this.mode,family:c,loc:h,text:t}}else s={type:l,mode:this.mode,loc:h,text:t};i=s}else{if(!(t.charCodeAt(0)>=128))return null;this.settings.strict&&(S(t.charCodeAt(0))?"math"===this.mode&&this.settings.reportNonstrict("unicodeTextInMathMode",'Unicode text character "'+t[0]+'" used in math mode',e):this.settings.reportNonstrict("unknownSymbol",'Unrecognized Unicode character "'+t[0]+'" ('+t.charCodeAt(0)+")",e)),i={type:"textord",mode:"text",loc:Fr.range(e),text:t}}if(this.consume(),o)for(var m=0;m> (shell {:out :string} + "grep -E -oh" "\\bt\\('[^ ']+" "-r" "tldraw/apps/tldraw-logseq/src/components") + :out + string/split-lines + (map #(keyword (subs % 3))))) + (defn- validate-ui-translations-are-used "This validation checks to see that translations done by (t ...) are equal to the ones defined for the default :en lang. This catches translations that have @@ -129,6 +137,7 @@ string/split-lines (map #(keyword (subs % 4))) (concat (mapcat val manual-ui-dicts)) + (concat (whiteboard-dicts)) set) expected-dicts (set (remove #(re-find #"^(command|shortcut)\." (str (namespace %))) (keys (:en (get-dicts))))) @@ -145,31 +154,55 @@ (task-util/print-table (map #(hash-map :invalid-key %) expected-only))) (System/exit 1))))) -(defn validate-translations - "Runs multiple translation validations that fail fast if one of them is invalid" - [] - (validate-non-default-languages) - (validate-ui-translations-are-used)) +(def allowed-duplicates + "Allows certain keys in a language to have the same translation + as English. Happens more in romance languages but pretty rare otherwise" + {:fr #{:port :type :help/docs :search-item/page :shortcut.category/navigating :text/image + :settings-of-plugins} + :de #{:graph :host :plugins :port :right-side-bar/whiteboards :search-item/block + :settings-of-plugins :search-item/whiteboard :shortcut.category/navigating + :settings-page/enable-tooltip :settings-page/enable-whiteboards :settings-page/plugin-system} + :es #{:settings-page/tab-general :settings-page/tab-editor :whiteboard/color} + :it #{:plugins} + :nl #{:plugins :type :left-side-bar/nav-recent-pages :plugin/update} + :pl #{:port} + :pt-BR #{:plugins :right-side-bar/flashcards :settings-page/enable-flashcards :page/backlinks + :host :settings-page/tab-editor :shortcut.category/plugins :whiteboard/link} + :pt-PT #{:plugins :settings-of-plugins :plugin/downloads :right-side-bar/flashcards + :settings-page/enable-flashcards :settings-page/plugin-system} + :nb-NO #{:port :type :whiteboard :right-side-bar/flashcards :right-side-bar/whiteboards + :search-item/whiteboard :settings-page/enable-flashcards :settings-page/enable-whiteboards + :settings-page/tab-editor :shortcut.category/whiteboard :whiteboard/medium + :whiteboard/twitter-url :whiteboard/youtube-url} + :tr #{:help/awesome-logseq} + }) -(defn list-duplicates - "Lists translations that are the same as the one in English" - [& args] +(defn- validate-languages-dont-have-duplicates + "Looks up duplicates for all languages" + [] (let [dicts (get-dicts) en-dicts (dicts :en) - lang (or (keyword (first args)) - (task-util/print-usage "LOCALE")) - lang-dicts (dicts lang) invalid-dicts - (sort-by - :translation-key - (keep - #(when (= (en-dicts %) (lang-dicts %)) - {:translation-key % - :duplicate-value (shorten (lang-dicts %) 70)}) - (keys lang-dicts)))] + (->> (dissoc dicts :en) + (mapcat + (fn [[lang lang-dicts]] + (keep + #(when (= (en-dicts %) (lang-dicts %)) + {:translation-key % + :lang lang + :duplicate-value (shorten (lang-dicts %) 70)}) + (keys (apply dissoc lang-dicts (allowed-duplicates lang)))))) + (sort-by (juxt :lang :translation-key)))] (if (empty? invalid-dicts) - (println "No duplicated keys found!") + (println "All languages have no duplicate English values!") (do - (println "Keys with duplicate values found:") + (println "These translations keys are invalid because they are just copying the English value:") (task-util/print-table invalid-dicts) (System/exit 1))))) + +(defn validate-translations + "Runs multiple translation validations that fail fast if one of them is invalid" + [] + (validate-non-default-languages) + (validate-ui-translations-are-used) + (validate-languages-dont-have-duplicates)) diff --git a/src/electron/electron/handler.cljs b/src/electron/electron/handler.cljs index 22be96d57b4..4ba10229ddb 100644 --- a/src/electron/electron/handler.cljs +++ b/src/electron/electron/handler.cljs @@ -502,7 +502,8 @@ js/__dirname) (defmethod handle :getAppBaseInfo [^js win [_ _opts]] - {:isFullScreen (.isFullScreen win)}) + {:isFullScreen (.isFullScreen win) + :isMaximized (.isMaximized win)}) (defmethod handle :getAssetsFiles [^js win [_ {:keys [exts]}]] (when-let [graph-path (state/get-window-graph-path win)] @@ -679,6 +680,20 @@ (when-let [web-content (.-webContents win)] (.reload web-content))) +(defmethod handle :window-minimize [^js win] + (.minimize win)) + +(defmethod handle :window-toggle-maximized [^js win] + (if (.isMaximized win) + (.unmaximize win) + (.maximize win))) + +(defmethod handle :window-toggle-fullscreen [^js win] + (.setFullScreen win (not (.isFullScreen win)))) + +(defmethod handle :window-close [^js win] + (.close win)) + ;;;;;;;;;;;;;;;;;;;;;;; ;; file-sync-rs-apis ;; ;;;;;;;;;;;;;;;;;;;;;;; diff --git a/src/electron/electron/plugin.cljs b/src/electron/electron/plugin.cljs index a80d356b795..96fe4860bf6 100644 --- a/src/electron/electron/plugin.cljs +++ b/src/electron/electron/plugin.cljs @@ -19,6 +19,23 @@ (.. win -webContents (send (name type) (bean/->js payload)))))) +(defonce github-api-0 "https://api.github.com") +(defonce github-api-1 "https://plugins.logseq.io/github/api") +(defonce *github-api (atom github-api-0)) +(defonce *last-valid-github-api (atom nil)) + +(defn valid-github-api! + [] + (when (or (nil? @*last-valid-github-api) + (> (- (js/Date.now) @*last-valid-github-api) (* 1000 60))) + (let [target github-api-1] + (-> (fetch (str target "/rate_limit") {:timeout 2000}) + (p/then #(when (not= (.-status %) 200) (throw (js/Error. (.-statusText %))))) + (p/then #(do (reset! *github-api target) (debug "INFO: use github api - " target))) + (p/catch #(do (reset! *github-api github-api-0) (debug "ERR: valid github api - " %))) + (p/finally #(reset! *last-valid-github-api (js/Date.now))))))) + + (defn dotdir-file? [file] (and file (string/starts-with? (node-path/normalize file) cfgs/dot-root))) @@ -34,13 +51,14 @@ (defn- fetch-release-asset [{:keys [repo theme]} url-suffix {:keys [response-transform] :or {response-transform identity}}] - (-> (p/let [repo (some-> repo (string/trim) (string/replace #"^/+(.+?)/+$" "$1")) - api #(str "https://api.github.com/repos/" repo "/" %) + (-> (p/let [_ (valid-github-api!) + repo (some-> repo (string/trim) (string/replace #"^/+(.+?)/+$" "$1")) + api #(str @*github-api "/repos/" repo "/" %) endpoint (api url-suffix) - ^js res (fetch endpoint) + ^js res (fetch endpoint {:timeout (* 1000 5)}) illegal-text (when-not (= 200 (.-status res)) (.text res)) _ (when-not (string/blank? illegal-text) (throw (js/Error. (str "Github API Failed(" (.-status res) ") " illegal-text)))) - _ (debug "[Release URL] " endpoint "[Status/Text]" (.-status res)) + _ (debug "Release latest:" endpoint ":status" (.-status res)) res (response-transform res) res (.json res) res (bean/->clj res) @@ -83,7 +101,7 @@ ;; cases. Previous logseq versions did not store the ;; plugin's git tag required to correctly install it (let [repo' (some-> repo (string/trim) (string/replace #"^/+(.+?)/+$" "$1")) - api #(str "https://api.github.com/repos/" repo' "/" %)] + api #(str @*github-api "/repos/" repo' "/" %)] (fetch (api "releases/latest"))) res))})) @@ -174,10 +192,10 @@ updating? (and version (. semver valid coerced-version) (not= action :install))] - (debug (if updating? "Updating:" "Installing:") repo) + (debug "===" (if updating? "Updating:" "Installing:") repo "===") (-> (p/create - (fn [resolve _reject] + (fn [resolve reject] ;;(reset! *installing-or-updating item) ;; get releases (-> (p/let [[asset latest-version notes] @@ -185,18 +203,19 @@ (fetch-specific-release-asset item) (fetch-latest-release-asset item)) - _ (debug "[Release Asset] #" latest-version " =>" (:url asset)) + _ (debug "Release latest:" latest-version " from" (:url asset)) ;; compare latest version _ (when-let [coerced-latest-version (and updating? latest-version (. semver coerce latest-version))] - (debug "[Updating Latest?] " version " > " latest-version) + (debug "Release compare:" version "(current) > " latest-version "(latest)") (if (. semver lt coerced-version coerced-latest-version) - (debug "[Updating Latest] " latest-version) - (throw (js/Error. :no-new-version)))) + (debug "Updating latest:" latest-version) + (do (debug "Update skip: no new version") + (throw (js/Error. :no-new-version))))) dl-url (if-not (string? asset) (:browser_download_url asset) asset) @@ -207,7 +226,7 @@ dest (.join node-path cfgs/dot-root "plugins" (:id item)) _ (when-not only-check (download-asset-zip item dl-url latest-version dest)) - _ (debug (str "[" (if only-check "Checked" "Updated") "DONE]") latest-version)] + _ (debug (str "[" (if only-check "Checked" "Updated") " DONE]") latest-version)] (emit :lsp-updates {:status :completed @@ -224,8 +243,12 @@ {:status :error :only-check only-check :payload (assoc item :error-code (.-message e))}) - (debug e)) - (resolve nil))))) + (reject e)))))) + + (p/catch + (fn [^js e] + (when-not (contains? #{":no-new-version"} (.-message e)) + (debug e)))) (p/finally (fn [])))) diff --git a/src/electron/electron/window.cljs b/src/electron/electron/window.cljs index 2e0f8c5c4d6..a8f59ecdb5b 100644 --- a/src/electron/electron/window.cljs +++ b/src/electron/electron/window.cljs @@ -26,10 +26,11 @@ (create-main-window! url nil)) ([url opts] (let [win-state (windowStateKeeper (clj->js {:defaultWidth 980 :defaultHeight 700})) + native-titlebar? (cfgs/get-item :window/native-titlebar?) win-opts (cond-> {:width (.-width win-state) :height (.-height win-state) - :frame true + :frame (or mac? native-titlebar?) :titleBarStyle "hiddenInset" :trafficLightPosition {:x 16 :y 16} :autoHideMenuBar (not mac?) @@ -187,7 +188,9 @@ (doto win (.on "enter-full-screen" #(.send web-contents "full-screen" "enter")) - (.on "leave-full-screen" #(.send web-contents "full-screen" "leave"))) + (.on "leave-full-screen" #(.send web-contents "full-screen" "leave")) + (.on "maximize" #(.send web-contents "maximize" true)) + (.on "unmaximize" #(.send web-contents "maximize" false))) ;; clear (fn [] diff --git a/src/main/electron/listener.cljs b/src/main/electron/listener.cljs index 983514b6ec5..9507e74cf6f 100644 --- a/src/main/electron/listener.cljs +++ b/src/main/electron/listener.cljs @@ -5,7 +5,6 @@ [datascript.core :as d] [dommy.core :as dom] [electron.ipc :as ipc] - [frontend.context.i18n :refer [t]] [frontend.db :as db] [frontend.db.model :as db-model] [frontend.fs.sync :as sync] @@ -35,9 +34,7 @@ [] ;; only persist current db! ;; TODO rename the function and event to persist-db - (repo-handler/persist-db! {:before #(notification/show! - (ui/loading (t :graph/persist)) - :warning) + (repo-handler/persist-db! {:before #(ui/notify-graph-persist!) :on-success #(ipc/ipc "persistent-dbs-saved") :on-error #(ipc/ipc "persistent-dbs-error")})) @@ -139,15 +136,11 @@ ;; fire back "broadcastPersistGraphDone" on done (fn [data] (let [repo (bean/->clj data) - before-f #(notification/show! - (ui/loading (t :graph/persist)) - :warning) + before-f #(ui/notify-graph-persist!) after-f #(ipc/ipc "broadcastPersistGraphDone") error-f (fn [] (after-f) - (notification/show! - (t :graph/persist-error) - :error)) + (ui/notify-graph-persist-error!)) handlers {:before before-f :on-success after-f :on-error error-f}] diff --git a/src/main/frontend/commands.cljs b/src/main/frontend/commands.cljs index 8c52d67a3c1..803c659c6c7 100644 --- a/src/main/frontend/commands.cljs +++ b/src/main/frontend/commands.cljs @@ -30,6 +30,7 @@ (defonce angle-bracket "<") (defonce hashtag "#") (defonce colon ":") +(defonce command-trigger "/") (defonce *current-command (atom nil)) (def query-doc @@ -52,7 +53,7 @@ "."]]) (defn link-steps [] - [[:editor/input (str (state/get-editor-command-trigger) "link")] + [[:editor/input (str command-trigger "link")] [:editor/show-input [{:command :link :id :link :placeholder "Link" @@ -62,7 +63,7 @@ :placeholder "Label"}]]]) (defn image-link-steps [] - [[:editor/input (str (state/get-editor-command-trigger) "link")] + [[:editor/input (str command-trigger "link")] [:editor/show-input [{:command :image-link :id :link :placeholder "Link" @@ -72,7 +73,7 @@ :placeholder "Label"}]]]) (defn zotero-steps [] - [[:editor/input (str (state/get-editor-command-trigger) "zotero")] + [[:editor/input (str command-trigger "zotero")] [:editor/show-zotero]]) (def *extend-slash-commands (atom [])) @@ -96,19 +97,19 @@ [type] (let [template (util/format "@@%s: @@" type)] - [[:editor/input template {:last-pattern (state/get-editor-command-trigger) + [[:editor/input template {:last-pattern command-trigger :backward-pos 2}]])) (defn embed-page [] (conj - [[:editor/input "{{embed [[]]}}" {:last-pattern (state/get-editor-command-trigger) + [[:editor/input "{{embed [[]]}}" {:last-pattern command-trigger :backward-pos 4}]] [:editor/search-page :embed])) (defn embed-block [] - [[:editor/input "{{embed (())}}" {:last-pattern (state/get-editor-command-trigger) + [[:editor/input "{{embed (())}}" {:last-pattern command-trigger :backward-pos 4}] [:editor/search-block :embed]]) @@ -229,9 +230,9 @@ ["Image link" (image-link-steps) "Create a HTTP link to a image"] (when (state/markdown?) ["Underline" [[:editor/input "" - {:last-pattern (state/get-editor-command-trigger) + {:last-pattern command-trigger :backward-pos 6}]] "Create a underline text decoration"]) - ["Template" [[:editor/input (state/get-editor-command-trigger) nil] + ["Template" [[:editor/input command-trigger nil] [:editor/search-template]] "Insert a created template here"] (cond (and (util/electron?) (config/local-file-based-graph? (state/get-current-repo))) @@ -277,7 +278,7 @@ [["Query" [[:editor/input "{{query }}" {:backward-pos 2}] [:editor/exit]] query-doc] ["Zotero" (zotero-steps) "Import Zotero journal article"] - ["Query table function" [[:editor/input "{{function }}" {:backward-pos 2}]] "Create a query table function"] + ["Query function" [[:editor/input "{{function }}" {:backward-pos 2}]] "Create a query function"] ["Calculator" [[:editor/input "```calc\n\n```" {:type "block" :backward-pos 4}] [:codemirror/focus]] "Insert a calculator"] @@ -290,12 +291,12 @@ text)) "Draw a graph with Excalidraw"] ["Embed HTML " (->inline "html")] - ["Embed Video URL" [[:editor/input "{{video }}" {:last-pattern (state/get-editor-command-trigger) + ["Embed Video URL" [[:editor/input "{{video }}" {:last-pattern command-trigger :backward-pos 2}]]] ["Embed Youtube timestamp" [[:youtube/insert-timestamp]]] - ["Embed Twitter tweet" [[:editor/input "{{tweet }}" {:last-pattern (state/get-editor-command-trigger) + ["Embed Twitter tweet" [[:editor/input "{{tweet }}" {:last-pattern command-trigger :backward-pos 2}]]]] @*extend-slash-commands @@ -335,7 +336,7 @@ (when-let [input (gdom/getElement id)] (let [last-pattern (when-not (= last-pattern :skip-check) (when-not backward-truncate-number - (or last-pattern (state/get-editor-command-trigger)))) + (or last-pattern command-trigger))) edit-content (gobj/get input "value") current-pos (cursor/pos input) current-pos (or @@ -527,7 +528,7 @@ (let [edit-content (gobj/get current-input "value") current-pos (cursor/pos current-input) prefix (subs edit-content 0 current-pos) - prefix (util/replace-last (state/get-editor-command-trigger) prefix "" (boolean space?)) + prefix (util/replace-last command-trigger prefix "" (boolean space?)) new-value (str prefix (subs edit-content current-pos))] (state/set-block-content-and-last-pos! input-id diff --git a/src/main/frontend/components/assets.cljs b/src/main/frontend/components/assets.cljs index be5e74c96f9..69aa5cab129 100644 --- a/src/main/frontend/components/assets.cljs +++ b/src/main/frontend/components/assets.cljs @@ -88,11 +88,11 @@ :disabled (string/blank? val) :on-click on-submit)]])) -(rum/defc restart-button [active?] - (when active? - (ui/button (t :plugin/restart) - :on-click #(js/logseq.api.relaunch) - :small? true :intent "logseq"))) +(rum/defc restart-button + [] + (ui/button (t :plugin/restart) + :on-click #(js/logseq.api.relaunch) + :small? true :intent "logseq")) (rum/defcs ^:large-vars/data-var alias-directories < rum/reactive @@ -215,7 +215,7 @@ #(state/set-assets-alias-enabled! (not alias-enabled?)) true)] [:span - (restart-button alias-enabled-changed?)]] + (when alias-enabled-changed? (restart-button))]] (when alias-enabled? [:div.pt-4 diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index f60d03a0ab1..ff8cc0592db 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -6,13 +6,13 @@ [cljs-bean.core :as bean] [cljs.core.match :refer [match]] [cljs.reader :as reader] - [clojure.set :as set] [clojure.string :as string] [clojure.walk :as walk] [datascript.core :as d] [datascript.impl.entity :as de] [dommy.core :as dom] [frontend.commands :as commands] + [frontend.components.block.macros :as block-macros] [frontend.components.datetime :as datetime-comp] [frontend.components.lazy-editor :as lazy-editor] [frontend.components.macro :as macro] @@ -39,13 +39,11 @@ [frontend.fs :as fs] [frontend.handler.assets :as assets-handler] [frontend.handler.block :as block-handler] - [frontend.handler.common :as common-handler] [frontend.handler.dnd :as dnd] [frontend.handler.editor :as editor-handler] [frontend.handler.file-sync :as file-sync] [frontend.handler.notification :as notification] [frontend.handler.plugin :as plugin-handler] - [frontend.handler.query :as query-handler] [frontend.handler.repeated :as repeated] [frontend.handler.route :as route-handler] [frontend.handler.ui :as ui-handler] @@ -63,6 +61,7 @@ [frontend.util.clock :as clock] [frontend.util.drawer :as drawer] [frontend.util.property-edit :as property-edit] + [frontend.util.property :as property] [frontend.util.text :as text-util] [goog.dom :as gdom] [goog.object :as gobj] @@ -70,7 +69,6 @@ [logseq.graph-parser.block :as gp-block] [logseq.graph-parser.config :as gp-config] [logseq.graph-parser.mldoc :as gp-mldoc] - [logseq.graph-parser.property :as gp-property] [logseq.graph-parser.text :as text] [logseq.graph-parser.util :as gp-util] [logseq.graph-parser.util.block-ref :as block-ref] @@ -554,7 +552,7 @@ untitled? (str " opacity-50")) :data-ref page-name :draggable true - :on-drag-start (fn [e] (editor-handler/block->data-transfer! page-name e)) + :on-drag-start (fn [e] (editor-handler/block->data-transfer! page-name-in-block e)) :on-mouse-down (fn [_e] (reset! *mouse-down? true)) :on-mouse-up (fn [e] (when @*mouse-down? @@ -1253,17 +1251,7 @@ (defn- macro-function-cp [config arguments] (or - (when (:query-result config) - (when-let [query-result (rum/react (:query-result config))] - (let [fn-string (-> (util/format "(fn [result] %s)" (first arguments)) - (common-handler/safe-read-string "failed to parse function") - (query-handler/normalize-query-function query-result) - (str)) - f (sci/eval-string fn-string)] - (when (fn? f) - (try (f query-result) - (catch :default e - (js/console.error e))))))) + (some-> (:query-result config) rum/react (block-macros/function-macro arguments)) [:span.warning (util/format "{{function %s}}" (first arguments))])) @@ -1696,7 +1684,7 @@ :block) (util/stop e)) - (whiteboard-handler/inside-portal? (.-target e)) + (and (util/meta-key? e) (whiteboard-handler/inside-portal? (.-target e))) (do (whiteboard-handler/add-new-block-portal-shape! uuid (whiteboard-handler/closest-shape (.-target e))) @@ -1967,11 +1955,12 @@ (not= "nil" marker)) {:class (str (string/lower-case marker))}) (when bg-color - {:style {:background-color (if (some #{bg-color} ui/block-background-colors) - (str "var(--ls-highlight-color-" bg-color ")") - bg-color) - :color (when-not (some #{bg-color} ui/block-background-colors) "white")} - :class "px-1 with-bg-color"})) + (let [built-in-color? (ui/built-in-color? bg-color)] + {:style {:background-color (if built-in-color? + (str "var(--ls-highlight-color-" bg-color ")") + bg-color) + :color (when-not built-in-color? "white")} + :class "px-1 with-bg-color"}))) ;; children (let [area? (= :area (keyword (:hl-type properties))) @@ -2067,66 +2056,25 @@ :else (inline-text config (:block/format block) (str v)))]])) -(def hidden-editable-page-properties - "Properties that are hidden in the pre-block (page property)" - #{:title :filters :icon}) - -(assert (set/subset? hidden-editable-page-properties (gp-property/editable-built-in-properties)) - "Hidden editable page properties must be valid editable properties") - -(def hidden-editable-block-properties - "Properties that are hidden in a block (block property)" - (into #{:logseq.query/nlp-date} - gp-property/editable-view-and-table-properties)) - -(assert (set/subset? hidden-editable-block-properties (gp-property/editable-built-in-properties)) - "Hidden editable page properties must be valid editable properties") - -(defn- add-aliases-to-properties - [properties block] - (let [repo (state/get-current-repo) - aliases (db/get-page-alias-names repo - (:block/name (db/pull (:db/id (:block/page block)))))] - (if (seq aliases) - (if (:alias properties) - (update properties :alias (fn [c] - (util/distinct-by string/lower-case (concat c aliases)))) - (assoc properties :alias aliases)) - properties))) - (rum/defc properties-cp [config {:block/keys [pre-block?] :as block}] - (let [dissoc-keys (fn [m keys] (apply dissoc m keys)) - properties (cond-> (update-keys (:block/properties block) keyword) - true - (dissoc-keys (property-edit/hidden-properties)) - pre-block? - (dissoc-keys hidden-editable-page-properties) - (not pre-block?) - (dissoc-keys hidden-editable-block-properties) - pre-block? - (add-aliases-to-properties block))] + (let [ordered-properties + (property/get-visible-ordered-properties (:block/properties block) + (:block/properties-order block) + {:pre-block? pre-block? + :page-id (:db/id (:block/page block))})] (cond - (seq properties) - (let [properties-order (cond->> (:block/properties-order block) - true - (remove (property-edit/hidden-properties)) - pre-block? - (remove hidden-editable-page-properties)) - properties-order (distinct properties-order) - ordered-properties (if (seq properties-order) - (map (fn [k] [k (get properties k)]) properties-order) - properties)] - [:div.block-properties - {:class (when pre-block? "page-properties") - :title (if pre-block? - "Click to edit this page's properties" - "Click to edit this block's properties")} - (for [[k v] ordered-properties] - (rum/with-key (property-cp config block k v) - (str (:block/uuid block) "-" k)))]) - - (and pre-block? properties) + (seq ordered-properties) + [:div.block-properties + {:class (when pre-block? "page-properties") + :title (if pre-block? + "Click to edit this page's properties" + "Click to edit this block's properties")} + (for [[k v] ordered-properties] + (rum/with-key (property-cp config block k v) + (str (:block/uuid block) "-" k)))] + + (and pre-block? ordered-properties) [:span.opacity-50 "Properties"] :else @@ -2764,27 +2712,49 @@ (= (:id config) (str (:block/uuid block))))) +(defn- build-config [config block {:keys [navigating-block navigated?]}] + (cond-> config + navigated? + (assoc :id (str navigating-block)) + + true + (assoc :block block) + + ;; Each block might have multiple queries, but we store only the first query's result. + ;; This :query-result atom is used by the query function feature to share results between + ;; the parent's query block and the children blocks. This works because config is shared + ;; between parent and children blocks + (nil? (:query-result config)) + (assoc :query-result (atom nil)) + + (:ref? config) + (block-handler/attach-order-list-state block))) + +(defn- build-block [repo config block* {:keys [navigating-block navigated?]}] + (let [block (if (or (and (:custom-query? config) + (empty? (:block/_parent block*)) + (not (and (:dsl-query? config) + (string/includes? (:query config) "not")))) + navigated?) + (db/entity [:block/uuid navigating-block]) + block*)] + (merge (db/sub-block (:db/id block)) + (select-keys block [:block/level])))) + (rum/defc ^:large-vars/cleanup-todo block-container-inner < rum/reactive db-mixins/query - [state repo config block {:keys [edit? edit-input-id]}] - (let [ref? (:ref? config) - custom-query? (boolean (:custom-query? config)) + [state repo config* block* {:keys [edit? edit-input-id]}] + (let [ref? (:ref? config*) + custom-query? (boolean (:custom-query? config*)) ref-or-custom-query? (or ref? custom-query?) *navigating-block (get state ::navigating-block) navigating-block (rum/react *navigating-block) - navigated? (and (not= (:block/uuid block) navigating-block) navigating-block) - block (merge (db/sub-block (:db/id block)) - (select-keys block [:block/level])) - {:block/keys [uuid pre-block? refs level format content properties]} block + navigated? (and (not= (:block/uuid block*) navigating-block) navigating-block) + block (build-block repo config* block* {:navigating-block navigating-block :navigated? navigated?}) + {:block/keys [uuid pre-block? refs level content properties]} block children (db/sort-by-left (:block/_parent block) block) {:block.temp/keys [top?]} block - config (if navigated? (assoc config :id (str navigating-block)) config) + config (build-config config* block {:navigated? navigated? :navigating-block navigating-block}) blocks-container-id (:blocks-container-id config) - config (assoc config :block block) - ;; Each block might have multiple queries, but we store only the first query's result - config (if (nil? (:query-result config)) - (assoc config :query-result (atom nil)) - config) - config (if ref? (block-handler/attach-order-list-state config block) config) heading? (:heading properties) *control-show? (get state ::control-show?) db-collapsed? (util/collapsed? block) @@ -2810,6 +2780,8 @@ data-refs-self (build-refs-data-value refs) card? (string/includes? data-refs-self "\"card\"") review-cards? (:review-cards? config) + own-number-list? (:own-order-number-list? config) + order-list? (boolean own-number-list?) selected? (when-not slide? (state/sub-block-selected? blocks-container-id uuid))] [:div.ls-block @@ -2822,6 +2794,7 @@ (when pre-block? " pre-block") (when (and card? (not review-cards?)) " shadow-md") (when selected? " selected noselect") + (when order-list? " is-order-list") (when (string/blank? content) " is-blank")) :blockid (str uuid) :haschild (str (boolean has-child?))} @@ -2850,7 +2823,7 @@ (when top? (dnd-separator-wrapper block block-id slide? true false)) - [:div.flex.flex-row.pr-2 + [:div.block-main-container.flex.flex-row.pr-2 {:class (if (and heading? (seq (:block/title block))) "items-baseline" "") :on-touch-start (fn [event uuid] (block-handler/on-touch-start event uuid)) :on-touch-move (fn [event] @@ -2872,7 +2845,7 @@ (if whiteboard-block? (block-reference {} (str uuid) nil) ;; Not embed self - (let [block (merge block (block/parse-title-and-body uuid format pre-block? content)) + (let [block (merge block (block/parse-title-and-body uuid (:block/format block) pre-block? content)) hide-block-refs-count? (and (:embed? config) (= (:block/uuid block) (:embed-id config)))] (block-content-or-editor config block edit-input-id block-id edit? hide-block-refs-count?))) @@ -3140,14 +3113,15 @@ :else (let [language (if (contains? #{"edn" "clj" "cljc" "cljs"} language) "clojure" language)] - [:div {:ref (fn [el] - (set-inside-portal? (and el (whiteboard-handler/inside-portal? el))))} + [:div.ui-fenced-code-editor + {:ref (fn [el] + (set-inside-portal? (and el (whiteboard-handler/inside-portal? el))))} (cond (nil? inside-portal?) nil (or (:slide? config) inside-portal?) (highlight/highlight (str (random-uuid)) - {:class (str "language-" language) + {:class (str "language-" language) :data-lang language} code) @@ -3316,10 +3290,14 @@ [:sup.fn (str name "↩︎")]])]]) ["Src" options] - [:div.cp__fenced-code-block - (if-let [opts (plugin-handler/hook-fenced-code-by-type (util/safe-lower-case (:language options)))] - (plugins/hook-ui-fenced-code (string/join "" (:lines options)) opts) - (src-cp config options html-export?))] + (let [lang (util/safe-lower-case (:language options))] + [:div.cp__fenced-code-block + {:data-lang lang} + (if-let [opts (plugin-handler/hook-fenced-code-by-type lang)] + [:div.ui-fenced-code-wrap + (src-cp config options html-export?) + (plugins/hook-ui-fenced-code (:block config) (string/join "" (:lines options)) opts)] + (src-cp config options html-export?))]) :else "") diff --git a/src/main/frontend/components/block.css b/src/main/frontend/components/block.css index 33441e031d6..654b8f7afeb 100644 --- a/src/main/frontend/components/block.css +++ b/src/main/frontend/components/block.css @@ -1,7 +1,7 @@ .block-content-wrapper { /* 38px is the width of block-control */ width: calc(100% - 22px); - + user-select: text; @screen sm { width: calc(100% - 33px); overflow-x: visible; diff --git a/src/main/frontend/components/block/macros.cljs b/src/main/frontend/components/block/macros.cljs new file mode 100644 index 00000000000..55481721b6b --- /dev/null +++ b/src/main/frontend/components/block/macros.cljs @@ -0,0 +1,71 @@ +(ns frontend.components.block.macros + "Logseq macros that render and evaluate in blocks" + (:require [clojure.walk :as walk] + [frontend.extensions.sci :as sci] + [frontend.handler.common :as common-handler] + [goog.string :as gstring] + [goog.string.format])) + +(defn- normalize-query-function + [ast result] + (let [ast (walk/prewalk + (fn [f] + (if (and (list? f) + (keyword? (second f)) + (contains? #{'sum 'average 'count 'min 'max} (first f))) + (if (contains? #{'min 'max} (first f)) + (list + 'apply + (first f) + (list 'map (second f) 'result)) + (list + (first f) + (list 'map (second f) 'result))) + f)) + ast)] + (walk/postwalk + (fn [f] + (cond + (keyword? f) + ;; These keyword aliases should be the same as those used in the query-table for sorting + (case f + :block + :block/content + + :page + :block/name + + :created-at + :block/created-at + + :updated-at + :block/updated-at + + (let [vals (map #(get-in % [:block/properties f]) result) + int? (some integer? vals)] + `(~'fn [~'b] + (~'let [~'result-str (~'get-in ~'b [:block/properties ~f]) + ~'result-num (~'parseFloat ~'result-str) + ~'result (if (~'isNaN ~'result-num) ~'result-str ~'result-num)] + (~'or ~'result (~'when ~int? 0)))))) + + :else + f)) + ast))) + +(defn function-macro + "Provides functionality for {{function}}" + [query-result* arguments] + (let [query-result (if (map? query-result*) + ;; Ungroup results grouped by page in page view + (mapcat val query-result*) + query-result*) + fn-string (-> (gstring/format "(fn [result] %s)" (first arguments)) + (common-handler/safe-read-string "failed to parse function") + (normalize-query-function query-result) + (str)) + f (sci/eval-string fn-string)] + (when (fn? f) + (try (f query-result) + (catch :default e + (js/console.error e)))))) \ No newline at end of file diff --git a/src/main/frontend/components/bug_report.cljs b/src/main/frontend/components/bug_report.cljs index afe93dcfc54..f6cd0c272cf 100644 --- a/src/main/frontend/components/bug_report.cljs +++ b/src/main/frontend/components/bug_report.cljs @@ -5,7 +5,8 @@ [frontend.util :as util] [reitit.frontend.easy :as rfe] [clojure.string :as string] - [frontend.handler.notification :as notification])) + [frontend.handler.notification :as notification] + [frontend.context.i18n :refer [t]])) (defn parse-clipboard-data-transfer "parse dataTransfer @@ -42,7 +43,7 @@ copy-result-to-clipboard! (fn [result] (util/copy-to-clipboard! result) - (notification/show! "Copied to clipboard!")) + (notification/show! (t :bug-report/inspector-page-copy-notif))) reset-step! (fn [] (set-step! 0) @@ -56,26 +57,26 @@ [:div.flex.flex-col (when (= step 0) - (list [:div.mx-auto "Press Ctrl+V / ⌘+V to inspect your clipboard data"] - [:div.mx-auto "or click here to paste if you are using the mobile version"] + (list [:div.mx-auto (t :bug-report/inspector-page-desc-1)] + [:div.mx-auto (t :bug-report/inspector-page-desc-2)] ;; for mobile - [:input.form-input.is-large.transition.duration-150.ease-in-out {:type "text" :placeholder "Long press here to paste if you are on mobile"}] + [:input.form-input.is-large.transition.duration-150.ease-in-out {:type "text" :placeholder (t :bug-report/inspector-page-placeholder)}] [:div.flex.justify-between.items-center.mt-2 - [:div "Something wrong? No problem, click to go back to the previous step."] - (ui/button "Go back" :on-click #(util/open-url (rfe/href :bug-report)))])) + [:div (t :bug-report/inspector-page-tip)] + (ui/button (t :bug-report/inspector-page-btn-back) :on-click #(util/open-url (rfe/href :bug-report)))])) (when (= step 1) (list - [:div "Here is the data read from clipboard."] + [:div (t :bug-report/inspector-page-desc-clipboard)] [:div.flex.justify-between.items-center.mt-2 - [:div "If this is okay to share, click the copy button."] - (ui/button "Copy the result" :on-click #(copy-result-to-clipboard! (js/JSON.stringify (clj->js result) nil 2)))] + [:div (t :bug-report/inspector-page-desc-copy)] + (ui/button (t :bug-report/inspector-page-btn-copy) :on-click #(copy-result-to-clipboard! (js/JSON.stringify (clj->js result) nil 2)))] [:div.flex.justify-between.items-center.mt-2 - [:div "Now you can report the result pasted to your clipboard. Please paste the result in the 'Additional Context' section and state where you copied the original content from. Thanks!"] - (ui/button "Create an issue" :href header/bug-report-url)] + [:div (t :bug-report/inspector-page-desc-create-issue)] + (ui/button (t :bug-report/inspector-page-btn-create-issue) :href header/bug-report-url)] [:div.flex.justify-between.items-center.mt-2 - [:div "Something wrong? No problem, click to go back to the previous step."] - (ui/button "Go back" :on-click reset-step!)] + [:div (t :bug-report/inspector-page-tip)] + (ui/button (t :bug-report/inspector-page-btn-back) :on-click reset-step!)] [:pre.whitespace-pre-wrap [:code (js/JSON.stringify (clj->js result) nil 2)]]))])) @@ -102,17 +103,17 @@ [:div.flex.flex-col.items-center [:div.flex.items-center.mb-2 (ui/icon "bug") - [:h1.text-3xl.ml-2 "Bug report"]] - [:div.opacity-60 "Can you help us out by submitting a bug report? We'll get it sorted out as soon as we can."]] + [:h1.text-3xl.ml-2 (t :bug-report/main-title)]] + [:div.opacity-60 (t :bug-report/main-desc)]] [:div.cp__bug-report-reporter.rounded-lg.p-8.mt-8 - [:h1.text-2xl "Is the bug you encountered related to these features?"] - [:div.opacity-60 "You can use these handy tools to give us additional information."] - (report-item-button "Clipboard helper" - "Inspect and collect clipboard data" + [:h1.text-2xl (t :bug-report/section-clipboard-title)] + [:div.opacity-60 (t :bug-report/section-clipboard-desc)] + (report-item-button (t :bug-report/section-clipboard-btn-title) + (t :bug-report/section-clipboard-btn-desc) "clipboard" {:on-click #(util/open-url (rfe/href :bug-report-tools {:tool "clipboard-data-inspector"}))}) [:div.py-2] ;; divider [:div.flex.flex-col - [:h1.text-2xl "Or..."] - [:div.opacity-60 "If there are no tools available for you to gather additional information, please report the bug directly."] - (report-item-button "Submit a bug report" "Help Make Logseq Better!" "message-report" {:on-click #(util/open-url header/bug-report-url)})]]]) + [:h1.text-2xl (t :bug-report/section-issues-title)] + [:div.opacity-60 (t :bug-report/section-issues-desc)] + (report-item-button (t :bug-report/section-issues-btn-title) (t :bug-report/section-issues-btn-desc) "message-report" {:on-click #(util/open-url header/bug-report-url)})]]]) diff --git a/src/main/frontend/components/container.cljs b/src/main/frontend/components/container.cljs index c76b1391949..b66c1fdcac9 100644 --- a/src/main/frontend/components/container.cljs +++ b/src/main/frontend/components/container.cljs @@ -35,12 +35,13 @@ [frontend.ui :as ui] [frontend.util :as util] [frontend.util.cursor :as cursor] + [frontend.components.window-controls :as window-controls] [goog.dom :as gdom] [goog.object :as gobj] + [logseq.common.path :as path] [react-draggable] [reitit.frontend.easy :as rfe] - [rum.core :as rum] - [logseq.common.path :as path])) + [rum.core :as rum])) (rum/defc nav-content-item < rum/reactive [name {:keys [class]} child] @@ -284,8 +285,8 @@ (when (< touching-x-offset 0) (max touching-x-offset (- 0 (:width el-rect)))))) offset-ratio (and (number? touching-x-offset) - (some->> (:width el-rect) - (/ touching-x-offset)))] + (some->> (:width el-rect) + (/ touching-x-offset)))] (rum/use-effect! #(js/setTimeout @@ -481,7 +482,7 @@ (rum/defc main < {:did-mount (fn [state] - (when-let [element (gdom/getElement "main-content-container")] + (when-let [element (gdom/getElement "app-container")] (dnd/subscribe! element :upload-files @@ -492,19 +493,23 @@ (common-handler/listen-to-scroll! element) (when (:margin-less-pages? (first (:rum/args state))) ;; makes sure full screen pages displaying without scrollbar (set! (.. element -scrollTop) 0))) - state)} + state) + :will-unmount (fn [state] + (when-let [el (gdom/getElement "app-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?]}] - (let [left-sidebar-open? (state/sub :ui/left-sidebar-open?) + (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?) (= :home route-name)) - margin-less-pages? (or (and (mobile-util/native-platform?) onboarding-and-home?) margin-less-pages?)] + margin-less-pages? (or (and (mobile-util/native-platform?) onboarding-and-home?) margin-less-pages?)] [:div#main-container.cp__sidebar-main-layout.flex-1.flex {:class (util/classnames [{:is-left-sidebar-open left-sidebar-open?}])} ;; desktop left sidebar layout (left-sidebar {:left-sidebar-open? left-sidebar-open? - :route-match route-match}) + :route-match route-match}) [:div#main-content-container.scrollbar-spacing.w-full.flex.justify-center.flex-row.outline-none.relative @@ -536,7 +541,7 @@ db-restoring? [:div.mt-20 [:div.ls-center - (ui/loading (t :loading))]] + (ui/loading)]] :else [:div @@ -730,6 +735,8 @@ indexeddb-support? (state/sub :indexeddb/support?) page? (= :page route-name) home? (= :home route-name) + native-titlebar? (state/sub [:electron/user-cfgs :window/native-titlebar?]) + window-controls? (and (util/electron?) (not util/mac?) (not native-titlebar?)) edit? (:editor/editing? @state/state) default-home (get-default-home-if-valid) logged? (user-handler/logged-in?) @@ -759,6 +766,7 @@ {:class (util/classnames [{:ls-left-sidebar-open left-sidebar-open? :ls-right-sidebar-open sidebar-open? :ls-wide-mode wide-mode? + :ls-window-controls window-controls? :ls-fold-button-on-right fold-button-on-right? :ls-hl-colored ls-block-hl-colored?}])} @@ -795,6 +803,9 @@ :show-action-bar? show-action-bar? :show-recording-bar? show-recording-bar?})] + (when window-controls? + (window-controls/container)) + (right-sidebar/sidebar) [:div#app-single-container]] diff --git a/src/main/frontend/components/container.css b/src/main/frontend/components/container.css index 6f8c4385477..d8b1acb57ea 100644 --- a/src/main/frontend/components/container.css +++ b/src/main/frontend/components/container.css @@ -93,6 +93,7 @@ height: calc(100vh - var(--ls-headbar-inner-top-padding) - 50px); margin-top: 30px; width: 100%; + padding-top: var(--ls-win32-title-bar-height); > .fake-bar { @apply w-full px-5 pt-1 sm:hidden; @@ -450,6 +451,28 @@ } } +.ls-window-controls { + &.ls-right-sidebar-open { + .cp__right-sidebar-topbar { + margin-right: 144px; + + .is-fullscreen & { + margin-right: 48px; + } + } + } + + &:not(.ls-right-sidebar-open) { + .cp__header > .r { + margin-right: 144px; + + .is-fullscreen & { + margin-right: 48px; + } + } + } +} + .ls-wide-mode { .cp__sidebar-main-content { max-width: var(--ls-main-content-max-width-wide); @@ -465,7 +488,8 @@ html[data-theme='dark'] { } .settings-modal { - margin: -15px; + @apply -m-8 rounded-lg; + /* box-shadow: inset 0 0 0 1px var(--ls-border-color); */ } .cp__sidebar-main-layout { @@ -513,6 +537,7 @@ html[data-theme='dark'] { .resizer { @apply absolute top-0 bottom-0; + touch-action: none; left: 0; width: 4px; user-select: none; @@ -537,7 +562,6 @@ html[data-theme='dark'] { } &.open { - width: var(--ls-right-sidebar-width); max-width: 60vw; } @@ -573,7 +597,9 @@ html[data-theme='dark'] { user-select: none; -webkit-app-region: drag; - a, svg { + a, + svg, + button { -webkit-app-region: no-drag; } } diff --git a/src/main/frontend/components/conversion.cljs b/src/main/frontend/components/conversion.cljs index 81526e03d2c..8d927bcb15e 100644 --- a/src/main/frontend/components/conversion.cljs +++ b/src/main/frontend/components/conversion.cljs @@ -149,7 +149,7 @@ [:p (t :file-rn/need-action)]) [:p (ui/button - (str (t :file-rn/all-action) " (" (count rename-items) ")") + (t :file-rn/all-action (count rename-items)) :on-click > [(when (state/enable-editing?) @@ -128,8 +128,13 @@ :options {:href (rfe/href :bug-report)} :icon (ui/icon "bug")}) + (when config/publishing? + {:title (t :toggle-theme) + :options {:on-click #(state/toggle-theme!)} + :icon (ui/icon "bulb")}) + (when (and (state/sub :auth/id-token) (user-handler/logged-in?)) - {:title (str (t :logout) " (" (user-handler/email) ")") + {:title (t :logout-user (user-handler/email)) :options {:on-click #(user-handler/logout)} :icon (ui/icon "logout")})] (concat page-menu-and-hr) @@ -143,12 +148,12 @@ (ui/with-shortcut :go/backward "bottom" [:button.it.navigation.nav-left.button.icon - {:title "Go back" :on-click #(js/window.history.back)} + {:title (t :header/go-back) :on-click #(js/window.history.back)} (ui/icon "arrow-left" {:size ui/icon-size})]) (ui/with-shortcut :go/forward "bottom" [:button.it.navigation.nav-right.button.icon - {:title "Go forward" :on-click #(js/window.history.forward)} + {:title (t :header/go-forward) :on-click #(js/window.history.forward)} (ui/icon "arrow-right" {:size ui/icon-size})])]) (rum/defc updater-tips-new-version @@ -213,13 +218,13 @@ (when-not (or (state/home?) custom-home-page? (state/whiteboard-dashboard?)) (ui/with-shortcut :go/backward "bottom" [:button.it.navigation.nav-left.button.icon.opacity-70 - {:title "Go back" :on-click #(js/window.history.back)} + {:title (t :header/go-back) :on-click #(js/window.history.back)} (ui/icon "chevron-left" {:size 26})])) ;; search button for non-mobile (when current-repo (ui/with-shortcut :go/search "right" [:button.button.icon#search-button - {:title "Search" + {:title (t :header/search) :on-click #(do (when (or (mobile-util/native-android?) (mobile-util/native-iphone?)) (state/set-left-sidebar-open! false)) @@ -269,7 +274,6 @@ :current-repo current-repo :default-home default-home}) - (when (not (state/sub :ui/sidebar-open?)) - (sidebar/toggle)) + (sidebar/toggle) (updater-tips-new-version t)]])) diff --git a/src/main/frontend/components/header.css b/src/main/frontend/components/header.css index 17a3640bdcc..5507cd5a802 100644 --- a/src/main/frontend/components/header.css +++ b/src/main/frontend/components/header.css @@ -1,7 +1,9 @@ .cp__header { - @apply z-10; - - padding-top: var(--ls-headbar-inner-top-padding); + @apply shadow z-10; + -webkit-app-region: drag; + + padding-top: calc(var(--ls-headbar-inner-top-padding)); + margin-top: var(--ls-win32-title-bar-height); height: calc(var(--ls-headbar-height) + var(--ls-headbar-inner-top-padding)); display: flex; align-items: center; diff --git a/src/main/frontend/components/onboarding.cljs b/src/main/frontend/components/onboarding.cljs index abb78363ee3..ab2dc132c76 100644 --- a/src/main/frontend/components/onboarding.cljs +++ b/src/main/frontend/components/onboarding.cljs @@ -16,7 +16,7 @@ [:span.mr-1 (t :help/forum-community)] (ui/icon "message-circle" {:style {:font-size 20}})] list - [{:title "Usage" + [{:title (t :help/title-usage) :children [[[:a {:on-click (fn [] (state/sidebar-add-block! (state/get-current-repo) "shortcut-settings" :shortcut-settings))} [:div.flex-row.inline-flex.items-center @@ -26,21 +26,21 @@ [(t :help/start) "https://docs.logseq.com/#/page/tutorial"] ["FAQ" "https://docs.logseq.com/#/page/faq"]]} - {:title "Community" + {:title (t :help/title-community) :children [[(t :help/awesome-logseq) "https://github.com/logseq/awesome-logseq"] [(t :help/blog) "https://blog.logseq.com"] [discourse-with-icon "https://discuss.logseq.com"]]} - {:title "Development" + {:title (t :help/title-development) :children [[(t :help/roadmap) "https://trello.com/b/8txSM12G/roadmap"] [(t :help/bug) "https://github.com/logseq/logseq/issues/new?labels=from:in-app&template=bug_report.yaml"] [(t :help/feature) "https://discuss.logseq.com/c/feature-requests/"] [(t :help/changelog) "https://docs.logseq.com/#/page/changelog"]]} - {:title "About" + {:title (t :help/title-about) :children [[(t :help/about) "https://blog.logseq.com/about/"]]} - {:title "Terms" + {:title (t :help/title-terms) :children [[(t :help/privacy) "https://blog.logseq.com/privacy-policy/"] [(t :help/terms) "https://blog.logseq.com/terms/"]]}]] diff --git a/src/main/frontend/components/onboarding/quick_tour.cljs b/src/main/frontend/components/onboarding/quick_tour.cljs index 70532408626..0f923805d1a 100644 --- a/src/main/frontend/components/onboarding/quick_tour.cljs +++ b/src/main/frontend/components/onboarding/quick_tour.cljs @@ -18,7 +18,7 @@ [^js jsTour] (let [^js el (js/document.createElement "button")] (.add (.-classList el) "cp__onboarding-skip-quick-tour") - (set! (.-innerHTML el) (h/render-html [:span [:i.ti.ti-player-skip-forward] "Skip Quick Tour"])) + (set! (.-innerHTML el) (h/render-html [:span [:i.ti.ti-player-skip-forward] (t :on-boarding/quick-tour-btn-skip)])) (.addEventListener el "click" #(.cancel jsTour)) [#(.appendChild js/document.body el) #(.removeChild js/document.body el)])) @@ -36,21 +36,21 @@ (h/render-html [:div.steps - [:strong (str "STEP " current)] + [:strong (str (t :on-boarding/quick-tour-steps) current)] [:ul (for [i (range total)] [:li {:class (when (= current (inc i)) "active")} i])]])) (defn- create-steps! [^js jsTour] [ ;; step 1 {:id "nav-help" - :text (h/render-html [:section [:h2 "❓ Help"] - [:p "You can always click here for help and other information about Logseq."]]) + :text (h/render-html [:section [:h2 (t :on-boarding/quick-tour-help-title)] + [:p (t :on-boarding/quick-tour-help-desc)]]) :attachTo {:element ".cp__sidebar-help-btn" :on "top"} :beforeShowPromise #(if (state/sub :ui/sidebar-open?) (wait-target state/hide-right-sidebar! 700) (p/resolved true)) :canClickTarget true - :buttons [{:text "Next" :action (.-next jsTour)}] + :buttons [{:text (t :on-boarding/quick-tour-btn-next) :action (.-next jsTour)}] :popperOptions {:modifiers [{:name "preventOverflow" :options {:padding 20}} {:name "offset" @@ -58,11 +58,11 @@ ;; step 2 {:id "nav-journal-page" - :text (h/render-html [:section [:h2 "📆 Daily Journal Page"] + :text (h/render-html [:section [:h2 (t :on-boarding/quick-tour-journal-page-title)] [:p - [:span "This is today’s daily journal page. Here you can dump your thoughts, learnings and ideas. Don’t worry about organizing. Just write and"] - [:a "[[link]]"] - [:span "your thoughts."]]]) + [:span (t :on-boarding/quick-tour-journal-page-desc-1)] + [:a (t :on-boarding/quick-tour-journal-page-desc-2)] + [:span (t :on-boarding/quick-tour-journal-page-desc-3)]]]) :attachTo {:element ".page.is-journals .page-title" :on "top-end"} :beforeShowPromise #(if-not (= (util/safe-lower-case (state/get-current-page)) @@ -71,8 +71,8 @@ (route-handler/redirect-to-page! (date/today)) (util/scroll-to-top)) 200) (p/resolved true)) - :buttons [{:text "Back" :classes "back" :action (.-back jsTour)} - {:text "Next" :action (.-next jsTour)}] + :buttons [{:text (t :on-boarding/quick-tour-btn-back) :classes "back" :action (.-back jsTour)} + {:text (t :on-boarding/quick-tour-btn-next) :action (.-next jsTour)}] :popperOptions {:modifiers [{:name "preventOverflow" :options {:padding 63}} {:name "offset" @@ -80,13 +80,13 @@ ;; step 3 {:id "nav-left-sidebar" - :text (h/render-html [:section [:h2 "👀 Left Sidebar"] - [:p [:span "Open the left sidebar to explore important menu items in Logseq."]]]) + :text (h/render-html [:section [:h2 (t :on-boarding/quick-tour-left-sidebar-title)] + [:p [:span (t :on-boarding/quick-tour-left-sidebar-desc)]]]) :attachTo {:element "#left-menu" :on "top"} :beforeShowPromise #(p/resolved true) - :buttons [{:text "Back" :classes "back" :action (.-back jsTour)} - {:text "Next" :action (.-next jsTour)}] + :buttons [{:text (t :on-boarding/quick-tour-btn-back) :classes "back" :action (.-back jsTour)} + {:text (t :on-boarding/quick-tour-btn-next) :action (.-next jsTour)}] :popperOptions {:modifiers [{:name "preventOverflow" :options {:padding 20}} {:name "offset" @@ -94,15 +94,15 @@ ;; step 4 {:id "nav-favorites" - :text (h/render-html [:section [:h2 "⭐️ Favorites"] - [:p "Pin your favorite pages via the `... `menu on any page."] - [:p "We’ve also added some template pages here to help you get started. You can remove these once you start writing your own notes."]]) + :text (h/render-html [:section [:h2 (t :on-boarding/quick-tour-favorites-title)] + [:p (t :on-boarding/quick-tour-favorites-desc-1)] + [:p (t :on-boarding/quick-tour-favorites-desc-2)]]) :beforeShowPromise #(if-not (state/sub :ui/left-sidebar-open?) (wait-target state/toggle-left-sidebar! 500) (p/resolved true)) :attachTo {:element ".nav-content-item.favorites" :on "right"} - :buttons [{:text "Back" :classes "back" :action (.-back jsTour)} - {:text "Finish" :action (.-complete jsTour)}]} + :buttons [{:text (t :on-boarding/quick-tour-btn-back) :classes "back" :action (.-back jsTour)} + {:text (t :on-boarding/quick-tour-btn-finish) :action (.-complete jsTour)}]} ]) (defn- create-steps-file-sync! [^js jsTour] @@ -164,7 +164,7 @@ (wait-target ".nav-header .whiteboard" 500) (util/scroll-to-top)) :canClickTarget true - :buttons [{:text "Next" :action (.-next jsTour)}] + :buttons [{:text (t :on-boarding/tour-whiteboard-btn-next) :action (.-next jsTour)}] :popperOptions {:modifiers [{:name "preventOverflow" :options {:padding 20}} {:name "offset" @@ -178,8 +178,8 @@ (route-handler/redirect-to-whiteboard-dashboard!) (wait-target ".dashboard-create-card" 500)) :attachTo {:element ".dashboard-create-card" :on "bottom"} - :buttons [{:text "Back" :classes "back" :action (.-back jsTour)} - {:text "Finish" :action (.-complete jsTour)}] + :buttons [{:text (t :on-boarding/tour-whiteboard-btn-back) :classes "back" :action (.-back jsTour)} + {:text (t :on-boarding/tour-whiteboard-btn-finish) :action (.-complete jsTour)}] :popperOptions {:modifiers [{:name "preventOverflow" :options {:padding 20}} {:name "offset" @@ -277,7 +277,7 @@ (defn init [] (command-palette/register {:id :document/quick-tour - :desc "Quick tour for onboarding" + :desc (t :on-boarding/command-palette-quick-tour) :action #(ready start)}) ;; TODO: fix logic diff --git a/src/main/frontend/components/onboarding/setups.cljs b/src/main/frontend/components/onboarding/setups.cljs index 8f3c92d6f31..06885e4fe4d 100644 --- a/src/main/frontend/components/onboarding/setups.cljs +++ b/src/main/frontend/components/onboarding/setups.cljs @@ -30,13 +30,13 @@ [:h1.text-xl (if picker? - [:span [:strong (ui/icon "heart")] "Welcome to " [:strong "Logseq!"]] - [:span [:strong (ui/icon "file-import")] "Import existing notes"])] + [:span [:strong (ui/icon "heart")] (t :on-boarding/main-title) [:strong "Logseq!"]] + [:span [:strong (ui/icon "file-import")] (t :on-boarding/importing-main-title)])] [:h2 (if picker? - "First you need to choose a folder where Logseq will store your thoughts, ideas, notes." - "You can also do this later in the app.")] + (t :on-boarding/main-desc) + (t :on-boarding/importing-main-desc))] content])]) @@ -93,8 +93,8 @@ (if parsing? (ui/loading "") - [[:strong "Choose a folder"] - [:small "Open existing directory or Create a new one"]])]]] + [[:strong (t :on-boarding/section-btn-title)] + [:small (t :on-boarding/section-btn-desc)]])]]] [:div.px-5 (ui/admonition :warning (widgets/native-fs-api-alert))]))] @@ -102,22 +102,22 @@ [:p.flex [:i.as-flex-center (ui/icon "zoom-question" {:style {:fontSize "22px"}})] [:span.flex-1.flex.flex-col - [:strong "How Logseq saves your work"] - [:small.opacity-60 "Inside the directory you choose, Logseq will create 4 folders."]]] + [:strong (t :on-boarding/section-title)] + [:small.opacity-60 (t :on-boarding/section-desc)]]] [:p.text-sm.pt-5.tracking-wide - [:span (str "Each page is a file stored only on your " DEVICE ".")] + [:span (str (t :on-boarding/section-tip-1) DEVICE ".")] [:br] - [:span "You may choose to sync it later."]] + [:span (t :on-boarding/section-tip-2)]] [:ul (for [[title label icon] - [["Graphics & Documents" "/assets" "whiteboard"] - ["Daily notes" "/journals" "calendar-plus"] - ["PAGES" "/pages" "page"] + [[(t :on-boarding/section-assets) "/assets" "whiteboard"] + [(t :on-boarding/section-journals) "/journals" "calendar-plus"] + [(t :on-boarding/section-pages) "/pages" "page"] [] - ["APP Internal" "/logseq" "tool"] - ["Config File" "/logseq/config.edn"]]] + [(t :on-boarding/section-app) "/logseq" "tool"] + [(t :on-boarding/section-config) "/logseq/config.edn"]]] (if-not title [:li.hr] [:li @@ -221,14 +221,14 @@ :importer [:article.flex.flex-col.items-center.importer.py-16.px-8 [:section.c.text-center - [:h1 "Do you already have notes that you want to import?"] - [:h2 "If they are in a JSON, EDN or Markdown format Logseq can work with them."]] + [:h1 (t :on-boarding/importing-title)] + [:h2 (t :on-boarding/importing-desc)]] [:section.d.md:flex [:label.action-input.flex.items-center.mx-2.my-2 [:span.as-flex-center [:i (svg/roam-research 28)]] [:div.flex.flex-col [[:strong "RoamResearch"] - [:small "Import a JSON Export of your Roam graph"]]] + [:small (t :on-boarding/importing-roam-desc)]]] [:input.absolute.hidden {:id "import-roam" :type "file" @@ -238,7 +238,7 @@ [:span.as-flex-center [:i (svg/logo 28)]] [:span.flex.flex-col [[:strong "EDN / JSON"] - [:small "Import an EDN or a JSON Export of your Logseq graph"]]] + [:small (t :on-boarding/importing-lsq-desc)]]] [:input.absolute.hidden {:id "import-lsq" :type "file" @@ -248,7 +248,7 @@ [:span.as-flex-center (ui/icon "sitemap" {:style {:fontSize "26px"}})] [:span.flex.flex-col [[:strong "OPML"] - [:small " Import OPML files"]]] + [:small (t :on-boarding/importing-opml-desc)]]] [:input.absolute.hidden {:id "import-opml" diff --git a/src/main/frontend/components/page.cljs b/src/main/frontend/components/page.cljs index 1ee8dd302b9..9457d128d34 100644 --- a/src/main/frontend/components/page.cljs +++ b/src/main/frontend/components/page.cljs @@ -202,8 +202,7 @@ [:ul.mt-2 (for [[original-name name] (sort-by last pages)] [:li {:key (str "tagged-page-" name)} - [:a {:href (rfe/href :page {:name name})} - original-name]])] + (component-block/page-cp {} {:block/name name :block/original-name original-name})])] {:default-collapsed? false})]]))) (rum/defc page-title-editor < rum/reactive @@ -213,6 +212,11 @@ (util/page-name-sanity-lc @*title-value)) (db/page-exists? page-name) (db/page-exists? @*title-value)) + rollback-fn #(do + (reset! *title-value old-name) + (gobj/set (rum/deref input-ref) "value" old-name) + (reset! *edit? true) + (.focus (rum/deref input-ref))) confirm-fn (fn [] (let [new-page-name (string/trim @*title-value)] (ui/make-confirm-modal @@ -223,16 +227,7 @@ (close-fn) (page-handler/rename! (or title page-name) @*title-value) (reset! *edit? false)) - :on-cancel (fn [] - (reset! *title-value old-name) - (gobj/set (rum/deref input-ref) "value" old-name) - (reset! *edit? true) - (.focus (rum/deref input-ref)))}))) - rollback-fn #(do - (reset! *title-value old-name) - (gobj/set (rum/deref input-ref) "value" old-name) - (reset! *edit? false) - (when-not untitled? (notification/show! "Illegal page name, can not rename!" :warning))) + :on-cancel rollback-fn}))) blur-fn (fn [e] (when (gp-util/wrapped-by-quotes? @*title-value) (swap! *title-value gp-util/unquote-string) @@ -242,13 +237,16 @@ (reset! *edit? false) (string/blank? @*title-value) - (rollback-fn) + (do (when-not untitled? (notification/show! (t :page/illegal-page-name) :warning)) + (rollback-fn)) - (and (collide?) whiteboard-page?) - (notification/show! (str "Page “" @*title-value "” already exists!") :error) + (and (collide?) (or whiteboard-page? (model/whiteboard-page? @*title-value))) + (do (notification/show! (t :page/page-already-exists @*title-value) :error) + (rollback-fn)) (and (date/valid-journal-title? @*title-value) whiteboard-page?) - (notification/show! (str "Whiteboard page cannot be renamed with journal titles!") :error) + (do (notification/show! (t :page/whiteboard-to-journal-error) :error) + (rollback-fn)) untitled? (page-handler/rename! (or title page-name) @*title-value) @@ -815,7 +813,7 @@ [:div.mt-3.text-center.sm:mt-0.sm:ml-4.sm:text-left [:h3#modal-headline.text-lg.leading-6.font-medium (if orphaned-pages? - (str (t :remove-orphaned-pages) "?") + (t :remove-orphaned-pages) (t :page/delete-confirmation))]]] [:table.table-auto.cp__all_pages_table.mt-4 @@ -851,7 +849,7 @@ (close-fn) (doseq [page-name (map :block/name pages)] (page-handler/delete! page-name #())) - (notification/show! (str (t :tips/all-done) "!") :success) + (notification/show! (t :tips/all-done) :success) (js/setTimeout #(refresh-fn) 200)))]])) (rum/defc pagination @@ -1036,7 +1034,7 @@ [:div.r.flex.items-center.justify-between [:div (ui/tippy - {:html [:small (str (t :page/show-whiteboards) " ?")] + {:html [:small (t :page/show-whiteboards)] :arrow true} [:a.button.whiteboard {:class (util/classnames [{:active (boolean @*whiteboard?)}]) @@ -1044,7 +1042,7 @@ (ui/icon "whiteboard" {:extension? true :style {:fontSize ui/icon-size}})])] [:div (ui/tippy - {:html [:small (str (t :page/show-journals) " ?")] + {:html [:small (t :page/show-journals)] :arrow true} [:a.button.journal {:class (util/classnames [{:active (boolean @*journal?)}]) diff --git a/src/main/frontend/components/plugins.cljs b/src/main/frontend/components/plugins.cljs index 82df11102da..f10a946f286 100644 --- a/src/main/frontend/components/plugins.cljs +++ b/src/main/frontend/components/plugins.cljs @@ -5,6 +5,7 @@ [frontend.context.i18n :refer [t]] [frontend.ui :as ui] [frontend.handler.ui :as ui-handler] + [frontend.handler.editor :as editor-handler] [frontend.handler.plugin-config :as plugin-config-handler] [frontend.handler.common.plugin :as plugin-common-handler] [frontend.search :as search] @@ -191,10 +192,7 @@ (ui/admonition :warning [:p.text-md - "Plugins can access your graph and your local files, issue network requests. - They can also cause data corruption or loss. We're working on proper access rules for your graphs. - Meanwhile, make sure you have regular backups of your graphs and only install the plugins when you can read and - understand the source code."])) + (t :plugin/security-warning)])) (rum/defc card-ctls-of-market < rum/static [item stat installed? installing-or-updating?] @@ -273,7 +271,7 @@ (if installing-or-updating? (t :plugin/updating) (if new-version - (str (t :plugin/update) " 👉 " new-version) + [:span (t :plugin/update) " 👉 " new-version] (t :plugin/check-update)))]]) (ui/toggle (not disabled?) @@ -365,7 +363,7 @@ (.focus target))} (ui/icon "x")]) [:input.form-input.is-small - {:placeholder "Search plugins" + {:placeholder (t :plugin/search-plugin) :ref *search-ref :auto-focus true :on-key-down (fn [^js e] @@ -459,6 +457,22 @@ (state/set-state! [:electron/user-cfgs :settings/agent] opts) (state/close-sub-modal! :https-proxy-panel))))]]])) +(rum/defc auto-check-for-updates-control + [] + (let [[enabled, set-enabled!] (rum/use-state (plugin-handler/get-enabled-auto-check-for-updates?)) + text (t :plugin/auto-check-for-updates)] + + [:div.flex.items-center.justify-between.px-4.py-2 + {:on-click (fn [] + (let [t (not enabled)] + (set-enabled! t) + (plugin-handler/set-enabled-auto-check-for-updates t) + (notification/show! + [:span text [:strong.pl-1 (if t "ON" "OFF")] "!"] + (if t :success :info))))} + [:span.pr-3.opacity-80 text] + (ui/toggle enabled #() true)])) + (rum/defc ^:large-vars/cleanup-todo panel-control-tabs < rum/static [search-key *search-key category *category sort-by *sort-by filter-by *filter-by total-nums @@ -557,7 +571,7 @@ :options {:on-click #(reset! *sort-by :stars)} :icon (ui/icon (aim-icon :stars))} - {:title (str (t :plugin/title) " (A - Z)") + {:title (t :plugin/title "A - Z") :options {:on-click #(reset! *sort-by :letters)} :icon (ui/icon (aim-icon :letters))}]) {})) @@ -585,14 +599,18 @@ (when (state/developer-mode?) [{:hr true} - {:title [:span.flex.items-center (ui/icon "file-code") "Open Preferences"] + {:title [:span.flex.items-center (ui/icon "file-code") (t :plugin/open-preferences)] :options {:on-click #(p/let [root (plugin-handler/get-ls-dotdir-root)] (js/apis.openPath (str root "/preferences.json")))}} - {:title [:span.flex.items-center (ui/icon "bug") "Open " [:code " ~/.logseq"]] + {:title [:span.flex.items-center.whitespace-nowrap.space-x-1 (ui/icon "bug") (t :plugin/open-logseq-dir) [:code "~/.logseq"]] :options {:on-click #(p/let [root (plugin-handler/get-ls-dotdir-root)] - (js/apis.openPath root))}}])) + (js/apis.openPath root))}}]) + + [{:hr true :key "dropdown-more"} + {:title (auto-check-for-updates-control) + :options {:no-padding? true}}]) {}) ;; developer @@ -730,7 +748,7 @@ [:p.flex.justify-center.py-20 svg/loading] @*error - [:p.flex.justify-center.pt-20.opacity-50 "Remote error: " (.-message @*error)] + [:p.flex.justify-center.pt-20.opacity-50 (t :plugin/remote-error) (.-message @*error)] :else [:div.cp__plugins-marketplace-cnt @@ -895,7 +913,7 @@ [:span.opacity-30.hover:opacity-80 (ui/icon "info-circle")]))]])] ;; all done - [:div.py-4 [:strong.text-4xl "\uD83C\uDF89 All updated!"]]) + [:div.py-4 [:strong.text-4xl (str "\uD83C\uDF89 " (t :plugin/all-updated))]]) ;; actions (when (seq updates) @@ -1047,7 +1065,11 @@ [:span (t :plugin/found-updates)] (ui/point "bg-red-600" 5 {:style {:margin-top 2}})] :options {:on-click #(open-waiting-updates-modal!) :class "extra-item"} - :icon (ui/icon "download")})]) + :icon (ui/icon "download")})] + + [{:hr true :key "dropdown-more"} + {:title (auto-check-for-updates-control) + :options {:no-padding? true}}]) {:trigger-class "toolbar-plugins-manager-trigger"}))) (rum/defc header-ui-items-list-wrap @@ -1116,14 +1138,61 @@ (let [updates-coming (state/sub :plugin/updates-coming)] (toolbar-plugins-manager-list updates-coming items)))]])))) -(rum/defcs hook-ui-fenced-code < rum/reactive - [_state content {:keys [render edit] :as _opts}] +(rum/defc hook-ui-fenced-code + [block content {:keys [render edit] :as _opts}] - [:div - {:on-mouse-down (fn [e] (when (false? edit) (util/stop e))) - :class (util/classnames [{:not-edit (false? edit)}])} - (when (fn? render) - (js/React.createElement render #js {:content content}))]) + (let [[content1 set-content1!] (rum/use-state content) + [editor-active? set-editor-active!] (rum/use-state (string/blank? content)) + *cm (rum/use-ref nil) + *el (rum/use-ref nil)] + + (rum/use-effect! + #(set-content1! content) + [content]) + + (rum/use-effect! + (fn [] + (some-> (rum/deref *el) + (.closest ".ui-fenced-code-wrap") + (.-classList) + (#(if editor-active? + (.add % "is-active") + (.remove % "is-active")))) + (when-let [cm (rum/deref *cm)] + (.refresh cm) + (.focus cm) + (.setCursor cm (.lineCount cm) (count (.getLine cm (.lastLine cm)))))) + [editor-active?]) + + (rum/use-effect! + (fn [] + (let [t (js/setTimeout + #(when-let [^js cm (some-> (rum/deref *el) + (.closest ".ui-fenced-code-wrap") + (.querySelector ".CodeMirror") + (.-CodeMirror))] + (rum/set-ref! *cm cm) + (doto cm + (.on "change" (fn [] + (some-> cm (.getDoc) (.getValue) (set-content1!)))))) + ;; wait for the cm loaded + 1000)] + #(js/clearTimeout t))) + []) + + [:div.ui-fenced-code-result + {:on-mouse-down (fn [e] (when (false? edit) (util/stop e))) + :class (util/classnames [{:not-edit (false? edit)}]) + :ref *el} + [:<> + [:span.actions + {:on-mouse-down #(util/stop %)} + (ui/button (ui/icon "square-toggle-horizontal" {:size 14}) + :on-click #(set-editor-active! (not editor-active?))) + (ui/button (ui/icon "source-code" {:size 14}) + :on-click #(editor-handler/edit-block! block (count content1) (:block/uuid block)))] + (when (fn? render) + (js/React.createElement render #js {:content content1}))]])) (rum/defc plugins-page [] @@ -1183,7 +1252,7 @@ [sub-content, _set-sub-content!] (rum-utils/use-atom *updates-sub-content) notify! (fn [content status] (if auto-checking? - (println "Plugin Updates: " content) + (println (t :plugin/list-of-updates) content) (let [cb #(plugin-handler/cancel-user-checking!)] (try (set-uid (notification/show! content status false uid nil cb)) @@ -1195,7 +1264,7 @@ (if check-pending? (notify! [:div - [:div (str "Checking for plugin updates ...")] + [:div (t :plugin/checking-for-updates)] (when sub-content [:p.opacity-60 sub-content])] (ui/loading "")) (when uid (notification/clear! uid)))) @@ -1206,9 +1275,11 @@ (fn [] (when online? (let [last-updates (storage/get :lsp-last-auto-updates)] - (when (or (not (number? last-updates)) - ;; interval 12 hours - (> (- (js/Date.now) last-updates) (* 60 60 12 1000))) + (when (and (not (false? last-updates)) + (or (true? last-updates) + (not (number? last-updates)) + ;; interval 12 hours + (> (- (js/Date.now) last-updates) (* 60 60 12 1000)))) (js/setTimeout (fn [] (plugin-handler/auto-check-enabled-for-updates!) @@ -1237,7 +1308,8 @@ [:div.cp__plugins-settings.cp__settings-main [:header - [:h1.title (ui/icon "puzzle") (str " " (or title (t :settings-of-plugins)))]] + [:h1.title (ui/icon "puzzle" {:size 22}) + [:strong (or title (t :settings-of-plugins))]]] [:div.cp__settings-inner.md:flex {:class (util/classnames [{:no-aside (not nav?)}])} @@ -1247,7 +1319,7 @@ [:ul.settings-plugin-list (for [{:keys [id name title icon]} plugins] [:li - {:class (util/classnames [{:active (= id focused)}])} + {:key id :class (util/classnames [{:active (= id focused)}])} [:a.flex.items-center.settings-plugin-item {:data-id id :on-click #(do (state/set-state! :plugin/focused-settings id))} @@ -1332,4 +1404,5 @@ [:div.settings-modal.of-plugins (focused-settings-content title)]) {:center? false + :label "plugin-settings-modal" :id "ls-focused-settings-modal"})) diff --git a/src/main/frontend/components/plugins.css b/src/main/frontend/components/plugins.css index 342e664807f..583b3e675b2 100644 --- a/src/main/frontend/components/plugins.css +++ b/src/main/frontend/components/plugins.css @@ -482,6 +482,15 @@ } &-settings { + > header { + padding: 8px 12px; + border-bottom: 1px solid var(--ls-quaternary-background-color); + + h1 { + @apply flex items-center text-[22px] m-0 space-x-1; + } + } + &-inner { position: relative; padding: 10px 0 20px; @@ -598,25 +607,23 @@ } } - aside { - max-height: 70vh; - overflow: auto; - margin-bottom: -17px; + .cp__settings-inner { + aside { + @apply max-h-[70vh] overflow-auto mb-[-17px] p-3; - ul { - img.icon { - height: 24px; - width: 24px; - } + ul { + @apply list-none p-0 m-0; - li { - strong { - font-weight: 400; - overflow: hidden; - height: 22px; + img.icon { + @apply w-[24px] h-[24px]; + } - text-overflow: ellipsis; - white-space: nowrap; + li { + @apply p-1.5 rounded; + + strong { + @apply overflow-hidden text-ellipsis whitespace-nowrap; + } } } } @@ -898,6 +905,42 @@ } } +.ui-fenced-code { + &-wrap { + &:not(.is-active) { + .ui-fenced-code-editor { + display: none !important; + } + } + + &.is-active { + .ui-fenced-code-result { + @apply pt-2; + } + } + } + + &-result { + @apply relative; + + > .actions { + @apply absolute top-2 right-1 z-10 opacity-0 transition-opacity; + + .ui__button { + font-size: 13px; + padding: 4px; + margin-left: 6px; + } + } + + &:hover { + > .actions { + @apply opacity-100; + } + } + } +} + .lsp-frame-readme { margin: -2rem; min-height: 75vh; @@ -939,6 +982,12 @@ html[data-theme='dark'] { } } +.ui__modal[label=plugin-settings-modal] { + .ui__modal-close-wrap { + padding-top: 14px; + } +} + .ui__modal[label=plugins-dashboard] { .panel-content { overflow-y: auto; diff --git a/src/main/frontend/components/query.cljs b/src/main/frontend/components/query.cljs index cdd9e789fce..29d3db07db9 100644 --- a/src/main/frontend/components/query.cljs +++ b/src/main/frontend/components/query.cljs @@ -59,7 +59,6 @@ (:block/name (ffirst result)) (:block/uuid (first (second (first result)))) true)] - (println "this should be a function" inline) (if @*query-error (do (log/error :exception @*query-error) @@ -142,10 +141,8 @@ (when-not (or built-in? dsl-query?) (when collapsed? (editor-handler/collapse-block! current-block-uuid)))) - state)} - (rum/local nil ::query-result) - {:init (fn [state] (assoc state :query-error (atom nil)))} - [state config {:keys [title builder query view collapsed? table-view?] :as q} *query-triggered?] + (assoc state :query-error (atom nil)))} + [state config {:keys [title builder query view collapsed? table-view?] :as q}] (let [*query-error (:query-error state) built-in? (built-in-custom-query? title) dsl-query? (:dsl-query? config) @@ -166,11 +163,12 @@ view-f (and view-fn (sci/eval-string (pr-str view-fn))) dsl-page-query? (and dsl-query? (false? (:blocks? (query-dsl/parse-query query)))) + ;; FIXME: This isn't getting set for full-text searches full-text-search? (and dsl-query? (util/electron?) (symbol? (gp-util/safe-read-string query))) result (when (or built-in-collapsed? (not collapsed?')) - (query-result/get-query-result state config *query-error *query-triggered? current-block-uuid q {:table? table?})) + (query-result/get-query-result config q *query-error current-block-uuid {:table? table?})) query-time (:query-time (meta result)) page-list? (and (seq result) (some? (:block/name (first result)))) @@ -209,13 +207,13 @@ (if table? [:a.flex.ml-1.fade-link {:title "Switch to list view" :on-click (fn [] (editor-property/set-block-property! current-block-uuid - "query-table" - false))} + "query-table" + false))} (ui/icon "list" {:style {:font-size 20}})] [:a.flex.ml-1.fade-link {:title "Switch to table view" :on-click (fn [] (editor-property/set-block-property! current-block-uuid - "query-table" - true))} + "query-table" + true))} (ui/icon "table" {:style {:font-size 20}})])) [:a.flex.ml-1.fade-link @@ -231,7 +229,7 @@ (query-refresh-button query-time {:full-text-search? full-text-search? :on-mouse-down (fn [e] (util/stop e) - (query-result/trigger-custom-query! state *query-error *query-triggered?))}))]])]) + (query-result/trigger-custom-query! config q *query-error))}))]])]) (when dsl-query? builder) @@ -248,11 +246,10 @@ (custom-query-inner config q opts))])])))) (rum/defcs custom-query < rum/static - (rum/local false ::query-triggered?) [state config q] (ui/catch-error (ui/block-error "Query Error:" {:content (:query q)}) (ui/lazy-visible (fn [] - (custom-query* config q (::query-triggered? state))) + (custom-query* config q)) {:debug-id q}))) diff --git a/src/main/frontend/components/query/result.cljs b/src/main/frontend/components/query/result.cljs index d6a9c4a8273..5f21f253194 100644 --- a/src/main/frontend/components/query/result.cljs +++ b/src/main/frontend/components/query/result.cljs @@ -13,9 +13,8 @@ [frontend.modules.outliner.tree :as tree])) (defn trigger-custom-query! - [state *query-error *query-triggered?] - (let [[config query] (:rum/args state) - repo (state/get-current-repo) + [config query *query-error] + (let [repo (state/get-current-repo) result-atom (atom nil) current-block-uuid (or (:block/uuid (:block config)) (:block/uuid config)) @@ -45,40 +44,41 @@ (catch :default e (reset! *query-error e) (atom nil)))] - (when *query-triggered? - (reset! *query-triggered? true)) (if (instance? Atom query-atom) query-atom result-atom))) -(defn get-group-by-page [{:keys [result-transform query] :as q} +(defn get-group-by-page [{:keys [result-transform query] :as query-m} {:keys [table?]}] (if table? false ;; Immediately return false as table view can't handle grouping - (get q :group-by-page? + (get query-m :group-by-page? (and (not result-transform) (not (and (string? query) (string/includes? query "(by-page false)"))))))) (defn get-query-result - [state config *query-error *query-triggered? current-block-uuid q options] - (or (when-let [*result (:query-result config)] @*result) - (let [query-atom (trigger-custom-query! state *query-error *query-triggered?) - query-result (and query-atom (rum/react query-atom)) - ;; exclude the current one, otherwise it'll loop forever - remove-blocks (if current-block-uuid [current-block-uuid] nil) - transformed-query-result (when query-result - (let [result (db/custom-query-result-transform query-result remove-blocks q)] - (if (and query-result (coll? result) (:block/uuid (first result))) - (cond-> result - (get q :remove-block-children? true) - tree/filter-top-level-blocks) - result))) - group-by-page? (get-group-by-page q options) - result (if (and group-by-page? (:block/uuid (first transformed-query-result))) - (let [result (db-utils/group-by-page transformed-query-result)] - (if (map? result) - (dissoc result nil) - result)) - transformed-query-result)] - (when query-atom - (util/safe-with-meta result (meta @query-atom)))))) + "Fetches a query's result, transforms it as needed and saves the result into + an atom that is passed in as an argument" + [config query-m *query-error current-block-uuid options] + (let [query-atom (trigger-custom-query! config query-m *query-error) + query-result (and query-atom (rum/react query-atom)) + ;; exclude the current one, otherwise it'll loop forever + remove-blocks (if current-block-uuid [current-block-uuid] nil) + transformed-query-result (when query-result + (let [result (db/custom-query-result-transform query-result remove-blocks query-m)] + (if (and query-result (coll? result) (:block/uuid (first result))) + (cond-> result + (get query-m :remove-block-children? true) + tree/filter-top-level-blocks) + result))) + group-by-page? (get-group-by-page query-m options) + result (if (and group-by-page? (:block/uuid (first transformed-query-result))) + (let [result (db-utils/group-by-page transformed-query-result)] + (if (map? result) + (dissoc result nil) + result)) + transformed-query-result)] + (when-let [query-result (:query-result config)] + (reset! query-result result)) + (when query-atom + (util/safe-with-meta result (meta @query-atom))))) \ No newline at end of file diff --git a/src/main/frontend/components/repo.cljs b/src/main/frontend/components/repo.cljs index f0407446f98..52f672a96e6 100644 --- a/src/main/frontend/components/repo.cljs +++ b/src/main/frontend/components/repo.cljs @@ -107,7 +107,7 @@ [:div.pl-1.content.mt-3 [:div - [:h2.text-lg.font-medium.my-4 (str (t :graph/local-graphs) ":")] + [:h2.text-lg.font-medium.my-4 (t :graph/local-graphs)] (when (seq local-graphs) (repos-inner local-graphs)) @@ -123,7 +123,7 @@ [:div [:hr] [:div.flex.align-items.justify-between - [:h2.text-lg.font-medium.my-4 (str (t :graph/remote-graphs) ":")] + [:h2.text-lg.font-medium.my-4 (t :graph/remote-graphs)] [:div (ui/button [:span.flex.items-center "Refresh" diff --git a/src/main/frontend/components/right_sidebar.cljs b/src/main/frontend/components/right_sidebar.cljs index 892bd08f177..b71adebfa36 100644 --- a/src/main/frontend/components/right_sidebar.cljs +++ b/src/main/frontend/components/right_sidebar.cljs @@ -29,7 +29,7 @@ (when-not (util/sm-breakpoint?) (ui/with-shortcut :ui/toggle-right-sidebar "left" [:button.button.icon.toggle-right-sidebar - {:title "Toggle right sidebar" + {:title (t :right-side-bar/toggle-right-sidebar) :on-click ui-handler/toggle-right-sidebar!} (ui/icon "layout-sidebar-right" {:size 20})]))) @@ -56,7 +56,7 @@ (rum/defc shortcut-settings [] [:div.contents.flex-col.flex.ml-3 - (shortcut/shortcut {:show-title? false})]) + (shortcut/shortcut-page {:show-title? false})]) (defn- block-with-breadcrumb [repo block idx sidebar-key ref?] @@ -73,6 +73,9 @@ (when v [:.ml-4 (ui/foldable [:div (str k)] [:.ml-4 (case k + :tx-id + [:.my-1 [:pre.code.pre-wrap-white-space.bg-base-4 (str v)]] + :blocks (map (fn [block] [:.my-1 [:pre.code.pre-wrap-white-space.bg-base-4 (str block)]]) v) @@ -111,7 +114,7 @@ (defn build-sidebar-item [repo idx db-id block-type] - (case block-type + (case (keyword block-type) :contents [(t :right-side-bar/contents) (contents)] @@ -120,11 +123,11 @@ [(t :right-side-bar/help) (onboarding/help)] :page-graph - [(str (t :right-side-bar/page-graph)) + [(t :right-side-bar/page-graph) (page/page-graph)] :history - [(str (t :right-side-bar/history)) + [(t :right-side-bar/history) (history)] :block-ref @@ -220,6 +223,7 @@ (rum/defc sidebar-resizer [sidebar-open? sidebar-id handler-position] (let [el-ref (rum/use-ref nil) + min-px-width 144 ; Custom window controls width min-ratio 0.1 max-ratio 0.7 keyboard-step 5 @@ -227,12 +231,12 @@ remove-resizing-class (fn [] (.. js/document.documentElement -classList (remove "is-resizing-buf")) (reset! ui-handler/*right-sidebar-resized-at (js/Date.now))) - set-width! (fn [ratio element] - (when (and el-ref element) - (let [width (str (* ratio 100) "%")] - (#(.setProperty (.-style element) "width" width) - (.setAttribute (rum/deref el-ref) "aria-valuenow" ratio) - (ui-handler/persist-right-sidebar-width!)))))] + set-width! (fn [ratio] + (when el-ref + (let [value (* ratio 100) + width (str value "%")] + (.setAttribute (rum/deref el-ref) "aria-valuenow" value) + (ui-handler/persist-right-sidebar-width! width))))] (rum/use-effect! (fn [] (when-let [el (and (fn? js/window.interact) (rum/deref el-ref))] @@ -243,6 +247,7 @@ {:move (fn [^js/MouseEvent e] (let [width js/document.documentElement.clientWidth + min-ratio (max min-ratio (/ min-px-width width)) sidebar-el (js/document.getElementById sidebar-id) offset (.-pageX e) ratio (.toFixed (/ offset width) 6) @@ -259,7 +264,7 @@ (and (< ratio max-ratio) sidebar-el) (when sidebar-el (#(.. js/document.documentElement -classList (remove cursor-class)) - (set-width! ratio sidebar-el))) + (set-width! ratio))) :else #(.. js/document.documentElement -classList (remove cursor-class))) (when (> ratio (/ min-ratio 2)) (state/open-right-sidebar!)))))}})) @@ -269,6 +274,7 @@ (.on "keydown" (fn [e] (when-let [sidebar-el (js/document.getElementById sidebar-id)] (let [width js/document.documentElement.clientWidth + min-ratio (max min-ratio (/ min-px-width width)) keyboard-step (case (.-code e) "ArrowLeft" (- keyboard-step) "ArrowRight" keyboard-step @@ -278,7 +284,7 @@ ratio (if (= handler-position :west) (- 1 ratio) ratio)] (when (and (> ratio min-ratio) (< ratio max-ratio) (not (zero? keyboard-step))) ((add-resizing-class) - (set-width! ratio sidebar-el))))))) + (set-width! ratio))))))) (.on "keyup" remove-resizing-class))) #()) []) @@ -333,9 +339,7 @@ (when config/dev? [:div.text-sm [:button.button.cp__right-sidebar-settings-btn {:on-click (fn [_e] (state/sidebar-add-block! repo "history" :history))} - (t :right-side-bar/history)]])] - - (toggle)] + (t :right-side-bar/history)]])]] [:.sidebar-item-list.flex-1.scrollbar-spacing.flex.flex-col.gap-2 (if @*anim-finished? @@ -353,9 +357,11 @@ [[(state/get-current-repo) "contents" :contents nil]] blocks) sidebar-open? (state/sub :ui/sidebar-open?) + width (state/sub :ui/sidebar-width) repo (state/sub :git/current-repo)] [:div#right-sidebar.cp__right-sidebar.h-screen - {:class (if sidebar-open? "open" "closed")} + {:class (if sidebar-open? "open" "closed") + :style {:width width}} (sidebar-resizer sidebar-open? "right-sidebar" :west) (when sidebar-open? (sidebar-inner repo t blocks))])) diff --git a/src/main/frontend/components/search.cljs b/src/main/frontend/components/search.cljs index 2c9755aa1bd..8b2f715b912 100644 --- a/src/main/frontend/components/search.cljs +++ b/src/main/frontend/components/search.cljs @@ -257,8 +257,8 @@ {:name icon :class "highlight" :extension? true} - [:div.text.font-bold (str label ": ") - [:span.ml-1 name]])) + [:div.text.font-bold label + [:span.ml-2 name]])) (defn- search-item-render [search-q {:keys [type data alias]}] @@ -312,7 +312,7 @@ :else (do (log/error "search result with non-existing uuid: " data) - (str "Cache is outdated. Please click the 'Re-index' button in the graph's dropdown menu."))))]) + (t :search/cache-outdated))))]) :page-content (let [{:block/keys [snippet uuid]} data ;; content here is normalized @@ -327,7 +327,7 @@ (if page (page-content-search-result-item repo uuid format snippet search-q search-mode) (do (log/error "search result with non-existing uuid: " data) - (str "Cache is outdated. Please click the 'Re-index' button in the graph's dropdown menu."))))])) + (t :search/cache-outdated))))])) nil)])) @@ -396,11 +396,11 @@ [in-page-search?] [:div.recent-search [:div.wrap.px-4.pb-2.text-sm.opacity-70.flex.flex-row.justify-between.align-items.mx-1.sm:mx-0 - [:div "Recent search:"] + [:div (t :search/recent)] [:div.hidden.md:flex (ui/with-shortcut :go/search-in-page "bottom" [:div.flex-row.flex.align-items - [:div.mr-3.flex "Search blocks in page:"] + [:div.mr-3.flex (t :search/blocks-in-page)] [:div.flex.items-center (ui/toggle in-page-search? (fn [_value] @@ -408,7 +408,7 @@ true)] (ui/tippy {:html [:div ;; TODO: fetch from config - "Tip: " [:code (util/->platform-shortcut "Ctrl + Shift + p")] " to open the commands palette"] + (t :search/command-palette-tip-1) [:code (util/->platform-shortcut "Ctrl + Shift + p")] (t :search/command-palette-tip-2)] :interactive true :arrow true :theme "monospace"} diff --git a/src/main/frontend/components/settings.cljs b/src/main/frontend/components/settings.cljs index fa22c986dfc..3b231407a9e 100644 --- a/src/main/frontend/components/settings.cljs +++ b/src/main/frontend/components/settings.cljs @@ -1,37 +1,39 @@ (ns frontend.components.settings (:require [clojure.string :as string] - [frontend.components.svg :as svg] - [frontend.components.plugins :as plugins] + [electron.ipc :as ipc] [frontend.components.assets :as assets] + [frontend.components.conversion :as conversion-component] + [frontend.components.file-sync :as fs] + [frontend.components.plugins :as plugins] + [frontend.components.svg :as svg] [frontend.config :as config] [frontend.context.i18n :refer [t]] - [frontend.storage :as storage] - [frontend.spec.storage :as storage-spec] [frontend.date :as date] + [frontend.db :as db] [frontend.dicts :as dicts] [frontend.handler :as handler] [frontend.handler.config :as config-handler] + [frontend.handler.file-sync :as file-sync-handler] + [frontend.handler.global-config :as global-config-handler] [frontend.handler.notification :as notification] + [frontend.handler.plugin :as plugin-handler] [frontend.handler.route :as route-handler] [frontend.handler.ui :as ui-handler] [frontend.handler.user :as user-handler] - [frontend.handler.plugin :as plugin-handler] - [frontend.handler.file-sync :as file-sync-handler] - [frontend.handler.global-config :as global-config-handler] + [frontend.mobile.util :as mobile-util] [frontend.modules.instrumentation.core :as instrument] [frontend.modules.shortcut.data-helper :as shortcut-helper] + [frontend.spec.storage :as storage-spec] [frontend.state :as state] + [frontend.storage :as storage] [frontend.ui :as ui] - [electron.ipc :as ipc] - [promesa.core :as p] [frontend.util :refer [classnames web-platform?] :as util] [frontend.version :refer [version]] [goog.object :as gobj] + [goog.string :as gstring] + [promesa.core :as p] [reitit.frontend.easy :as rfe] - [rum.core :as rum] - [frontend.mobile.util :as mobile-util] - [frontend.db :as db] - [frontend.components.conversion :as conversion-component])) + [rum.core :as rum])) (defn toggle [label-for name state on-toggle & [detail-text]] @@ -57,19 +59,19 @@ [:div (cond (mobile-util/native-android?) (ui/button - "Check for updates" + (t :settings-page/check-for-updates) :class "text-sm p-1 mr-1" - :href "https://github.com/logseq/logseq/releases" ) + :href "https://github.com/logseq/logseq/releases") (mobile-util/native-ios?) (ui/button - "Check for updates" + (t :settings-page/check-for-updates) :class "text-sm p-1 mr-1" - :href "https://apps.apple.com/app/logseq/id1601013908" ) + :href "https://apps.apple.com/app/logseq/id1601013908") (util/electron?) (ui/button - (if update-pending? "Checking ..." "Check for updates") + (if update-pending? (t :settings-page/checking) (t :settings-page/check-for-updates)) :class "text-sm p-1 mr-1" :disabled update-pending? :on-click #(js/window.apis.checkForUpdates false)) @@ -78,7 +80,7 @@ nil)] [:div.text-sm.cursor - {:title (str "Revision: " config/revision) + {:title (str (t :settings-page/revision) config/revision) :on-click (fn [] (notification/show! [:div "Current Revision: " [:a {:target "_blank" @@ -91,18 +93,18 @@ [:a.text-sm.fade-link.underline.inline {:target "_blank" :href "https://docs.logseq.com/#/page/changelog"} - "What's new?"]]] + (t :settings-page/changelog)]]] (when-not (or update-pending? (string/blank? type)) [:div.update-state.text-sm (case type "update-not-available" - [:p "Your app is up-to-date 🎉"] + [:p (t :settings-page/app-updated)] "update-available" (let [{:keys [name url]} payload] - [:p (str "Found new release ") + [:p (str (t :settings-page/update-available)) [:a.link {:on-click (fn [e] @@ -111,7 +113,7 @@ svg/external-link name " 🎉"]]) "error" - [:p "⚠️ Oops, Something Went Wrong!" [:br] " Please check out the " + [:p (t :settings-page/update-error-1) [:br] (t :settings-page/update-error-2) [:a.link {:on-click (fn [e] @@ -125,10 +127,10 @@ {:style {:box-shadow "0 4px 20px 4px rgba(0, 20, 60, .1), 0 4px 80px -8px rgba(0, 20, 60, .2)"}} [:div {:style {:margin "12px" :max-width "500px"}} [:p.text-sm - "The left side shows outdenting with the default setting, and the right shows outdenting with logical outdenting enabled. " + (t :settings-page/preferred-outdenting-tip) [:a.text-sm {:target "_blank" :href "https://discuss.logseq.com/t/whats-your-preferred-outdent-behavior-the-direct-one-or-the-logical-one/978"} - "→ Learn more"]] + (t :settings-page/preferred-outdenting-tip-more)]] [:img {:src "https://discuss.logseq.com/uploads/default/original/1X/e8ea82f63a5e01f6d21b5da827927f538f3277b9.gif" :width 500 :height 500}]]]) @@ -139,7 +141,7 @@ {:style {:box-shadow "0 4px 20px 4px rgba(0, 20, 60, .1), 0 4px 80px -8px rgba(0, 20, 60, .2)"}} [:div {:style {:margin "12px" :max-width "500px"}} [:p.text-sm - "This option controls whether to expand the block references automatically when zoom-in."] + (t :settings-page/auto-expand-block-refs-tip)] [:img {:src "https://user-images.githubusercontent.com/28241963/225818326-118deda9-9d1e-477d-b0ce-771ca0bcd976.gif" :width 500 :height 500}]]]) @@ -293,12 +295,12 @@ (defn theme-modes-row [t switch-theme system-theme? dark?] (let [pick-theme [:ul.theme-modes-options - [:li {:on-click (partial state/use-theme-mode! "light") - :class (classnames [{:active (and (not system-theme?) (not dark?))}])} [:i.mode-light] [:strong "light"]] - [:li {:on-click (partial state/use-theme-mode! "dark") - :class (classnames [{:active (and (not system-theme?) dark?)}])} [:i.mode-dark] [:strong "dark"]] - [:li {:on-click (partial state/use-theme-mode! "system") - :class (classnames [{:active system-theme?}])} [:i.mode-system] [:strong "system"]]]] + [:li {:on-click (partial state/use-theme-mode! (t :settings-page/theme-light)) + :class (classnames [{:active (and (not system-theme?) (not dark?))}])} [:i.mode-light] [:strong (t :settings-page/theme-light)]] + [:li {:on-click (partial state/use-theme-mode! (t :settings-page/theme-dark)) + :class (classnames [{:active (and (not system-theme?) dark?)}])} [:i.mode-dark] [:strong (t :settings-page/theme-dark)]] + [:li {:on-click (partial state/use-theme-mode! (t :settings-page/theme-system)) + :class (classnames [{:active system-theme?}])} [:i.mode-system] [:strong (t :settings-page/theme-system)]]]] (row-with-button-action {:left-label (t :right-side-bar/switch-theme (string/capitalize switch-theme)) :-for "toggle_theme" :action pick-theme @@ -340,7 +342,7 @@ (when-not (string/blank? format) (config-handler/set-config! :journal/page-title-format format) (notification/show! - [:div "You must re-index your graph for this change to take effect"] + [:div (t :settings-page/custom-date-format-notification)] :warning false) (state/close-modal!) (route-handler/redirect! {:to :repos}))))} @@ -385,8 +387,13 @@ (defn preferred-pasting-file [t preferred-pasting-file?] (toggle "preferred_pasting_file" - (t :settings-page/preferred-pasting-file) - preferred-pasting-file? + [(t :settings-page/preferred-pasting-file) + (ui/tippy {:html (t :settings-page/preferred-pasting-file-hint) + :class "tippy-hover ml-2" + :interactive true + :disabled false} + (svg/info))] + preferred-pasting-file? config-handler/toggle-preferred-pasting-file!)) (defn auto-expand-row [t auto-expand-block-refs?] @@ -610,6 +617,19 @@ (fn [_] (conversion-component/files-breaking-changed)) {:id :filename-format-panel :center? true})})) +(rum/defcs native-titlebar-row < rum/reactive + [state t] + (let [enabled? (state/sub [:electron/user-cfgs :window/native-titlebar?])] + (toggle + "native-titlebar" + (t :settings-page/native-titlebar) + enabled? + #(when (js/confirm (t :relaunch-confirm-to-work)) + (state/set-state! [:electron/user-cfgs :window/native-titlebar?] (not enabled?)) + (ipc/ipc :userAppCfgs :window/native-titlebar? (not enabled?)) + (js/logseq.api.relaunch)) + [:span.text-sm.opacity-50 (t :settings-page/native-titlebar-desc)]))) + (rum/defcs settings-general < rum/reactive [_state current-repo] (let [preferred-language (state/sub [:preferred-language]) @@ -621,6 +641,7 @@ (version-row t version) (language-row t preferred-language) (theme-modes-row t switch-theme system-theme? dark?) + (when (and (util/electron?) (not util/mac?)) (native-titlebar-row t)) (when (config/global-config-enabled?) (edit-global-config-edn)) (when current-repo (edit-config-edn)) (when current-repo (edit-custom-css)) @@ -669,18 +690,16 @@ [:div.text-sm.my-4 (ui/admonition :tip - [:p "If you have Logseq Sync enabled, you can view a page's edit history directly. This section is for tech-savvy only."]) + [:p (t :settings-page/git-tip)]) [:span.text-sm.opacity-50.my-4 - "To view page's edit history, click the three horizontal dots in the top-right corner and select \"View page history\"."] + (t :settings-page/git-desc-1)] [:br][:br] [:span.text-sm.opacity-50.my-4 - "For professional users, Logseq also supports using "] + (t :settings-page/git-desc-2)] [:a {:href "https://git-scm.com/" :target "_blank"} "Git"] [:span.text-sm.opacity-50.my-4 - " for version control."] - [:span.text-sm.opacity-50.my-4 - "Use Git at your own risk as general Git issues are not supported by the Logseq team"]] + (t :settings-page/git-desc-3)]] [:br] (switch-git-auto-commit-row t) (git-auto-commit-seconds t) @@ -731,6 +750,196 @@ {:left-label (t :settings-page/enable-whiteboards) :action (whiteboards-enabled-switcher enabled?)})) +(rum/defc settings-account-usage-description [pro-account? graph-usage] + (let [count-usage (count graph-usage) + count-limit (if pro-account? 10 1) + count-percent (js/Math.round (/ count-usage count-limit 0.01)) + storage-usage (->> (map :used-gbs graph-usage) + (reduce + 0)) + storage-usage-formatted (cond + (zero? storage-usage) "0.0" + (< storage-usage 0.01) "Less than 0.01" + :else (gstring/format "%.2f" storage-usage)) + ;; TODO: check logic on this. What are the rules around storage limits? + ;; do we, and should we be able to, give individual users more storage? + ;; should that be on a per graph or per user basis? + default-storage-limit (if pro-account? 10 0.05) + storage-limit (->> (range 0 count-limit) + (map #(get-in graph-usage [% :limit-gbs] default-storage-limit)) + (reduce + 0)) + storage-percent (/ storage-usage storage-limit 0.01) + storage-percent-formatted (gstring/format "%.1f" storage-percent)] + [:div.text-sm + (when pro-account? + [:<> + (gstring/format "%s of %s synced graphs " count-usage count-limit) + [:strong.text-white (gstring/format "(%s%%)" count-percent)] + ", "]) + (gstring/format "%sGB of %sGB total storage " storage-usage-formatted storage-limit) + [:strong.text-white (gstring/format "(%s%%)" storage-percent-formatted)]])) + ; storage-usage-formatted "GB of " storage-limit "GB total storage" + ; [:strong.text-white " (" storage-percent-formatted "%)"]])) + + +(rum/defc settings-account-usage-graphs [_pro-account? graph-usage] + (when (< 0 (count graph-usage)) + [:div.grid.gap-3 {:style {:grid-template-columns (str "repeat(" (count graph-usage) ", 1fr)")}} + (for [{:keys [name used-percent]} graph-usage + :let [color (if (<= 100 used-percent) "bg-red-500" "bg-blue-500")]] + [:div.rounded-full.w-full.h-2 {:class "bg-black/50" + :tooltip name} + [:div.rounded-full.h-2 {:class color + :style {:width (str used-percent "%") + :min-width "0.5rem" + :max-width "100%"}}]])])) + +(rum/defc ^:large-vars/cleanup-todo settings-account < rum/reactive + [] + (let [current-graph-uuid (state/sub-current-file-sync-graph-uuid) + graph-usage (state/get-remote-graph-usage) + current-graph-is-remote? ((set (map :uuid graph-usage)) current-graph-uuid) + logged-in? (user-handler/logged-in?) + user-info (state/get-user-info) + paid-user? (#{"active" "on_trial" "cancelled"} (:LemonStatus user-info)) + gift-user? (some #{"pro"} (:UserGroups user-info)) + pro-account? (or paid-user? gift-user?) + expiration-date (some-> user-info :LemonEndsAt date/parse-iso) + renewal-date (some-> user-info :LemonRenewsAt date/parse-iso) + has-subscribed? (some? (:LemonStatus user-info))] + [:div.panel-wrap.is-features.mb-8 + [:div.mt-1.sm:mt-0.sm:col-span-2 + (cond + logged-in? + [:div.grid.grid-cols-3.gap-8.pt-2 + [:div "Current plan"] + [:div.col-span-2 + [:div {:class "w-full bg-gray-500/10 rounded-lg p-4 flex flex-col gap-4"} + [:div.flex.gap-4.items-center + (if pro-account? + [:div.flex-1 "Pro"] + [:div.flex-1 "Free"]) + (cond + has-subscribed? + (ui/button "Manage plan" {:class "p-1 h-8 justify-center" + :disabled true + :icon "upload"}) + ; :on-click user-handler/upgrade}) + (not pro-account?) + (ui/button "Upgrade plan" {:class "p-1 h-8 justify-center" + :icon "upload" + :on-click user-handler/upgrade}) + :else nil)] + (settings-account-usage-graphs pro-account? graph-usage) + (settings-account-usage-description pro-account? graph-usage) + (if current-graph-is-remote? + (ui/button "Deactivate syncing" {:class "p-1 h-8 justify-center" + :disabled true + :background "gray" + :icon "cloud-off"}) + (ui/button "Activate syncing" {:class "p-1 h-8 justify-center" + :background "blue" + :icon "cloud" + :on-click #(fs/maybe-onboarding-show :sync-initiate)}))]] + (when has-subscribed? + [:<> + [:div "Billing"] + [:div.col-span-2.flex.flex-col.gap-4 + (cond + ;; If there is no expiration date, print the renewal date + (and renewal-date (nil? expiration-date)) + [:div + [:strong.font-semibold "Next billing date: " + (date/get-locale-string renewal-date)]] + ;; If the expiration date is in the future, word it as such + (< (js/Date.) expiration-date) + [:div + [:strong.font-semibold "Pro plan expires on: " + (date/get-locale-string expiration-date)]] + ;; Otherwise, ind + :else + [:div + [:strong.font-semibold "Pro plan expired on: " + (date/get-locale-string expiration-date)]]) + + [:div (ui/button "Open invoices" {:class "w-full h-8 p-1 justify-center" + :disabled true + :background "gray" + :icon "receipt"})]]]) + [:div "Profile"] + [:div.col-span-2.grid.grid-cols-2.gap-4 + [:div.flex.flex-col.gap-2.box-border {:class "basis-1/2"} + [:label.text-sm.font-semibold "First name"] + [:input.rounded.border.px-2.py-1.box-border {:class "border-blue-500 bg-black/25 w-full"}]] + [:div.flex.flex-col.gap-2 {:class "basis-1/2"} + [:label.text-sm.font-semibold "Last name"] + [:input.rounded.border.px-2.py-1.box-border {:class "border-blue-500 bg-black/25 w-full"}]] + [:div.flex-1.flex.flex-col.gap-2.col-span-2 + [:label.text-sm.font-semibold "Username"] + [:input.rounded.border.px-2.py-1.box-border {:class "border-blue-500 bg-black/25" + :value (user-handler/email)}]]] + [:div "Authentication"] + [:div.col-span-2 + [:div.grid.grid-cols-2.gap-4 + [:div (ui/button (t :logout) {:class "p-1 h-8 justify-center w-full" + :background "gray" + :icon "logout" + :on-click user-handler/logout})] + [:div (ui/button "Reset password" {:class "p-1 h-8 justify-center w-full" + :disabled true + :background "gray" + :icon "key" + :on-click user-handler/logout})] + [:div.col-span-2 (ui/button "Delete Account" {:class "p-1 h-8 justify-center w-full" + :disabled true + :background "red"})]]]] + + (not logged-in?) + [:div.grid.grid-cols-3.gap-8.pt-2 + [:div "Authentication"] + [:div.col-span-2.flex.flex-wrap.gap-4 + [:div.w-full.text-white "With a Logseq account, you can access cloud-based services like Logseq Sync and alpha/beta features."] + [:div.flex-1 (ui/button "Sign up" {:class "h-8 w-full text-center justify-center" + :on-click (fn [] + (state/close-settings!) + (state/pub-event! [:user/login]))})] + [:div.flex-1 (ui/button (t :login) {:icon "login" + :class "h-8 w-full text-center justify-center" + :background "gray" + :on-click (fn [] + (state/close-settings!) + (state/pub-event! [:user/login]))})]] + [:div.col-span-3.flex.flex-col.gap-4 {:class "bg-black/20 p-4 rounded-lg"} + [:div.flex.w-full.items-center + [:div {:class "w-1/2 text-lg"} + "Discover the power of " + [:strong {:class "text-white/80"} "Logseq Sync"]] + [:div {:class "w-1/2 bg-gradient-to-r from-white/10 to-transparent p-3 rounded-lg flex items-center gap-2 px-5 ml-5"} + [:div.w-3.h-3.rounded-full.bg-green-500] + "Synced"]] + [:div.flex.w-full.gap-4 + [:div {:class "w-1/2 bg-black/50 rounded-lg p-4 pt-10 relative flex flex-col gap-4"} + [:div.absolute.top-0.left-4.bg-gray-700.uppercase.px-2.py-1.rounded-b-lg.font-bold.text-xs "Free"] + [:div + [:strong.text-white.text-xl.font-normal "$0"]] + [:div.text-white.font-bold {:class "h-[2.5rem] "} "Get started with basic syncing"] + [:ul.text-xs.list-none.m-0.flex.flex-col.gap-0.5 + [:li "Unlimited unsynced graphs"] + [:li "1 synced graph (up to 50MB, notes only)"] + [:li "No asset syncing"] + [:li "Access to core Logseq features"]]] + [:div {:class "w-1/2 bg-black/50 rounded-lg p-4 pt-10 relative flex flex-col gap-4"} + [:div.absolute.top-0.left-4.bg-blue-700.uppercase.px-2.py-1.rounded-b-lg.font-bold.text-xs "Pro"] + [:div + [:strong.text-white.text-xl.font-normal "$10"] + [:span.text-xs.font-base {:class "ml-0.5"} "/ month"]] + [:div.text-white.font-bold {:class "h-[2.5rem]"} "Unlock advanced syncing and more"] + [:ul.text-xs.list-none.m-0.flex.flex-col.gap-0.5 + [:li "Unlimited unsynced graphs"] + [:li "10 synced graphs (up to 5GB each)"] + [:li "Sync assets up to 100MB per file"] + [:li "Early access to alpha/beta features"] + [:li "Upcoming cloud-based features, including Logseq Publish"]]]]]])]])) + (rum/defc settings-features < rum/reactive [] (let [current-repo (state/get-current-repo) @@ -786,11 +995,11 @@ {:class (when-not user-handler/alpha-or-beta-user? "opacity-50 pointer-events-none cursor-not-allowed")} (sync-switcher-row enable-sync?) [:div.text-sm - "Click" + (t :settings-page/sync-desc-1) [:a.mx-1 {:href "https://blog.logseq.com/how-to-setup-and-use-logseq-sync/" :target "_blank"} - "here"] - "for instructions on how to set up and use Sync."]]]) + (t :settings-page/sync-desc-2)] + (t :settings-page/sync-desc-3)]]])])) ;; (when-not web-platform? ;; [:<> @@ -801,10 +1010,12 @@ ;; {:class (when-not user-handler/alpha-user? "opacity-50 pointer-events-none cursor-not-allowed")} ;; ;; features ;; ]]) - ])) + + +(def DEFAULT-ACTIVE-TAB-STATE (if config/ENABLE-SETTINGS-ACCOUNT-TAB [:account :account] [:general :general])) (rum/defcs settings - < (rum/local [:general :general] ::active) + < (rum/local DEFAULT-ACTIVE-TAB-STATE ::active) {:will-mount (fn [state] (state/load-app-user-cfgs) @@ -822,15 +1033,18 @@ *active (::active state)] [:div#settings.cp__settings-main - [:header - [:h1.title (t :settings)]] [:div.cp__settings-inner [:aside.md:w-64 {:style {:min-width "10rem"}} + [:header.cp__settings-header + (ui/icon "settings") + [:h1.cp__settings-modal-title (t :settings)]] [:ul.settings-menu (for [[label id text icon] - [[:general "general" (t :settings-page/tab-general) (ui/icon "adjustments")] + [(when config/ENABLE-SETTINGS-ACCOUNT-TAB + [:account "account" (t :settings-page/tab-account) (ui/icon "user-circle")]) + [:general "general" (t :settings-page/tab-general) (ui/icon "adjustments")] [:editor "editor" (t :settings-page/tab-editor) (ui/icon "writing")] (when (util/electron?) @@ -852,11 +1066,13 @@ :on-click #(reset! *active [label (first @*active)])} [:a.flex.items-center.settings-menu-link - {:data-id id} + {:data-id id} icon [:strong text]]]))]] [:article + [:header.cp__settings-header + [:h1.cp__settings-category-title (name (first @*active))]] (case (first @*active) @@ -866,6 +1082,9 @@ (reset! *active [label label]) nil) + :account + (settings-account) + :general (settings-general current-repo) diff --git a/src/main/frontend/components/settings.css b/src/main/frontend/components/settings.css index 96c7762048d..12355f52b6c 100644 --- a/src/main/frontend/components/settings.css +++ b/src/main/frontend/components/settings.css @@ -1,44 +1,76 @@ .cp__settings { - &-main { - > header { - padding: 10px; - padding-top: 0; - border-bottom: 1px solid var(--ls-quaternary-background-color); + aside { + @apply bg-gray-400/5 p-4; + } - h1 { - font-size: 22px; - margin: 0; + article { + @apply p-4 flex-1 min-h-[12rem] w-auto overflow-y-auto; + @apply md:max-h-[70vh] md:w-[40rem]; + /* margin-right: -17px; */ + /* margin-bottom: -17px; */ + + @screen md { + /* max-height: 70vh; */ + /* width: 680px; */ } } + + aside > .cp__settings-header, + article > .cp__settings-header { + @apply h-10 py-2 flex flex-row items-center justify-start gap-2; + } + + aside > .cp__settings-header { + @apply px-2; + } + + aside > .cp__settings-header > .ui__icon { + @apply h-8 w-8 bg-gray-700/10 rounded grid place-items-center; + } + + aside > .cp__settings-header > .ui__icon > svg { + @apply h-6 w-6; + } + + h1.cp__settings-modal-title { + @apply text-2xl font-semibold lowercase; + } + + h1.cp__settings-category-title { + @apply text-xl lowercase; + } + + h1.cp__settings-modal-title:first-letter, + h1.cp__settings-category-title:first-letter { + @apply uppercase; + } + + .settings-menu { + @apply p-0 m-0 mt-4 pr-3; + } + + .settings-menu-item { + @apply list-none p-0 my-1.5 rounded; + @apply hover:bg-black/10; + } + + .settings-menu-link { + @apply px-2 py-1.5 select-none; + color: var(--ls-primary-text-color); + } } &-inner { @apply flex flex-col md:flex-row; > aside { - border-right: 0 solid var(--ls-quaternary-background-color); - border-bottom: 1px solid var(--ls-quaternary-background-color); - - @screen md { - border-right: 1px solid var(--ls-quaternary-background-color); - border-bottom: 0 solid var(--ls-quaternary-background-color); - } ul { - padding: 12px 12px 12px 5px; - margin: 0; > li { - list-style: none; - padding: 0; - margin: 5px 0; - border-radius: 4px; > a { - padding: 10px; - user-select: none; - color: var(--ls-primary-text-color); > i { overflow: hidden; @@ -65,21 +97,6 @@ } } - > article { - flex: 1; - padding: 0 12px 12px; - min-height: 380px; - width: auto; - overflow: auto; - margin-right: -17px; - margin-bottom: -17px; - - @screen md { - max-height: 70vh; - width: 680px; - } - } - &.no-aside { > article { padding-left: 0; @@ -87,7 +104,7 @@ } .panel-wrap { - padding: 12px; + @apply p-1; @screen sm { width: 600px; diff --git a/src/main/frontend/components/shortcut.cljs b/src/main/frontend/components/shortcut.cljs index bc57ab7fb83..0173c2626e0 100644 --- a/src/main/frontend/components/shortcut.cljs +++ b/src/main/frontend/components/shortcut.cljs @@ -13,12 +13,15 @@ (rum/defcs customize-shortcut-dialog-inner < (rum/local "") + (rum/local nil :rum/action) (shortcut/record!) [state k action-name current-binding] - (let [keypress (:rum/local state) - keyboard-shortcut (if (= "" @keypress) current-binding @keypress)] - [:div - [:div + (let [*keypress (:rum/local state) + *action (:rum/action state) + keypressed? (not= "" @*keypress) + keyboard-shortcut (if-not keypressed? current-binding @*keypress)] + [:<> + [:div.sm:w-lsm [:p.mb-4 "Press any sequence of keys to set the shortcut for the " [:b action-name] " action."] [:p.mb-4.mt-4 (ui/render-keyboard-shortcut (-> keyboard-shortcut @@ -26,26 +29,30 @@ (str/lower-case) (str/split #" |\+"))) " " - [:a.text-sm - {:style {:margin-left "12px"} - :on-click (fn [] - (dh/remove-shortcut k) - (shortcut/refresh!) - (swap! keypress (fn [] "")) ;; Clear local state - )} - "Reset"]]] + (when keypressed? + [:a.text-sm + {:style {:margin-left "12px"} + :on-click (fn [] + (dh/remove-shortcut k) + (shortcut/refresh!) + (swap! *keypress (constantly "")) ;; Clear local state + )} + "Reset"])]] [:div.cancel-save-buttons.text-right.mt-4 - (ui/button "Save" :on-click state/close-modal!) + (ui/button "Save" :on-click (fn [] + (reset! *action :save) + (state/close-modal!))) [:a.ml-4 {:on-click (fn [] - (reset! keypress (dh/binding-for-storage current-binding)) + (reset! *keypress (dh/binding-for-storage current-binding)) + (reset! *action :cancel) (state/close-modal!))} "Cancel"]]])) (defn customize-shortcut-dialog [k action-name displayed-binding] (fn [_] (customize-shortcut-dialog-inner k action-name displayed-binding))) -(rum/defc shortcut-col [k binding configurable? action-name] +(rum/defc shortcut-col [_category k binding configurable? action-name] (let [conflict? (dh/potential-conflict? k) displayed-binding (dh/binding-for-display k binding) disabled? (str/includes? displayed-binding "system default")] @@ -61,28 +68,48 @@ (if disabled? "Cannot override system default" "Click to modify")) :background (if conflict? "pink" (when disabled? "gray")) :on-click (when-not disabled? - #(state/set-modal! (customize-shortcut-dialog k action-name displayed-binding))))]))) - -(rum/defc shortcut-table < rum/reactive - ([name] - (shortcut-table name false)) - ([name configurable?] - (let [shortcut-config (rum/cursor-in - state/state - [:config (state/get-current-repo) :shortcuts]) - _ (rum/react shortcut-config)] - [:div - [:table - [:thead - [:tr - [:th.text-left [:b (t name)]] - [:th.text-right]]] - [:tbody - (map (fn [[k {:keys [binding]}]] - [:tr {:key (str k)} - [:td.text-left (t (dh/decorate-namespace k))] - (shortcut-col k binding configurable? (t (dh/decorate-namespace k)))]) - (dh/binding-by-category name))]]]))) + #(state/set-sub-modal! + (customize-shortcut-dialog k action-name displayed-binding) + {:center? true})))]))) + +(rum/defcs shortcut-table + < rum/reactive + (rum/local true ::folded?) + {:will-mount (fn [state] + (let [name (first (:rum/args state))] + (cond-> state + (contains? #{:shortcut.category/basics} + name) + (-> ::folded? (reset! false) (do state)))))} + [state category configurable?] + (let [*folded? (::folded? state) + plugin? (= category :shortcut.category/plugins) + _ (state/sub [:config (state/get-current-repo) :shortcuts])] + [:div.cp__shortcut-table-wrap + [:a.fold + {:on-click #(reset! *folded? (not @*folded?))} + (ui/icon (if @*folded? "chevron-left" "chevron-down"))] + [:table + [:thead + [:tr + [:th.text-left [:b (t category)]] + [:th.text-right]]] + (when-not @*folded? + [:tbody + (map (fn [[k {:keys [binding]}]] + (let [cmd (dh/shortcut-cmd k) + label (cond + (string? (:desc cmd)) + [:<> + [:code.text-xs (namespace k)] + [:small.pl-1 (:desc cmd)]] + + (not plugin?) (-> k (dh/decorate-namespace) (t)) + :else (str k))] + [:tr {:key (str k)} + [:td.text-left.flex.items-center label] + (shortcut-col category k binding configurable? label)])) + (dh/binding-by-category category))])]])) (rum/defc trigger-table [] [:table @@ -167,13 +194,9 @@ [:td.text-right (get rendered name)]]) list)]])) -(rum/defc shortcut - [{:keys [show-title?] - :or {show-title? true}}] - [:div - (when show-title? [:h1.title (t :help/shortcut-page-title)]) - (trigger-table) - (markdown-and-orgmode-syntax) +(rum/defc keymap-tables + [] + [:div.cp__keymap-tables (shortcut-table :shortcut.category/basics true) (shortcut-table :shortcut.category/navigating true) (shortcut-table :shortcut.category/block-editing true) @@ -182,4 +205,27 @@ (shortcut-table :shortcut.category/formatting true) (shortcut-table :shortcut.category/toggle true) (when (state/enable-whiteboards?) (shortcut-table :shortcut.category/whiteboard true)) + (shortcut-table :shortcut.category/plugins true) (shortcut-table :shortcut.category/others true)]) + +(rum/defc keymap-pane + [] + (let [[ready?, set-ready!] (rum/use-state false)] + (rum/use-effect! + (fn [] (js/setTimeout #(set-ready! true) 32)) + []) + + [:div.cp__keymap-pane + [:h1.pb-2.text-3xl.pt-2 "Keymap"] + (if ready? + (keymap-tables) + [:p.flex.justify-center.py-20 (ui/loading "")])])) + +(rum/defc shortcut-page + [{:keys [show-title?] + :or {show-title? true}}] + [:div.cp__shortcut-page + (when show-title? [:h1.title (t :help/shortcut-page-title)]) + (trigger-table) + (markdown-and-orgmode-syntax) + (keymap-tables)]) diff --git a/src/main/frontend/components/shortcut.css b/src/main/frontend/components/shortcut.css new file mode 100644 index 00000000000..3b2041ad4f1 --- /dev/null +++ b/src/main/frontend/components/shortcut.css @@ -0,0 +1,28 @@ +.ui__modal { + &[label="keymap-manager"] { + .panel-content { + @apply m-[-16px]; + } + + @screen lg { + .panel-content { + width: 980px; + } + } + } +} + +.cp__shortcut { + &-table-wrap { + @apply relative; + + a.fold { + @apply absolute right-0 top-0 w-full pt-3 pr-3 + pb-3 flex items-center justify-end select-none; + + &:active { + @apply bg-white/50 opacity-60; + } + } + } +} \ No newline at end of file diff --git a/src/main/frontend/components/svg.cljs b/src/main/frontend/components/svg.cljs index 7b5c145a5d7..74a565a6548 100644 --- a/src/main/frontend/components/svg.cljs +++ b/src/main/frontend/components/svg.cljs @@ -386,3 +386,29 @@ [:path {:d "M256 0C114.6 0 0 114.6 0 256c0 141.4 114.6 256 256 256s256-114.6 256-256C512 114.6 397.4 0 256 0zM352 328c0 13.2-10.8 24-24 24h-144C170.8 352 160 341.2 160 328v-144C160 170.8 170.8 160 184 160h144C341.2 160 352 170.8 352 184V328z"}]]) + +;; Titlebar icons from https://github.com/microsoft/vscode-codicons +(defn window-minimize + ([] (window-minimize 16)) + ([size] + [:svg.icon {:width size :height size :viewBox "0 0 16 16" :fill "currentColor"} + [:path {:d "M14 8v1H3V8h11z"}]])) + +(defn window-maximize + ([] (window-maximize 16)) + ([size] + [:svg.icon {:width size :height size :viewBox "0 0 16 16" :fill "currentColor"} + [:path {:d "M3 3v10h10V3H3zm9 9H4V4h8v8z"}]])) + +(defn window-restore + ([] (window-restore 16)) + ([size] + [:svg.icon {:width size :height size :viewBox "0 0 16 16" :fill "currentColor"} + [:path {:d "M3 5v9h9V5H3zm8 8H4V6h7v7z"}] + [:path {:fill-rule "evenodd" :clip-rule "evenodd" :d "M5 5h1V4h7v7h-1v1h2V3H5v2z"}]])) + +(defn window-close + ([] (window-close 16)) + ([size] + [:svg.icon {:width size :height size :viewBox "0 0 16 16" :fill "currentColor"} + [:path {:fill-rule "evenodd" :clip-rule "evenodd" :d "M7.116 8l-4.558 4.558.884.884L8 8.884l4.558 4.558.884-.884L8.884 8l4.558-4.558-.884-.884L8 7.116 3.442 2.558l-.884.884L7.116 8z"}]])) diff --git a/src/main/frontend/components/theme.css b/src/main/frontend/components/theme.css index d9c9bdbe3eb..f35d65c38a3 100644 --- a/src/main/frontend/components/theme.css +++ b/src/main/frontend/components/theme.css @@ -8,8 +8,6 @@ --ls-z-index-level-3: 999; --ls-z-index-level-4: 9999; --ls-z-index-level-5: 99999; - - --ls-right-sidebar-width: 40%; } html { diff --git a/src/main/frontend/components/whiteboard.cljs b/src/main/frontend/components/whiteboard.cljs index 8e3e637e330..0be02e436dc 100644 --- a/src/main/frontend/components/whiteboard.cljs +++ b/src/main/frontend/components/whiteboard.cljs @@ -146,7 +146,7 @@ [page-name] (let [page-entity (model/get-page page-name) {:block/keys [updated-at created-at]} page-entity] - (str (if (= created-at updated-at) "Created " "Edited ") + (str (if (= created-at updated-at) (t :whiteboard/dashboard-card-created) (t :whiteboard/dashboard-card-edited)) (util/time-ago (js/Date. updated-at))))) (rum/defc dashboard-preview-card @@ -190,7 +190,7 @@ (whiteboard-handler/create-new-whiteboard-and-redirect!))} (ui/icon "plus") [:span.dashboard-create-card-caption.select-none - "New whiteboard"]]) + (t :whiteboard/dashboard-card-new-whiteboard)]]) (rum/defc whiteboard-dashboard [] diff --git a/src/main/frontend/components/window_controls.cljs b/src/main/frontend/components/window_controls.cljs new file mode 100644 index 00000000000..8506dc8f3e8 --- /dev/null +++ b/src/main/frontend/components/window_controls.cljs @@ -0,0 +1,52 @@ +(ns frontend.components.window-controls + (:require [electron.ipc :as ipc] + [frontend.components.svg :as svg] + [frontend.context.i18n :refer [t]] + [frontend.state :as state] + [frontend.ui :as ui] + [rum.core :as rum])) + +(defn minimize + [] + (ipc/ipc "window-minimize")) + +(defn toggle-maximized + [] + (ipc/ipc "window-toggle-maximized")) + +(defn close + [] + (ipc/ipc "window-close")) + +(defn toggle-fullscreen + [] + (ipc/ipc "window-toggle-fullscreen")) + +(rum/defc container < rum/reactive + [] + (let [maximized? (state/sub :electron/window-maximized?) + fullscreen? (state/sub :electron/window-fullscreen?)] + [:div.window-controls.flex + (if fullscreen? + [:button.button.icon.fullscreen-toggle + {:title (t :window/exit-fullscreen) + :on-click toggle-fullscreen} + (ui/icon "arrows-minimize")] + [:<> + [:button.button.icon.minimize + {:title (t :window/minimize) + :on-click minimize} + (svg/window-minimize)] + + [:button.button.icon.maximize-toggle + {:title (if maximized? (t :window/restore) (t :window/maximize)) + :class (if maximized? "restore" "maximize") + :on-click toggle-maximized} + (if maximized? + (svg/window-restore) + (svg/window-maximize))] + + [:button.button.icon.close + {:title (t :window/close) + :on-click close} + (svg/window-close)]])])) diff --git a/src/main/frontend/components/window_controls.css b/src/main/frontend/components/window_controls.css new file mode 100644 index 00000000000..04b313cd455 --- /dev/null +++ b/src/main/frontend/components/window_controls.css @@ -0,0 +1,14 @@ +.window-controls { + position: fixed; + top: 0; + right: 0; + z-index: 10; + + .button { + -webkit-app-region: no-drag; + background: transparent; + border-radius: 0; + width: 48px; + height: 48px; + } +} diff --git a/src/main/frontend/config.cljs b/src/main/frontend/config.cljs index 7588a854e29..c2f02ee7734 100644 --- a/src/main/frontend/config.cljs +++ b/src/main/frontend/config.cljs @@ -29,6 +29,10 @@ (goog-define ENABLE-FILE-SYNC-PRODUCTION false) +;; this is a feature flag to enable the account tab +;; when it launches (when pro plan launches) it should be removed +(def ENABLE-SETTINGS-ACCOUNT-TAB false) + (if ENABLE-FILE-SYNC-PRODUCTION (do (def FILE-SYNC-PROD? true) (def LOGIN-URL @@ -339,7 +343,7 @@ (def custom-css-file "custom.css") (def export-css-file "export.css") (def custom-js-file "custom.js") -(def config-default-content (rc/inline "config.edn")) +(def config-default-content (rc/inline "templates/config.edn")) (def config-default-content-md5 (let [md5 (new crypt/Md5)] (.update md5 (crypt/stringToUtf8ByteArray config-default-content)) (crypt/byteArrayToHex (.digest md5)))) @@ -482,7 +486,7 @@ (defn get-current-repo-assets-root [] (when-let [repo-dir (and (local-file-based-graph? (state/get-current-repo)) - (get-repo-dir (state/get-current-repo)))] + (get-repo-dir (state/get-current-repo)))] (path/path-join repo-dir "assets"))) (defn get-custom-js-path diff --git a/src/main/frontend/date.cljs b/src/main/frontend/date.cljs index 71f279f48c6..62643c3a0aa 100644 --- a/src/main/frontend/date.cljs +++ b/src/main/frontend/date.cljs @@ -62,11 +62,13 @@ (tf/unparse custom-formatter date-time))) (defn get-locale-string - [s] + "Accepts a :date-time-no-ms string representation, or a cljs-time date object" + [input] (try - (->> (tf/parse (tf/formatters :date-time-no-ms) s) - (t/to-default-time-zone) - (tf/unparse (tf/formatter "MMM do, yyyy"))) + (->> (cond->> input + (string? input) (tf/parse (tf/formatters :date-time-no-ms))) + (t/to-default-time-zone) + (tf/unparse (tf/formatter "MMM do, yyyy"))) (catch :default _e nil))) @@ -209,12 +211,22 @@ (tf/formatter "yyyy-MM-dd HH:mm") (t/to-default-time-zone (tc/from-long n)))) +(def iso-parser (tf/formatter "yyyy-MM-dd'T'HH:mm:ss.SSSS'Z'")) +(defn parse-iso [string] + (tf/parse iso-parser string)) + (comment (def default-formatter (tf/formatter "MMM do, yyyy")) (def zh-formatter (tf/formatter "YYYY年MM月dd日")) - (tf/show-formatters)) + (tf/show-formatters) ;; :date 2020-05-31 ;; :rfc822 Sun, 31 May 2020 03:00:57 Z + (let [info {:ExpireTime 1680781356, + :UserGroups [], + :LemonRenewsAt "2024-04-11T07:28:00.000000Z", + :LemonEndsAt nil, + :LemonStatus "active"}] + (->> info :LemonRenewsAt (tf/parse iso-parser) (< (js/Date.))))) diff --git a/src/main/frontend/db/model.cljs b/src/main/frontend/db/model.cljs index 8876c003cbb..c55338a5cd0 100644 --- a/src/main/frontend/db/model.cljs +++ b/src/main/frontend/db/model.cljs @@ -50,6 +50,7 @@ :block/marker :block/priority :block/properties + :block/properties-order :block/properties-text-values :block/pre-block? :block/scheduled diff --git a/src/main/frontend/db/react.cljs b/src/main/frontend/db/react.cljs index fe07d2b836a..5aba35b06ea 100644 --- a/src/main/frontend/db/react.cljs +++ b/src/main/frontend/db/react.cljs @@ -48,10 +48,10 @@ (defonce query-state (atom {})) ;; Current dynamic component -(def ^:dynamic *query-component*) +(def ^:dynamic *query-component* nil) ;; Which reactive queries are triggered by the current component -(def ^:dynamic *reactive-queries*) +(def ^:dynamic *reactive-queries* nil) ;; component -> query-key (defonce query-components (atom {})) diff --git a/src/main/frontend/extensions/excalidraw.cljs b/src/main/frontend/extensions/excalidraw.cljs index c0d719b4b94..14fd4e97bc9 100644 --- a/src/main/frontend/extensions/excalidraw.cljs +++ b/src/main/frontend/extensions/excalidraw.cljs @@ -17,8 +17,7 @@ [goog.object :as gobj] [goog.functions :refer [debounce]] [rum.core :as rum] - [frontend.mobile.util :as mobile-util] - [frontend.context.i18n :refer [t]])) + [frontend.mobile.util :as mobile-util])) (def excalidraw (r/adapt-class Excalidraw)) @@ -148,8 +147,7 @@ (when (:file option) (cond db-restoring? - [:div.ls-center - (ui/loading (t :loading))] + [:div.ls-center (ui/loading)] (false? loading?) (draw-inner data option) diff --git a/src/main/frontend/extensions/latex.cljs b/src/main/frontend/extensions/latex.cljs index dd65f9ef779..7e98007b12d 100644 --- a/src/main/frontend/extensions/latex.cljs +++ b/src/main/frontend/extensions/latex.cljs @@ -6,8 +6,7 @@ [frontend.util :as util] [frontend.handler.plugin :refer [hook-extensions-enhancer-by-type] :as plugin-handler] [promesa.core :as p] - [goog.dom :as gdom] - [frontend.context.i18n :refer [t]])) + [goog.dom :as gdom])) ;; TODO: extracted to a rum mixin (defn loaded? [] @@ -62,7 +61,7 @@ [id s block? _display?] (let [loading? (rum/react *loading?)] (if loading? - (ui/loading (t :loading)) + (ui/loading) (let [element (if block? :div.latex :span.latex-inline)] diff --git a/src/main/frontend/extensions/pdf/core.cljs b/src/main/frontend/extensions/pdf/core.cljs index 762331cc02c..c5920bdbce4 100644 --- a/src/main/frontend/extensions/pdf/core.cljs +++ b/src/main/frontend/extensions/pdf/core.cljs @@ -347,9 +347,8 @@ (.setAttribute target "data-x" ax) (.setAttribute target "data-y" ay)) ))} - :modifiers [;; minimum - (js/interact.modifiers.restrictSize - (bean/->js {:min {:width 60 :height 25}}))] + :modifiers [(js/interact.modifiers.restrict + (bean/->js {:restriction (.closest el ".page")}))] :inertia true}) ))] ;; destroy @@ -376,10 +375,10 @@ (for [hl page-hls] (let [vw-hl (update-in hl [:position] #(pdf-utils/scaled-to-vw-pos viewer %))] (rum/with-key - (if (get-in hl [:content :image]) - (pdf-highlight-area-region viewer vw-hl hl ops) - (pdf-highlights-text-region viewer vw-hl hl ops)) - (:id hl)) + (if (get-in hl [:content :image]) + (pdf-highlight-area-region viewer vw-hl hl ops) + (pdf-highlights-text-region viewer vw-hl hl ops)) + (:id hl)) ))]) (rum/defc ^:large-vars/cleanup-todo pdf-highlight-area-selection @@ -388,41 +387,59 @@ (let [^js viewer-clt (.. viewer -viewer -classList) ^js cnt-el (.-container viewer) *el (rum/use-ref nil) - *sta-el (rum/use-ref nil) + *start-el (rum/use-ref nil) *cnt-rect (rum/use-ref nil) + *page-el (rum/use-ref nil) + *page-rect (rum/use-ref nil) + *start-xy (rum/use-ref nil) - [start-coord, set-start-coord!] (rum/use-state nil) - [end-coord, set-end-coord!] (rum/use-state nil) + [start, set-start!] (rum/use-state nil) + [end, set-end!] (rum/use-state nil) [_ set-area-mode!] (use-atom *area-mode?) should-start (fn [^js e] (let [^js target (.-target e)] - (when (and (not - (.contains (.-classList target) "extensions__pdf-hls-area-region")) + (when (and (not (.contains (.-classList target) "extensions__pdf-hls-area-region")) (.closest target ".page")) (and e (or (.-metaKey e) (and util/win32? (.-shiftKey e)) @*area-mode?))))) - reset-coords #(do - (set-start-coord! nil) - (set-end-coord! nil) - (rum/set-ref! *sta-el nil)) + reset-coords! #(do + (set-start! nil) + (set-end! nil) + (rum/set-ref! *start-xy nil) + (rum/set-ref! *start-el nil) + (rum/set-ref! *cnt-rect nil) + (rum/set-ref! *page-el nil) + (rum/set-ref! *page-rect nil)) - calc-coords (fn [page-x page-y] + calc-coords! (fn [page-x page-y] (when cnt-el - (let [cnt-rect (rum/deref *cnt-rect) - cnt-rect (or cnt-rect (bean/->clj (.toJSON (.getBoundingClientRect cnt-el)))) - _ (rum/set-ref! *cnt-rect cnt-rect)] + (let [cnt-rect (rum/deref *cnt-rect) + cnt-rect (or cnt-rect (bean/->clj (.toJSON (.getBoundingClientRect cnt-el)))) + page-rect (rum/deref *page-rect) + [start-x, start-y] (rum/deref *start-xy) + dx-left? (> start-x page-x) + dy-top? (> start-y page-y) + page-left (:left page-rect) + page-right (:right page-rect) + page-top (:top page-rect) + page-bottom (:bottom page-rect) + _ (rum/set-ref! *cnt-rect cnt-rect)] {:x (-> page-x - (- (:left cnt-rect)) + (#(if dx-left? + (if (< % page-left) page-left %) + (if (> % page-right) page-right %))) (+ (.-scrollLeft cnt-el))) :y (-> page-y - (- (:top cnt-rect)) + (#(if dy-top? + (if (< % page-top) page-top %) + (if (> % page-bottom) page-bottom %))) (+ (.-scrollTop cnt-el)))}))) - calc-pos (fn [start end] + calc-rect (fn [start end] {:left (min (:x start) (:x end)) :top (min (:y start) (:y end)) :width (js/Math.abs (- (:x end) (:x start))) @@ -431,81 +448,78 @@ disable-text-selection! #(js-invoke viewer-clt (if % "add" "remove") "disabled-text-selection") fn-move (rum/use-callback - (fn [^js/MouseEvent e] - (set-end-coord! (calc-coords (.-pageX e) (.-pageY e)))) - [])] + (fn [^js/MouseEvent e] + (set-end! (calc-coords! (.-pageX e) (.-pageY e)))) + [])] (rum/use-effect! - (fn [] - (when-let [^js/HTMLElement root cnt-el] - (let [fn-start (fn [^js/MouseEvent e] - (if (should-start e) - (do - (rum/set-ref! *sta-el (.-target e)) - (set-start-coord! (calc-coords (.-pageX e) (.-pageY e))) - (disable-text-selection! true) - - (.addEventListener root "mousemove" fn-move)) - - ;; reset - (reset-coords))) - - fn-end (fn [^js/MouseEvent e] - (when-let [start-el (rum/deref *sta-el)] - (let [end (calc-coords (.-pageX e) (.-pageY e)) - pos (calc-pos start-coord end)] - - (if (and (> (:width pos) 10) - (> (:height pos) 10)) - - (when-let [^js page-el (.closest start-el ".page")] - (let [page-number (int (.-pageNumber (.-dataset page-el))) - page-pos (merge pos {:top (- (:top pos) (.-offsetTop page-el)) - :left (- (:left pos) (.-offsetLeft page-el))}) - vw-pos {:bounding page-pos :rects [] :page page-number} - sc-pos (pdf-utils/vw-to-scaled-pos viewer vw-pos) - - point {:x (.-clientX e) :y (.-clientY e)} - hl {:id nil - :page page-number - :position sc-pos - :content {:text "[:span]" :image (js/Date.now)} - :properties {}}] - - ;; ctx tips - (show-ctx-menu! viewer hl point {:reset-fn #(reset-coords)}) - - ;; export area highlight - ;;(dd "[selection end] :start" - ;; start-coord ":end" end ":pos" pos - ;; ":page" page-number - ;; ":offset" page-pos - ;; ":vw-pos" vw-pos - ;; ":sc-pos" sc-pos) - ) - - (set-area-mode! false)) - - ;; reset - (reset-coords))) - - (disable-text-selection! false) - (.removeEventListener root "mousemove" fn-move)))] - - (doto root - (.addEventListener "mousedown" fn-start) - (.addEventListener "mouseup" fn-end #js {:once true})) - - ;; destroy - #(doto root - (.removeEventListener "mousedown" fn-start) - (.removeEventListener "mouseup" fn-end))))) - [start-coord]) + (fn [] + (when-let [^js/HTMLElement root cnt-el] + (let [fn-start (fn [^js/MouseEvent e] + (if (should-start e) + (let [target (.-target e) + page-el (.closest target ".page") + [x y] [(.-pageX e) (.-pageY e)]] + (rum/set-ref! *start-el target) + (rum/set-ref! *start-xy [x y]) + (rum/set-ref! *page-el page-el) + (rum/set-ref! *page-rect (some-> page-el (.getBoundingClientRect) (.toJSON) (bean/->clj))) + (set-start! (calc-coords! x y)) + (disable-text-selection! true) + + (.addEventListener root "mousemove" fn-move)) + + ;; reset + (do (reset-coords!) + (disable-text-selection! false)))) + + fn-end (fn [^js/MouseEvent e] + (when-let [start-el (rum/deref *start-el)] + (let [end (calc-coords! (.-pageX e) (.-pageY e)) + rect (calc-rect start end)] + + (if (and (> (:width rect) 10) + (> (:height rect) 10)) + + (when-let [^js page-el (.closest start-el ".page")] + (let [page-number (int (.-pageNumber (.-dataset page-el))) + page-pos (merge rect {:top (- (:top rect) (.-offsetTop page-el)) + :left (- (:left rect) (.-offsetLeft page-el))}) + vw-pos {:bounding page-pos :rects [] :page page-number} + sc-pos (pdf-utils/vw-to-scaled-pos viewer vw-pos) + + point {:x (.-clientX e) :y (.-clientY e)} + hl {:id nil + :page page-number + :position sc-pos + :content {:text "[:span]" :image (js/Date.now)} + :properties {}}] + + ;; ctx tips + (show-ctx-menu! viewer hl point {:reset-fn #(reset-coords!)})) + + (set-area-mode! false)) + + ;; reset + (reset-coords!))) + + (disable-text-selection! false) + (.removeEventListener root "mousemove" fn-move)))] + + (doto root + (.addEventListener "mousedown" fn-start) + (.addEventListener "mouseup" fn-end #js {:once true})) + + ;; destroy + #(doto root + (.removeEventListener "mousedown" fn-start) + (.removeEventListener "mouseup" fn-end))))) + [start]) [:div.extensions__pdf-area-selection {:ref *el} - (when (and start-coord end-coord) - [:div.shadow-rect {:style (calc-pos start-coord end-coord)}])])) + (when (and start end) + [:div.shadow-rect {:style (calc-rect start end)}])])) (rum/defc ^:large-vars/cleanup-todo pdf-highlights [^js el ^js viewer initial-hls loaded-pages {:keys [set-dirty-hls!]}] @@ -641,8 +655,6 @@ ;; render hls (rum/use-effect! (fn [] - ;;(dd "=== rebuild highlights ===" (count highlights)) - (when-let [grouped-hls (and (sequential? highlights) (group-by :page highlights))] (doseq [page loaded-pages] (when-let [^js/HTMLDivElement hls-layer (pdf-utils/resolve-hls-layer! viewer page)] diff --git a/src/main/frontend/extensions/pdf/toolbar.cljs b/src/main/frontend/extensions/pdf/toolbar.cljs index 7c4d1edee54..4faef3cda27 100644 --- a/src/main/frontend/extensions/pdf/toolbar.cljs +++ b/src/main/frontend/extensions/pdf/toolbar.cljs @@ -21,6 +21,7 @@ (def *area-dashed? (atom ((fnil identity false) (storage/get (str "ls-pdf-area-is-dashed"))))) (def *area-mode? (atom false)) (def *highlight-mode? (atom false)) +#_:clj-kondo/ignore (rum/defcontext *highlights-ctx*) (rum/defc pdf-settings diff --git a/src/main/frontend/extensions/srs.cljs b/src/main/frontend/extensions/srs.cljs index be559747da7..25805d3bffc 100644 --- a/src/main/frontend/extensions/srs.cljs +++ b/src/main/frontend/extensions/srs.cljs @@ -28,7 +28,8 @@ [clojure.string :as string] [rum.core :as rum] [frontend.modules.shortcut.core :as shortcut] - [medley.core :as medley])) + [medley.core :as medley] + [frontend.context.i18n :refer [t]])) ;;; ================================================================ ;;; Commentary @@ -409,7 +410,7 @@ (reset! *phase 1))) (def review-finished - [:p.p-2 "Congrats, you've reviewed all the cards for this query, see you next time! 💯"]) + [:p.p-2 (t :flashcards/modal-finished)]) (defn- btn-with-shortcut [{:keys [shortcut id btn-text background on-click class]}] (ui/button @@ -457,9 +458,9 @@ [:div.flex.my-4.justify-between (when-not (and (not preview?) (= next-phase 1)) (btn-with-shortcut {:btn-text (case next-phase - 1 "Hide answers" - 2 "Show answers" - 3 "Show clozes") + 1 (t :flashcards/modal-btn-hide-answers) + 2 (t :flashcards/modal-btn-show-answers) + 3 (t :flashcards/modal-btn-show-clozes)) :shortcut "s" :id "card-answers" :class "mr-2" @@ -467,7 +468,7 @@ (when (and (not= @card-index (count blocks)) cards? preview?) - (btn-with-shortcut {:btn-text "Next" + (btn-with-shortcut {:btn-text (t :flashcards/modal-btn-next-card) :shortcut "n" :id "card-next" :class "mr-2" @@ -477,7 +478,7 @@ (when (and (not preview?) (= 1 next-phase)) [:<> - (btn-with-shortcut {:btn-text "Forgotten" + (btn-with-shortcut {:btn-text (t :flashcards/modal-btn-forgotten) :shortcut "f" :id "card-forgotten" :background "red" @@ -486,12 +487,12 @@ (let [tomorrow (tc/to-string (t/plus (t/today) (t/days 1)))] (editor-property/set-block-property! root-block-id card-next-schedule-property tomorrow)))}) - (btn-with-shortcut {:btn-text (if (util/mobile?) "Hard" "Took a while to recall") + (btn-with-shortcut {:btn-text (if (util/mobile?) "Hard" (t :flashcards/modal-btn-recall)) :shortcut "t" :id "card-recall" :on-click #(score-and-next-card 3 card card-index finished? phase review-records cb)}) - (btn-with-shortcut {:btn-text "Remembered" + (btn-with-shortcut {:btn-text (t :flashcards/modal-btn-remembered) :shortcut "r" :id "card-remembered" :background "green" @@ -499,10 +500,10 @@ (when preview? (ui/tippy {:html [:div.text-sm - "Reset this card so that you can review it immediately."] + (t :flashcards/modal-btn-reset-tip)] :class "tippy-hover" :interactive true} - (ui/button [:span "Reset"] + (ui/button [:span (t :flashcards/modal-btn-reset)] :id "card-reset" :class (util/hiccup->class "opacity-60.hover:opacity-100.card-reset") :on-click (fn [e] @@ -589,11 +590,11 @@ (let [cards (db-model/get-macro-blocks (state/get-current-repo) "cards") items (->> (map (comp :logseq.macro-arguments :block/properties) cards) (map (fn [col] (string/join " " col)))) - items (concat items ["All"])] + items (concat items [(t :flashcards/modal-select-all)])] (component-select/select {:items items :on-chosen on-chosen :close-modal? false - :input-default-placeholder "Switch to" + :input-default-placeholder (t :flashcards/modal-select-switch) :extract-fn nil}))) ;;; register cards macro @@ -626,12 +627,12 @@ {:on-mouse-down (fn [e] (util/stop e) (toggle-fn))} - [:span.flex (if (string/blank? query-string) "All" query-string) + [:span.flex (if (string/blank? query-string) (t :flashcards/modal-select-all) query-string) [:span {:style {:margin-top 2}} (svg/caret-down)]]]) (fn [{:keys [toggle-fn]}] (cards-select {:on-chosen (fn [query] - (let [query' (if (= query "All") "" query)] + (let [query' (if (= query (t :flashcards/modal-select-all)) "" query)] (reset! query-atom query') (toggle-fn)))})) {:modal-class (util/hiccup->class @@ -641,13 +642,13 @@ ;; FIXME: CSS issue (if @*preview-mode? - (ui/tippy {:html [:div.text-sm "current/total"] + (ui/tippy {:html [:div.text-sm (t :flashcards/modal-current-total)] :interactive true} [:div.opacity-60.text-sm.mr-3 @*card-index [:span "/"] total]) - (ui/tippy {:html [:div.text-sm "overdue/total"] + (ui/tippy {:html [:div.text-sm (t :flashcards/modal-overdue-total)] ;; :class "tippy-hover" :interactive true} [:div.opacity-60.text-sm.mr-3 @@ -656,7 +657,7 @@ total])) (ui/tippy - {:html [:div.text-sm "Toggle preview mode"] + {:html [:div.text-sm (t :flashcards/modal-toggle-preview-mode)] :delay [1000, 100] :class "tippy-hover" :interactive true @@ -671,7 +672,7 @@ "A"]) (ui/tippy - {:html [:div.text-sm "Toggle random mode"] + {:html [:div.text-sm (t :flashcards/modal-toggle-random-mode)] :delay [1000, 100] :class "tippy-hover" :interactive true} @@ -701,15 +702,15 @@ *card-index))]]) (if (:global? config) [:div.ls-card.content - [:h1.title "Time to create a card!"] + [:h1.title (t :flashcards/modal-welcome-title)] [:div - [:p "You can add \"#card\" to any block to turn it into a card or trigger \"/cloze\" to add some clozes."] + [:p (t :flashcards/modal-welcome-desc-1)] [:img.my-4 {:src "https://docs.logseq.com/assets/2021-07-22_22.28.02_1626964258528_0.gif"}] - [:p "You can " - [:a {:href "https://docs.logseq.com/#/page/cards" :target "_blank"} - "click this link"] - " to check the documentation."]]] + [:p (t :flashcards/modal-welcome-desc-2) + [:a {:href "https://docs.logseq.com/#/page/Flashcards" :target "_blank"} + (t :flashcards/modal-welcome-desc-3)] + (t :flashcards/modal-welcome-desc-4)]]] [:div.opacity-60.custom-query-title.ls-card.content [:div.w-full.flex-1 [:code.p-1 (str "Cards: " query-string)]] @@ -809,4 +810,4 @@ (when (nil? @*due-cards-interval) ;; refresh every hour (let [interval (js/setInterval f (* 3600 1000))] - (reset! *due-cards-interval interval)))))) + (reset! *due-cards-interval interval)))))) \ No newline at end of file diff --git a/src/main/frontend/extensions/tldraw.cljs b/src/main/frontend/extensions/tldraw.cljs index 13c2ddaac7e..409fafcf6d8 100644 --- a/src/main/frontend/extensions/tldraw.cljs +++ b/src/main/frontend/extensions/tldraw.cljs @@ -5,6 +5,7 @@ [frontend.components.export :as export] [frontend.components.page :as page] [frontend.config :as config] + [frontend.context.i18n :refer [t]] [frontend.db.model :as model] [frontend.handler.editor :as editor-handler] [frontend.handler.route :as route-handler] @@ -93,7 +94,8 @@ (def undo (fn [] (history/undo! nil))) (def redo (fn [] (history/redo! nil))) (defn get-tldraw-handlers [current-whiteboard-name] - {:search search-handler + {:t (fn [key] (t (keyword key))) + :search search-handler :queryBlockByUUID (fn [block-uuid] (clj->js (model/query-block-by-uuid (parse-uuid block-uuid)))) @@ -128,7 +130,7 @@ (rum/defc tldraw-app [page-name block-id] - (let [populate-onboarding? (whiteboard-handler/should-populate-onboarding-whiteboard? page-name) + (let [populate-onboarding? (whiteboard-handler/should-populate-onboarding-whiteboard? page-name) data (whiteboard-handler/page-name->tldr! page-name) [loaded-app set-loaded-app] (rum/use-state nil) on-mount (fn [^js tln] diff --git a/src/main/frontend/handler/code.cljs b/src/main/frontend/handler/code.cljs index bc8829cbb36..c8a835bffc5 100644 --- a/src/main/frontend/handler/code.cljs +++ b/src/main/frontend/handler/code.cljs @@ -18,9 +18,12 @@ (when editor (.save editor) (let [textarea (.getTextArea editor) + ds (.-dataset textarea) value (gobj/get textarea "value") - default-value (gobj/get textarea "defaultValue")] + default-value (or (.-v ds) (gobj/get textarea "defaultValue"))] (when (not= value default-value) + ;; update default value for the editor initial state + (set! ds -v value) (cond ;; save block content (:block/uuid config) diff --git a/src/main/frontend/handler/common/config_edn.cljs b/src/main/frontend/handler/common/config_edn.cljs index 90b7233fb91..c26b0b20e7c 100644 --- a/src/main/frontend/handler/common/config_edn.cljs +++ b/src/main/frontend/handler/common/config_edn.cljs @@ -92,7 +92,7 @@ nested keys or positional errors e.g. tuples" (let [body (try (edn/read-string content) (catch :default _ ::failed-to-detect)) warnings {:editor/command-trigger - "Will no longer be supported soon. Please use '/' and report bugs on it."}] + "is no longer supported. Please use '/' and report bugs on it."}] (cond (= body ::failed-to-detect) (log/info :msg "Skip deprecation check since config is not valid edn") diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index ed5919fe1e6..bb8cf580dd5 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -169,7 +169,6 @@ ([text] (when-let [m (get-selection-and-format)] (let [{:keys [selection-start selection-end format selection value edit-id input]} m - cur-pos (cursor/pos input) empty-selection? (= selection-start selection-end) selection-link? (and selection (gp-mldoc/mldoc-link? format selection)) [content forward-pos] (cond @@ -191,7 +190,7 @@ (subs value 0 selection-start) content (subs value selection-end)) - cur-pos (or selection-start cur-pos)] + cur-pos (or selection-start (cursor/pos input))] (state/set-edit-content! edit-id new-value) (cursor/move-cursor-to input (+ cur-pos forward-pos)))))) @@ -301,10 +300,10 @@ (save-block-inner! block value opts))))))) (defn- compute-fst-snd-block-text - [value pos] + [value selection-start selection-end] (when (string? value) - (let [fst-block-text (subs value 0 pos) - snd-block-text (string/triml (subs value pos))] + (let [fst-block-text (subs value 0 selection-start) + snd-block-text (string/triml (subs value selection-end))] [fst-block-text snd-block-text]))) (declare save-current-block!) @@ -342,13 +341,21 @@ (= uuid block-id))) (defn insert-new-block-before-block-aux! - [config block _value {:keys [ok-handler]}] - (let [new-m {:block/uuid (db/new-block-id) + [config block value {:keys [ok-handler]}] + (let [edit-input-id (state/get-edit-input-id) + input (gdom/getElement edit-input-id) + input-text-selected? (util/input-text-selected? input) + new-m {:block/uuid (db/new-block-id) :block/content ""} prev-block (-> (merge (select-keys block [:block/parent :block/left :block/format :block/page :block/journal?]) new-m) (editor-impl/wrap-parse-block)) left-block (db/pull (:db/id (:block/left block)))] + (when input-text-selected? + (let [selection-start (util/get-selection-start input) + selection-end (util/get-selection-end input) + [_ new-content] (compute-fst-snd-block-text value selection-start selection-end)] + (state/set-edit-content! edit-input-id new-content))) (profile "outliner insert block" (let [sibling? (not= (:db/id left-block) (:db/id (:block/parent block)))] @@ -365,8 +372,9 @@ :as _opts}] (let [block-self? (block-self-alone-when-insert? config uuid) input (gdom/getElement (state/get-edit-input-id)) - pos (cursor/pos input) - [fst-block-text snd-block-text] (compute-fst-snd-block-text value pos) + selection-start (util/get-selection-start input) + selection-end (util/get-selection-end input) + [fst-block-text snd-block-text] (compute-fst-snd-block-text value selection-start selection-end) current-block (assoc block :block/content fst-block-text) current-block (apply dissoc current-block db-schema/retract-attributes) new-m {:block/uuid (db/new-block-id) @@ -419,8 +427,9 @@ block) block-self? (block-self-alone-when-insert? config block-id) input (gdom/getElement (state/get-edit-input-id)) - pos (cursor/pos input) - [fst-block-text snd-block-text] (compute-fst-snd-block-text value pos) + selection-start (util/get-selection-start input) + selection-end (util/get-selection-end input) + [fst-block-text snd-block-text] (compute-fst-snd-block-text value selection-start selection-end) insert-fn (cond block-self? insert-new-block-aux! @@ -691,7 +700,7 @@ (delete-block! repo true)) ([repo delete-children?] (state/set-editor-op! :delete) - (let [{:keys [id block-id block-parent-id value format]} (get-state)] + (let [{:keys [id block-id block-parent-id value format config]} (get-state)] (when block-id (let [page-id (:db/id (:block/page (db/entity [:block/uuid block-id]))) page-blocks-count (and page-id (db/get-page-blocks-count repo page-id))] @@ -707,24 +716,28 @@ (when-not (and has-children? left-has-children?) (when block-parent-id (let [block-parent (gdom/getElement block-parent-id) - sibling-block (util/get-prev-block-non-collapsed-non-embed block-parent) + sibling-block (if (:embed? config) + (util/get-prev-block-non-collapsed + block-parent + {:container (util/rec-get-blocks-container block-parent)}) + (util/get-prev-block-non-collapsed-non-embed block-parent)) {:keys [prev-block new-content move-fn]} (move-to-prev-block repo sibling-block format id value false) concat-prev-block? (boolean (and prev-block new-content)) transact-opts (cond-> - {:outliner-op :delete-blocks} + {:outliner-op :delete-blocks} concat-prev-block? (assoc :concat-data {:last-edit-block (:block/uuid block)}))] (outliner-tx/transact! transact-opts - (if concat-prev-block? - (let [prev-block' (if (seq (:block/_refs block-e)) - (assoc prev-block - :block/uuid (:block/uuid block) - :block.temp/additional-properties (:block/properties block)) - prev-block)] - (delete-block-aux! block delete-children?) - (save-block! repo prev-block' new-content {:editor/op :delete})) - (delete-block-aux! block delete-children?))) + (if concat-prev-block? + (let [prev-block' (if (seq (:block/_refs block-e)) + (assoc prev-block + :block/uuid (:block/uuid block) + :block.temp/additional-properties (:block/properties block)) + prev-block)] + (delete-block-aux! block delete-children?) + (save-block! repo prev-block' new-content {:editor/op :delete})) + (delete-block-aux! block delete-children?))) (move-fn))))))))) (state/set-editor-op! nil))) @@ -1416,7 +1429,7 @@ (if file-obj (.-name file-obj) (if image? "image" "asset")) image?) format - {:last-pattern (if drop-or-paste? "" (state/get-editor-command-trigger)) + {:last-pattern (if drop-or-paste? "" commands/command-trigger) :restore? true :command :insert-asset}))))) (p/finally @@ -1555,7 +1568,7 @@ last-command (and last-slash-caret-pos (subs edit-content last-slash-caret-pos pos))] (when (> pos 0) (or - (and (= (state/get-editor-command-trigger) (util/nth-safe edit-content (dec pos))) + (and (= commands/command-trigger (util/nth-safe edit-content (dec pos))) @commands/*initial-commands) (and last-command (commands/get-matched-commands last-command))))) @@ -1673,7 +1686,7 @@ id (get-link format link label) format - {:last-pattern (str (state/get-editor-command-trigger) "link") + {:last-pattern (str commands/command-trigger "link") :command :link}))) :image-link (let [{:keys [link label]} m] @@ -1682,7 +1695,7 @@ id (get-image-link format link label) format - {:last-pattern (str (state/get-editor-command-trigger) "link") + {:last-pattern (str commands/command-trigger "link") :command :image-link}))) nil) @@ -1748,12 +1761,11 @@ (cond (and (= content "1. ") (= last-input-char " ") input-id edit-block (not (own-order-number-list? edit-block))) - (do - (state/set-edit-content! input-id "") - (-> (p/delay 10) - (p/then #(state/pub-event! [:editor/toggle-own-number-list edit-block])))) + (p/do! + (state/pub-event! [:editor/toggle-own-number-list edit-block]) + (state/set-edit-content! input-id "")) - (and (= last-input-char (state/get-editor-command-trigger)) + (and (= last-input-char commands/command-trigger) (or (re-find #"(?m)^/" (str (.-value input))) (start-of-new-word? input pos))) (do (state/set-editor-action-data! {:pos (cursor/get-caret-pos input)}) @@ -1935,6 +1947,7 @@ :keep-uuid? keep-uuid?})] (edit-last-block-after-inserted! result)))))) + (defn- block-tree->blocks "keep-uuid? - maintain the existing :uuid in tree vec" [repo tree-vec format keep-uuid? page-name] @@ -2605,7 +2618,7 @@ (delete-block! repo false)))) (and (> current-pos 1) - (= (util/nth-safe value (dec current-pos)) (state/get-editor-command-trigger))) + (= (util/nth-safe value (dec current-pos)) commands/command-trigger)) (do (util/stop e) (commands/restore-state) @@ -2891,8 +2904,8 @@ (util/event-is-composing? e true)])] (cond ;; When you type something after / - (and (= :commands (state/get-editor-action)) (not= k (state/get-editor-command-trigger))) - (if (= (state/get-editor-command-trigger) (second (re-find #"(\S+)\s+$" value))) + (and (= :commands (state/get-editor-action)) (not= k commands/command-trigger)) + (if (= commands/command-trigger (second (re-find #"(\S+)\s+$" value))) (state/clear-editor-action!) (let [matched-commands (get-matched-commands input)] (if (seq matched-commands) @@ -3495,7 +3508,7 @@ edit-block (state/get-edit-block) target-element (.-nodeName (.-target e))] (cond - (whiteboard?) + (and (whiteboard?) (not edit-input)) (do (util/stop e) (.selectAll (.-api ^js (state/active-tldraw-app)))) diff --git a/src/main/frontend/handler/editor/lifecycle.cljs b/src/main/frontend/handler/editor/lifecycle.cljs index fe52b5495f7..d660cd7aea2 100644 --- a/src/main/frontend/handler/editor/lifecycle.cljs +++ b/src/main/frontend/handler/editor/lifecycle.cljs @@ -27,7 +27,7 @@ (js/setTimeout #(util/scroll-editor-cursor element) 50))) state) -(defn did-remount! +(defn will-remount! [_old-state state] (keyboards-handler/esc-save! state) state) @@ -45,5 +45,5 @@ (def lifecycle {:did-mount did-mount! - :did-remount did-remount! + :will-remount will-remount! :will-unmount will-unmount}) diff --git a/src/main/frontend/handler/events.cljs b/src/main/frontend/handler/events.cljs index f304b3feb47..d8eecf41c6e 100644 --- a/src/main/frontend/handler/events.cljs +++ b/src/main/frontend/handler/events.cljs @@ -23,6 +23,7 @@ [frontend.components.shell :as shell] [frontend.components.whiteboard :as whiteboard] [frontend.components.user.login :as login] + [frontend.components.shortcut :as shortcut] [frontend.components.repo :as repo] [frontend.config :as config] [frontend.context.i18n :refer [t]] @@ -167,12 +168,8 @@ ;; Parameters for the `persist-db` function, to show the notification messages (def persist-db-noti-m - {:before #(notification/show! - (ui/loading (t :graph/persist)) - :warning) - :on-error #(notification/show! - (t :graph/persist-error) - :error)}) + {:before #(ui/notify-graph-persist!) + :on-error #(ui/notify-graph-persist-error!)}) (defn- graph-switch-on-persisted "Logic for keeping db sync when switching graphs @@ -949,6 +946,11 @@ (defmethod handle :editor/quick-capture [[_ args]] (quick-capture/quick-capture args)) +(defmethod handle :modal/keymap-manager [[_]] + (state/set-modal! + #(shortcut/keymap-pane) + {:label "keymap-manager"})) + (defmethod handle :editor/toggle-own-number-list [[_ blocks]] (let [batch? (sequential? blocks) blocks (cond->> blocks @@ -973,15 +975,20 @@ [] (let [chan (state/get-events-chan)] (async/go-loop [] - (let [payload (async/js payload) "\n" error) - (state/pub-event! [:capture-error {:error error - :payload {:type type - :payload payload}}]))))) + (let [[payload d] (async/ + (try + (p/resolved (handle payload)) + (catch :default error + (p/rejected error))) + (p/then (fn [result] + (p/resolve! d result))) + (p/catch (fn [error] + (let [type :handle-system-events/failed] + (state/pub-event! [:capture-error {:error error + :payload {:type type + :payload payload}}]) + (p/reject! d error)))))) (recur)) chan)) diff --git a/src/main/frontend/handler/global_config.cljs b/src/main/frontend/handler/global_config.cljs index b1f2f6e3a78..e366fa61875 100644 --- a/src/main/frontend/handler/global_config.cljs +++ b/src/main/frontend/handler/global_config.cljs @@ -41,7 +41,7 @@ (state/set-global-config! config) config)) -(def default-content (rc/inline "global-config.edn")) +(def default-content (rc/inline "templates/global-config.edn")) (defn- create-global-config-file-if-not-exists [repo-url] diff --git a/src/main/frontend/handler/page.cljs b/src/main/frontend/handler/page.cljs index 62ac6e7a6cd..1038533f62f 100644 --- a/src/main/frontend/handler/page.cljs +++ b/src/main/frontend/handler/page.cljs @@ -6,7 +6,6 @@ [datascript.core :as d] [frontend.commands :as commands] [frontend.config :as config] - [frontend.context.i18n :refer [t]] [frontend.date :as date] [frontend.db :as db] [frontend.db.conn :as conn] @@ -850,10 +849,6 @@ (fn [chosen _click?] (state/clear-editor-action!) (let [wrapped? (= page-ref/left-brackets (gp-util/safe-subs edit-content (- pos 2) pos)) - prefix (str (t :new-page) ": ") - chosen (if (string/starts-with? chosen prefix) ;; FIXME: What if a page named "New page: XXX"? - (string/replace-first chosen prefix "") - chosen) chosen (if (and (util/safe-re-find #"\s+" chosen) (not wrapped?)) (page-ref/->page-ref chosen) chosen) @@ -872,11 +867,7 @@ :command :page-ref}))) (fn [chosen _click?] (state/clear-editor-action!) - (let [prefix (str (t :new-page) ": ") - chosen (if (string/starts-with? chosen prefix) - (string/replace-first chosen prefix "") - chosen) - page-ref-text (get-page-ref-text chosen)] + (let [page-ref-text (get-page-ref-text chosen)] (editor-handler/insert-command! id page-ref-text format diff --git a/src/main/frontend/handler/paste.cljs b/src/main/frontend/handler/paste.cljs index 583db899ffb..e5e57cfc664 100644 --- a/src/main/frontend/handler/paste.cljs +++ b/src/main/frontend/handler/paste.cljs @@ -114,77 +114,87 @@ (when (= (set (map :block/uuid blocks)) recent-cut-block-ids) (seq revert-tx)))) -(defn- paste-copied-blocks-or-text - ;; todo: logseq/whiteboard-shapes is now text/html - [text e html] - (util/stop e) - (-> - (p/let [copied-blocks (get-copied-blocks)] - (let [input (state/get-input) - input-id (state/get-edit-input-id) - text (string/replace text "\r\n" "\n") ;; Fix for Windows platform - replace-text-f (fn [text] - (let [input-id (state/get-edit-input-id)] - (commands/delete-selection! input-id) - (commands/simple-insert! input-id text nil))) - internal-paste? (seq copied-blocks)] - (if internal-paste? - (let [revert-cut-tx (get-revert-cut-tx copied-blocks) - cut-paste? (boolean (seq revert-cut-tx)) - keep-uuid? cut-paste?] - (editor-handler/paste-blocks copied-blocks {:revert-cut-tx revert-cut-tx - :cut-paste? cut-paste? - :keep-uuid? keep-uuid?})) - (let [shape-refs-text (when (and (not (string/blank? html)) - (get-whiteboard-tldr-from-text html)) - ;; text should always be prepared block-ref generated in tldr - text) - {:keys [value selection] :as selection-and-format} (editor-handler/get-selection-and-format) - text-url? (gp-util/url? text) - selection-url? (gp-util/url? selection)] - (cond - (not (string/blank? shape-refs-text)) - (commands/simple-insert! input-id shape-refs-text nil) +(defn- paste-copied-text + [input *text html] + (let [replace-text-f (fn [text] + (let [input-id (state/get-edit-input-id)] + (commands/delete-selection! input-id) + (commands/simple-insert! input-id text nil))) + text (string/replace *text "\r\n" "\n") ;; Fix for Windows platform + input-id (state/get-edit-input-id) + shape-refs-text (when (and (not (string/blank? html)) + (get-whiteboard-tldr-from-text html)) + ;; text should always be prepared block-ref generated in tldr + text) + {:keys [value selection] :as selection-and-format} (editor-handler/get-selection-and-format) + text-url? (gp-util/url? text) + selection-url? (gp-util/url? selection)] + (cond + (not (string/blank? shape-refs-text)) + (commands/simple-insert! input-id shape-refs-text nil) + + ;; When a url is selected in a formatted link, replaces it with pasted text + (or (and (or text-url? selection-url?) + (selection-within-link? selection-and-format)) + (and text-url? selection-url?)) + (replace-text-f text) - (or (and (or text-url? selection-url?) - (selection-within-link? selection-and-format)) - (and text-url? selection-url?)) - (replace-text-f text) + ;; Pastes a formatted link over selected text + (and (or text-url? + (and value (gp-util/url? (string/trim value)))) + (not (string/blank? (util/get-selected-text)))) + (editor-handler/html-link-format! text) - (and (or text-url? - (and value (gp-util/url? (string/trim value)))) - (not (string/blank? (util/get-selected-text)))) - (editor-handler/html-link-format! text) + ;; Pastes only block id when inside of '(())' + (and (block-ref/block-ref? text) + (editor-handler/wrapped-by? input block-ref/left-parens block-ref/right-parens)) + (commands/simple-insert! input-id (block-ref/get-block-ref-id text) nil) - (and (block-ref/block-ref? text) - (editor-handler/wrapped-by? input block-ref/left-parens block-ref/right-parens)) - (commands/simple-insert! input-id (block-ref/get-block-ref-id text) nil) + :else + ;; from external + (let [format (or (db/get-page-format (state/get-current-page)) :markdown) + html-text (let [result (when-not (string/blank? html) + (try + (html-parser/convert format html) + (catch :default e + (log/error :exception e) + nil)))] + (if (string/blank? result) nil result)) + text-blocks? (if (= format :markdown) markdown-blocks? org-blocks?) + blocks? (text-blocks? text) + text' (or html-text + (when (gp-util/url? text) + (wrap-macro-url text)) + text)] + (cond + blocks? + (paste-text-parseable format text) - :else - ;; from external - (let [format (or (db/get-page-format (state/get-current-page)) :markdown) - html-text (let [result (when-not (string/blank? html) - (try - (html-parser/convert format html) - (catch :default e - (log/error :exception e) - nil)))] - (if (string/blank? result) nil result)) - text-blocks? (if (= format :markdown) markdown-blocks? org-blocks?) - blocks? (text-blocks? text) - text' (or html-text text)] - (cond - blocks? - (paste-text-parseable format text) + (util/safe-re-find #"(?:\r?\n){2,}" text') + (paste-segmented-text format text') - (util/safe-re-find #"(?:\r?\n){2,}" text') - (paste-segmented-text format text') + :else + (replace-text-f text')))))) - :else - (replace-text-f text')))))))) +(defn- paste-copied-blocks-or-text + ;; todo: logseq/whiteboard-shapes is now text/html + [input text e html] + (util/stop e) + (-> + (p/let [copied-blocks (get-copied-blocks)] + (if (seq copied-blocks) + ;; Handle internal paste + (let [revert-cut-tx (get-revert-cut-tx copied-blocks) + cut-paste? (boolean (seq revert-cut-tx)) + keep-uuid? cut-paste?] + (editor-handler/paste-blocks copied-blocks {:revert-cut-tx revert-cut-tx + :cut-paste? cut-paste? + :keep-uuid? keep-uuid?})) + (paste-copied-text input text html))) (p/catch (fn [error] - (prn "Paste failed: ") - (log/error :exception error))))) + (log/error :msg "Paste failed" :exception error) + (state/pub-event! [:capture-error {:error error + :payload {:type ::paste-copied-blocks-or-text}}]))))) (defn paste-text-in-one-block-at-point [] @@ -206,7 +216,7 @@ (when-not (mobile-util/native-ios?) (util/stop e) (paste-text-in-one-block-at-point)) - (paste-copied-blocks-or-text text e html))) + (paste-copied-blocks-or-text input text e html))) (defn- paste-file-if-exists [id e] (when id @@ -248,10 +258,7 @@ (paste-file-if-exists id e) :else - (let [text' (or (when (gp-util/url? text) - (wrap-macro-url text)) - text)] - (paste-text-or-blocks-aux (state/get-input) e text' html)))))) + (paste-text-or-blocks-aux (state/get-input) e text html))))) (defn editor-on-paste-raw! "Raw pastes without _any_ formatting. Can also replace selected text with a paste" diff --git a/src/main/frontend/handler/plugin.cljs b/src/main/frontend/handler/plugin.cljs index 121450b7e7f..edac2513750 100644 --- a/src/main/frontend/handler/plugin.cljs +++ b/src/main/frontend/handler/plugin.cljs @@ -7,6 +7,7 @@ [logseq.graph-parser.mldoc :as gp-mldoc] [frontend.handler.notification :as notification] [frontend.handler.common.plugin :as plugin-common-handler] + [frontend.storage :as storage] [camel-snake-kebab.core :as csk] [frontend.state :as state] [medley.core :as medley] @@ -186,8 +187,6 @@ [] (let [channel (name :lsp-updates) listener (fn [_ ^js e] - (js/console.debug (str :lsp-updates) e) - (when-let [{:keys [status payload only-check]} (bean/->clj e)] (case (keyword status) @@ -203,7 +202,7 @@ #(do ;;(if theme (select-a-plugin-theme id)) (notification/show! - (str (t :plugin/update) (t :plugins) ": " name " - " (.-version (.-options pl))) :success) + (t :plugin/update-plugin name (.-version (.-options pl))) :success) (state/consume-updates-from-coming-plugin! payload true)))) (do ;; register new @@ -211,7 +210,7 @@ (js/LSPluginCore.register (bean/->js {:key id :url dst})) (fn [] (when theme (js/setTimeout #(select-a-plugin-theme id) 300)))) (notification/show! - (str (t :plugin/installed) (t :plugins) ": " name) :success))))) + (t :plugin/installed-plugin name) :success))))) :error (let [error-code (keyword (string/replace (:error-code payload) #"^[\s\:\[]+" "")) @@ -219,7 +218,7 @@ [msg type] (case error-code :no-new-version - [(str (t :plugin/up-to-date) " :)") :success] + [(t :plugin/up-to-date ":)") :success] [error-code :error]) pending? (seq (:plugin/updates-pending @state/state))] @@ -297,9 +296,10 @@ [pid key keybinding] (let [id (keyword (str "plugin." pid "/" key)) binding (:binding keybinding) + binding (some->> (if (string? binding) [binding] (seq binding)) + (map util/normalize-user-keyname)) binding (if util/mac? - (or (:mac keybinding) binding) - binding) + (or (:mac keybinding) binding) binding) mode (or (:mode keybinding) :global) mode (get keybinding-mode-handler-map (keyword mode))] [mode id {:binding binding}])) @@ -630,6 +630,14 @@ (state/pub-event! [:plugin/consume-updates]) (set-auto-checking! true)))) +(defn get-enabled-auto-check-for-updates? + [] + (not (false? (storage/get :lsp-last-auto-updates)))) + +(defn set-enabled-auto-check-for-updates + [v?] + (storage/set :lsp-last-auto-updates (boolean v?))) + (defn call-plugin [^js pl type payload] (when pl diff --git a/src/main/frontend/handler/query.cljs b/src/main/frontend/handler/query.cljs deleted file mode 100644 index ab9165013d2..00000000000 --- a/src/main/frontend/handler/query.cljs +++ /dev/null @@ -1,49 +0,0 @@ -(ns frontend.handler.query - "Provides util handler fns for query" - (:require [clojure.walk :as walk])) - -(defn normalize-query-function - [ast result] - (let [ast (walk/prewalk - (fn [f] - (if (and (list? f) - (keyword? (second f)) - (contains? #{'sum 'average 'count 'min 'max} (first f))) - (if (contains? #{'min 'max} (first f)) - (list - 'apply - (first f) - (list 'map (second f) 'result)) - (list - (first f) - (list 'map (second f) 'result))) - f)) - ast)] - (walk/postwalk - (fn [f] - (cond - (keyword? f) - (case f - :block - :block/content - - :page - :block/name - - :created-at - :block/created-at - - :updated-at - :block/updated-at - - (let [vals (map #(get-in % [:block/properties f]) result) - int? (some integer? vals)] - `(~'fn [~'b] - (~'let [~'result-str (~'get-in ~'b [:block/properties ~f]) - ~'result-num (~'parseFloat ~'result-str) - ~'result (if (~'isNaN ~'result-num) ~'result-str ~'result-num)] - (~'or ~'result (~'when ~int? 0)))))) - - :else - f)) - ast))) diff --git a/src/main/frontend/handler/repo.cljs b/src/main/frontend/handler/repo.cljs index 17cb52896cc..0e8ea279038 100644 --- a/src/main/frontend/handler/repo.cljs +++ b/src/main/frontend/handler/repo.cljs @@ -51,8 +51,8 @@ (let [format (state/get-preferred-format) file-rpath (str "pages/" "contents." (config/get-file-extension format)) default-content (case (name format) - "org" (rc/inline "contents.org") - "markdown" (rc/inline "contents.md") + "org" (rc/inline "templates/contents.org") + "markdown" (rc/inline "templates/contents.md") "")] (p/let [_ (fs/mkdir-if-not-exists (path/path-join repo-dir pages-dir)) file-exists? (fs/create-if-not-exists repo-url repo-dir file-rpath default-content)] diff --git a/src/main/frontend/handler/route.cljs b/src/main/frontend/handler/route.cljs index fb6eb8bad81..7659fc17851 100644 --- a/src/main/frontend/handler/route.cljs +++ b/src/main/frontend/handler/route.cljs @@ -86,7 +86,9 @@ (defn redirect-to-whiteboard! ([name] (redirect-to-whiteboard! name nil)) - ([name {:keys [block-id]}] + ([name {:keys [block-id new-whiteboard?]}] + ;; Always skip onboarding when loading an existing whiteboard + (when-not new-whiteboard? (state/set-onboarding-whiteboard! true)) (recent-handler/add-page-to-recent! (state/get-current-repo) name false) (if (= name (state/get-current-whiteboard)) (state/focus-whiteboard-shape block-id) @@ -99,6 +101,8 @@ (case name :home "Logseq" + :whiteboards + (t :whiteboards) :repos "Repos" :repo-add @@ -129,6 +133,15 @@ (let [page (db/pull [:block/name (util/page-name-sanity-lc name)])] (or (util/get-page-original-name page) "Logseq")))) + :whiteboard + (let [name (:name path-params) + block? (util/uuid-string? name)] + (str + (if block? + (t :untitled) + (let [page (db/pull [:block/name (util/page-name-sanity-lc name)])] + (or (util/get-page-original-name page) + "Logseq"))) " - " (t :whiteboard))) :tag (str "#" (:name path-params)) :diff diff --git a/src/main/frontend/handler/ui.cljs b/src/main/frontend/handler/ui.cljs index 16aeda524c9..cf93904a041 100644 --- a/src/main/frontend/handler/ui.cljs +++ b/src/main/frontend/handler/ui.cljs @@ -17,26 +17,18 @@ [promesa.core :as p] [logseq.common.path :as path])) -(defn- get-css-var-value - [var-name] - (.getPropertyValue (js/getComputedStyle (.-documentElement js/document)) var-name)) - ;; sidebars (def *right-sidebar-resized-at (atom (js/Date.now))) -(defn- get-right-sidebar-width - [] - (or (.. (js/document.getElementById "right-sidebar") -style -width) - (get-css-var-value "--right-sidebar-width"))) - (defn persist-right-sidebar-width! - [] - (storage/set "ls-right-sidebar-width" (get-right-sidebar-width))) + [width] + (state/set-state! :ui/sidebar-width width) + (storage/set "ls-right-sidebar-width" width)) (defn restore-right-sidebar-width! [] (when-let [width (storage/get "ls-right-sidebar-width")] - (.setProperty (.-style (js/document.getElementById "right-sidebar")) "width" width))) + (state/set-state! :ui/sidebar-width width))) (defn close-left-sidebar! [] diff --git a/src/main/frontend/handler/user.cljs b/src/main/frontend/handler/user.cljs index 19f6b73c114..6686a4e0d96 100644 --- a/src/main/frontend/handler/user.cljs +++ b/src/main/frontend/handler/user.cljs @@ -199,6 +199,16 @@ (state/clear-user-info!) (state/pub-event! [:user/logout])) +(defn upgrade [] + (let [base-upgrade-url "https://logseqdemo.lemonsqueezy.com/checkout/buy/13e194b5-c927-41a8-af58-ed1a36d6000d" + user-uuid (user-uuid) + url (cond-> base-upgrade-url + user-uuid (str "?checkout[custom][user_uuid]=" (name user-uuid)))] + (println " ~~~ LEMON: " url " ~~~ ") + (js/window.open url))) + ; (js/window.open + ; "https://logseqdemo.lemonsqueezy.com/checkout/buy/13e194b5-c927-41a8-af58-ed1a36d6000d")) + (defn logseq-portal-shape [block-id point] @@ -328,7 +329,7 @@ :assets assets :bindings bindings}))))) (defn should-populate-onboarding-whiteboard? - "When there is not whiteboard, or there is only whiteboard that is the given page name, we should populate the onboarding whiteboard" + "When there is no whiteboard, or there is only one whiteboard that has the given page name, we should populate the onboarding shapes" [page-name] (let [whiteboards (model/get-all-whiteboards (state/get-current-repo))] (and (or (empty? whiteboards) diff --git a/src/main/frontend/mixins.cljs b/src/main/frontend/mixins.cljs index 40fdc76bec8..a17b25c9cfb 100644 --- a/src/main/frontend/mixins.cljs +++ b/src/main/frontend/mixins.cljs @@ -99,10 +99,10 @@ :did-mount (fn [state] (attach-listeners state) state) - :did-remount (fn [old-state new-state] - (detach old-state) - (attach-listeners new-state) - new-state)}))) + :will-remount (fn [old-state new-state] + (detach old-state) + (attach-listeners new-state) + new-state)}))) (defn modal [k] diff --git a/src/main/frontend/mobile/intent.cljs b/src/main/frontend/mobile/intent.cljs index d44da915b56..74c3366ce4c 100644 --- a/src/main/frontend/mobile/intent.cljs +++ b/src/main/frontend/mobile/intent.cljs @@ -65,6 +65,7 @@ (p/let [basename (node-path/basename url) label (-> basename util/node-path.name) time (date/get-current-time) + date-ref-name (date/today) path (editor-handler/get-asset-path basename) _file (p/catch (.copy Filesystem (clj->js {:from url :to path})) @@ -75,21 +76,25 @@ template (get-in (state/get-config) [:quick-capture-templates :media] "**{time}** [[quick capture]]: {url}")] - (-> (string/replace template "{time}" time) + (-> template + (string/replace "{time}" time) + (string/replace "{date}" date-ref-name) + (string/replace "{text}" "") (string/replace "{url}" (or url ""))))) (defn- embed-text-file "Store external content with url into Logseq repo" [url title] (p/let [time (date/get-current-time) + date-ref-name (date/today) title (some-> (or title (node-path/basename url)) gp-util/safe-decode-uri-component util/node-path.name ;; make the title more user friendly gp-util/page-name-sanity) path (node-path/join (config/get-repo-dir (state/get-current-repo)) - (config/get-pages-directory) - (str (js/encodeURI (fs-util/file-name-sanity title)) (node-path/extname url))) + (config/get-pages-directory) + (str (js/encodeURI (fs-util/file-name-sanity title)) (node-path/extname url))) _ (p/catch (.copy Filesystem (clj->js {:from url :to path})) (fn [error] @@ -98,7 +103,10 @@ template (get-in (state/get-config) [:quick-capture-templates :text] "**{time}** [[quick capture]]: {url}")] - (-> (string/replace template "{time}" time) + (-> template + (string/replace "{time}" time) + (string/replace "{date}" date-ref-name) + (string/replace "{text}" "") (string/replace "{url}" (or url ""))))) (defn- handle-received-media [result] diff --git a/src/main/frontend/modules/file/core.cljs b/src/main/frontend/modules/file/core.cljs index d042b7ceda1..b9df1271142 100644 --- a/src/main/frontend/modules/file/core.cljs +++ b/src/main/frontend/modules/file/core.cljs @@ -157,7 +157,7 @@ (if (and (string/blank? new-content) (not blocks-just-deleted?)) (state/pub-event! [:capture-error {:error (js/Error. "Empty content") - :payload {:file-path file-path}}]) + :payload {}}]) (let [files [[file-path new-content]] repo (state/get-current-repo)] (file-handler/alter-files-handler! repo files {} {})))) diff --git a/src/main/frontend/modules/outliner/core.cljs b/src/main/frontend/modules/outliner/core.cljs index 50385c431e9..8e29b9026f7 100644 --- a/src/main/frontend/modules/outliner/core.cljs +++ b/src/main/frontend/modules/outliner/core.cljs @@ -564,8 +564,6 @@ (do (state/pub-event! [:capture-error {:error "Outliner invalid structure" :payload {:type :outliner/invalid-structure - :blocks blocks - :target-block target-block' :opt opts :data (mapv #(dissoc % :block/content) tx)}}]) (throw (ex-info "Invalid outliner data" diff --git a/src/main/frontend/modules/outliner/tree.cljs b/src/main/frontend/modules/outliner/tree.cljs index 39069a317e7..9471b424abf 100644 --- a/src/main/frontend/modules/outliner/tree.cljs +++ b/src/main/frontend/modules/outliner/tree.cljs @@ -87,14 +87,16 @@ (defn block-entity->map [e] - {:db/id (:db/id e) - :block/uuid (:block/uuid e) - :block/parent {:db/id (:db/id (:block/parent e))} - :block/left {:db/id (:db/id (:block/left e))} - :block/page (:block/page e) - :block/refs (:block/refs e) - :block/children (:block/children e) - :block/content (:block/content e)}) + (cond-> {:db/id (:db/id e) + :block/uuid (:block/uuid e) + :block/parent {:db/id (:db/id (:block/parent e))} + :block/page (:block/page e)} + (:db/id (:block/left e)) + (assoc :block/left {:db/id (:db/id (:block/left e))}) + (:block/refs e) + (assoc :block/refs (:block/refs e)) + (:block/children e) + (assoc :block/children (:block/children e)))) (defn filter-top-level-blocks [blocks] diff --git a/src/main/frontend/modules/shortcut/config.cljs b/src/main/frontend/modules/shortcut/config.cljs index b94820d23d8..55ac3ea9207 100644 --- a/src/main/frontend/modules/shortcut/config.cljs +++ b/src/main/frontend/modules/shortcut/config.cljs @@ -113,19 +113,19 @@ :whiteboard/zoom-out {:binding "shift+dash" :fn #(.zoomOut (.-api ^js (state/active-tldraw-app)) false)} - :whiteboard/zoom-in {:binding "shift+=" + :whiteboard/zoom-in {:binding "shift+equals" :fn #(.zoomIn (.-api ^js (state/active-tldraw-app)) false)} - :whiteboard/send-backward {:binding "[" + :whiteboard/send-backward {:binding "open-square-bracket" :fn #(.sendBackward ^js (state/active-tldraw-app))} - :whiteboard/send-to-back {:binding "shift+[" + :whiteboard/send-to-back {:binding "shift+open-square-bracket" :fn #(.sendToBack ^js (state/active-tldraw-app))} - :whiteboard/bring-forward {:binding "]" + :whiteboard/bring-forward {:binding "close-square-bracket" :fn #(.bringForward ^js (state/active-tldraw-app))} - :whiteboard/bring-to-front {:binding "shift+]" + :whiteboard/bring-to-front {:binding "shift+close-square-bracket" :fn #(.bringToFront ^js (state/active-tldraw-app))} :whiteboard/lock {:binding "mod+l" @@ -439,7 +439,7 @@ :fn route-handler/redirect-to-whiteboard-dashboard!} :go/keyboard-shortcuts {:binding "g s" - :fn #(route-handler/redirect! {:to :shortcut-setting})} + :fn #(state/pub-event! [:modal/keymap-manager])} :go/tomorrow {:binding "g t" :fn journal-handler/go-to-tomorrow!} @@ -927,7 +927,10 @@ :dev/show-block-ast :dev/show-page-data :dev/show-page-ast - :ui/clear-all-notifications]}) + :ui/clear-all-notifications] + + :shortcut.category/plugins + []}) (let [category-maps {::category (set (keys category*)) ::dicts/category dicts/categories}] @@ -942,10 +945,14 @@ (fn [v] (vec (remove #(:inactive (get all-default-keyboard-shortcuts %)) v))))) +(def *shortcut-cmds (atom {})) + (defn add-shortcut! [handler-id id shortcut-map] - (swap! config assoc-in [handler-id id] shortcut-map)) + (swap! config assoc-in [handler-id id] shortcut-map) + (swap! *shortcut-cmds assoc id (:cmd shortcut-map))) (defn remove-shortcut! [handler-id id] - (swap! config medley/dissoc-in [handler-id id])) + (swap! config medley/dissoc-in [handler-id id]) + (swap! *shortcut-cmds dissoc id)) diff --git a/src/main/frontend/modules/shortcut/core.cljs b/src/main/frontend/modules/shortcut/core.cljs index d45f1fc2d24..640d38d6891 100644 --- a/src/main/frontend/modules/shortcut/core.cljs +++ b/src/main/frontend/modules/shortcut/core.cljs @@ -66,7 +66,7 @@ (doseq [k (dh/shortcut-binding id)] (try (log/debug :shortcut/register-shortcut {:id id :binding k}) - (.registerShortcut handler (util/keyname id) (dh/normalize-user-keyname k)) + (.registerShortcut handler (util/keyname id) (util/normalize-user-keyname k)) (catch :default e (log/error :shortcut/register-shortcut {:id id :binding k @@ -81,24 +81,24 @@ (when-let [handler (get-handler-by-id handler-id)] (when-let [ks (dh/shortcut-binding shortcut-id)] (doseq [k ks] - (.unregisterShortcut ^js handler (dh/normalize-user-keyname k)))) + (.unregisterShortcut ^js handler (util/normalize-user-keyname k)))) (shortcut-config/remove-shortcut! handler-id shortcut-id))) -(defn uninstall-shortcut! +(defn uninstall-shortcut-handler! [install-id] (when-let [handler (-> (get @*installed install-id) :handler)] (.dispose ^js handler) (swap! *installed dissoc install-id))) -(defn install-shortcut! +(defn install-shortcut-handler! [handler-id {:keys [set-global-keys? prevent-default? state] :or {set-global-keys? true prevent-default? false}}] (when-let [install-id (get-handler-by-id handler-id)] - (uninstall-shortcut! install-id)) + (uninstall-shortcut-handler! install-id)) (let [shortcut-map (dh/shortcut-map handler-id state) handler (new KeyboardShortcutHandler js/window)] @@ -136,23 +136,23 @@ :shortcut.handler/editor-global :shortcut.handler/global-non-editing-only :shortcut.handler/global-prevent-default] - (map #(install-shortcut! % {})) + (map #(install-shortcut-handler! % {})) doall)) (defn mixin [handler-id] {:did-mount (fn [state] - (let [install-id (install-shortcut! handler-id {:state state})] + (let [install-id (install-shortcut-handler! handler-id {:state state})] (assoc state ::install-id install-id))) - :did-remount (fn [old-state new-state] - (uninstall-shortcut! (::install-id old-state)) - (when-let [install-id (install-shortcut! handler-id {:state new-state})] + :will-remount (fn [old-state new-state] + (uninstall-shortcut-handler! (::install-id old-state)) + (when-let [install-id (install-shortcut-handler! handler-id {:state new-state})] (assoc new-state ::install-id install-id))) :will-unmount (fn [state] (when-let [install-id (::install-id state)] - (uninstall-shortcut! install-id)) + (uninstall-shortcut-handler! install-id)) state)}) (defn unlisten-all [] @@ -183,7 +183,7 @@ (state/set-state! :ui/shortcut-handler-refreshing? true) (doseq [id (keys @*installed)] - (uninstall-shortcut! id)) + (uninstall-shortcut-handler! id)) (install-shortcuts!) (state/pub-event! [:shortcut-handler-refreshed]) (state/set-state! :ui/shortcut-handler-refreshing? false))) @@ -216,7 +216,7 @@ keystroke (:rum/local state)] (doseq [id (keys @*installed)] - (uninstall-shortcut! id)) + (uninstall-shortcut-handler! id)) (events/listen handler "key" (fn [e] @@ -226,13 +226,16 @@ (assoc state ::key-record-handler handler))) :will-unmount - (fn [{:rum/keys [args local] :as state}] + (fn [{:rum/keys [args local action] :as state}] (let [k (first args) keystroke (str/trim @local)] - (when-not (empty? keystroke) - (config-handler/set-config! :shortcuts (merge - (:shortcuts (state/get-config)) - {k keystroke})))) + (when (and (= @action :save) + (seq keystroke)) + (config-handler/set-config! + :shortcuts + (merge + (:shortcuts (state/get-config)) + {k keystroke})))) (when-let [^js handler (::key-record-handler state)] (.dispose handler)) diff --git a/src/main/frontend/modules/shortcut/data_helper.cljs b/src/main/frontend/modules/shortcut/data_helper.cljs index 3be8271e30c..8acff61041e 100644 --- a/src/main/frontend/modules/shortcut/data_helper.cljs +++ b/src/main/frontend/modules/shortcut/data_helper.cljs @@ -52,27 +52,21 @@ shortcut) (mapv mod-key))))) -(defn normalize-user-keyname - [k] - (let [keynames {";" "semicolon" - "=" "equals" - "-" "dash" - "[" "open-square-bracket" - "]" "close-square-bracket" - "'" "single-quote"}] - (some-> k - (util/safe-lower-case) - (str/replace #"[;=-\[\]']" (fn [s] - (get keynames s)))))) +(defn shortcut-cmd + [id] + (get @shortcut-config/*shortcut-cmds id)) ;; returns a vector to preserve order (defn binding-by-category [name] - (let [dict (->> (vals @shortcut-config/config) - (apply merge) - (map (fn [[k _]] - {k {:binding (shortcut-binding k)}})) - (into {}))] - (->> (shortcut-config/category name) + (let [dict (->> (vals @shortcut-config/config) + (apply merge) + (map (fn [[k _]] + {k {:binding (shortcut-binding k)}})) + (into {})) + plugin? (= name :shortcut.category/plugins)] + (->> (if plugin? + (->> (keys dict) (filter #(str/starts-with? (str %) ":plugin."))) + (shortcut-config/category name)) (mapv (fn [k] [k (k dict)]))))) (defn shortcut-map @@ -148,13 +142,14 @@ (defn remove-shortcut [k] (let [repo (state/get-current-repo) path (config/get-repo-config-path)] - (when-let [content (db/get-file path)] - (let [result (config-handler/parse-repo-config content) - new-result (rewrite/update - result - :shortcuts - #(dissoc (rewrite/sexpr %) k)) - new-content (str new-result)] + (when-let [result (some-> (db/get-file path) + (config-handler/parse-repo-config))] + (when-let [new-content (and (:shortcuts result) + (-> (rewrite/update + result + :shortcuts + #(dissoc (rewrite/sexpr %) k)) + (str)))] (repo-config-handler/set-repo-config-state! repo new-content) (file/set-file-content! repo path new-content))))) diff --git a/src/main/frontend/page.cljs b/src/main/frontend/page.cljs index 967b485c318..a44bbf7b4b1 100644 --- a/src/main/frontend/page.cljs +++ b/src/main/frontend/page.cljs @@ -88,6 +88,7 @@ {:did-mount (fn [state] (state/set-root-component! (:rum/react-component state)) (state/setup-electron-updater!) + (state/load-app-user-cfgs) (ui/inject-document-devices-envs!) (ui/inject-dynamic-style-node!) (quick-tour/init) diff --git a/src/main/frontend/quick_capture.cljs b/src/main/frontend/quick_capture.cljs index b7fb01151ff..72af9aa6a0b 100644 --- a/src/main/frontend/quick_capture.cljs +++ b/src/main/frontend/quick_capture.cljs @@ -18,6 +18,8 @@ (defn quick-capture [args] (let [{:keys [url title content page append]} (bean/->clj args) + title (or title "") + url (or url "") insert-today? (get-in (state/get-config) [:quick-capture-options :insert-today?] false) diff --git a/src/main/frontend/routes.cljs b/src/main/frontend/routes.cljs index 58c5752d125..58b62cce0f8 100644 --- a/src/main/frontend/routes.cljs +++ b/src/main/frontend/routes.cljs @@ -71,7 +71,7 @@ ["/settings/shortcut" {:name :shortcut-setting - :view shortcut/shortcut}] + :view shortcut/shortcut-page}] ["/settings/zotero" {:name :zotero-setting diff --git a/src/main/frontend/search.cljs b/src/main/frontend/search.cljs index 4f0eaf9735d..f8bfc993a44 100644 --- a/src/main/frontend/search.cljs +++ b/src/main/frontend/search.cljs @@ -228,7 +228,8 @@ (remove string/blank?) (map search-db/original-page-name->index)) pages-to-remove-set (->> (remove :added pages) - (map :v)) + (map :v) + set) pages-to-remove-id-set (->> (remove :added pages) (map :e) set)] @@ -263,12 +264,15 @@ (let [data (:tx-data tx-report) datoms (filter (fn [datom] - (contains? #{:block/name :block/content} (:a datom))) + ;; Capture any direct change on page display title, page ref or block content + (contains? #{:block/name :block/original-name :block/content} (:a datom))) data)] (when (seq datoms) (let [datoms (group-by :a datoms) blocks (:block/content datoms) - pages (:block/name datoms)] + pages (concat ;; Duplicated eids are handled in `get-pages-from-datoms-impl` + (:block/name datoms) + (:block/original-name datoms))] (merge (get-blocks-from-datoms-impl blocks) (get-pages-from-datoms-impl pages)))))) diff --git a/src/main/frontend/state.cljs b/src/main/frontend/state.cljs index c4ab9f1f241..cc000801c60 100644 --- a/src/main/frontend/state.cljs +++ b/src/main/frontend/state.cljs @@ -75,9 +75,9 @@ :ui/navigation-item-collapsed? {} ;; right sidebar - :ui/fullscreen? false :ui/settings-open? false :ui/sidebar-open? false + :ui/sidebar-width "40%" :ui/left-sidebar-open? (boolean (storage/get "ls-left-sidebar-open?")) :ui/theme (or (storage/get :ui/theme) "light") :ui/system-theme? ((fnil identity (or util/mac? util/win32? false)) (storage/get :ui/system-theme?)) @@ -166,6 +166,8 @@ :electron/updater {} :electron/user-cfgs nil :electron/server nil + :electron/window-maximized? false + :electron/window-fullscreen? false ;; assets :assets/alias-enabled? (or (storage/get :assets/alias-enabled?) false) @@ -426,15 +428,6 @@ should be done through this fn in order to get global config and config defaults (get-in @state [:me :preferred_format] "markdown"))))) -;; TODO: consider adding a pane in Settings to set this through the GUI (rather -;; than having to go through the config.edn file) -(defn get-editor-command-trigger - ([] (get-editor-command-trigger (get-current-repo))) - ([repo-url] - (or - (:editor/command-trigger (get-config repo-url)) ;; Get from user config - "/"))) ;; Set the default - (defn markdown? [] (= (keyword (get-preferred-format)) @@ -818,6 +811,18 @@ Similar to re-frame subscriptions" (when-let [graphs (seq (get-in @state [:file-sync/remote-graphs :graphs]))] (some #(when (= (:GraphUUID %) (str uuid)) %) graphs))) +(defn get-remote-graph-usage + [] + (when-let [graphs (seq (get-in @state [:file-sync/remote-graphs :graphs]))] + (->> graphs + (map #(hash-map :uuid (:GraphUUID %) + :name (:GraphName %) + :used-gbs (/ (:GraphStorageUsage %) 1024 1024 1024) + :limit-gbs (/ (:GraphStorageLimit %) 1024 1024 1024) + :used-percent (/ (:GraphStorageUsage %) (:GraphStorageLimit %) 0.01))) + (map #(assoc % :free-gbs (- (:limit-gbs %) (:used-gbs %)))) + (vec)))) + (defn delete-remote-graph! [repo] (swap! state update-in [:file-sync/remote-graphs :graphs] @@ -1762,8 +1767,10 @@ Similar to re-frame subscriptions" (defn pub-event! {:malli/schema [:=> [:cat vector?] :any]} [payload] - (let [chan (get-events-chan)] - (async/put! chan payload))) + (let [d (p/deferred) + chan (get-events-chan)] + (async/put! chan [payload d]) + d)) (defn get-export-block-text-indent-style [] (:copy/export-block-text-indent-style @state)) @@ -2067,9 +2074,10 @@ Similar to re-frame subscriptions" (fn [old-value] (merge old-value m))))) (defn http-proxy-enabled-or-val? [] - (when-let [agent-opts (sub [:electron/user-cfgs :settings/agent])] - (when (every? not-empty (vals agent-opts)) - (str (:protocol agent-opts) "://" (:host agent-opts) ":" (:port agent-opts))))) + (when-let [{:keys [type protocol host port] :as agent-opts} (sub [:electron/user-cfgs :settings/agent])] + (when (and (not (contains? #{"system"} type)) + (every? not-empty (vals agent-opts))) + (str protocol "://" host ":" port)))) (defn set-mobile-app-state-change [is-active?] @@ -2152,6 +2160,9 @@ Similar to re-frame subscriptions" (when (seq groups) (storage/set :user-groups groups))))) +(defn get-user-info [] + (sub :user/info)) + (defn clear-user-info! [] (storage/remove :user-groups)) diff --git a/src/main/frontend/ui.cljs b/src/main/frontend/ui.cljs index a2f9ef1829c..e9f2abf1b31 100644 --- a/src/main/frontend/ui.cljs +++ b/src/main/frontend/ui.cljs @@ -55,7 +55,7 @@ (defonce icon-size (if (mobile-util/native-platform?) 26 20)) -(def block-background-colors +(def built-in-colors ["yellow" "red" "pink" @@ -64,11 +64,15 @@ "purple" "gray"]) +(defn built-in-color? + [color] + (some #{color} built-in-colors)) + (rum/defc menu-background-color [add-bgcolor-fn rm-bgcolor-fn] [:div.flex.flex-row.justify-between.py-1.px-2.items-center [:div.flex.flex-row.justify-between.flex-1.mx-2.mt-2 - (for [color block-background-colors] + (for [color built-in-colors] [:a {:title (t (keyword "color" color)) :on-click #(add-bgcolor-fn color)} @@ -171,12 +175,18 @@ sequence)])) (rum/defc menu-link - [options child shortcut] - (if (:only-child? options) + [{:keys [only-child? no-padding? class] :as options} child shortcut] + (if only-child? [:div.menu-link (dissoc options :only-child?) child] [:a.flex.justify-between.px-4.py-2.text-sm.transition.ease-in-out.duration-150.cursor.menu-link - options + (cond-> options + (true? no-padding?) + (assoc :class (str class " no-padding")) + + true + (dissoc :no-padding?)) + [:span.flex-1 child] (when shortcut [:span.ml-1 (render-keyboard-shortcut shortcut)])])) @@ -210,7 +220,7 @@ [:div.title-wrap {:style {:margin-right "8px" :margin-left "4px"}} title]]))] (if hr - [:hr.menu-separator {:key "dropdown-hr"}] + [:hr.menu-separator {:key (or key "dropdown-hr")}] (rum/with-key (menu-link new-options child nil) title))))) @@ -367,11 +377,15 @@ (doseq [[event function] [["persist-zoom-level" #(storage/set :zoom-level %)] ["restore-zoom-level" #(when-let [zoom-level (storage/get :zoom-level)] (js/window.apis.setZoomLevel zoom-level))] - ["full-screen" #(js-invoke cl (if (= % "enter") "add" "remove") "is-fullscreen")]]] + ["full-screen" #(do (js-invoke cl (if (= % "enter") "add" "remove") "is-fullscreen") + (state/set-state! :electron/window-fullscreen? (= % "enter")))] + ["maximize" #(state/set-state! :electron/window-maximized? %)]]] (.on js/window.apis event function)) - (p/then (ipc/ipc :getAppBaseInfo) #(let [{:keys [isFullScreen]} (js->clj % :keywordize-keys true)] - (and isFullScreen (.add cl "is-fullscreen"))))))) + (p/then (ipc/ipc :getAppBaseInfo) #(let [{:keys [isFullScreen isMaximized]} (js->clj % :keywordize-keys true)] + (when isFullScreen ((.add cl "is-fullscreen") + (state/set-state! :electron/window-fullscreen? true))) + (when isMaximized (state/set-state! :electron/window-maximized? true))))))) (defn inject-dynamic-style-node! [] @@ -712,6 +726,7 @@ (modal-panel show? modal-panel-content state close-fn false close-btn?)))])))) (defn loading + ([] (loading (t :loading))) ([content] (loading content nil)) ([content opts] [:div.flex.flex-row.items-center.inline @@ -719,6 +734,18 @@ (when-not (string/blank? content) [:span.text.pl-2 content])]])) +(defn notify-graph-persist! + [] + (notification/show! + (loading (t :graph/persist)) + :warning)) + +(defn notify-graph-persist-error! + [] + (notification/show! + (t :graph/persist-error) + :error)) + (rum/defc rotating-arrow [collapsed?] [:span diff --git a/src/main/frontend/ui.css b/src/main/frontend/ui.css index 0fe11001f49..25dca8d4c12 100644 --- a/src/main/frontend/ui.css +++ b/src/main/frontend/ui.css @@ -41,6 +41,12 @@ } } +.menu-link { + &.no-padding { + padding: 0 !important; + } +} + .ui__ac-group-name { @apply p-2 text-xs; color: var(--ls-block-ref-link-text-color); @@ -100,11 +106,12 @@ } &-overlay div { - background: var(--ls-tertiary-background-color); + background-image: linear-gradient(to bottom, var(--ls-primary-background-color), var(--ls-quaternary-background-color)); } &-panel { - @apply relative rounded-md shadow-xl; + @apply relative rounded-md shadow-xl border; + border-color: var(--ls-border-color); overflow: hidden; background: var(--ls-secondary-background-color); @@ -150,7 +157,7 @@ hover:opacity-100; &-wrap { - @apply absolute top-0 right-0 pt-2 pr-2; + @apply z-10 absolute top-0 right-0 pt-2 pr-2; } } diff --git a/src/main/frontend/util.cljc b/src/main/frontend/util.cljc index fae61d01c12..4d9954ca1ac 100644 --- a/src/main/frontend/util.cljc +++ b/src/main/frontend/util.cljc @@ -67,6 +67,18 @@ [parts] (string/join "/" parts)) +(defn normalize-user-keyname + [k] + (let [keynames {";" "semicolon" + "=" "equals" + "-" "dash" + "[" "open-square-bracket" + "]" "close-square-bracket" + "'" "single-quote"}] + (some-> (str k) + (string/lower-case) + (string/replace #"[;=-\[\]']" (fn [s] + (get keynames s)))))) #?(:cljs (defn safe-re-find @@ -778,9 +790,13 @@ (rec-get-blocks-content-section (gobj/get node "parentNode")))))) #?(:cljs - (defn get-blocks-noncollapse [] - (->> (d/sel "div:not(.reveal) .ls-block") - (filter (fn [b] (some? (gobj/get b "offsetParent"))))))) + (defn get-blocks-noncollapse + ([] + (->> (d/sel "div:not(.reveal) .ls-block") + (filter (fn [b] (some? (gobj/get b "offsetParent")))))) + ([blocks-container] + (->> (d/sel blocks-container "div:not(.reveal) .ls-block") + (filter (fn [b] (some? (gobj/get b "offsetParent")))))))) #?(:cljs (defn remove-embedded-blocks [blocks] @@ -848,14 +864,19 @@ #?(:cljs (defn get-prev-block-non-collapsed - [block] - (when-let [blocks (get-blocks-noncollapse)] - (let [block-id (.-id block) - block-ids (mapv #(.-id %) blocks)] - (when-let [index (.indexOf block-ids block-id)] - (let [idx (dec index)] - (when (>= idx 0) - (nth-safe blocks idx)))))))) + "Gets previous non-collapsed block. If given a container + looks up blocks in that container e.g. for embed" + ([block] (get-prev-block-non-collapsed block {})) + ([block {:keys [container]}] + (when-let [blocks (if container + (get-blocks-noncollapse container) + (get-blocks-noncollapse))] + (let [block-id (.-id block) + block-ids (mapv #(.-id %) blocks)] + (when-let [index (.indexOf block-ids block-id)] + (let [idx (dec index)] + (when (>= idx 0) + (nth-safe blocks idx))))))))) #?(:cljs (defn get-prev-block-non-collapsed-non-embed diff --git a/src/main/frontend/util/property.cljs b/src/main/frontend/util/property.cljs index 4180d578d99..3418746a7b6 100644 --- a/src/main/frontend/util/property.cljs +++ b/src/main/frontend/util/property.cljs @@ -10,6 +10,8 @@ [logseq.graph-parser.util.page-ref :as page-ref] [frontend.format.mldoc :as mldoc] [logseq.graph-parser.text :as text] + [frontend.db :as db] + [frontend.state :as state] [frontend.util.cursor :as cursor])) (defn hidden-properties @@ -414,3 +416,50 @@ (util/format (config/properties-wrapper-pattern page-format) (string/join "\n" lines)))) + +(def hidden-editable-page-properties + "Properties that are hidden in the pre-block (page property)" + #{:title :filters :icon}) + +(assert (set/subset? hidden-editable-page-properties (gp-property/editable-built-in-properties)) + "Hidden editable page properties must be valid editable properties") + +(def hidden-editable-block-properties + "Properties that are hidden in a block (block property)" + (into #{:logseq.query/nlp-date} + gp-property/editable-view-and-table-properties)) + +(assert (set/subset? hidden-editable-block-properties (gp-property/editable-built-in-properties)) + "Hidden editable page properties must be valid editable properties") + +(defn- add-aliases-to-properties + "Adds aliases to a page when a page has aliases and is also an alias of other pages" + [properties page-id] + (let [repo (state/get-current-repo) + aliases (db/get-page-alias-names repo + (:block/name (db/pull page-id)))] + (if (seq aliases) + (if (:alias properties) + (update properties :alias (fn [c] + (util/distinct-by string/lower-case (concat c aliases)))) + (assoc properties :alias aliases)) + properties))) + +(defn get-visible-ordered-properties + "Given a block's properties, order of properties and any display context, + returns a tuple of property pairs that are visible when not being edited" + [properties* properties-order {:keys [pre-block? page-id]}] + (let [dissoc-keys (fn [m keys] (apply dissoc m keys)) + properties (cond-> (update-keys properties* keyword) + true + (dissoc-keys (hidden-properties)) + pre-block? + (dissoc-keys hidden-editable-page-properties) + (not pre-block?) + (dissoc-keys hidden-editable-block-properties) + pre-block? + (add-aliases-to-properties page-id))] + (if (seq properties-order) + (keep (fn [k] (when (contains? properties k) [k (get properties k)])) + (distinct properties-order)) + properties*))) \ No newline at end of file diff --git a/src/main/frontend/version.cljs b/src/main/frontend/version.cljs index c7942737be2..0729ca7cc4d 100644 --- a/src/main/frontend/version.cljs +++ b/src/main/frontend/version.cljs @@ -1,3 +1,3 @@ (ns ^:no-doc frontend.version) -(defonce version "0.9.8") +(defonce version "0.9.9") diff --git a/src/main/logseq/api.cljs b/src/main/logseq/api.cljs index 65b6c9d3289..a4648d617cc 100644 --- a/src/main/logseq/api.cljs +++ b/src/main/logseq/api.cljs @@ -367,8 +367,8 @@ (if palette? (palette-handler/invoke-command palette-cmd) (action'))) - [handler-id id shortcut-map] (update shortcut-args 2 assoc :fn dispatch-cmd)] - (js/console.debug :shortcut/register-shortcut [handler-id id shortcut-map]) + [handler-id id shortcut-map] (update shortcut-args 2 assoc :fn dispatch-cmd :cmd palette-cmd)] + (println :shortcut/register-shortcut [handler-id id shortcut-map]) (st/register-shortcut! handler-id id shortcut-map))))))) (defn ^:export unregister_plugin_simple_command @@ -384,7 +384,7 @@ (palette-handler/unregister (:id cmd)) ;; remove keybinding commands (when (seq (:shortcut cmd)) - (js/console.debug :shortcut/unregister-shortcut cmd) + (println :shortcut/unregister-shortcut cmd) (st/unregister-shortcut! (:handler-id cmd) (:id cmd))))))) (defn ^:export register_search_service @@ -700,7 +700,7 @@ (fn [block-uuid] (when-let [block (db-model/query-block-by-uuid (sdk-utils/uuid-or-throw-error block-uuid))] (when-let [right-sibling (outliner/get-right-sibling (:db/id block))] - (let [block (db/pull (:id right-sibling))] + (let [block (db/pull (:db/id right-sibling))] (bean/->js (sdk-utils/normalize-keyword-for-json block))))))) (def ^:export set_block_collapsed diff --git a/src/resources/dicts/af.edn b/src/resources/dicts/af.edn index e96f6ffd99e..4d84c8fcbe2 100644 --- a/src/resources/dicts/af.edn +++ b/src/resources/dicts/af.edn @@ -1,16 +1,7 @@ -{:on-boarding/demo-graph "This is a demo graph, changes will not be saved until you open a local folder." - :on-boarding/add-graph "Add a graph" - :on-boarding/open-local-dir "Open a local directory" - :on-boarding/new-graph-desc-1 "Logseq supports both Markdown and Org-mode. You can open an existing directory or create a new one on your device, a directory is also known simply as a folder. Your data will be stored only on this device." - :on-boarding/new-graph-desc-2 "After you have opened your directory, it will create three folders in that directory:" - :on-boarding/new-graph-desc-3 "/journals - store your journal pages" - :on-boarding/new-graph-desc-4 "/pages - store the other pages" - :on-boarding/new-graph-desc-5 "/logseq - store configuration, custom.css, and some metadata." - :help/about "Oor Logseq" +{:help/about "Oor Logseq" :help/bug "Fout verslag" :help/feature "Funksie versoek" :help/changelog "Verandering-dagboek" - :help/blog "Logseq blog" :help/privacy "Privaatheidsbeleid" :help/terms "Terme" :help/shortcuts "Sleutelbord kortpaaie" @@ -32,16 +23,9 @@ :right-side-bar/switch-theme "Skakel oor na die {1} tema" :right-side-bar/contents "Inhoud" :right-side-bar/block-ref "Blok verwysing" - :right-side-bar/graph-view "Graph view" - :right-side-bar/all-pages "All pages" - :right-side-bar/flashcards "Flashcards" - :right-side-bar/new-page "New page" - :left-side-bar/journals "Journals" :page/presentation-mode "Aanbiedings modus" :page/delete-confirmation "Is jy seker jy wil die bladsy uitvee?" - :page/delete "Delete page (will delete the file too)" :page/show-journals "Wys joernale" - :block/name "Page name" :file/name "Lêer naam" :file/last-modified-at "Laas verander op" :file/no-data "Geen data" @@ -53,9 +37,6 @@ :content/open-in-sidebar "Maak in kantlys oop" :content/click-to-edit "Kliek om te wysig" :settings-page/edit-config-edn "Wysig config.edn (vir huidige stoor)" - :settings-page/git-confirm "You need to restart the app after updating the Git settings." - :settings-page/git-switcher-label "Enable Git auto commit" - :settings-page/git-commit-delay "Git auto commit seconds" :settings-page/preferred-file-format "Voorkeur lêer formaat" :settings-page/preferred-workflow "Voorkeur werkstroom" :settings-page/developer-mode "Ontwikkelaar modus" @@ -66,7 +47,6 @@ :re-index "Herindekseer" :export-json "Uitvoer as JSON" :search "Soek" - :new-page "Nuwe bladsy" :graph "Grafiek" :all-pages "Alle blaaie" :all-files "Alle lêers" @@ -74,7 +54,6 @@ :import "Invoer" :join-community "Sluit by die gemeenskap aan" :help-shortcut-title "Kliek op die kortpad en ander wenke" - :loading "Laai tans" :parsing-files "Lêer ontleding" :loading-files "Laai lêers" :download "Laai af" diff --git a/src/resources/dicts/de.edn b/src/resources/dicts/de.edn index 95ca11cacdd..5cd90a0a9b9 100644 --- a/src/resources/dicts/de.edn +++ b/src/resources/dicts/de.edn @@ -30,14 +30,11 @@ :italics "Kursiv" :join-community "Treten Sie der Community bei" :language "Sprache" - :loading "Laden" :loading-files "Dateien laden" :login "Einloggen" :logout "Ausloggen" :more "Mehr" :new-graph "Neuen Graphen hinzufügen" - :new-page "Neue Seite" - :new-whiteboard "Neues Whiteboard" :open-a-directory "Öffne ein lokales Verzeichnis" :open-new-window "Neues Fenster" :page-search "In der aktuellen Seite suchen" @@ -51,7 +48,6 @@ :relaunch-confirm-to-work "Sie sollten die App neu starten, damit sie funktioniert. Möchten Sie sie jetzt neu starten?" :remove-background "Hintergrund entfernen" :remove-heading "Überschrift entfernen" - :remove-orphaned-pages "Verweiste Seiten entfernen" :save "Speichern" :search "Suchen oder Seite erstellen" :settings "Einstellungen" @@ -106,7 +102,6 @@ :file/no-data "Keine Daten" :file/validate-existing-file-error "Seite existiert bereits mit einer anderen Datei: {1}, aktuelle Datei: {2}. Bitte behalten Sie nur eine davon und indizieren Sie Ihren Graphen neu." - :file-rn/all-action "Alle Aktionen anwenden!" :file-rn/apply-rename "Anwenden des Vorgangs zur Datei-Umbenennung" :file-rn/close-panel "Das Panel schließen" :file-rn/confirm-proceed "Format aktualisieren!" @@ -133,31 +128,23 @@ :file-rn/unreachable-title "Warnung! Der Seitenname wird unter dem aktuellen Dateinamenformat zu {1}, es sei denn, die Eigenschaft `title::` wird manuell gesetzt" :graph/all-graphs "Alle Graphen" - :graph/local-graphs "Lokale Graphen" :graph/persist "Logseq synchronisiert gerade den internen Status, bitte warten Sie einige Sekunden." :graph/persist-error "Synchronisation des internen Status fehlgeschlagen." - :graph/remote-graphs "Remote Graphen" :graph/save "Speichern..." :graph/save-error "Speichern fehlgeschlagen" :graph/save-success "Erfolgreich gespeichert" :help-shortcut-title "Hier klicken, um Tastenkombinationen und weitere Tipps zu sehen" :help/about "Über Logseq" - :help/awesome-logseq "Awesome Logseq" :help/block-content-autocomplete "Blockinhalt (Quelltext, Zitate, Abfragen, etc.) Autovervollständigung" :help/block-reference "Blockverweis" - :help/blog "Logseq Blog" :help/bug "Fehlerbericht" :help/changelog "Änderungsprotokoll" :help/context-menu "Kontextmenü" :help/docs "Dokumentation" :help/feature "Feature-Anfrage" - :help/forum-community "Forum-Community" - :help/markdown-syntax "Markdown-Syntax" - :help/org-mode-syntax "Org-Mode-Syntax" :help/privacy "Datenschutzrichtlinie" :help/reference-autocomplete "Seitenverweis Autovervollständigung" - :help/roadmap "Roadmap" :help/shortcut "Tastaturkürzel" :help/shortcut-page-title "Tastaturbefehl" :help/shortcuts "Tastaturkürzel" @@ -196,7 +183,6 @@ :on-boarding/welcome-whiteboard-modal-start "Whiteboarding beginnen" :page/add-to-favorites "Zu Favoriten hinzufügen" - :page/backlinks "Backlinks" :page/copy-page-url "Seiten-URL kopieren" :page/created-at "Erstellt am" :page/delete "Seite löschen" @@ -232,7 +218,6 @@ :plugin/custom-js-alert "Datei custom.js gefunden. Darf sie ausgeführt werden? (Wenn Sie den Inhalt dieser Datei nicht verstehen, wird empfohlen, die Ausführung nicht zuzulassen, da dies gewisse Sicherheitsrisiken birgt)." :plugin/delete-alert "Wollen Sie wirklich das Plugin [{1}] deinstallieren?" :plugin/disabled "Deaktiviert" - :plugin/downloads "Downloads" :plugin/enabled "Aktiviert" :plugin/install "Installieren" :plugin/installed "Installiert" @@ -246,14 +231,12 @@ :plugin/reload "Neu laden" :plugin/restart "App neu starten" :plugin/stars "Sterne" - :plugin/title "Titel" :plugin/uninstall "Deinstallieren" :plugin/unpacked "Entpackt" :plugin/unpacked-tips "Plugin-Verzeichnis auswählen" :plugin/update "Aktualisierung" :plugin/update-available "Aktualisierung verfügbar" :plugin/updating "Aktualisiere" - :plugin/up-to-date "Es ist auf dem neuesten Stand" :plugin.install-from-file/menu-title "Aus plugins.edn installieren" :plugin.install-from-file/title "Plugins aus plugins.edn installieren" @@ -340,14 +323,11 @@ :settings-page/tab-advanced "Erweitert" :settings-page/tab-assets "Anlagen" :settings-page/tab-features "Funktionen" - :settings-page/tab-editor "Editor" :settings-page/tab-general "Allgemein" :settings-page/tab-version-control "Versionskontrolle" :text/image "Bild" - :tips/all-done "Alles erledigt" - :updater/new-version-install "Eine neue Version wurde heruntergeladen." :updater/quit-and-install "Neu starten, um zu installieren" @@ -432,7 +412,6 @@ :command.editor/forward-word "Cursor ein Wort vorwärts bewegen" :command.editor/highlight "Hervorheben" :command.editor/indent "Block einrücken" - :command.editor/insert-link "HTML Link" :command.editor/insert-youtube-timestamp "YouTube-Zeitstempel einfügen" :command.editor/italics "Kursiv" :command.editor/kill-line-after "Zeile nach der Cursorposition löschen" @@ -490,7 +469,6 @@ :command.graph/re-index "Aktuellen Graph neu indizieren" :command.graph/remove "Einen Graph entfernen" :command.graph/save "Aktuellen Graph auf Festplatte speichern" - :command.misc/copy "mod+c" :command.pdf/close "PDF: Aktuelles PDF-Dokument schließen" :command.pdf/find "PDF: Text des aktuellen PDF-Dokuments durchsuchen" :command.pdf/next-page "PDF: Nächste Seite des aktuellen PDF-Dokuments" diff --git a/src/resources/dicts/en.edn b/src/resources/dicts/en.edn index 38a1a11b77e..fefdc15cc10 100644 --- a/src/resources/dicts/en.edn +++ b/src/resources/dicts/en.edn @@ -17,6 +17,72 @@ :on-boarding/tour-whiteboard-home-description "Whiteboards have their own section in the app where you can see them at a glance, create new ones or delete them easily." :on-boarding/tour-whiteboard-new "{1} Create new whiteboard" :on-boarding/tour-whiteboard-new-description "There are multiple ways of creating a new whiteboard. One of them is always right here in the dashboard." + :on-boarding/tour-whiteboard-btn-next "Next" + :on-boarding/tour-whiteboard-btn-back "Back" + :on-boarding/tour-whiteboard-btn-finish "Finish" + :on-boarding/quick-tour-btn-next "Next" + :on-boarding/quick-tour-btn-back "Back" + :on-boarding/quick-tour-btn-finish "Finish" + :on-boarding/quick-tour-btn-skip "Skip Quick Tour" + :on-boarding/quick-tour-steps "STEP " + :on-boarding/quick-tour-help-title "❓ Help" + :on-boarding/quick-tour-help-desc "You can always click here for help and other information about Logseq." + :on-boarding/quick-tour-journal-page-title "📆 Daily Journal Page" + :on-boarding/quick-tour-journal-page-desc-1 "This is today’s daily journal page. Here you can dump your thoughts, learnings and ideas. Don’t worry about organizing. Just write and" + :on-boarding/quick-tour-journal-page-desc-2 "[[link]]" + :on-boarding/quick-tour-journal-page-desc-3 "your thoughts." + :on-boarding/quick-tour-left-sidebar-title "👀 Left Sidebar" + :on-boarding/quick-tour-left-sidebar-desc "Open the left sidebar to explore important menu items in Logseq." + :on-boarding/quick-tour-favorites-title "⭐️ Favorites" + :on-boarding/quick-tour-favorites-desc-1 "Pin your favorite pages via the `... `menu on any page." + :on-boarding/quick-tour-favorites-desc-2 "We’ve also added some template pages here to help you get started. You can remove these once you start writing your own notes." + :on-boarding/command-palette-quick-tour "Quick tour for onboarding" + :on-boarding/importing-main-title "Import existing notes" + :on-boarding/importing-main-desc "You can also do this later in the app." + :on-boarding/importing-title "Do you already have notes that you want to import?" + :on-boarding/importing-desc "If they are in a JSON, EDN or Markdown format Logseq can work with them." + :on-boarding/importing-roam-desc "Import a JSON Export of your Roam graph" + :on-boarding/importing-lsq-desc "Import an EDN or a JSON Export of your Logseq graph" + :on-boarding/importing-opml-desc " Import OPML files" + :on-boarding/main-title "Welcome to " + :on-boarding/main-desc "First you need to choose a folder where Logseq will store your thoughts, ideas, notes." + :on-boarding/section-btn-title "Choose a folder" + :on-boarding/section-btn-desc "Open existing directory or Create a new one" + :on-boarding/section-title "How Logseq saves your work" + :on-boarding/section-desc "Inside the directory you choose, Logseq will create 4 folders." + :on-boarding/section-tip-1 "Each page is a file stored only on your " + :on-boarding/section-tip-2 "You may choose to sync it later." + :on-boarding/section-assets "Graphics & Documents" + :on-boarding/section-journals "Daily notes" + :on-boarding/section-pages "PAGES" + :on-boarding/section-app "APP Internal" + :on-boarding/section-config "Config File" + :bug-report/main-title "Bug report" + :bug-report/main-desc "Can you help us out by submitting a bug report? We'll get it sorted out as soon as we can." + :bug-report/section-clipboard-title "Is the bug you encountered related to these features?" + :bug-report/section-clipboard-desc "You can use these handy tools to give us additional information." + :bug-report/section-clipboard-btn-title "Clipboard helper" + :bug-report/section-clipboard-btn-desc "Inspect and collect clipboard data" + :bug-report/section-issues-title "Or..." + :bug-report/section-issues-desc "If there are no tools available for you to gather additional information, please report the bug directly." + :bug-report/section-issues-btn-title "Submit a bug report" + :bug-report/section-issues-btn-desc "Help Make Logseq Better!" + :bug-report/inspector-page-desc-1 "Press Ctrl+V / ⌘+V to inspect your clipboard data" + :bug-report/inspector-page-desc-2 "or click here to paste if you are using the mobile version" + :bug-report/inspector-page-placeholder "Long press here to paste if you are on mobile" + :bug-report/inspector-page-tip "Something wrong? No problem, click to go back to the previous step." + :bug-report/inspector-page-btn-back "Go back" + :bug-report/inspector-page-btn-copy "Copy the result" + :bug-report/inspector-page-copy-notif "Copied to clipboard!" + :bug-report/inspector-page-btn-create-issue "Create an issue" + :bug-report/inspector-page-desc-clipboard "Here is the data read from clipboard." + :bug-report/inspector-page-desc-copy "If this is okay to share, click the copy button." + :bug-report/inspector-page-desc-create-issue "Now you can report the result pasted to your clipboard. Please paste the result in the 'Additional Context' section and state where you copied the original content from. Thanks!" + :help/title-usage "Usage" + :help/title-community "Community" + :help/title-development "Development" + :help/title-about "About" + :help/title-terms "Terms" :help/start "Getting started" :help/about "About Logseq" :help/roadmap "Roadmap" @@ -41,6 +107,11 @@ :search/result-for "Search result for " :search/items "items" :search/page-names "Search page names" + :search/recent "Recent search:" + :search/blocks-in-page "Search blocks in page:" + :search/command-palette-tip-1 "Tip: " + :search/command-palette-tip-2 " to open the commands palette" + :search/cache-outdated "Cache is outdated. Please click the 'Re-index' button in the graph's dropdown menu." :search-item/whiteboard "Whiteboard" :search-item/page "Page" :search-item/file "File" @@ -67,6 +138,7 @@ :right-side-bar/new-page "New page" :right-side-bar/show-journals "Show Journals" :right-side-bar/separator "Right sidebar resize handler" + :right-side-bar/toggle-right-sidebar "Toggle right sidebar" :left-side-bar/journals "Journals" :left-side-bar/create "Create" :left-side-bar/new-page "New page" @@ -93,6 +165,9 @@ :block/name "Page name" :page/earlier "Earlier" :page/copy-page-url "Copy page URL" + :page/illegal-page-name "Illegal page name!" + :page/page-already-exists "Page “{1}” already exists!" + :page/whiteboard-to-journal-error "Whiteboard pages cannot be renamed to journal titles!" :file/name "File name" :file/last-modified-at "Last modified at" :file/no-data "No data" @@ -104,7 +179,7 @@ :file-rn/or-select-actions-2 ". These actions are not available once you close this panel." :file-rn/legend "🟢 Optional rename actions; 🟡 Rename action required to avoid title change; 🔴 Breaking change." :file-rn/close-panel "Close the Panel" - :file-rn/all-action "Apply all Actions!" + :file-rn/all-action "Apply all Actions! ({1})" :file-rn/select-format "(Developer Mode Option, Dangerous!) Select filename format" :file-rn/rename "rename file \"{1}\" to \"{2}\"" :file-rn/apply-rename "Apply the file rename operation" @@ -125,7 +200,7 @@ :file-rn/instruct-3 "2. Follow the instructions below to rename the files to the new format:" :page/created-at "Created At" :page/updated-at "Updated At" - :page/backlinks "Back Links" + :page/backlinks "Backlinks" :linked-references/filter-search "Search in linked pages" :editor/block-search "Search for a block" :text/image "Image" @@ -170,9 +245,13 @@ :context-menu/input-template-name "What's the template's name?" :context-menu/template-include-parent-block "Including the parent block in the template?" :context-menu/template-exists-warning "Template already exists!" - :settings-page/git-confirm "You need to restart the app after updating the Git settings." + :settings-page/git-tip "If you have Logseq Sync enabled, you can view a page's edit history directly. This section is for tech-savvy only." + :settings-page/git-desc-1 "To view page's edit history, click the three horizontal dots in the top-right corner and select \"View page history\"." + :settings-page/git-desc-2 "For professional users, Logseq also supports using " + :settings-page/git-desc-3 " for version control. Use Git at your own risk as general Git issues are not supported by the Logseq team." :settings-page/git-switcher-label "Enable Git auto commit" :settings-page/git-commit-delay "Git auto commit seconds" + :settings-page/git-confirm "You need to restart the app after updating the Git settings." :settings-page/edit-config-edn "Edit config.edn" :settings-page/edit-global-config-edn "Edit global config.edn" :settings-page/edit-custom-css "Edit custom.css" @@ -180,6 +259,9 @@ :settings-page/edit-setting "Edit" :settings-page/custom-configuration "Custom configuration" :settings-page/custom-global-configuration "Custom global configuration" + :settings-page/theme-light "light" + :settings-page/theme-dark "dark" + :settings-page/theme-system "system" :settings-page/custom-theme "Custom theme" :settings-page/export-theme "Export theme" :settings-page/show-brackets "Show brackets" @@ -188,10 +270,15 @@ :settings-page/disable-sentry "Send usage data and diagnostics to Logseq" :settings-page/disable-sentry-desc "Logseq will never collect your local graph database or sell your data." :settings-page/preferred-outdenting "Logical outdenting" + :settings-page/preferred-outdenting-tip "The left side shows outdenting with the default setting, and the right shows outdenting with logical outdenting enabled " + :settings-page/preferred-outdenting-tip-more "→ Learn more" :settings-page/show-full-blocks "Show all lines of a block reference" :settings-page/auto-expand-block-refs "Expand block references automatically when zoom-in" + :settings-page/auto-expand-block-refs-tip "This option controls whether to expand the block references automatically when zoom-in." :settings-page/custom-date-format "Preferred date format" :settings-page/custom-date-format-warning "Re-index required! Existing journal references would be broken!" + :settings-page/custom-date-format-notification "You must re-index your graph for this change to take effect" + :settings-page/preferred-pasting-file-hint "When enabled, pasting an image from the internet will download and insert the image. When disabled, it will paste the link to the image." :settings-page/preferred-file-format "Preferred file format" :settings-page/preferred-workflow "Preferred workflow" :settings-page/preferred-pasting-file "Prefer pasting file" @@ -213,6 +300,7 @@ :settings-page/tab-general "General" :settings-page/tab-editor "Editor" :settings-page/tab-version-control "Version control" + :settings-page/tab-account "Account" :settings-page/tab-advanced "Advanced" :settings-page/tab-assets "Assets" :settings-page/tab-features "Features" @@ -224,7 +312,20 @@ :settings-page/beta-features "Beta features" :settings-page/login-prompt "To access new features before anyone else you must be an Open Collective Sponsor or Backer of Logseq and therefore log in first." :settings-page/sync "Sync" + :settings-page/sync-desc-1 "Click" + :settings-page/sync-desc-2 "here" + :settings-page/sync-desc-3 "for instructions on how to set up and use Sync." :settings-page/enable-whiteboards "Whiteboards" + :settings-page/native-titlebar "Native title bar" + :settings-page/native-titlebar-desc "Enables the native window title bar on Windows and Linux." + :settings-page/check-for-updates "Check for updates" + :settings-page/checking "Checking ..." + :settings-page/revision "Revision: " + :settings-page/changelog "What's new?" + :settings-page/app-updated "Your app is up-to-date 🎉" + :settings-page/update-available "Found new release " + :settings-page/update-error-1 "⚠️ Oops, Something Went Wrong!" + :settings-page/update-error-2 " Please check out the " :yes "Yes" :submit "Submit" @@ -247,10 +348,123 @@ :search/publishing "Search" :search "Search or create page" :whiteboard/link-whiteboard-or-block "Link whiteboard/page/block" + :whiteboard/align-left "Align left" + :whiteboard/align-center-horizontally "Align center horizontally" + :whiteboard/align-right "Align right" + :whiteboard/distribute-horizontally "Distribute horizontally" + :whiteboard/align-top "Align top" + :whiteboard/align-center-vertically "Align center vertically" + :whiteboard/align-bottom "Align bottom" + :whiteboard/distribute-vertically "Distribute vertically" + :whiteboard/pack-into-rectangle "Pack into rectangle" + :whiteboard/zoom-to-fit "Zoom to fit" + :whiteboard/ungroup "Ungroup" + :whiteboard/group "Group" + :whiteboard/cut "Cut" + :whiteboard/copy "Copy" + :whiteboard/paste "Paste" + :whiteboard/paste-as-link "Paste as link" + :whiteboard/export "Export" + :whiteboard/select-all "Select all" + :whiteboard/deselect-all "Deselect all" + :whiteboard/lock "Lock" + :whiteboard/unlock "Unlock" + :whiteboard/delete "Delete" + :whiteboard/flip-horizontally "Flip horizontally" + :whiteboard/flip-vertically "Flip vertically" + :whiteboard/move-to-front "Move to front" + :whiteboard/move-to-back "Move to back" + :whiteboard/dev-print-shape-props "(Dev) Print shape props" + :whiteboard/auto-resize "Auto resize" + :whiteboard/expand "Expand" + :whiteboard/collapse "Collapse" + :whiteboard/website-url "Website url" + :whiteboard/reload "Reload" + :whiteboard/open-website-url "Open website url" + :whiteboard/youtube-url "YouTube url" + :whiteboard/open-youtube-url "Open YouTube url" + :whiteboard/twitter-url "Twitter url" + :whiteboard/open-twitter-url "Open Twitter url" + :whiteboard/fill "Fill" + :whiteboard/stroke-type "Stroke type" + :whiteboard/arrow-head "Arrow head" + :whiteboard/bold "Bold" + :whiteboard/italic "Italic" + :whiteboard/undo "Undo" + :whiteboard/redo "Redo" + :whiteboard/zoom-in "Zoom in" + :whiteboard/zoom-out "Zoom out" + :whiteboard/select "Select" + :whiteboard/pan "Pan" + :whiteboard/add-block-or-page "Add block or page" + :whiteboard/draw "Draw" + :whiteboard/highlight "Highlight" + :whiteboard/eraser "Eraser" + :whiteboard/connector "Connector" + :whiteboard/text "Text" + :whiteboard/color "Color" + :whiteboard/select-custom-color "Select custom color" + :whiteboard/opacity "Opacity" + :whiteboard/extra-small "Extra Small" + :whiteboard/small "Small" + :whiteboard/medium "Medium" + :whiteboard/large "Large" + :whiteboard/extra-large "Extra Large" + :whiteboard/huge "Huge" + :whiteboard/scale-level "Scale level" + :whiteboard/rectangle "Rectangle" + :whiteboard/circle "Circle" + :whiteboard/triangle "Triangle" + :whiteboard/shape "Shape" + :whiteboard/open-page "Open page" + :whiteboard/open-page-in-sidebar "Open page in sidebar" + :whiteboard/remove-link "Remove link" + :whiteboard/link "Link" + :whiteboard/references "References" + :whiteboard/link-to-any-page-or-block "Link to any page or block" + :whiteboard/start-typing-to-search "Start typing to search..." + :whiteboard/new-block-no-colon "New block" + :whiteboard/new-block "New block:" + :whiteboard/new-page "New page:" + :whiteboard/new-whiteboard "New whiteboard" + :whiteboard/search-only-blocks "Search only blocks" + :whiteboard/search-only-pages "Search only pages" + :whiteboard/cache-outdated "Cache is outdated. Please click the 'Re-index' button in the graph's dropdown menu." + :whiteboard/shape-quick-links "Shape Quick Links" + :whiteboard/dashboard-card-new-whiteboard "New whiteboard" + :whiteboard/dashboard-card-created "Created " + :whiteboard/dashboard-card-edited "Edited " + :whiteboard/toggle-grid "Toggle grid" + :whiteboard/snap-to-grid "Snap to grid" + :flashcards/modal-welcome-title "Time to create a card!" + :flashcards/modal-welcome-desc-1 "You can add \"#card\" to any block to turn it into a card or trigger \"/cloze\" to add some clozes." + :flashcards/modal-welcome-desc-2 "You can " + :flashcards/modal-welcome-desc-3 "click this link" + :flashcards/modal-welcome-desc-4 " to check the documentation." + :flashcards/modal-btn-show-answers "Show answers" + :flashcards/modal-btn-hide-answers "Hide answers" + :flashcards/modal-btn-show-clozes "Show clozes" + :flashcards/modal-btn-next-card "Next" + :flashcards/modal-btn-reset "Reset" + :flashcards/modal-btn-reset-tip "Reset this card so that you can review it immediately." + :flashcards/modal-btn-forgotten "Forgotten" + :flashcards/modal-btn-remembered "Remembered" + :flashcards/modal-btn-recall "Took a while to recall" + :flashcards/modal-finished "Congrats, you've reviewed all the cards for this query, see you next time! 💯" + :flashcards/modal-select-all "All" + :flashcards/modal-select-switch "Switch to" + :flashcards/modal-current-total "Current/Total" + :flashcards/modal-overdue-total "Overdue/Total" + :flashcards/modal-toggle-preview-mode "Toggle preview mode" + :flashcards/modal-toggle-random-mode "Toggle random mode" + :page-search "Search in the current page" :graph-search "Search graph" - :new-page "New page" - :new-whiteboard "New whiteboard" + :home "Home" + :new-page "New page:" + :whiteboard "Whiteboard" + :whiteboards "Whiteboards" + :new-whiteboard "New whiteboard:" :new-graph "Add new graph" :graph "Graph" :graph/persist "Logseq is syncing internal status, please wait for several seconds." @@ -259,8 +473,8 @@ :graph/save-success "Saved successfully" :graph/save-error "Save failed" :graph/all-graphs "All graphs" - :graph/local-graphs "Local graphs" - :graph/remote-graphs "Remote graphs" + :graph/local-graphs "Local graphs:" + :graph/remote-graphs "Remote graphs:" :export "Export" :export-graph "Export graph" :export-page "Export page" @@ -274,7 +488,7 @@ :all-pages "All pages" :all-whiteboards "All whiteboards" :all-files "All files" - :remove-orphaned-pages "Remove orphaned pages" + :remove-orphaned-pages "Remove orphaned pages?" :all-journals "All journals" :settings "Settings" :settings-of-plugins "Plugins" @@ -286,11 +500,12 @@ :join-community "Join the community" :discourse-title "Our forum!" :help-shortcut-title "Click to check shortcuts and other tips" - :loading "Loading" + :loading "Loading..." :parsing-files "Parsing files" :loading-files "Loading files" :login "Login" :logout "Logout" + :logout-user "Logout ({1})" :download "Download" :language "Language" :remove-background "Remove background" @@ -298,20 +513,24 @@ :heading "Heading {1}" :auto-heading "Auto heading" :open-a-directory "Open a local directory" + :toggle-theme "Toggle theme" :help/shortcut-page-title "Keyboard shortcuts" :plugin/installed "Installed" + :plugin/installed-plugin "Installed plugin: {1}" :plugin/not-installed "Not installed" :plugin/installing "Installing" :plugin/install "Install" :plugin/reload "Reload" :plugin/update "Update" + :plugin/update-plugin "Update plugin: {1} - {2}" :plugin/check-update "Check update" :plugin/check-all-updates "Check all updates" :plugin/found-updates "New updates" :plugin/found-n-updates "Found {1} updates" :plugin/update-all-selected "Update all of selected" + :plugin/all-updated "All updated!" :plugin/updates-downloading "Downloading updates" :plugin/refresh-lists "Refresh lists" :plugin/enabled "Enabled" @@ -322,7 +541,7 @@ :plugin/marketplace "Marketplace" :plugin/downloads "Downloads" :plugin/stars "Stars" - :plugin/title "Title" + :plugin/title "Title ({1})" :plugin/all "All" :plugin/unpacked "Unpacked" :plugin/delete-alert "Are you sure you want to uninstall the plugin [{1}]?" @@ -332,8 +551,19 @@ :plugin/restart "Restart App" :plugin/unpacked-tips "Select the plugin directory" :plugin/contribute "✨ Write and submit new plugin" - :plugin/up-to-date "It's up to date" + :plugin/up-to-date "It's up to date {1}" :plugin/custom-js-alert "Found the custom.js file, is it allowed to execute? (If you don't understand the content of this file, it is recommended not to allow execution, which has certain security risks.)" + :plugin/security-warning "Plugins can access your graph and your local files, issue network requests. + They can also cause data corruption or loss. We're working on proper access rules for your graphs. + Meanwhile, make sure you have regular backups of your graphs and only install the plugins when you can read and + understand the source code." + :plugin/search-plugin "Search plugins" + :plugin/open-preferences "Open Preferences" + :plugin/open-logseq-dir "Open" + :plugin/remote-error "Remote error: " + :plugin/checking-for-updates "Checking for plugin updates ..." + :plugin/list-of-updates "Plugin Updates: " + :plugin/auto-check-for-updates "Auto check for updates" :plugin.install-from-file/menu-title "Install from plugins.edn" :plugin.install-from-file/title "Install plugins from plugins.edn" :plugin.install-from-file/notice "The following plugins will replace your plugins:" @@ -353,7 +583,7 @@ :paginates/prev "Prev" :paginates/next "Next" - :tips/all-done "All Done" + :tips/all-done "All Done!" :command-palette/prompt "Type a command" :select/default-prompt "Select one" @@ -377,9 +607,21 @@ :shortcut.category/toggle "Toggle" :shortcut.category/whiteboard "Whiteboard" :shortcut.category/others "Others" + :shortcut.category/plugins "Plugins" + :window/minimize "Minimize" + :window/maximize "Maximize" + :window/restore "Restore" + :window/close "Close" + :window/exit-fullscreen "Exit full screen" + + :header/toggle-left-sidebar "Toggle left sidebar" + :header/search "Search" + :header/more "More" + :header/go-back "Go back" + :header/go-forward "Go forward" - ;; Commands are nested for now to stay in sync with the shortcuts system. - ;; Other languages should not nest keys under :commands + ;; Commands are nested for now to stay in sync with the shortcuts system. + ;; Other languages should not nest keys under :commands :commands {:date-picker/complete "Date picker: Choose selected day" :date-picker/prev-day "Date picker: Select previous day" @@ -491,7 +733,7 @@ :sidebar/open-today-page "Open today's page in the right sidebar" :sidebar/close-top "Closes the top item in the right sidebar" :sidebar/clear "Clear all in the right sidebar" - :misc/copy "mod+c" + :misc/copy "Copy" :command-palette/toggle "Toggle command palette" :graph/export-as-html "Export public graph pages as html" :graph/open "Select graph to open" @@ -517,7 +759,6 @@ :ui/toggle-help "Toggle help" :ui/toggle-theme "Toggle between dark/light theme" :ui/toggle-contents "Toggle Contents in sidebar" - ;; :ui/open-new-window "Open another window" :command/toggle-favorite "Add to/remove from favorites" :editor/open-file-in-default-app "Open file in default app" :editor/open-file-in-directory "Open file in parent directory" @@ -534,4 +775,4 @@ :dev/show-block-data "(Dev) Show block data" :dev/show-block-ast "(Dev) Show block AST" :dev/show-page-data "(Dev) Show page data" - :dev/show-page-ast "(Dev) Show page AST"}} \ No newline at end of file + :dev/show-page-ast "(Dev) Show page AST"}} diff --git a/src/resources/dicts/es.edn b/src/resources/dicts/es.edn index cd47ec63229..c841ebf1379 100644 --- a/src/resources/dicts/es.edn +++ b/src/resources/dicts/es.edn @@ -19,11 +19,10 @@ :help/privacy "Política de privacidad" :help/terms "Términos" :help/forum-community "Foro de la comunidad" - :help/awesome-logseq "Awesome Logseq" :help/shortcuts "Atajos de teclado" :help/shortcuts-triggers "Iniciadores" :help/shortcut "Atajo" - :help/slash-autocomplete "Autocompletado Slash" + :help/slash-autocomplete "Autocompletado de barra '/'" :help/block-content-autocomplete "Autocompletado bloque de contenido (Src, Quote, Query, etc)" :help/reference-autocomplete "Referencia de página" :help/block-reference "Referencia de bloque" @@ -78,7 +77,6 @@ :file-rn/or-select-actions-2 ". Estas acciones no estarán disponibles una vez cierres este panel." :file-rn/legend "🟢 Acciones de cambio de nombre opcionales; 🟡 Cambio de nombre obligatorio para evitar el cambio de título; 🔴 Cambio destructor." :file-rn/close-panel "Cerrar el panel" - :file-rn/all-action "¡Aplicar todas las acciones!" :file-rn/select-format "(Opción modo desarrollador, ¡peligroso!) Seccione el formato de nombre de archivo" :file-rn/rename "Renombrar \"{1}\" a \"{2}\"" :file-rn/apply-rename "Aplicar la operación de cambio de nombre de archivo" @@ -171,7 +169,9 @@ :search "Buscar o Crear Página" :page-search "Buscar en la página actual" :graph-search "Buscar grafo" - :new-page "Nueva página" + :home "Inicio" + :whiteboard "Pizarra" + :whiteboards "Pizarras" :new-graph "Añadir nuevo grafo" :graph "Grafo" :graph/persist "Logseq está sincronizando su estado interno, por favor espere unos segundos." @@ -191,7 +191,6 @@ :all-graphs "Lista de grafos" :all-pages "Lista de páginas" :all-files "Lista de archivos" - :remove-orphaned-pages "Eliminar páginas huérfanas" :all-journals "Lista de diarios" :settings "Opciones" :settings-of-plugins "Opciones de Extensiones" @@ -200,16 +199,15 @@ :relaunch-confirm-to-work "Debe relanzar la aplicación para hacer que funcione. ¿Desea reiniciarla ahora?" :import "Importar" :join-community "Unirse a la comunidad" - :discourse-title "Nuestro foro!" + :discourse-title "¡Nuestro foro!" :help-shortcut-title "Clic para ver atajos y otras sugerencias" - :loading "Cargando" :parsing-files "Analizando archivos" :loading-files "Cargando archivos" :login "Iniciar sesión" :logout "Cerrar sesión" :download "Descargar" :language "Idioma" - :remove-background "Remover el fondo" + :remove-background "Eliminar el fondo" :open-a-directory "Abrir un directorio local" :help/shortcut-page-title "Atajos de teclado" :plugin/installed "Instalado" @@ -229,7 +227,6 @@ :plugin/marketplace "Tienda" :plugin/downloads "Descargas" :plugin/stars "Estrellas" - :plugin/title "Título" :plugin/all "Todo" :plugin/unpacked "Desempaquetado" :plugin/delete-alert "¿Está seguro de desinstalar la extensión [{1}]?" @@ -239,7 +236,6 @@ :plugin/restart "Reiniciar la aplicación" :plugin/unpacked-tips "Seleccionar el directorio de la extensión" :plugin/contribute "✨ Escribir y publicar nueva extensión" - :plugin/up-to-date "Está actualizada" :plugin/custom-js-alert "Se encontró el archivo custom.js, desea permitir que se ejecute? (Si no comprende el contenido de este archivo se recomienda no permitir su ejecución dado que representa ciertos riesgos de seguridad)." :pdf/copy-ref "Copiar referencia" :pdf/copy-text "Copiar texto" @@ -250,7 +246,6 @@ :paginates/pages "Total {1} páginas" :paginates/prev "Anterior" :paginates/next "Siguiente" - :tips/all-done "Todo Hecho" :command-palette/prompt "Escriba un comando" :select/default-prompt "Seleccione uno" :select.graph/prompt "Seleccione un grafo" @@ -262,7 +257,6 @@ :auto-heading "Encabezados automáticos" :heading "Encabezado {1}" :importing "Importando" - :new-whiteboard "Nueva pizarra" :remove-heading "Eliminar encabezado" :accessibility/skip-to-main-content "Saltar a contenido principal" :asset/copy "Copiar imagen" @@ -299,8 +293,6 @@ :editor/expand-block-children "Expandir todo" :file/validate-existing-file-error "La página existe en otro archivo: {1}, actual... " :graph/all-graphs "Todos los grafos" - :graph/local-graphs "Grafos locales" - :graph/remote-graphs "Grafos remotos" :left-side-bar/create "Crear" :left-side-bar/new-whiteboard "Nueva pizarra" :notification/clear-all "Limpiar todo" @@ -477,7 +469,6 @@ :command.graph/re-index "Reindexar grafo actual" :command.graph/remove "Eliminar un grafo" :command.graph/save "Guardar grafo actual al disco" - :command.misc/copy "mod + c" :command.pdf/close "Pdf: Cerrar documento pdf actual" :command.pdf/find "Pdf: Buscar texto del documento pdf actual" :command.pdf/next-page "Pdf: Página siguiente del documento pdf actual" @@ -518,4 +509,138 @@ :command.whiteboard/zoom-to-selection "Zoom para ajustar a la selección" :shortcut.category/whiteboard "Pizarra" :context-menu/toggle-number-list "Alternar lista de números" - :file-sync/rsapi-cannot-upload-err "Incapaz de comenzar la sincronización, favor de checar si..."} \ No newline at end of file + :file-sync/rsapi-cannot-upload-err "Incapaz de comenzar la sincronización, favor de checar si..." + :toggle-theme "Alternar tema" + :settings-page/native-titlebar "Barra de título nativa" + :settings-page/native-titlebar-desc "Habilta la barra de título nativa de la ventana en Windows y ..." + :window/close "Cerrar" + :window/exit-fullscreen "Salir de pantalla completa" + :window/maximize "Maximizar" + :window/minimize "Minimizar" + :window/restore "Restaurar" + :loading "Cargando..." + :logout-user "Cerrar sesión ({1})" + :new-page "Nueva página:" + :new-whiteboard "Nueva pizarra:" + :remove-orphaned-pages "¿Eliminar páginas huérfanas?" + :command.misc/copy "Copiar" + :file-rn/all-action "¡Aplicar todas las acciones! ({1})" + :graph/local-graphs "Grafos locales:" + :graph/remote-graphs "Grafos remotos:" + :header/go-back "Ir hacia atrás" + :header/go-forward "Ir haca adelante" + :header/more "Más" + :header/search "Buscar" + :header/toggle-left-sidebar "Alternar barra lateral izquierda" + :help/awesome-logseq "Increíble Logseq" + :help/title-about "Acerca de" + :help/title-community "Comunidad" + :help/title-development "Desarrollo" + :help/title-terms "Términos" + :help/title-usage "Uso" + :page/illegal-page-name "¡Nombre de página ilegal!" + :page/page-already-exists "¡La página “{1}” ya existe!" + :page/whiteboard-to-journal-error "Las páginas de pizarra no pueden ser renombradas con título de diario..." + :plugin/all-updated "¡Todo está actualizado!" + :plugin/checking-for-updates "Comprobando por actualizaciones de extensiones ..." + :plugin/installed-plugin "Extensión instalada: {1}" + :plugin/list-of-updates "Actualizaciones de extensiones: " + :plugin/open-logseq-dir "Abrir" + :plugin/open-preferences "Abrir preferencias" + :plugin/remote-error "Error remoto: " + :plugin/search-plugin "Buscar extensiones" + :plugin/security-warning "Las extensiones pueden acceder a tu grafo y tus archivos locales..." + :plugin/title "Título ({1})" + :plugin/up-to-date "Está actualizado {1}" + :plugin/update-plugin "Actualizar extensión: {1} - {2}" + :right-side-bar/toggle-right-sidebar "Alternar barra lateral derecha" + :search/blocks-in-page "Buscar bloques en página:" + :search/cache-outdated "La cache está desactualizada. Por favor dé clic en el botón 'Reindexar'..." + :search/recent "Búsqueda reciente:" + :settings-page/preferred-pasting-file-hint "Cuando está habilitado, al pegar una imagen del internet ..." + :settings-page/tab-account "Cuenta" + :shortcut.category/plugins "Extensiones" + :tips/all-done "¡Todo hecho!" + :whiteboard/add-block-or-page "Añadir bloque o página" + :whiteboard/align-bottom "Alinear abajo" + :whiteboard/align-center-horizontally "Alinear al centro horizontalmente" + :whiteboard/align-center-vertically "Alinear al centro verticalmente" + :whiteboard/align-left "Alinear a la izquierda" + :whiteboard/align-right "Alinear a la derecha" + :whiteboard/align-top "Alinear arriba" + :whiteboard/arrow-head "Cabeza de flecha" + :whiteboard/auto-resize "Cambiar tamaño automaticamente" + :whiteboard/bold "Negrita" + :whiteboard/cache-outdated "La cache está desactualizada. Por favor dé clic en el botón 'Reindexar'..." + :whiteboard/circle "Círculo" + :whiteboard/collapse "Colapsar" + :whiteboard/color "Color" + :whiteboard/connector "Conector" + :whiteboard/copy "Copiar" + :whiteboard/cut "Cortar" + :whiteboard/delete "Eliminar" + :whiteboard/deselect-all "Deseleccionar todo" + :whiteboard/dev-print-shape-props "(Dev) Imprimir propiedades de figura" + :whiteboard/distribute-horizontally "Distribuir horizontalmente" + :whiteboard/distribute-vertically "Distribuir verticalmente" + :whiteboard/draw "Dibujar" + :whiteboard/eraser "Borrar" + :whiteboard/expand "Expandir" + :whiteboard/export "Exportar" + :whiteboard/extra-large "Extra grande" + :whiteboard/extra-small "Extra pequeño" + :whiteboard/fill "Rellenar" + :whiteboard/flip-horizontally "Voltear horizontalmente" + :whiteboard/flip-vertically "Voltear verticalmente" + :whiteboard/group "Agrupar" + :whiteboard/highlight "Resaltar" + :whiteboard/huge "Enorme" + :whiteboard/italic "Itálica" + :whiteboard/large "Grande" + :whiteboard/link "Enlace" + :whiteboard/link-to-any-page-or-block "Enlace a cualquier página o bloque" + :whiteboard/lock "Bloquear" + :whiteboard/medium "Medio" + :whiteboard/move-to-back "Mover al fondo" + :whiteboard/move-to-front "Mover al frente" + :whiteboard/new-block "Nuevo bloque:" + :whiteboard/new-block-no-colon "Nuevo bloque" + :whiteboard/new-page "Nueva página:" + :whiteboard/new-whiteboard "Nueva pizarra" + :whiteboard/opacity "Opacidad" + :whiteboard/open-page "Abrir página" + :whiteboard/open-page-in-sidebar "Abrir página en barra lateral" + :whiteboard/open-twitter-url "Abrir url de Twitter" + :whiteboard/open-website-url "Abrir url de sitio web" + :whiteboard/open-youtube-url "Abrir url de YouTube" + :whiteboard/pack-into-rectangle "Empacar en un rectángulo" + :whiteboard/pan "Mover" + :whiteboard/paste "Pegar" + :whiteboard/paste-as-link "Pegar como enlace" + :whiteboard/rectangle "Recargar" + :whiteboard/redo "Rehacer" + :whiteboard/references "Referencias" + :whiteboard/reload "Recargar" + :whiteboard/remove-link "Eliminar enlace" + :whiteboard/scale-level "Escalar nivel" + :whiteboard/search-only-blocks "Buscar solo bloques" + :whiteboard/search-only-pages "Buscar solo páginas" + :whiteboard/select "Seleccionar" + :whiteboard/select-all "Seleccionar todo" + :whiteboard/select-custom-color "Seleccionar color personalizado" + :whiteboard/shape "Figura" + :whiteboard/shape-quick-links "Enlaces rápidos de figura" + :whiteboard/small "Pequeño" + :whiteboard/start-typing-to-search "Comienza a escribir para buscar..." + :whiteboard/stroke-type "Tipo de línea" + :whiteboard/text "Texto" + :whiteboard/triangle "Triángulo" + :whiteboard/twitter-url "url de Twitter" + :whiteboard/undo "Deshacer" + :whiteboard/ungroup "Desagrupar" + :whiteboard/unlock "Desbloquear" + :whiteboard/website-url "url de sitio web" + :whiteboard/youtube-url "url de YouTube" + :whiteboard/zoom-in "Acercar" + :whiteboard/zoom-out "Alejar" + :whiteboard/zoom-to-fit "Zoom para ajustar"} diff --git a/src/resources/dicts/fr.edn b/src/resources/dicts/fr.edn index cbf57e01158..d353948838e 100644 --- a/src/resources/dicts/fr.edn +++ b/src/resources/dicts/fr.edn @@ -24,7 +24,6 @@ :italics "Italique" :highlight "Surligner" :strikethrough "Barré" - :code "Code" :right-side-bar/help "Aide" :right-side-bar/switch-theme "Basculer sur le thème {1}" :right-side-bar/contents "Contenus" @@ -66,7 +65,6 @@ :export-json "Exporter au format JSON" :search/publishing "Rechercher" :search "Rechercher ou Créer la Page" - :new-page "Nouvelle page" :graph "Graphe" :all-pages "Toutes les pages" :all-files "Tous les fichiers" @@ -74,7 +72,6 @@ :settings "Préférences" :import "Importer" :join-community "Rejoindre la communauté" - :loading "Chargement en cours" :parsing-files "Analyse des fichiers" :loading-files "Chargement des fichiers" :download "Télécharger" @@ -105,7 +102,6 @@ :logout "Déconnexion" :more "Plus" :new-graph "Ajouter un nouveau graphe" - :new-whiteboard "Nouveau tableau blanc" :open-a-directory "Ouvrir un dossier local" :open-new-window "Nouvelle fenêtre" :page-search "Chercher dans la page en cours" @@ -116,15 +112,14 @@ :re-index-multiple-windows-warning "Vous devez d'abord fermer les autres fenêtres avant de réindexer" :relaunch-confirm-to-work "Il est nécessaire de relancer l'application pour que ça fonctionne. Voulez-vous redémarrer ?" :remove-heading "Retirer les entêtes" - :remove-orphaned-pages "Supprimer les pages orphelines" :save "Sauver" :settings-of-plugins "Extensions" :sync-from-local-changes-detected "Le rafraîchissement va mettre à jour le contenu de Logseq en fonction des modifications réalisées sur les fichiers locaux. Voulez-vous continuer ?" :sync-from-local-files "Rafraîchir" :sync-from-local-files-detail "Importer les changements depuis les fichiers locaux" :themes "Thèmes" - :type "Type" :untitled "Sans titre" + :type "Type" :accessibility/skip-to-main-content "Aller au contenu principal" :asset/confirm-delete "Êtes-vous sûr de vouloir supprimer {1} ?" :asset/copy "Copier l'image" @@ -142,7 +137,6 @@ :color/yellow "Jaune" :command-palette/prompt "Tapez un commande" :content/copy-block-emebed "Copier l'intégration du bloc" - :file-rn/all-action "Appliquer toutes les actions !" :file-rn/apply-rename "Appliquer le renommage" :file-rn/close-panel "Fermer le panneau" :file-rn/confirm-proceed "Mettre à jour le format !" @@ -168,16 +162,12 @@ :file-rn/suggest-rename "Action requise : " :file-rn/unreachable-title "Attention ! la page deviendra {1} sous le format actuel, à moins que vous n'ayez modifié la propriété `title::`" :graph/all-graphs "Tous les graphes" - :graph/local-graphs "Locaux graphes" :graph/persist "Logseq synchronise son statut local, veuillez patienter quelques secondes." :graph/persist-error "La synchronisation interne a échoué." - :graph/remote-graphs "Graphes distants" :graph/save "Enregistrement ..." :graph/save-error "Enregistrement échoué" :graph/save-success "Enregistrement réussi" - :help/awesome-logseq "Awesome Logseq" :help/forum-community "Forum communautaire" - :help/roadmap "Roadmap" :help/shortcut-page-title "Raccourcis clavier" :help/start "Démarrage" :left-side-bar/create "Créer" @@ -207,7 +197,6 @@ :page/updated-at "Mis à jour le" :page/version-history "Consulter l'historique de la page" :paginates/next "Suiv." - :paginates/pages "Total {1} pages" :paginates/prev "Préc." :pdf/copy-ref "Copier la référence" :pdf/copy-text "Copier le texte" @@ -236,11 +225,9 @@ :plugin/reload "Recharger" :plugin/restart "Redémarrer l'application" :plugin/stars "Étoiles" - :plugin/title "Titre" :plugin/uninstall "Désinstaller" :plugin/unpacked "Décompressée" :plugin/unpacked-tips "Sélectionnez le dossier de l'extension" - :plugin/up-to-date "C'est à jour" :plugin/update "Mettre à jour" :plugin/update-available "Mise à jour disponible" :plugin/updating "Mise à jour en cours" @@ -282,7 +269,6 @@ :settings-page/enable-all-pages-public "Toutes les pages publiques lors de la publication" :settings-page/enable-block-time "Horodatage de bloc" :settings-page/enable-flashcards "Cartes-mémoire" - :settings-page/enable-journals "Journals" :settings-page/enable-shortcut-tooltip "Activer les astuces sur les raccourcis" :settings-page/enable-tooltip "Astuces" :settings-page/enable-whiteboards "Tableaux blancs" @@ -307,7 +293,6 @@ :settings-page/tab-general "Général" :settings-page/tab-version-control "Contrôle de version" :text/image "Image" - :tips/all-done "Tout terminé" :updater/new-version-install "Une nouvelle version a été téléchargée." :updater/quit-and-install "Relancez pour installer" :whiteboard/link-whiteboard-or-block "Lier un tablau blanc/page/bloc" @@ -325,7 +310,6 @@ :settings-page/clear-cache-warning "Vider le cache supprimera les graphiques ouverts. Vous perdrez les modifications non enregistrées." :settings-page/disable-sentry-desc "Logseq ne collectera jamais votre base de données de graphes locale ni ne vendra vos données." - :shortcut.category/formatting "Formats" :command.editor/indent "Indenter un Bloc vers la droite" :command.editor/outdent "Indenter un Bloc vers la gauche" :command.editor/move-block-up "Déplacer un bloc au dessus" @@ -428,7 +412,6 @@ :command.graph/re-index "Réindexer le graph actuel" :command.graph/remove "Retirer un graphe" :command.graph/save "Enregistrer le graphe sur le disque" - :command.misc/copy "mod+c" :command.pdf/close "PDF: Fermer le document PDF" :command.pdf/find "PDF: Rechercher du texte dans le document" :command.pdf/next-page "PDF: Page suivante du document en cours" @@ -449,6 +432,7 @@ :shortcut.category/block-command-editing "Édition de commande de bloc" :shortcut.category/block-editing "Édition de bloc en générale" :shortcut.category/block-selection "Sélection de bloc (appuyer sur Esc pour quitter la sélection)" + :shortcut.category/formatting "Formats" :shortcut.category/navigating "Navigation" :shortcut.category/others "Autres" :shortcut.category/toggle "Basculer" diff --git a/src/resources/dicts/it.edn b/src/resources/dicts/it.edn index 6e1a19093ae..e65ec6318b7 100644 --- a/src/resources/dicts/it.edn +++ b/src/resources/dicts/it.edn @@ -10,7 +10,6 @@ :on-boarding/new-graph-desc-5 "/logseq - contiene i dati di configurazione, custom.css, e alcuni metadati." :help/start "Per iniziare" :help/about "Informazioni su Logseq" - :help/roadmap "Roadmap" :help/bug "Segnala un problema" :help/feature "Richiedi una funzionalità" :help/changelog "Registro delle modifiche" @@ -18,7 +17,6 @@ :help/docs "Documentazione" :help/privacy "Politica sulla riservatezza" :help/terms "Termini di Servizio" - :help/awesome-logseq "Awesome Logseq" :help/shortcuts "Scorciatoie da tastiera" :help/shortcuts-triggers "Attivazione delle scorciatoie" :help/shortcut "Scorciatoia" @@ -47,7 +45,6 @@ :right-side-bar/block-ref "Riferimento di Blocco" :right-side-bar/graph-view "Vista del grafico" :right-side-bar/all-pages "Tutte le pagine" - :right-side-bar/flashcards "Flashcard" :right-side-bar/new-page "Nuova pagina" :right-side-bar/show-journals "Mostra diari" :left-side-bar/journals "Diario" @@ -116,7 +113,6 @@ :settings-page/developer-mode-desc "La modalità sviluppatore aiuta i contributori e gli sviluppatori di estensioni a testare le loro integrazioni con Logseq in modo più efficiente." :settings-page/current-version "Versione attuale" :settings-page/tab-general "Generale" - :settings-page/tab-editor "Editor" :settings-page/tab-version-control "Controllo di versione" :settings-page/tab-advanced "Avanzate" :settings-page/plugin-system "Sistema di plugin" @@ -128,7 +124,6 @@ :delete "Elimina" :save "Salva" :type "Tipo" - :host "Host" :port "Porta" :re-index "Re-indicizza" :re-index-detail "Ricostruisci il grafo" @@ -143,7 +138,6 @@ :search "Cerca o crea una pagina" :page-search "Cerca nella pagina corrente" :graph-search "Cerca nel grafo" - :new-page "Nuova pagina" :new-graph "Aggiungi nuovo grafo" :graph "Grafo" :graph/persist "Logseq sta sincronizzando lo stato interno, per favore attendi alcuni secondi." @@ -163,17 +157,15 @@ :all-graphs "Tutti i grafi" :all-pages "Tutte le pagine" :all-files "Tutti i file" - :remove-orphaned-pages "Rimuovi pagine orfane" :all-journals "Tutte le pagine di diario" :settings "Impostazioni" :settings-of-plugins "Impostazioni plugin" - :plugins "Plugin" + :plugins "Plugins" :themes "Temi" :relaunch-confirm-to-work "È necessario riavviare l'app per farla funzionare. Vuoi riavviarla ora?" :import "Importa" :join-community "Unisciti alla comunità" :help-shortcut-title "Clicca per conoscere le scorciatoie e altri suggerimenti" - :loading "Caricamento" :parsing-files "Analisi dei file" :loading-files "Caricamento dei file" :login "Accedi" @@ -202,7 +194,6 @@ :plugin/marketplace "Libreria" :plugin/downloads "Numero di scaricamenti" :plugin/stars "Stelle" - :plugin/title "Titolo" :plugin/all "Tutti" :plugin/unpacked "Non pacchettizzati" :plugin/delete-alert "Sei sicuro di voler disinstallare [{1}]?" @@ -212,7 +203,6 @@ :plugin/restart "Riavvia app" :plugin/unpacked-tips "Seleziona la cartella del plugin" :plugin/contribute "✨ Sviluppa e sottoponici un nuovo plugin" - :plugin/up-to-date "È aggiornato" :plugin/custom-js-alert "Trovato il file custom.js, è consentito eseguirlo? (Se non si comprende il contenuto di questo file, si consiglia di non consentire l'esecuzione, che presenta alcuni rischi per la sicurezza.)" :pdf/copy-ref "Copia riferimenti" @@ -227,8 +217,6 @@ :paginates/prev "Precedente" :paginates/next "Successivo" - :tips/all-done "Completato" - :command-palette/prompt "Digita un comando" :select/default-prompt "Selezionane uno" :select.graph/prompt "Seleziona un grafo" @@ -302,7 +290,6 @@ :command.editor/cut "Taglia" :command.editor/undo "Annulla" :command.editor/redo "Rifai" - :command.editor/insert-link "Link HTML" :command.editor/select-all-blocks "Seleziona tutti i blocchi" :command.editor/zoom-in "Ingrandisci blocco di modifica / Avanti altrimenti" :command.editor/zoom-out "Rimpicciolisci il blocco di modifica / Indietro altrimenti" @@ -315,7 +302,6 @@ :command.search/re-index "Ricostruisci indice di ricerca" :command.sidebar/open-today-page "Apri la pagina di oggi nella barra laterale destra" :command.sidebar/clear "Pulisci tutto nella barra laterale destra" - :command.misc/copy "mod+c" :command.command-palette/toggle "Attiva/disattiva tavolozza comandi" :command.graph/open "Seleziona il diagramma da aprire" :command.graph/remove "Rimuovi un diagramma" @@ -337,7 +323,6 @@ :command.ui/toggle-help "Attiva/disattiva aiuto" :command.ui/toggle-theme "Passa dal tema scuro a quello chiaro" :command.ui/toggle-contents "Attiva/disattiva i contenuti nella barra laterale" - ;; :command.ui/open-new-window "Apri un'altra finestra" :command.command/toggle-favorite "Aggiungi a/rimuovi dai preferiti" :command.editor/open-file-in-default-app "Apri file nell'app predefinita" :command.editor/open-file-in-directory "Apri file nella directory principale" diff --git a/src/resources/dicts/ja.edn b/src/resources/dicts/ja.edn index 58b7dafdba0..2309e2bc74f 100644 --- a/src/resources/dicts/ja.edn +++ b/src/resources/dicts/ja.edn @@ -18,7 +18,6 @@ :help/docs "ドキュメント" :help/privacy "プライバシーポリシー" :help/terms "利用規約" - :help/awesome-logseq "Awesome Logseq" :help/shortcuts "キーボードショートカット" :help/shortcuts-triggers "トリガー" :help/shortcut "ショートカット" @@ -28,8 +27,6 @@ :help/block-reference "ブロック参照" :help/open-link-in-sidebar "サイドバーでリンクを開く" :more "詳細" - :search/result-for "Search result for " - :search/items "items" :search/page-names "ページ名で検索" :help/context-menu "ブロックのコンテキストメニュー" :help/markdown-syntax "マークダウン文法" @@ -147,7 +144,6 @@ :search "検索/新規ページ名" :page-search "現在のページを検索" :graph-search "グラフを検索" - :new-page "新規ページ" :new-graph "新規グラフを追加" :graph "グラフ" :graph/persist "Logseq の内部状態を同期中です。少々お待ちください。" @@ -156,8 +152,6 @@ :graph/save-success "保存に成功しました" :graph/save-error "保存に失敗しました" :graph/all-graphs "全グラフ" - :graph/local-graphs "ローカルグラフ" - :graph/remote-graphs "リモートグラフ" :export "エクスポート" :export-graph "グラフをエクスポート" :export-page "ページをエクスポート" @@ -170,7 +164,6 @@ :all-graphs "全グラフ" :all-pages "全ページ" :all-files "全ファイル" - :remove-orphaned-pages "孤立ページを削除" :all-journals "全日誌" :settings "設定" :settings-of-plugins "プラグイン設定" @@ -180,7 +173,6 @@ :import "インポート" :join-community "コミュニティへ参加" :help-shortcut-title "クリックしてショートカットと他のTipsを確認" - :loading "ロード中" :parsing-files "ファイル解析中" :loading-files "ファイルロード中" :login "ログイン" @@ -212,7 +204,6 @@ :plugin/marketplace "マーケットプレース" :plugin/downloads "ダウンロード" :plugin/stars "スター" - :plugin/title "タイトル" :plugin/all "全て" :plugin/unpacked "展開済" :plugin/delete-alert "プラグイン [{1}] をアンインストールしてもよいですか?" @@ -222,7 +213,6 @@ :plugin/restart "アプリを再起動" :plugin/unpacked-tips "プラグインディレクトリを選択" :plugin/contribute "✨ 新規プラグインの作成とサブミット" - :plugin/up-to-date "最新の状態です" :plugin/custom-js-alert "custom.js ファイルを見つけました。実行を許可しますか? (もしあなたがこのファイルの内容を理解していない場合、セキュリティのリスクがあるため許可しないことをお勧めします。)" :pdf/copy-ref "参照をコピー" @@ -237,8 +227,6 @@ :paginates/prev "前" :paginates/next "次" - :tips/all-done "All Done" - :command-palette/prompt "コマンドを入力" :select/default-prompt "選択してください" :select.graph/prompt "グラフを選んでください" @@ -289,7 +277,6 @@ :command.go/next-journal "次の日誌へ移動" :command.go/prev-journal "前の日誌へ移動" :command.go/keyboard-shortcuts "キーボードショートカットへ移動" - ;; :command.ui/open-new-window "別のウィンドウを開く" :command.go/search-in-page "ページ内を検索" :command.go/electron-find-in-page "ページ内で文字列検索" :command.go/electron-jump-to-the-next "文字列検索で次を検索" diff --git a/src/resources/dicts/ko.edn b/src/resources/dicts/ko.edn index 9d975d07f5f..7815ab00b40 100644 --- a/src/resources/dicts/ko.edn +++ b/src/resources/dicts/ko.edn @@ -18,7 +18,6 @@ :help/docs "안내 문서" :help/privacy "개인정보 보호정책" :help/terms "약관" - :help/awesome-logseq "Awesome Logseq" :help/shortcuts "키보드 단축키" :help/shortcuts-triggers "트리거" :help/shortcut "단축키" @@ -143,7 +142,6 @@ :search "페이지를 검색하거나 생성" :page-search "현재 페이지에서 검색" :graph-search "그래프 검색" - :new-page "새 페이지" :new-graph "새 그래프" :graph "그래프" :graph/persist "Logseq가 내부 상태를 동기화 중입니다. 잠시만 기다려주십시오." @@ -163,7 +161,6 @@ :all-graphs "모든 그래프" :all-pages "모든 페이지" :all-files "모든 파일" - :remove-orphaned-pages "고립된 페이지 삭제" :all-journals "모든 일지" :settings "설정" :settings-of-plugins "플러그인 설정" @@ -173,7 +170,6 @@ :import "불러오기" :join-community "커뮤니티에 참여" :help-shortcut-title "다른 단축키와 도움말 확인하기" - :loading "로딩 중" :parsing-files "파일 파싱 중" :loading-files "파일 로딩 중" :login "로그인" @@ -202,7 +198,6 @@ :plugin/marketplace "마켓플레이스" :plugin/downloads "다운로드" :plugin/stars "스타" - :plugin/title "제목" :plugin/all "전체" :plugin/unpacked "압축 해제됨" :plugin/delete-alert "다음 [{1}] 플러그인을 삭제하시겠습니까?" @@ -212,7 +207,6 @@ :plugin/restart "앱 다시 시작" :plugin/unpacked-tips "플러그인 디렉토리 열기" :plugin/contribute "✨ 새 플러그인을 만들고 기여하기" - :plugin/up-to-date "최신 상태입니다." :plugin/custom-js-alert "custom.js 파일을 감지했습니다. 실행을 허용하겠습니까? (파일의 내용을 이해하지 못한다면 보안과 안전 상의 이유로 실행하지 않는 것이 권장됩니다." :pdf/copy-ref "레퍼런스 복사하기" @@ -227,8 +221,6 @@ :paginates/prev "이전" :paginates/next "다음" - :tips/all-done "모두 완료" - :command-palette/prompt "커맨드를 입력하십시오" :select/default-prompt "하나를 선택하십시오" :select.graph/prompt "그래프를 선택하십시오." @@ -243,7 +235,6 @@ :discourse-title "포럼!" :heading "헤딩 {1}" :importing "불러오는 중" - :new-whiteboard "새 화이트보드" :remove-heading "헤딩 제거" :untitled "제목 없음" :accessibility/skip-to-main-content "메인 컨텐츠로 건너뛰기" @@ -268,7 +259,6 @@ :on-boarding/welcome-whiteboard-modal-start "화이트보드 시작하기" :on-boarding/welcome-whiteboard-modal-title "새 캔버스" :file/validate-existing-file-error "페이지가 이미 존재합니다: {1}, 현재 파일: {2}. 하나만 남겨놓은 뒤 그래프의 인덱스를 재생성하십시오." - :file-rn/all-action "모든 작업 적용!" :file-rn/apply-rename "파일명 변경" :file-rn/close-panel "패널 닫기" :file-rn/confirm-proceed "포맷 업데이트!" @@ -292,8 +282,6 @@ :file-rn/suggest-rename "작업 필요: " :file-rn/unreachable-title "경고! 이 페이지는 `title::` 속성이 설정되어 있지 않는 한, 현재 파일명 포맷에 따라 {1}(으)로 변경될 것입니다." :graph/all-graphs "모든 그래프" - :graph/local-graphs "로컬 그래프" - :graph/remote-graphs "원격 그래프" :help/forum-community "포럼 커뮤니티" :left-side-bar/create "생성" :left-side-bar/new-whiteboard "새 화이트보드" @@ -372,7 +360,6 @@ :command.go/next-journal "다음 일지로 이동" :command.go/prev-journal "이전 일지로 이동" :command.go/keyboard-shortcuts "키보드 단축키로 이동" - ;; :command.ui/open-new-window "새 창 열기" :command.go/search-in-page "페이지 안에서 검색" :command.ui/toggle-document-mode "문서 모드 토글" :command.ui/toggle-contents "목차 토글" @@ -386,7 +373,7 @@ :command.editor/bold "볼드체" :command.editor/italics "이탤릭체" :command.editor/insert-link "링크 삽입" - :command.editor/highlight "하이라이트" + :command.editor/highlight "하이라" :command.editor/undo "실행 취소" :command.editor/redo "다시 실행" :command.editor/copy "복사" diff --git a/src/resources/dicts/nb-no.edn b/src/resources/dicts/nb-no.edn index e0319fcac62..3a57b9f5987 100644 --- a/src/resources/dicts/nb-no.edn +++ b/src/resources/dicts/nb-no.edn @@ -46,7 +46,6 @@ :right-side-bar/block-ref "Blokkreferanse" :right-side-bar/graph-view "Grafvisning" :right-side-bar/all-pages "Alle sider" - :right-side-bar/flashcards "Flashcards" :right-side-bar/new-page "Ny side" :right-side-bar/separator "Høyre sidestolpe størrelsesendring" :right-side-bar/show-journals "Vis dagbøker" @@ -114,12 +113,10 @@ :settings-page/developer-mode-desc "Utviklermodus hjelper bidragsytere og tilleggsutviklere med å teste sine integrasjoner mot Logseq mer effektivt." :settings-page/current-version "Nåværende versjon" :settings-page/tab-general "Generelt" - :settings-page/tab-editor "Editor" :settings-page/tab-version-control "Versjonskontroll" :settings-page/tab-advanced "Avansert" :settings-page/custom-global-configuration "Egendefinert global konfigurasjon" :settings-page/edit-global-config-edn "Rediger global config.edn" - :settings-page/enable-flashcards "Flashcards" :settings-page/export-theme "Eksporter tema" :settings-page/sync "Synkronisering" :settings-page/tab-features "Funksjoner" @@ -137,7 +134,6 @@ :search "Søk eller Opprett Side" :page-search "Søk i denne siden" :graph-search "Søk graf" - :new-page "Ny side" :new-graph "Legg til ny graf" :graph "Graf" :export "Eksport" @@ -152,7 +148,6 @@ :all-graphs "Alle grafer" :all-pages "Alle sider" :all-files "Alle filer" - :remove-orphaned-pages "Fjern foreldreløse sider" :all-journals "Alle dagbøker" :settings "Innstillinger" :plugins "Utvidelser" @@ -161,7 +156,6 @@ :import "Importer" :join-community "Bli med i samfunnet" :help-shortcut-title "Klikk for å sjekke snarveier og andre tips" - :loading "Laster" :parsing-files "Analyserer filer" :loading-files "Laster filer" :login "Logg inn" @@ -189,7 +183,6 @@ :plugin/marketplace "Markedsplass" :plugin/downloads "Nedlastinger" :plugin/stars "Stjerner" - :plugin/title "Tittel" :plugin/all "Alle" :plugin/unpacked "Utpakket" :plugin/delete-alert "Vil du avinstallere utvidelse [{1}]?" @@ -199,7 +192,6 @@ :plugin/restart "Start App på nytt" :plugin/unpacked-tips "Velg mappe for utvidelse" :plugin/contribute "✨ Skriv og send inn en ny utvidelse" - :plugin/up-to-date "Den er oppdatert" :plugin/custom-js-alert "Fant custom.js fil, får den lov til å kjøre? (Hvis du ikke forstår innholdet i denne filen er det anbefalt å ikke la den kjøre. Dette kan ha sikkerhetsrisiko.)" :pdf/copy-ref "Kopier ref" @@ -214,8 +206,6 @@ :paginates/prev "Forrige" :paginates/next "Neste" - :tips/all-done "Alt ferdig" - :command-palette/prompt "Skriv en kommando" :select/default-prompt "Velg en" :select.graph/prompt "Velg en graf" @@ -225,21 +215,17 @@ :file-sync/other-user-graph "Nåværende lokal graf er bundet til annen brukers fjerngraf. Kan ikke begynne å synkronisere." :file-sync/graph-deleted "Nåværende fjerngraf er slettet" :host "Vert" - :port "Port" :re-index-discard-unsaved-changes-warning "Reindeksering vil forkaste nåværende graf, og deretter prosessere alle filene på nytt slik de er på disk akkurat nå. Du vil miste ulagrede endringer, og det kan ta litt tid. Forsette?" :re-index-multiple-windows-warning "Du må lukke de andre vinduene før du kan reindeksere denne grafen" :save "Lagrer..." :settings-of-plugins "Innstillinger for utvidelser" :sync-from-local-changes-detected "Oppfrisk oppdager og prosesserer filer på disk som er modifiserte og avviker fra sideinnholdet som vises i Logseq. Fortsett?" - :type "Type" :graph/persist "Logeq synkroniserer intern status, vennligst vent i flere sekunder." :graph/persist-error "Intern status synk feilet" :graph/save "Lagrer..." :graph/save-error "Lagring feilet" :graph/save-success "Lagring vellykket" :graph/all-graphs "Alle grafer" - :graph/local-graphs "Lokale grafer" - :graph/remote-graphs "Fjerngrafer" :page/copy-page-url "Kopier side URL" :page/open-backup-directory "Åpne mappe med sidens sikkerhetskopier" :plugin/not-installed "Ikke installert" @@ -247,7 +233,6 @@ :settings-page/network-proxy "Nettverksproxy" :settings-page/plugin-system "System for utvidelser" :discourse-title "Vårt forum!" - :importing "Import" :asset/copy "Kopier bilde" :asset/delete "Slett bilde" :asset/maximize "Maksimer bilde" @@ -257,7 +242,6 @@ :all-whiteboards "Alle whiteboard" :auto-heading "Automatisk overskrift" :heading "Overskrift {1}" - :new-whiteboard "Nytt whiteboard" :remove-heading "Fjern overskrift" :untitled "Uten navn" :accessibility/skip-to-main-content "Hopp til hovedinnhold" @@ -290,7 +274,6 @@ :editor/delete-selection "Slett valgte blokker" :editor/expand-block-children "Utvid alle" :file/validate-existing-file-error "Siden eksisterer allerede i en annen fil: {1}, nåværen..." - :file-rn/all-action "Utfør alle Handlinger!" :file-rn/apply-rename "Utfør omdøping av filen" :file-rn/close-panel "Lukk Panel" :file-rn/confirm-proceed "Oppdater format!" @@ -338,16 +321,14 @@ :plugin/update-all-selected "Oppdater alle valgte" :plugin/updates-downloading "Laster ned oppdateringer" :plugin.install-from-file/menu-title "Installer fra plugins.edn" - :plugin.install-from-file/notice "Følgende plugins vil erstatte dine plugins:" - :plugin.install-from-file/success "Alle plugins er installert!" - :plugin.install-from-file/title "Installer plugins fra plugins.edn" + :plugin.install-from-file/notice "Følgende utvidelser vil erstatte dine utvidelser:" + :plugin.install-from-file/success "Alle utvidelser er installert!" + :plugin.install-from-file/title "Installer utvidelser fra plugins.edn" :right-side-bar/history "(Dev) Angre/Gjør om logg" - :right-side-bar/whiteboards "Whiteboards" :search/items "elementer" :search-item/block "Blokk" :search-item/file "Fil" :search-item/page "Side" - :search-item/whiteboard "Whiteboard" :select/default-select-multiple "Velg en eller flere" :settings-page/alpha-features "Alpha funksjoner" :settings-page/auto-expand-block-refs "Utvid blokkreferanser automatisk når zoomet inn..." @@ -356,7 +337,6 @@ :settings-page/custom-date-format-warning "Re-indeksering kreves! Eksisterernde dagbokreferanse vi..." :settings-page/disable-sentry-desc "Logseq vil aldri samle inn dine lokale graf sin databas..." :settings-page/edit-setting "Rediger" - :settings-page/enable-whiteboards "Whiteboards" :settings-page/filename-format "Filnavn format" :settings-page/login-prompt "For å få tilgang til nye funksjoner før alle andre må du..." :settings-page/preferred-pasting-file "Foretrekk innliming av fil" @@ -477,14 +457,12 @@ :command.graph/remove "Fjern en graf" :command.graph/save "Lagre nåværende graf til disk" :command.graph/re-index "Reindekser nåværende graf" - :command.misc/copy "mod+c" :command.pdf/close "Lukk nåværende pdf leser" :command.pdf/next-page "Neste side i nåværende pdf dok" :command.pdf/previous-page "Forrige side i nåværende pdf dok" :command.sidebar/clear "Fjern alt i høyre sidestolpe" :command.sidebar/open-today-page "Åpne dagens side i høyre sidestolpe" :command.ui/goto-plugins "Gå til dashbord for utvidelser" - ;; :command.ui/open-new-window "Åpne et nytt vindu" :command.ui/select-theme-color "Velg tilgjengelige temafarger" :command.ui/toggle-cards "Veksle kort" :command.dev/show-block-ast "(Dev) Vis blokk AST" @@ -501,7 +479,7 @@ :command.pdf/find "Pdf: Søk tekst i nåværende pdf doc" :command.sidebar/close-top "Lukker øverste objekt i høyre sidestolpe" :command.ui/clear-all-notifications "Fjern alle varsler" - :command.ui/install-plugins-from-file "Installer plugins fra plugins.edn" + :command.ui/install-plugins-from-file "Installer utvidelser fra plugins.edn" :command.whiteboard/bring-forward "Flytt fremover" :command.whiteboard/bring-to-front "Flytt fremst" :command.whiteboard/connector "Koblingsverktøy" @@ -526,4 +504,134 @@ :command.whiteboard/zoom-out "Zoom ut" :command.whiteboard/zoom-to-fit "Zoom til tegning" :command.whiteboard/zoom-to-selection "Zoom for å passe seleksjonen" - :shortcut.category/whiteboard "Whiteboard"} \ No newline at end of file + + :home "Hjem" + :importing "Importerer" + :port "Port" + :toggle-theme "Bytt tema" + :type "Type" + :whiteboard "Whiteboard" + :whiteboards "Whiteboard" + :command.misc/copy "Kopier" + :file-sync/rsapi-cannot-upload-err "Kunne ikke starte synkronisering, vennligst sjekk om..." + :header/go-back "Gå tilbake" + :header/go-forward "Gå fremover" + :header/more "Mer" + :header/search "Søk" + :header/toggle-left-sidebar "Veksle venstre sidestolpe" + :help/title-about "Om" + :help/title-community "Samfunn" + :help/title-development "Utvikling" + :help/title-terms "Betingelser" + :help/title-usage "Bruk" + :plugin/all-updated "Alt er oppdatert!" + :plugin/checking-for-updates "Ser etter oppdateringer for utvidelser" + :plugin/list-of-updates "Oppdateringer for utvidelser: " + :plugin/open-logseq-dir "Åpne" + :plugin/open-preferences "Åpne Innstillinger" + :plugin/remote-error "Ekstern feil: " + :plugin/search-plugin "Søk utvidelser" + :plugin/security-warning "Utvidelser kan få tilgang til din graf og dine lokale filer..." + :right-side-bar/flashcards "Flashcards" + :right-side-bar/toggle-right-sidebar "Veksle høyre sidestolpe" + :right-side-bar/whiteboards "Whiteboards" + :search/blocks-in-page "Søk blokker på side:" + :search/cache-outdated "Cache er utdatert. Vennligst klikk 'Re-indekser' knappen" + :search/recent "Nylige søk:" + :search-item/whiteboard "Whiteboard" + :settings-page/enable-flashcards "Flashcards" + :settings-page/enable-whiteboards "Whiteboards" + :settings-page/native-titlebar "Native tittellinje" + :settings-page/native-titlebar-desc "Skrur på Windows native tittellinje på vinduet..." + :settings-page/preferred-pasting-file-hint "Når skrudd på gir dette et hint når du limer inn et bile fra internett..." + :settings-page/tab-editor "Editor" + :shortcut.category/plugins "Utvidelser" + :shortcut.category/whiteboard "Whiteboard" + :whiteboard/add-block-or-page "Legg til blokk eller side" + :whiteboard/align-bottom "Bunnjuster" + :whiteboard/align-center-horizontally "Sentrer horisontalt" + :whiteboard/align-center-vertically "Sentrer vertikalt" + :whiteboard/align-left "Venstrejuster" + :whiteboard/align-right "Høyrejuster" + :whiteboard/align-top "Toppjuster" + :whiteboard/arrow-head "Pilhode" + :whiteboard/auto-resize "Automatisk endre størrelse" + :whiteboard/bold "Fet" + :whiteboard/cache-outdated "Cache er utdatert. Vennligst klikk 'Re-indekser' knappen" + :whiteboard/circle "Sirkel" + :whiteboard/collapse "Trekk sammen" + :whiteboard/color "Farge" + :whiteboard/connector "Kobling" + :whiteboard/copy "Kopier" + :whiteboard/cut "Klipp ut" + :whiteboard/delete "Slett" + :whiteboard/deselect-all "Fjern alle valg" + :whiteboard/dev-print-shape-props "(Dev) Print form-innstillinger" + :whiteboard/distribute-horizontally "Distribuer horisontalt" + :whiteboard/distribute-vertically "Distribuer vertikalt" + :whiteboard/draw "Tegn" + :whiteboard/eraser "Viskelær" + :whiteboard/expand "Utvid" + :whiteboard/export "Eksporter" + :whiteboard/extra-large "Ekstra Stor" + :whiteboard/extra-small "Ekstra Liten" + :whiteboard/fill "Fyll" + :whiteboard/flip-horizontally "Vend horisontalt" + :whiteboard/flip-vertically "Vend vertikalt" + :whiteboard/group "Gruppe" + :whiteboard/highlight "Markering" + :whiteboard/huge "Enorm" + :whiteboard/italic "Kursiv" + :whiteboard/large "Stor" + :whiteboard/link "Lenke" + :whiteboard/link-to-any-page-or-block "Lenke til hvilkensomhelst side eller blokk" + :whiteboard/lock "Lås" + :whiteboard/medium "Medium" + :whiteboard/move-to-back "Flytt bakover" + :whiteboard/move-to-front "Flytt fremover" + :whiteboard/new-block "Ny blokk:" + :whiteboard/new-block-no-colon "Ny blokk" + :whiteboard/new-page "Ny side:" + :whiteboard/new-whiteboard "Nytt whiteboard" + :whiteboard/opacity "Ugjennomsiktighet" + :whiteboard/open-page "Åpne side" + :whiteboard/open-page-in-sidebar "Åpne siden i sidestolpen" + :whiteboard/open-twitter-url "Åpne Twitter url" + :whiteboard/open-website-url "Åpne nettside url" + :whiteboard/open-youtube-url "Åpne YouTube url" + :whiteboard/pack-into-rectangle "Pakk inn i firkant" + :whiteboard/pan "Panorer" + :whiteboard/paste "Lim inn" + :whiteboard/paste-as-link "Lim inn som lenke" + :whiteboard/rectangle "Rektangel" + :whiteboard/redo "Gjør om" + :whiteboard/references "Referanser" + :whiteboard/reload "Last på nytt" + :whiteboard/remove-link "Fjern lenke" + :whiteboard/scale-level "Skaleringsnivå" + :whiteboard/search-only-blocks "Søk kun blokker" + :whiteboard/search-only-pages "Søk kun sider" + :whiteboard/select "Velg" + :whiteboard/select-all "Velg alle" + :whiteboard/select-custom-color "Velg egendefinert farge" + :whiteboard/shape "Form" + :whiteboard/shape-quick-links "Form Hurtiglenker" + :whiteboard/small "Liten" + :whiteboard/start-typing-to-search "Begynn å skrive for å søke..." + :whiteboard/stroke-type "Type strøk" + :whiteboard/text "Tekst" + :whiteboard/triangle "Triangel" + :whiteboard/twitter-url "Twitter url" + :whiteboard/undo "Angre" + :whiteboard/ungroup "Del opp gruppe" + :whiteboard/unlock "Lås opp" + :whiteboard/website-url "Nettside url" + :whiteboard/youtube-url "YouTube url" + :whiteboard/zoom-in "Zoom inn" + :whiteboard/zoom-out "Zoom ut" + :whiteboard/zoom-to-fit "Tilpass zoom" + :window/close "Lukk" + :window/exit-fullscreen "Gå ut av fullskjerm" + :window/maximize "Maksimer" + :window/minimize "Minimer" + :window/restore "Gjenopprett"} \ No newline at end of file diff --git a/src/resources/dicts/nl.edn b/src/resources/dicts/nl.edn index 3b2c65c48b1..de496187db0 100644 --- a/src/resources/dicts/nl.edn +++ b/src/resources/dicts/nl.edn @@ -5,7 +5,6 @@ :bold "Vet" :cancel "Annuleren" :close "Sluiten" - :code "Code" :delete "Verwijderen" :discourse-title "Ons forum!" :download "Downloaden" @@ -22,18 +21,15 @@ :graph-search "Zoek grafiek" :help-shortcut-title "Klik om sneltoetsen en andere tips te bekijken" :highlight "Markeer" - :host "Host" :import "Importeren" :italics "Cursief" :join-community "Sluit u aan bij de gemeenschap" :language "Taal" :loading-files "Bestanden laden" - :loading "Laden" :login "Inloggen" :logout "Uitloggen" :more "Meer" :new-graph "Nieuwe grafiek toevoegen" - :new-page "Nieuwe pagina" :open-a-directory "Open een lokale map" :open-new-window "Nieuwe venster" :page-search "Zoek in de huidige pagina" @@ -46,7 +42,6 @@ :re-index-multiple-windows-warning "U moet de andere vensters sluiten voordat u deze grafiek opnieuw indexeert." :relaunch-confirm-to-work "U moet de app opnieuw opstarten om het te laten werken. Wil u het nu opnieuw opstarten?" :remove-background "Verwijder achtergrond" - :remove-orphaned-pages "Verwijder gelinkte pagina's" :save "Opslaan" :search "Zoek of maak pagina" :settings "Instellingen" @@ -90,25 +85,19 @@ :graph/save-success "Opslaan succesvol" :help/about "Over Logseq" - :help/awesome-logseq "Awesome Logseq" :help/block-content-autocomplete "Blokinhoud (brontekst, citaten, zoekopdrachten, enz.) autocomplete" :help/block-reference "Blok referentie" - :help/blog "Logseq blog" :help/bug "Rapporteer een fout" :help/changelog "Verander logboek" :help/context-menu "Blok context menu" :help/docs "Documentatie" :help/feature "Functie verzoek" :help/forum-community "Forum gemeenschap" - :help/markdown-syntax "Markdown-syntax" - :help/org-mode-syntax "Org-mode-syntax" :help/privacy "Privacybeleid" :help/reference-autocomplete "Automatisch aanvullen van paginareferenties" - :help/roadmap "Roadmap" :help/shortcut "Snelkoppeling" :help/shortcut-page-title "Toetsenbord snelkoppelingen" :help/shortcuts "Toetsenbord snelkoppelingen" - :help/shortcuts-triggers "Triggers" :help/slash-autocomplete "Slash-Autocomplete" :help/start "Aan de slag" :help/terms "Voorwaarden" @@ -131,7 +120,6 @@ :on-boarding/open-local-dir "Open een lokale map" :page/add-to-favorites "Voeg aan favorieten toe" - :page/backlinks "Back-Links" :page/copy-page-url "Kopieer pagina URL" :page/created-at "Aangemaakt op" :page/delete "Verwijder pagina" @@ -159,18 +147,15 @@ :plugin/all "Alle" :plugin/check-all-updates "Check alle updates" - :plugin/check-update "Check update" :plugin/contribute "✨ Schrijf en dien nieuwe plugin in" :plugin/custom-js-alert "custom.js bestand gevonden, mag deze uitgevoerd worden? (Als je niet begrijpt wat dit bestand inhoud is het aangeraden om het uivoeren hiervan niet toe te staan, dit is in verband met beveiligings risico's.)" ;; TODO :plugin/delete-alert "Weet je zeker dat je plugin [{1}] wilt verwijderen?" :plugin/disabled "Uitgeschakeld" - :plugin/downloads "Downloads" :plugin/enabled "Ingeschakeld" :plugin/install "Installeren" :plugin/installed "Geïnstalleerd" :plugin/installing "Installeren" :plugin/load-unpacked "Laad uitgepakte plugin" - :plugin/marketplace "Marketplace" :plugin/not-installed "Niet geïnstalleerd" :plugin/open-package "Open pakket" :plugin/open-settings "Open instellingen" @@ -178,11 +163,9 @@ :plugin/reload "Herlaad" :plugin/restart "Herstart app" :plugin/stars "Sterren" - :plugin/title "Titel" :plugin/uninstall "Verwijder" :plugin/unpacked "Uitgepakt" :plugin/unpacked-tips "Selecteer de plugin map" - :plugin/up-to-date "Het is up to date" :plugin/update "Update" :plugin/update-available "Update beschikbaar" :plugin/updating "Bijwerken" @@ -190,15 +173,12 @@ :right-side-bar/all-pages "Alle pagina's" :right-side-bar/block-ref "Blok verwijzingen" :right-side-bar/contents "Inhoud" - :right-side-bar/flashcards "Flashcards" :right-side-bar/graph-view "Grafiekweergave" - :right-side-bar/help "Help" :right-side-bar/new-page "Nieuwe pagina" :right-side-bar/page-graph "Pagina grafiek" :right-side-bar/show-journals "Toon Journaals" :right-side-bar/switch-theme "Thema modes" - :search/items "items" :search/page-names "Zoek paginanamen" :search/publishing "Zoek" :search/result-for "Zoekresultaat voor " @@ -207,7 +187,6 @@ :select.graph/empty-placeholder-description "Geen overeenkomende grafieken. Wilt u er een toevoegen?" :select.graph/prompt "Selecteer een grafiek" - :settings-page/auto-updater "Auto updater" :settings-page/clear "Verwijder" :settings-page/clear-cache "Cache wissen" :settings-page/current-version "Huidige versie" @@ -224,7 +203,6 @@ :settings-page/enable-all-pages-public "Alle pagina's openbaar bij publiceren" :settings-page/enable-block-time "Tijdstempel voor blokken inschakelen" - :settings-page/enable-flashcards "Flashcards" :settings-page/enable-journals "Journaals" :settings-page/enable-shortcut-tooltip "Snelkoppeling tooltip inschakelen" :settings-page/enable-timetracking "Tijdregistratie inschakelen" @@ -243,14 +221,11 @@ :settings-page/show-brackets "Toon beugels" :settings-page/spell-checker "Spellingcontrole" :settings-page/tab-advanced "Geavanceerd" - :settings-page/tab-editor "Editor" :settings-page/tab-general "Algemeen" :settings-page/tab-version-control "Versiebeheer" :text/image "Afbeelding" - :tips/all-done "Alles klaar" - :updater/new-version-install "Een nieuwe versie is gedownload." :updater/quit-and-install "Herstart om te installeren" @@ -296,7 +271,6 @@ :command.editor/forward-word "Verplaats de cursor een woord vooruit" :command.editor/highlight "Markeer" :command.editor/indent "Blok inspringen" - :command.editor/insert-link "HTML Link" :command.editor/insert-youtube-timestamp "Voeg youtube tijdstempel toe" :command.editor/italics "Cursief" :command.editor/kill-line-after "Verwijder regel na cursorpositie" @@ -329,7 +303,6 @@ :command.git/commit "Maak git commit met bericht" :command.go/all-pages "Ga naar alle pagina's" :command.go/backward "Achteruit" - :command.go/flashcards "Flashcards Toggle" :command.go/forward "Vooruit" :command.go/graph-view "Ga naar grafiekweergave" :command.go/home "Ga naar home" @@ -358,10 +331,8 @@ :command.ui/toggle-cards "Toggle kaarten" :command.ui/toggle-contents "Toggle inhoud in zijbalk" :command.ui/toggle-document-mode "Schakel tussen documentmodus" - :command.ui/toggle-help "Toggle help" :command.ui/toggle-left-sidebar "Toggle linker zijbalk" :command.ui/toggle-right-sidebar "Toggle rechter zijbalk" - :command.ui/toggle-settings "Toggle settings" :command.ui/toggle-theme "Toggle tussen donker/licht thema" :command.ui/toggle-wide-mode "Toggle brede modus" :shortcut.category/basics "Basis" @@ -370,5 +341,4 @@ :shortcut.category/block-selection "Blokselectie (druk op Esc om selectie te beëindigen)" :shortcut.category/formatting "Formatteren" :shortcut.category/navigating "Navigatie" - :shortcut.category/others "Anderen" - :shortcut.category/toggle "Toggle"} \ No newline at end of file + :shortcut.category/others "Anderen"} \ No newline at end of file diff --git a/src/resources/dicts/pl.edn b/src/resources/dicts/pl.edn index 0fac73ed94d..036ca917c91 100644 --- a/src/resources/dicts/pl.edn +++ b/src/resources/dicts/pl.edn @@ -19,7 +19,6 @@ :help/privacy "Polityka prywatności" :help/terms "Warunki użytkowania" :help/forum-community "Forum dyskusyjne" - :help/awesome-logseq "Awesome Logseq" :help/shortcuts "Skróty klawiszowe" :help/shortcuts-triggers "Akcja" :help/shortcut "Skrót" @@ -145,7 +144,6 @@ :search "Wyszukaj lub stwórz stronę" :page-search "Wyszukaj na stronie" :graph-search "Przeszukaj graf" - :new-page "Nowa strona" :new-graph "Dodaj nowy graf" :graph "Graf" :graph/persist "Logseq synchronizuje lokalny stan. Proszę poczekać kilka sekund." @@ -153,7 +151,6 @@ :graph/save "Zapisuję..." :graph/save-success "Zmiany zostały zapisane" :graph/save-error "Zapisywanie zakończone niepowodzeniem" - :host "Host" :port "Port" :import "Importuj" :export "Eksport" @@ -168,7 +165,6 @@ :all-graphs "Wszystkie grafy" :all-pages "Wszystkie strony" :all-files "Wszystkie pliki" - :remove-orphaned-pages "Usuń strony bez powiązań" :all-journals "Wszystkie dzienniki" :settings "Ustawienia" :settings-of-plugins "Ustawienia pluginu" @@ -178,7 +174,6 @@ :join-community "Dołącz do społeczności" :discourse-title "Nasze forum!" :help-shortcut-title "Kliknij, aby sprawdzić skróty klawiszowe oraz inne porady" - :loading "Ładuję" :parsing-files "Parsuję pliki" :loading-files "Ładuję pliki" :login "Zaloguj" @@ -204,10 +199,8 @@ :plugin/uninstall "Odinstaluj" :plugin/downloads "Ściągnięte" :plugin/stars "Gwiazdki" - :plugin/title "Tytuł" :plugin/all "Wszystkie" :plugin/unpacked "Rozpakowany" - :plugin/marketplace "Marketplace" :plugin/delete-alert "Czy na pewno chcesz usunąć plugin [{1}]?" :plugin/open-settings "Otwórz ustawienia" :plugin/open-package "Otwórz paczkę" @@ -215,7 +208,6 @@ :plugin/restart "Uruchom ponownie" :plugin/unpacked-tips "Wybierz katalog z pluginem" :plugin/contribute "✨ Napisz i prześlij nowy plugin" - :plugin/up-to-date "Wszystko jest aktualne" :plugin/custom-js-alert "Wykryto plik custom.js, czy chcesz go wykonać? Ze względów bezpieczeństwa, nie rekomendujemy wykonywania tego pliku, jeżeli nie znasz jego zawartości." :pdf/copy-ref "Kopiuj ref" @@ -230,8 +222,6 @@ :paginates/prev "← Poprzednia" :paginates/next "Następna →" - :tips/all-done "Wszystko zrobione" - :command-palette/prompt "Wprowadź komendę" :select/default-prompt "Wybierz jeden" :select.graph/prompt "Wybierz graf" @@ -314,10 +304,7 @@ :command.editor/cut "Wytnij" :command.editor/undo "Cofnij" :command.editor/redo "Ponów" - :command.editor/insert-link "HTML Link" :command.editor/select-all-blocks "Zaznacz wszystkie bloki" - :command.editor/zoom-in "Zoom in editing block / Forwards otherwise" - :command.editor/zoom-out "Zoom out editing block / Backwards otherwise" :command.ui/toggle-brackets "Pokaż / Ukrywaj kwadratowe nawiasy" :command.go/search-in-page "Szukaj na aktualnej stronie" :command.go/search "Wyszukiwanie tekstowe" @@ -327,7 +314,6 @@ :command.search/re-index "Przebuduj index wyszukiwania" :command.sidebar/open-today-page "Otwórz dzisiejszy dziennik w panelu bocznym" :command.sidebar/clear "Wyczyść wszystko w panelu bocznym" - :command.misc/copy "mod+c" :command.graph/open "Wybierz graf do otwarcia" :command.graph/remove "Usuń graf" :command.graph/add "Dodaj graf" @@ -350,13 +336,11 @@ :command.ui/toggle-left-sidebar "Pokaż / Ukryj lewy panel" :command.ui/toggle-help "Pogaż / Ukryj pomoc" :command.ui/toggle-theme "Zmień motyw graficzny na ciemny/jasny" - :command.ui/toggle-contents "Toggle Contents in sidebar" :command.editor/open-file-in-default-app "Otwórz plik w domyślnej aplikacji" :command.editor/open-file-in-directory "Otwórz plik w nadrzędnym katalogu" :command.editor/copy-current-file "Kopiuj aktualny plik" :command.editor/toggle-open-blocks "Zwiń / Rozwiń otwarte bloki" :command.ui/toggle-wide-mode "Włącz / wyłącz tryb szeroki" - :command.ui/select-theme-color "Select available theme colors" :command.ui/goto-plugins "Przejdź do dashboardu pluginów" :command.ui/toggle-cards "Pokaż / Ukryj karty" :command.git/commit "Wykonaj GIT COMMIT z wiadomością"} \ No newline at end of file diff --git a/src/resources/dicts/pt-br.edn b/src/resources/dicts/pt-br.edn index 065eb00afbb..f1e55d02bb8 100644 --- a/src/resources/dicts/pt-br.edn +++ b/src/resources/dicts/pt-br.edn @@ -39,7 +39,6 @@ :right-side-bar/contents "Conteúdo" :right-side-bar/page-graph "Grafo da página" :right-side-bar/block-ref "Referência de bloco" - :right-side-bar/flashcards "Flashcards" :right-side-bar/new-page "Nova página" :left-side-bar/journals "Diários" :page/presentation-mode "Modo de apresentação" @@ -60,7 +59,6 @@ :file/format-not-supported "Formato .{1} não suportado." :page/created-at "Criado em" :page/updated-at "Atualizado em" - :page/backlinks "Back Links" :editor/block-search "Pesquisar por um bloco" :text/image "Imagem" :asset/confirm-delete "Tem certeza que quer excluir este {1}?" @@ -96,7 +94,6 @@ :settings-page/developer-mode-desc "O modo de desenvolvimento ajuda os contribuidores e programadores de extensões a testar as suas integrações com o Logseq de forma eficiente." :settings-page/current-version "Versão atual" :settings-page/tab-general "Geral" - :settings-page/tab-editor "Editor" :settings-page/tab-advanced "Avançado" :settings-page/tab-version-control "Controle de Versões" :yes "Sim" @@ -126,7 +123,6 @@ :all-files "Todos os arquivos" :all-journals "Todos os diários" :settings "Configurações" - :plugins "Plugins" :themes "Temas" :relaunch-confirm-to-work "Deve reiniciar a aplicação para fazê-lo funcionar. Quer reiniciar agora?" :import "Importar" @@ -212,7 +208,6 @@ :page/open-backup-directory "Abra a listagem de backups de página" :save "Salvar" :type "Tipo" - :host "Host" :port "Porta" :settings-of-plugins "Configurações de Plugin" :graph/persist "O Logseq está sincronizando seu status interno, aguarde alguns segundos." @@ -229,7 +224,6 @@ :page/copy-page-url "Copiar URL da página" :plugin/not-installed "Não instalado" :settings-page/edit-export-css "Editar export.css" - :settings-page/enable-flashcards "Flashcards" :settings-page/export-theme "Exportar Tema" :discourse-title "Nosso fórum!" @@ -439,7 +433,6 @@ :command.graph/save "Salvar grafo atual no computador" :command.misc/copy "Copiar (copiar seleção ou referência do bloco)" :command.ui/goto-plugins "Ir para o painel de plugins" - ;; :command.ui/open-new-window "Abra uma nova janela" :command.editor/select-down "Selecione o conteúdo abaixo" :command.editor/select-up "Selecione o conteúdo acima" :command.editor/copy-embed "Copiar uma incorporação do bloco, apontando para o bloco atual" @@ -457,4 +450,209 @@ :command.graph/export-as-html "Exportar páginas de gráficos públicos como html" :command.pdf/find "PDF: Pesquisar no documento PDF atual" :command.sidebar/close-top "Fechar item superior na barra lateral direita" - :command.ui/install-plugins-from-file "Instalar plugins de plugins.edn"} + :command.ui/install-plugins-from-file "Instalar plugins de plugins.edn" + + :home "Início" + :toggle-theme "Trocar tema" + :whiteboard "Quadro Branco" + :whiteboards "Quadros Brancos" + :command.dev/show-block-ast "(Dev) Mostrar AST do bloco" + :command.dev/show-block-data "(Dev) Mostrar dados do bloco" + :command.dev/show-page-ast "(Dev) Mostrar AST da página" + :command.dev/show-page-data "(Dev) Mostrar dados da página" + :command.editor/copy-page-url "Copiar URL da página" + :command.editor/toggle-number-list "Alternar lista de números" + :command.editor/toggle-undo-redo-mode "Alternar modo de desfazer e refazer (somente global ou de página)" + :command.ui/clear-all-notifications "Limpar notificações" + :command.whiteboard/bring-forward "Mover para trás" + :command.whiteboard/bring-to-front "Mover para frente" + :command.whiteboard/connector "Conector" + :command.whiteboard/ellipse "Elipse" + :command.whiteboard/eraser "Borracha" + :command.whiteboard/group "Agrupar Seleção" + :command.whiteboard/highlighter "Marca-texto" + :command.whiteboard/lock "Travar Seleçãp" + :command.whiteboard/pan "Arrastar" + :command.whiteboard/pencil "Pincel" + :command.whiteboard/portal "Portal" + :command.whiteboard/rectangle "Retângulo" + :command.whiteboard/reset-zoom "Reiniciar Zoom" + :command.whiteboard/select "Seleção" + :command.whiteboard/send-backward "Mover ao contrário" + :command.whiteboard/send-to-back "Mover para trás" + :command.whiteboard/text "Texto" + :command.whiteboard/toggle-grid "Alternar a grade da tela" + :command.whiteboard/ungroup "Desagrupar seleção" + :command.whiteboard/unlock "Desbloquear seleção" + :command.whiteboard/zoom-in "Aumentar Zoom" + :command.whiteboard/zoom-out "Diminuir Zoom" + :command.whiteboard/zoom-to-fit "Zoom para o desenho" + :command.whiteboard/zoom-to-selection "Zoom para ajustar a seleção" + :content/copy-block-url "Copiar URL do bloco" + :content/copy-export-as "Copiar / Exportar como..." + :content/copy-ref "Copiar esta referência" + :content/delete-ref "Excluir esta referência" + :content/replace-with-embed "Substituir com incorporar" + :content/replace-with-text "Substituir por texto" + :context-menu/input-template-name "Qual o nome do modelo?" + :context-menu/make-a-flashcard "Crie um Flashcard" + :context-menu/make-a-template "Crie um Modelo" + :context-menu/preview-flashcard "Visualizar Flashcard" + :context-menu/template-exists-warning "O modelo já existe!" + :context-menu/template-include-parent-block "Incluindo o bloco pai no modelo?" + :context-menu/toggle-number-list "Alternar lista de números" + :dev/show-block-ast "(Dev) Mostrar AST do bloco" + :dev/show-block-data "(Dev) Mostrar dados do bloco" + :dev/show-page-ast "(Dev) Mostrar AST da página" + :dev/show-page-data "(Dev) Mostrar dados da página" + :editor/collapse-block-children "Comprimir tudo" + :editor/cycle-todo "Gira o estado TODO do item atual" + :editor/delete-selection "Excluir blocos selecionados" + :editor/expand-block-children "Expandir tudo" + :file-sync/rsapi-cannot-upload-err "Não foi possível iniciar a sincronização, verifique se a hora local está correta. t..." + :header/go-back "Voltar" + :header/go-forward "Avançar" + :header/more "Mais" + :header/search "Procurar" + :header/toggle-left-sidebar "Alternar barra lateral esquerda" + :help/open-link-in-sidebar "Abrir link na barra lateral" + :help/title-about "Sobre" + :help/title-community "Comunidade" + :help/title-development "Desenvolvimento" + :help/title-terms "Termos" + :help/title-usage "Uso" + :page/illegal-page-name "Nome de página inválido!" + :page/logseq-is-having-a-problem "Logseq está tendo um problema. Para tentar recuperá-lo em um estado de funcionamento, tente as seguintes etapas em ordem:" + :page/page-already-exists "Página “{1}” Já existe!" + :page/something-went-wrong "Algo deu errado" + :page/step "Passo {1}" + :page/try "Tentar" + :page/whiteboard-to-journal-error "As páginas do quadro branco não podem ser renomeadas para títulos de periódicos!" + :plugin/all-updated "Tudo atualizado!" + :plugin/checking-for-updates "Verificando atualizações de plugins..." + :plugin/found-n-updates "Encontradas {1} atualizações" + :plugin/found-updates "Novas atualizações" + :plugin/list-of-updates "Atualizações de plugins: " + :plugin/open-logseq-dir "Abrir" + :plugin/open-preferences "Abrir preferências" + :plugin/remote-error "Erro remoto: " + :plugin/search-plugin "Procurar plugins" + :plugin/security-warning "Os plug-ins podem acessar seu gráfico e seus arquivos locais, emitir solicitações de rede. + Eles também podem causar corrupção ou perda de dados. Estamos trabalhando em regras de acesso adequadas para seus gráficos. + Enquanto isso, certifique-se de fazer backups regulares de seus gráficos e instale os plug-ins apenas quando puder ler e + entender o código-fonte." + :plugin/update-all-selected "Atualizar todos os selecionados" + :plugin/updates-downloading "Baixando stualizações" + :right-side-bar/history "(Dev) Histórico de Desfazer/Refazer" + :right-side-bar/toggle-right-sidebar "Alternar barra lateral" + :search/blocks-in-page "Procurar blocos na página:" + :search/cache-outdated "O cache está desatualizado. Clique no botão 'Reindexar' no menu suspenso do gráfico." + :search/items "itens" + :search/recent "Buscas recentes:" + :select/default-select-multiple "Selecione um ou vários" + :settings-page/native-titlebar "Barra de título nativa" + :settings-page/native-titlebar-desc "Ativa a barra de título da janela nativa no Windows e no Linux" + :settings-page/preferred-pasting-file-hint "Quando ativado, colar uma imagem da Internet fará o download e inserirá a imagem. Quando desativado, ele colará o link na imagem." + :settings-page/show-full-blocks "Mostrar todas as linhas de uma referência de bloco" + :settings-page/tab-account "Conta" + :shortcut.category/whiteboard "Quadro branco" + :whiteboard/add-block-or-page "Adicionar bloco ou página" + :whiteboard/align-bottom "Alinhar em baixo" + :whiteboard/align-center-horizontally "Alinhar no centro horizontalmente" + :whiteboard/align-center-vertically "Alinhar no centro verticalmente" + :whiteboard/align-left "Alinhar na esquerda" + :whiteboard/align-right "Alinhar na direita" + :whiteboard/align-top "Alinhar no topo" + :whiteboard/arrow-head "Ponta de flecha" + :whiteboard/auto-resize "Redimensionar automaticamente" + :whiteboard/bold "Negrito" + :whiteboard/cache-outdated "O cache está desatualizado. Clique no botão 'Reindexar' no menu suspenso do gráfico." + :whiteboard/circle "Círculo" + :whiteboard/collapse "Fechar" + :whiteboard/color "Cor" + :whiteboard/connector "Conector" + :whiteboard/copy "Copiar" + :whiteboard/cut "Cortar" + :whiteboard/delete "Deletar" + :whiteboard/deselect-all "Deselecionar tudo" + :whiteboard/dev-print-shape-props "(Dev) Propriedades do formato de impressão" + :whiteboard/distribute-horizontally "Distribuir horizontalmente" + :whiteboard/distribute-vertically "Distribuir verticalmente" + :whiteboard/draw "Desenho" + :whiteboard/eraser "Borracha" + :whiteboard/expand "Expandir" + :whiteboard/export "Exportar" + :whiteboard/extra-large "Muito Grande" + :whiteboard/extra-small "Muito Pequeno" + :whiteboard/fill "Preencher" + :whiteboard/flip-horizontally "Virar horizontalmente" + :whiteboard/flip-vertically "Virar verticalmente" + :whiteboard/group "Agrupar" + :whiteboard/highlight "Destacar" + :whiteboard/huge "Enorme" + :whiteboard/italic "Itálico" + :whiteboard/large "Grande" + :whiteboard/link-to-any-page-or-block "Link para qualquer página ou bloco" + :whiteboard/lock "Travar" + :whiteboard/medium "Médio" + :whiteboard/move-to-back "Mover para trás" + :whiteboard/move-to-front "Mover para frente" + :whiteboard/new-block "Novo bloco:" + :whiteboard/new-block-no-colon "Novo bloco" + :whiteboard/new-page "Nova página:" + :whiteboard/new-whiteboard "Novo Quadro Branco" + :whiteboard/opacity "Opacidade" + :whiteboard/open-page "Abrir página" + :whiteboard/open-page-in-sidebar "Abrir página na barra lateral" + :whiteboard/open-twitter-url "Abrir URL do Twitter" + :whiteboard/open-website-url "Abrir URL do website" + :whiteboard/open-youtube-url "Abrir URL do YouTube" + :whiteboard/pack-into-rectangle "Envolva em um retângulo" + :whiteboard/pan "Arrastar" + :whiteboard/paste "Colar" + :whiteboard/paste-as-link "Color como link" + :whiteboard/rectangle "Retângulo" + :whiteboard/redo "Refazer" + :whiteboard/references "Referências" + :whiteboard/reload "Recarregar" + :whiteboard/remove-link "Remover link" + :whiteboard/scale-level "Nível da Escala" + :whiteboard/search-only-blocks "Pesquisar apenas blocos" + :whiteboard/search-only-pages "Pesquisar apenas páginas" + :whiteboard/select "Selecionar" + :whiteboard/select-all "Selecionar tudo" + :whiteboard/select-custom-color "Selecione a cor personalizada" + :whiteboard/shape "Forma" + :whiteboard/shape-quick-links "Links rápidos de forma" + :whiteboard/small "Pequeno" + :whiteboard/start-typing-to-search "Comece a digitar para pesquisar..." + :whiteboard/stroke-type "Tipo de borda" + :whiteboard/text "Texto" + :whiteboard/triangle "Triângulo" + :whiteboard/twitter-url "URL do Twitter" + :whiteboard/undo "Desfazer" + :whiteboard/ungroup "Desagrupar" + :whiteboard/unlock "Desbloquear" + :whiteboard/website-url "URL do Website" + :whiteboard/youtube-url "URL do YouTube" + :whiteboard/zoom-in "Aumentar Zoom" + :whiteboard/zoom-out "Diminuir Zoom" + :whiteboard/zoom-to-fit "Ampliar para caber" + :window/close "Fechar" + :window/exit-fullscreen "Sair da Tela Cheia" + :window/maximize "Maximizar" + :window/minimize "Minimizar" + :window/restore "Restaurar" + :logout-user "Sair ({1})" + :plugin/installed-plugin "Plugin instalado: {1}" + :plugin/update-plugin "Atualizar plugin: {1} - {2}" + + :plugins "Plugins" + :right-side-bar/flashcards "Flashcards" + :settings-page/enable-flashcards "Flashcards" + :page/backlinks "Backlinks" + :host "Host" + :settings-page/tab-editor "Editor" + :shortcut.category/plugins "Plugins" + :whiteboard/link "Link" +} diff --git a/src/resources/dicts/pt-pt.edn b/src/resources/dicts/pt-pt.edn index b3e63cdcc84..409d6e0af43 100644 --- a/src/resources/dicts/pt-pt.edn +++ b/src/resources/dicts/pt-pt.edn @@ -26,7 +26,6 @@ :help/privacy "Política de privacidade" :help/terms "Termos" :help/forum-community "Comunidade do fórum" - :help/awesome-logseq "Awesome Logseq" :help/shortcuts "Atalhos de Teclado" :help/shortcuts-triggers "Iniciadores" :help/shortcut "Atalho" @@ -100,7 +99,6 @@ :file-rn/or-select-actions-2 ". Estas ações não estarão mais disponíveis após fechar este painel." :file-rn/legend "🟢 Ações opcionais de alteração de nome; 🟡 É necessário uma alteração de nome para evitar uma mudança de título; 🔴 Mudança inválida." :file-rn/close-panel "Fechar o Painel" - :file-rn/all-action "Aplicar todas as Ações!" :file-rn/select-format "(Opção do modo de desenvolvedor, cuidado!) Selecione o formato de nome do ficheiro" :file-rn/rename "mudar o nome de \"{1}\" para \"{2}\"" :file-rn/apply-rename "Aplicar a mudança de nome do ficheiro" @@ -121,7 +119,6 @@ :file-rn/instruct-3 "2. Siga as instruções abaixo para mudar o nome dos ficheiros para o novo formato:" :page/created-at "Criada Em" :page/updated-at "Atualizada Em" - :page/backlinks "Back Links" :linked-references/filter-search "Procurar nas páginas vinculadas" :editor/block-search "Pesquisar por um bloco" :text/image "Imagem" @@ -189,14 +186,13 @@ :settings-page/developer-mode-desc "O modo de desenvolvedor ajuda os contribuidores e programadores de extensões a testar as suas integrações com o Logseq mais eficientemente." :settings-page/current-version "Versão atual" :settings-page/tab-general "Geral" - :settings-page/tab-editor "Editor" :settings-page/tab-version-control "Controlo de Versões" :settings-page/tab-advanced "Avançado" :settings-page/tab-assets "Recursos" :settings-page/tab-features "Funcionalidades" + :settings-page/network-proxy "Proxy de rede" :settings-page/plugin-system "Plugins" :settings-page/enable-flashcards "Flashcards" - :settings-page/network-proxy "Proxy de rede" :settings-page/filename-format "Formato do nome dos ficheiros" :settings-page/alpha-features "Funcionalidades em fase Alfa" :settings-page/beta-features "Funcionalidades em fase Beta" @@ -210,7 +206,6 @@ :delete "Apagar" :save "Guardar" :type "Tipo" - :host "Host" :port "Porta" :re-index "Reindexar" :re-index-detail "Reconstruir o grafo" @@ -226,8 +221,6 @@ :whiteboard/link-whiteboard-or-block "Vincular quadro/página/bloco" :page-search "Pesquisar na página atual" :graph-search "Pesquisar no grafo" - :new-page "Nova página" - :new-whiteboard "Novo quadro branco" :new-graph "Adicionar novo grafo" :graph "Grafo" :graph/persist "O Logseq está a sincronizar o seu estado interno, por favor aguarde alguns segundos." @@ -236,8 +229,6 @@ :graph/save-success "Guardado com sucesso" :graph/save-error "Falha ao guardar" :graph/all-graphs "Todos os grafos" - :graph/local-graphs "Grafos locais" - :graph/remote-graphs "Grafos remotos" :export "Exportar" :export-graph "Exportar grafo" :export-page "Exportar página" @@ -251,7 +242,6 @@ :all-pages "Todas as páginas" :all-whiteboards "Todos os quadros brancos" :all-files "Todos os ficheiros" - :remove-orphaned-pages "Remover páginas órfãs" :all-journals "Todas as págs. diárias" :settings "Definições" :settings-of-plugins "Plugins" @@ -263,7 +253,6 @@ :join-community "Junte-se à comunidade" :discourse-title "O nosso fórum!" :help-shortcut-title "Clique para ver atalhos e outras dicas" - :loading "A carregar" :parsing-files "A analisar ficheiros" :loading-files "A carregar ficheiros" :login "Iniciar sessão" @@ -295,7 +284,6 @@ :plugin/marketplace "Mercado" :plugin/downloads "Downloads" :plugin/stars "Estrelas" - :plugin/title "Título" :plugin/all "Todos" :plugin/unpacked "Desempacotado" :plugin/delete-alert "Tem a certeza de quer desinstalar o plugin [{1}]?" @@ -305,7 +293,6 @@ :plugin/restart "Reiniciar a aplicação" :plugin/unpacked-tips "Selecionar a pasta de plugins" :plugin/contribute "✨ Escreva e submeta um novo plugin" - :plugin/up-to-date "Está atualizado" :plugin/custom-js-alert "Ficheiro custom.js encontrado, quer executá-lo? (Se não compreender o conteúdo do ficheiro, é melhor não executá-lo, pois há certos riscos de segurança ao fazê-lo.)" :plugin.install-from-file/menu-title "Instalar a partir de plugins.edn" :plugin.install-from-file/title "Instalar plugins a partir de plugins.edn" @@ -326,8 +313,6 @@ :paginates/prev "Ant." :paginates/next "Próx." - :tips/all-done "Tudo feito" - :command-palette/prompt "Introduza um comando" :select/default-prompt "Selecione um" :select/default-select-multiple "Selecione um ou vários" @@ -340,7 +325,7 @@ :file-sync/rsapi-cannot-upload-err "Não foi possível iniciar a sincronização, verifique se a hora local está correta." :notification/clear-all "Limpar tudo" - + :shortcut.category/formatting "Formatação" :shortcut.category/basics "Básico" :shortcut.category/navigating "Navegação" diff --git a/src/resources/dicts/ru.edn b/src/resources/dicts/ru.edn index 5f74fba38db..be0e989b8a4 100644 --- a/src/resources/dicts/ru.edn +++ b/src/resources/dicts/ru.edn @@ -1,533 +1,666 @@ -{:accessibility/skip-to-main-content "Перейти к основному содержимому" - :tutorial/text #resource "tutorials/tutorial-ru.md" - :tutorial/dummy-notes #resource "tutorials/dummy-notes-ru.md" - :on-boarding/demo-graph "Это демонстрационный граф, изменения не будут сохранены, пока вы не откроете локальный файл." - :on-boarding/add-graph "Добавить новый граф" - :on-boarding/open-local-dir "Открыть локальный каталог" - :on-boarding/new-graph-desc-1 "Logseq поддерживает Markdown и Org-mode. Вы можете открыть существующий каталог или создать новый на вашем устройства, каталог также можно назвать просто папкой. Ваши данные будут храниться только на вашем устройстве." - :on-boarding/new-graph-desc-2 "После того, как вы укажете каталог, в нём будут созданы три папки:" - :on-boarding/new-graph-desc-3 "/journals - хранит страницы ваших журналов" - :on-boarding/new-graph-desc-4 "/pages - хранит остальные страницы" - :on-boarding/new-graph-desc-5 "/logseq - хранит конфигурации, custom.css, и другие метаданные." - :on-boarding/welcome-whiteboard-modal-title "Новый холст для ваших мыслей." - :on-boarding/welcome-whiteboard-modal-description "Интерактивные доски - отличный инструмент для мозгового штурма и самоорганизации. Теперь вы можете разместить любые свои мысли из базы знаний или новые мысли рядом друг с другом на пространственном холсте, чтобы соединить, ассоциировать и понять по-новому" - :on-boarding/welcome-whiteboard-modal-skip "Пропустить" - :on-boarding/welcome-whiteboard-modal-start "Начать работу с интерактивной доской" - :on-boarding/tour-whiteboard-home "{1} Дом для ваших досок" - :on-boarding/tour-whiteboard-home-description "Интерактивные доски имеют свой собственный раздел в приложении, где их сразу можно увидеть, создать новые или удалить." - :on-boarding/tour-whiteboard-new "{1} Создать новую интерактивную доску" - :on-boarding/tour-whiteboard-new-description "Существует несколько способов создания новой интерактивной доски. Один из них всегда находится прямо здесь, на панели управления." - :help/start "Начало работы" - :help/about "О Logseq" - :help/roadmap "Дорожная карта" - :help/bug "Сообщить об ошибке" - :help/feature "Предложить улучшение" - :help/changelog "Список изменений" - :help/blog "Блог Logseq" - :help/docs "Документация" - :help/privacy "Политика конфиденциальности" - :help/terms "Условия" - :help/forum-community "Форум сообщества" - :help/awesome-logseq "Потрясающий Logseq" - :help/shortcuts "Сочетания клавиш" - :help/shortcuts-triggers "Действия" - :help/shortcut "Горячие клавиши" - :help/slash-autocomplete "Слэш - автодополнение" - :help/block-content-autocomplete "Блок контента - автодополнение" - :help/reference-autocomplete "Автодополнение ссылок на страницу" - :help/block-reference "Ссылка на блок" - :help/open-link-in-sidebar "Открыть ссылку в боковой панели" - :more "Больше" - :search/result-for "Искать результат для " - :search/items "элементы" - :search/page-names "Искать имена страниц" - :search-item/whiteboard "Интерактивная доска" - :search-item/page "Страница" - :search-item/file "Файл" - :search-item/block "Блок" - :help/context-menu "Контекстное меню блока" - :help/markdown-syntax "Markdown синтаксис" - :help/org-mode-syntax "Org-mode синтаксис" - :bold "Жирный" - :italics "Курсив" - :highlight "Выделение" - :strikethrough "Перечёркнутый" - :code "Код" - :untitled "Без названия" - :right-side-bar/help "Справка" - :right-side-bar/switch-theme "Тема" - :right-side-bar/contents "Содержание" - :right-side-bar/page-graph "Граф страницы" - :right-side-bar/history "(Dev) Отменить/Повторить историю" - :right-side-bar/block-ref "Ссылка на блок" - :right-side-bar/graph-view "Визуальный граф" - :right-side-bar/all-pages "Все страницы" - :right-side-bar/whiteboards "Интерактивные доски" - :right-side-bar/flashcards "Карточки" - :right-side-bar/new-page "Новая страница" - :right-side-bar/show-journals "Показать журналы" - :right-side-bar/separator "Изменение размера правой боковой панели" - :left-side-bar/journals "Журналы" - :left-side-bar/create "Создать" - :left-side-bar/new-page "Новая страница" - :left-side-bar/new-whiteboard "Новая интерактивная доска" - :left-side-bar/nav-favorites "Избранное" - :left-side-bar/nav-recent-pages "Недавнее" - :page/something-went-wrong "Что-то пошло не так" - :page/logseq-is-having-a-problem "У Logseq возникла проблема. Чтобы попытаться вернуть его в рабочее состояние, пожалуйста, попробуйте выполнить следующие безопасные шаги по порядку:" - :page/step "Шаг {1}" - :page/try "Попробовать" - :page/presentation-mode "Презентация" - :page/delete-confirmation "Вы уверены, что хотите удалить эту страницу и ее файл?" - :page/open-in-finder "Открыть в каталоге" - :page/open-with-default-app "Открыть в приложении по умолчанию" - :page/make-public "Сделать доступной для публикации" - :page/version-history "Просмотр истории страницы" - :page/open-backup-directory "Открыть каталог резервных копий" - :page/make-private "Сделать приватной" - :page/delete "Удалить страницу" - :page/add-to-favorites "Добавить в Избранное" - :page/unfavorite "Удалить из Избранного" - :page/show-journals "Показать журналы" - :page/show-whiteboards "Показать интерактивные доски" - :block/name "Имя страницы" - :page/earlier "Ранее" - :page/copy-page-url "Копировать URL страницы" - :file/name "Имя файла" - :file/last-modified-at "Последнее изменение" - :file/no-data "Нет данных" - :file/format-not-supported "Расширение .{1} не поддерживается." - :file/validate-existing-file-error "Страница уже существует с другим файлом: {1}, текущий файл: {2}. Пожалуйста, оставьте только один из них и переиндексируйте ваш граф." - :file-rn/re-index "Настоятельно рекомендуется повторить индексацию после переименования файлов и синхронизации на других устройствах." - :file-rn/need-action "Предлагается выполнить действия по переименованию файлов, чтобы они соответствовали новому формату. Переиндексация требуется на всех устройствах после синхронизации переименованных файлов." - :file-rn/or-select-actions " или переименовать файлы ниже по отдельности, затем " - :file-rn/or-select-actions-2 ". Эти действия будут недоступны после закрытия этой панели." - :file-rn/legend "🟢 Необязательные действия по переименованию; 🟡 Действие по переименованию, необходимое для предотвращения изменения заголовка; 🔴 Обязательное изменение." - :file-rn/close-panel "Закрыть панель" - :file-rn/all-action "Применить все действия!" - :file-rn/select-format "(Опция режима разработчика. Опасно!) Выберите формат имени файла" - :file-rn/rename "переименовать файл \"{1}\" в \"{2}\"" - :file-rn/apply-rename "Применить операцию переименования файла" - :file-rn/suggest-rename "Требуется действие: " - :file-rn/otherwise-breaking "Или заголовок станет" - :file-rn/no-action "Отлично! Дальнейших действий не требуется." - :file-rn/confirm-proceed "Обновить формат!" - :file-rn/select-confirm-proceed "Dev: формат записи" - :file-rn/unreachable-title "Внимание! Имя страницы станет {1} при текущем формате имени файла, если `title::` не задано вручную" - :file-rn/optional-rename "Предложение: " - :file-rn/format-deprecated "В настоящее время вы используете устаревший формат. Настоятельно рекомендуется обновить формат до последней версии. Пожалуйста, создайте резервную копию данных и закройте клиенты Logseq на других устройствах перед началом операции." - :file-rn/filename-desc-1 "Этот параметр определяет способ сохранения страницы в файл. Logseq сохраняет страницу в файл с таким же именем." - :file-rn/filename-desc-2 "Некоторые символы, такие как \"/\" или \"?\" недопустимы для имени файла." - :file-rn/filename-desc-3 "Logseq заменяет недопустимые символы их эквивалентом в кодировке URL, чтобы сделать их допустимыми (например, \"?\" становится \"%3F\")." - :file-rn/filename-desc-4 "Разделитель пространства имен \"/\" также заменяется на \"___\" (тройное подчеркивание) из эстетических соображений." - :file-rn/instruct-1 "Этот процесс обновления формата имен файлов состоит из двух этапов:" - :file-rn/instruct-2 "1. Нажмите " - :file-rn/instruct-3 "2. Следуйте приведенным ниже инструкциям, чтобы переименовать файлы в новый формат:" - :page/created-at "Создан в" - :page/updated-at "Обновлен в" - :page/backlinks "Обратные ссылки" - :linked-references/filter-search "Поиск в связанных страницах" - :editor/block-search "Поиск блока" - :text/image "Изображение" - :asset/show-in-folder "Показать изображение в папке" - :asset/open-in-browser "Открыть изображение в браузере" - :asset/delete "Удалить изображение" - :asset/copy "Копировать изображение" - :asset/maximize "Увеличить изображение" - :asset/confirm-delete "Вы уверены, что хотите удалить {1}?" - :asset/physical-delete "Также удалить файл (обратите внимание, что его нельзя будет восстановить)" - :color/gray "Серый" - :color/red "Красный" - :color/yellow "Желтый" - :color/green "Зеленый" - :color/blue "Синий" - :color/purple "Фиолетовый" - :color/pink "Розовый" - :editor/copy "Копировать" - :editor/cut "Вырезать" - :editor/expand-block-children "Раскрыть всё" - :editor/collapse-block-children "Свернуть всё" - :editor/delete-selection "Удалить выбранные блоки" - :editor/cycle-todo "Изменить статус TODO текущего элемента" - :dev/show-page-data "(Dev) Показать данные страницы" - :dev/show-block-data "(Dev) Показать данные блока" - :dev/show-block-ast "(Dev) Показать AST блока" - :dev/show-page-ast "(Dev) Показать AST страницы" - :content/copy-export-as "Копировать / Экспортировать как.." - :content/copy-block-url "Копировать URL блока" - :content/copy-block-ref "Копировать ссылку блока" - :content/copy-block-emebed "Копировать встроенный блок" - :content/copy-ref "Скопировать эту ссылку" - :content/delete-ref "Удалить эту ссылку" - :content/replace-with-text "Заменить на текст" - :content/replace-with-embed "Заменить на встроенный элемент" - :content/open-in-sidebar "Открыть в боковой панели" - :content/click-to-edit "Нажмите для редактирования" - :context-menu/make-a-flashcard "Создать карточку" - :context-menu/toggle-number-list "Переключить номерной список" - :context-menu/preview-flashcard "Предварительный просмотр карточки" - :context-menu/make-a-template "Создать шаблон" - :context-menu/input-template-name "Как назовём шаблон?" - :context-menu/template-include-parent-block "Включить родительский блок в шаблон?" - :context-menu/template-exists-warning "Шаблон уже существует!" - :settings-page/git-confirm "Необходимо перезапустить приложение после изменения настроек Git." - :settings-page/git-switcher-label "Включить автокоммит в Git" - :settings-page/git-commit-delay "Задержка автокоммита Git в секундах" - :settings-page/edit-config-edn "Редактировать config.edn" - :settings-page/edit-global-config-edn "Редактировать глобальный config.edn" - :settings-page/edit-custom-css "Редактировать custom.css" - :settings-page/edit-export-css "Редактировать export.css" - :settings-page/edit-setting "Редактировать" - :settings-page/custom-configuration "Настройки пользователя" - :settings-page/custom-global-configuration "Глобальные настройки пользователя" - :settings-page/custom-theme "Тема пользователя" - :settings-page/export-theme "Экспорт темы" - :settings-page/show-brackets "Показывать скобки" - :settings-page/spell-checker "Проверка орфографии" - :settings-page/auto-updater "Обновлять автоматически" - :settings-page/disable-sentry "Отправлять данные использования и диагностики в Logseq" - :settings-page/disable-sentry-desc "Logseq никогда не будет собирать вашу локальную базу данных графов или продавать ваши данные" - :settings-page/preferred-outdenting "Логические отступы" - :settings-page/show-full-blocks "Показать все строки в ссылке на блок" - :settings-page/auto-expand-block-refs "Автоматически раскрывать ссылки на блок при увеличении масштаба" - :settings-page/custom-date-format "Формат даты" - :settings-page/custom-date-format-warning "Требуется переиндексация! Существующие ссылки на журналы будут нарушены!" - :settings-page/preferred-file-format "Предпочитаемый формат файлов" - :settings-page/preferred-workflow "Предпочтительный рабочий процесс" - :settings-page/preferred-pasting-file "Предпочтительнее вставлять файл" - :settings-page/enable-shortcut-tooltip "Всплывающие подсказки горячих клавиш" - :settings-page/enable-timetracking "Отслеживание времени" - :settings-page/enable-tooltip "Всплывающие подсказки" - :settings-page/enable-journals "Журналы" - :settings-page/enable-all-pages-public "При публикации все страницы становятся публичными" - :settings-page/customize-shortcuts "Сочетания клавиш" - :settings-page/shortcut-settings "Настроить горячие клавиши" - :settings-page/home-default-page "Установить домашнюю страницу по умолчанию" - :settings-page/enable-block-time "Временные метки блока" - :settings-page/clear-cache "Очистить кэш" - :settings-page/clear "Очистить" - :settings-page/clear-cache-warning "Очистка кэша приведет к удалению открытых графов. Вы потеряете несохраненные изменения." - :settings-page/developer-mode "Режим разработчика" - :settings-page/developer-mode-desc "Режим разработчика помогает людям, участвующим в разработке расширений, более эффективно тестировать свои интеграции с Logseq" - :settings-page/current-version "Версия" - :settings-page/tab-general "Общие" - :settings-page/tab-editor "Редактор" - :settings-page/tab-version-control "Управление версиями" - :settings-page/tab-advanced "Продвинутые" - :settings-page/tab-assets "Объекты" - :settings-page/tab-features "Особенные" - :settings-page/plugin-system "Расширения" - :settings-page/enable-flashcards "Карточки" - :settings-page/network-proxy "Прокси-сервер" - :settings-page/filename-format "Формат имени файла" - :settings-page/alpha-features "Альфа-функции" - :settings-page/beta-features "Бета-функции" - :settings-page/login-prompt "Чтобы получить доступ к новым функциям раньше других, вы должны быть открытым коллективным спонсором или сторонником Logseq и, следовательно, войти в систему первым." - :settings-page/sync "Синхронизация" - :settings-page/enable-whiteboards "Интерактивные доски" - :yes "Да" +{:accessibility/skip-to-main-content "Перейти к основному содержимому" + :tutorial/text #resource "tutorials/tutorial-ru.md" + :tutorial/dummy-notes #resource "tutorials/dummy-notes-ru.md" + :on-boarding/demo-graph "Это демонстрационный граф, изменения не будут сохранены, пока вы не откроете локальный файл." + :on-boarding/add-graph "Добавить новый граф" + :on-boarding/open-local-dir "Открыть локальный каталог" + :on-boarding/new-graph-desc-1 "Logseq поддерживает Markdown и Org-mode. Вы можете открыть существующий каталог или создать новый на вашем устройства, каталог также можно назвать просто папкой. Ваши данные будут храниться только на вашем устройстве." + :on-boarding/new-graph-desc-2 "После того, как вы укажете каталог, в нём будут созданы три папки:" + :on-boarding/new-graph-desc-3 "/journals - хранит страницы ваших журналов" + :on-boarding/new-graph-desc-4 "/pages - хранит остальные страницы" + :on-boarding/new-graph-desc-5 "/logseq - хранит конфигурации, custom.css, и другие метаданные." + :on-boarding/welcome-whiteboard-modal-title "Новый холст для ваших мыслей." + :on-boarding/welcome-whiteboard-modal-description "Интерактивные доски - отличный инструмент для мозгового штурма и самоорганизации. Теперь вы можете разместить любые свои мысли из базы знаний или новые мысли рядом друг с другом на пространственном холсте, чтобы соединить, ассоциировать и понять по-новому" + :on-boarding/welcome-whiteboard-modal-skip "Пропустить" + :on-boarding/welcome-whiteboard-modal-start "Начать работу с интерактивной доской" + :on-boarding/tour-whiteboard-home "{1} Дом для ваших интерактивных досок" + :on-boarding/tour-whiteboard-home-description "Интерактивные доски имеют свой собственный раздел в приложении, где их сразу можно увидеть, создать новые или удалить." + :on-boarding/tour-whiteboard-new "{1} Создать новую интерактивную доску" + :on-boarding/tour-whiteboard-new-description "Существует несколько способов создания новой интерактивной доски. Один из них всегда находится прямо здесь, на панели управления." + :help/title-usage "Использование" + :help/title-community "Сообщество" + :help/title-development "Разработка" + :help/title-about "О нас" + :help/title-terms "Условия и положения" + :help/start "Начало работы" + :help/about "О Logseq" + :help/roadmap "Дорожная карта" + :help/bug "Сообщить об ошибке" + :help/feature "Предложить улучшение" + :help/changelog "Список изменений" + :help/blog "Блог Logseq" + :help/docs "Документация" + :help/privacy "Политика конфиденциальности" + :help/terms "Условия" + :help/forum-community "Форум сообщества" + :help/awesome-logseq "Потрясающий Logseq" + :help/shortcuts "Сочетания клавиш" + :help/shortcuts-triggers "Действия" + :help/shortcut "Горячие клавиши" + :help/slash-autocomplete "Слэш - автодополнение" + :help/block-content-autocomplete "Блок контента - автодополнение" + :help/reference-autocomplete "Автодополнение ссылок на страницу" + :help/block-reference "Ссылка на блок" + :help/open-link-in-sidebar "Открыть ссылку на боковой панели" + :more "Больше" + :search/result-for "Искать результат для " + :search/items "элементы" + :search/page-names "Искать имена страниц" + :search/recent "История поиска" + :search/blocks-in-page "Поиск блоков на странице:" + :search/cache-outdated "Кэш устарел. Пожалуйста, нажмите кнопку 'Переиндексировать' в выпадающем меню графов." + :search-item/whiteboard "Интерактивная доска" + :search-item/page "Страница" + :search-item/file "Файл" + :search-item/block "Блок" + :help/context-menu "Контекстное меню блока" + :help/markdown-syntax "Markdown синтаксис" + :help/org-mode-syntax "Org-mode синтаксис" + :bold "Жирный" + :italics "Курсив" + :highlight "Выделение" + :strikethrough "Перечёркнутый" + :code "Код" + :untitled "Без названия" + :right-side-bar/help "Справка" + :right-side-bar/switch-theme "Тема" + :right-side-bar/contents "Содержание" + :right-side-bar/page-graph "Граф страницы" + :right-side-bar/history "(Dev) Отменить/Повторить историю" + :right-side-bar/block-ref "Ссылка на блок" + :right-side-bar/graph-view "Визуальный граф" + :right-side-bar/all-pages "Все страницы" + :right-side-bar/whiteboards "Интерактивные доски" + :right-side-bar/flashcards "Карточки" + :right-side-bar/new-page "Новая страница" + :right-side-bar/show-journals "Показать журналы" + :right-side-bar/separator "Изменение размера правой боковой панели" + :right-side-bar/toggle-right-sidebar "Переключить правую панель" + :left-side-bar/journals "Журналы" + :left-side-bar/create "Создать" + :left-side-bar/new-page "Новая страница" + :left-side-bar/new-whiteboard "Новая интерактивная доска" + :left-side-bar/nav-favorites "Избранное" + :left-side-bar/nav-recent-pages "Недавнее" + :page/something-went-wrong "Что-то пошло не так" + :page/logseq-is-having-a-problem "У Logseq возникла проблема. Чтобы попытаться вернуть его в рабочее состояние, пожалуйста, попробуйте выполнить следующие безопасные шаги по порядку:" + :page/step "Шаг {1}" + :page/try "Попробовать" + :page/presentation-mode "Презентация" + :page/delete-confirmation "Вы уверены, что хотите удалить эту страницу и её файл(ы)?" + :page/open-in-finder "Открыть в каталоге" + :page/open-with-default-app "Открыть в приложении по умолчанию" + :page/make-public "Сделать доступной для публикации" + :page/version-history "Просмотр истории страницы" + :page/open-backup-directory "Открыть каталог резервных копий" + :page/make-private "Сделать приватной" + :page/delete "Удалить страницу" + :page/add-to-favorites "Добавить в Избранное" + :page/unfavorite "Удалить из Избранного" + :page/show-journals "Показать журналы" + :page/show-whiteboards "Показать интерактивные доски" + :block/name "Имя страницы" + :page/earlier "Ранее" + :page/copy-page-url "Копировать URL страницы" + :page/illegal-page-name "Недопустимое название страницы!" + :page/page-already-exists "Страница “{1}” уже существует!" + :page/whiteboard-to-journal-error "Страницы интерактивной доски не могут быть переименованы в названия журналов!" + :file/name "Имя файла" + :file/last-modified-at "Последнее изменение" + :file/no-data "Нет данных" + :file/format-not-supported "Расширение .{1} не поддерживается." + :file/validate-existing-file-error "Страница уже существует с другим файлом: {1}, текущий файл: {2}. Пожалуйста, оставьте только один из них и переиндексируйте ваш граф." + :file-rn/re-index "Настоятельно рекомендуется выполнить переиндексацию после переименования файлов и синхронизации на других устройствах." + :file-rn/need-action "Предлагается выполнить действия по переименованию файлов, чтобы они соответствовали новому формату. Переиндексация требуется на всех устройствах после синхронизации переименованных файлов." + :file-rn/or-select-actions " или переименовать файлы ниже по отдельности, затем " + :file-rn/or-select-actions-2 ". Эти действия будут недоступны после закрытия этой панели." + :file-rn/legend "🟢 Необязательные действия по переименованию; 🟡 Действие по переименованию, необходимое для предотвращения изменения заголовка; 🔴 Обязательное изменение." + :file-rn/close-panel "Закрыть панель" + :file-rn/all-action "Применить все действия! ({1})" + :file-rn/select-format "(Опция режима разработчика. Опасно!) Выберите формат имени файла" + :file-rn/rename "Переименовать файл \"{1}\" в \"{2}\"" + :file-rn/apply-rename "Применить операцию переименования файла" + :file-rn/suggest-rename "Требуется действие: " + :file-rn/otherwise-breaking "Или заголовок станет" + :file-rn/no-action "Отлично! Дальнейших действий не требуется." + :file-rn/confirm-proceed "Обновить формат!" + :file-rn/select-confirm-proceed "Dev: формат записи" + :file-rn/unreachable-title "Внимание! Имя страницы станет {1} при текущем формате имени файла, если `title::` не задано вручную" + :file-rn/optional-rename "Предложение: " + :file-rn/format-deprecated "В настоящее время вы используете устаревший формат. Настоятельно рекомендуется обновить формат до последней версии. Пожалуйста, создайте резервную копию данных и закройте клиенты Logseq на других устройствах перед началом операции." + :file-rn/filename-desc-1 "Этот параметр определяет способ сохранения страницы в файл. Logseq сохраняет страницу в файл с таким же именем." + :file-rn/filename-desc-2 "Некоторые символы, такие как \"/\" или \"?\" недопустимы для имени файла." + :file-rn/filename-desc-3 "Logseq заменяет недопустимые символы их эквивалентом в кодировке URL, чтобы сделать их допустимыми (например, \"?\" становится \"%3F\")." + :file-rn/filename-desc-4 "Разделитель пространства имен \"/\" также заменяется на \"___\" (тройное подчеркивание) из эстетических соображений." + :file-rn/instruct-1 "Этот процесс обновления формата имен файлов состоит из двух этапов:" + :file-rn/instruct-2 "1. Нажмите " + :file-rn/instruct-3 "2. Следуйте приведенным ниже инструкциям, чтобы переименовать файлы в новый формат:" + :page/created-at "Создана" + :page/updated-at "Обновлена" + :page/backlinks "Обратные ссылки" + :linked-references/filter-search "Поиск в связанных страницах" + :editor/block-search "Поиск блока" + :text/image "Изображение" + :asset/show-in-folder "Показать изображение в папке" + :asset/open-in-browser "Открыть изображение в браузере" + :asset/delete "Удалить изображение" + :asset/copy "Копировать изображение" + :asset/maximize "Увеличить изображение" + :asset/confirm-delete "Вы уверены, что хотите удалить {1}?" + :asset/physical-delete "Также удалить файл (обратите внимание, что его нельзя будет восстановить)" + :color/gray "Серый" + :color/red "Красный" + :color/yellow "Желтый" + :color/green "Зеленый" + :color/blue "Синий" + :color/purple "Фиолетовый" + :color/pink "Розовый" + :editor/copy "Копировать" + :editor/cut "Вырезать" + :editor/expand-block-children "Раскрыть всё" + :editor/collapse-block-children "Свернуть всё" + :editor/delete-selection "Удалить выбранные блоки" + :editor/cycle-todo "Сменить статус задачи текущего элемента" + :dev/show-page-data "(Dev) Показать данные страницы" + :dev/show-block-data "(Dev) Показать данные блока" + :dev/show-block-ast "(Dev) Показать AST блока" + :dev/show-page-ast "(Dev) Показать AST страницы" + :content/copy-export-as "Копировать / Экспортировать как..." + :content/copy-block-url "Копировать URL блока" + :content/copy-block-ref "Копировать ссылку блока" + :content/copy-block-emebed "Копировать встраиваемый блок" + :content/copy-ref "Копировать ссылку" + :content/delete-ref "Удалить эту ссылку" + :content/replace-with-text "Заменить на текст" + :content/replace-with-embed "Заменить на встраиваемый элемент" + :content/open-in-sidebar "Открыть на боковой панели" + :content/click-to-edit "Нажмите для редактирования" + :context-menu/make-a-flashcard "Создать карточку" + :context-menu/toggle-number-list "Переключить формат нумерованного списка" + :context-menu/preview-flashcard "Предварительный просмотр карточки" + :context-menu/make-a-template "Создать шаблон" + :context-menu/input-template-name "Как назовём шаблон?" + :context-menu/template-include-parent-block "Включить родительский блок в шаблон?" + :context-menu/template-exists-warning "Шаблон уже существует!" + :settings-page/git-confirm "Необходимо перезапустить приложение после изменения настроек Git." + :settings-page/git-switcher-label "Включить автокоммит в Git" + :settings-page/git-commit-delay "Задержка автокоммита Git в секундах" + :settings-page/edit-config-edn "Редактировать config.edn" + :settings-page/edit-global-config-edn "Редактировать глобальный config.edn" + :settings-page/edit-custom-css "Редактировать custom.css" + :settings-page/edit-export-css "Редактировать export.css" + :settings-page/edit-setting "Редактировать" + :settings-page/custom-configuration "Пользовательская конфигурация" + :settings-page/custom-global-configuration "Глобальная пользовательская конфигурация" + :settings-page/custom-theme "Пользовательская тема" + :settings-page/export-theme "Экспорт темы" + :settings-page/show-brackets "Показывать скобки" + :settings-page/spell-checker "Проверка орфографии" + :settings-page/auto-updater "Обновлять автоматически" + :settings-page/disable-sentry "Отправлять данные использования и диагностики в Logseq" + :settings-page/disable-sentry-desc "Logseq никогда не будет собирать вашу локальную базу данных графов или продавать ваши данные" + :settings-page/preferred-outdenting "Логические отступы" + :settings-page/preferred-outdenting-tip "С левой стороны показаны отступы с настройкой по умолчанию, а справа - отступы с включённой настройкой. " + :settings-page/preferred-outdenting-tip-more "→ Узнать больше" + :settings-page/show-full-blocks "Показать все строки в ссылке на блок" + :settings-page/auto-expand-block-refs "Автоматически раскрывать ссылки на блок при увеличении масштаба" + :settings-page/auto-expand-block-refs-tip "Этот параметр определяет, следует ли автоматически раскрывать ссылки на блоки при увеличении масштаба." + :settings-page/custom-date-format "Формат даты" + :settings-page/custom-date-format-warning "Требуется переиндексация! Существующие ссылки на журналы будут нарушены!" + :settings-page/preferred-pasting-file-hint "Если функция включена, то при вставке изображения из интернета оно будет загружено и вставлено. При отключении будет вставлена ссылка на изображение." + :settings-page/preferred-file-format "Предпочитаемый формат файлов" + :settings-page/preferred-workflow "Предпочтительный рабочий процесс" + :settings-page/preferred-pasting-file "Предпочтительнее вставлять файл" + :settings-page/enable-shortcut-tooltip "Всплывающие подсказки горячих клавиш" + :settings-page/enable-timetracking "Отслеживание времени" + :settings-page/enable-tooltip "Всплывающие подсказки" + :settings-page/enable-journals "Журналы" + :settings-page/enable-all-pages-public "При публикации все страницы становятся публичными" + :settings-page/customize-shortcuts "Сочетания клавиш" + :settings-page/shortcut-settings "Настроить горячие клавиши" + :settings-page/home-default-page "Установить домашнюю страницу по умолчанию" + :settings-page/enable-block-time "Временные метки блока" + :settings-page/clear-cache "Очистить кэш" + :settings-page/clear "Очистить" + :settings-page/clear-cache-warning "Очистка кэша приведет к удалению открытых графов. Вы потеряете несохраненные изменения." + :settings-page/developer-mode "Режим разработчика" + :settings-page/developer-mode-desc "Режим разработчика помогает людям, участвующим в разработке расширений, более эффективно тестировать свои интеграции с Logseq" + :settings-page/current-version "Версия" + :settings-page/tab-general "Общие" + :settings-page/tab-editor "Редактор" + :settings-page/tab-version-control "Управление версиями" + :settings-page/tab-account "Аккаунт" + :settings-page/tab-advanced "Продвинутые" + :settings-page/tab-assets "Объекты" + :settings-page/tab-features "Функции" + :settings-page/plugin-system "Расширения" + :settings-page/enable-flashcards "Карточки" + :settings-page/network-proxy "Прокси-сервер" + :settings-page/filename-format "Формат имени файла" + :settings-page/alpha-features "Альфа-функции" + :settings-page/beta-features "Бета-функции" + :settings-page/login-prompt "Чтобы получить доступ к новым функциям раньше других, вы должны быть открытым коллективным спонсором или сторонником Logseq и, следовательно, войти в систему первым." + :settings-page/sync "Синхронизация" + :settings-page/enable-whiteboards "Интерактивные доски" + :settings-page/native-titlebar "Встроенная строка заголовка" + :settings-page/native-titlebar-desc "Включить встроенную строку заголовка окна в Windows и Linux." + :settings-page/check-for-updates "Проверить наличие обновлений" + :settings-page/checking "Проверка ..." + :settings-page/revision "Редакция: " + :settings-page/changelog "Что нового?" + :settings-page/app-updated "Приложение обновлено 🎉" + :yes "Да" - :submit "Подтвердить" - :cancel "Отмена" - :close "Закрыть" - :delete "Удалить" - :save "Сохранить" - :type "Тип" - :host "Хост" - :port "Порт" - :re-index "Переиндексация" - :re-index-detail "Переиндексировать граф" - :re-index-multiple-windows-warning "Перед переиндексацией этого графа необходимо закрыть другие окна." - :re-index-discard-unsaved-changes-warning "Переиндексация удалит текущий граф, а затем снова обработает все файлы в том виде, в каком они в данный момент хранятся на диске. Вы потеряете несохраненные изменения, и это может занять некоторое время. Продолжить?" - :open-new-window "Новое окно" - :sync-from-local-files "Обновить" - :sync-from-local-files-detail "Импортировать изменения из локальных файлов" - :sync-from-local-changes-detected "При обновлении будут найдены и обработаны файлы, изменённые на диске и отличающиеся от текущего содержимого страниц Logseq. Продолжить?" - - :search/publishing "Искать" - :search "Искать или создать страницу" - :whiteboard/link-whiteboard-or-block "Ссылка на доску/страницу/блок" - :page-search "Искать на текущей странице" - :graph-search "Искать граф" - :new-page "Новая страница" - :new-whiteboard "Новая интерактивная доска" - :new-graph "Добавить новый граф" - :graph "Граф" - :graph/persist "Logseq синхронизирует внутреннее состояние, пожалуйста, подождите несколько секунд." - :graph/persist-error "Не удалось выполнить внутреннюю синхронизацию состояния." - :graph/save "Сохранение..." - :graph/save-success "Успешно сохранено" - :graph/save-error "Сохранить не удалось" - :graph/all-graphs "Все графы" - :graph/local-graphs "Локальные графы" - :graph/remote-graphs "Удаленные(remote) графы" - :export "Экспорт" - :export-graph "Экспортировать граф" - :export-page "Экспортировать страницу" - :export-markdown "Экспортировать как стандартный Markdown (без свойств блока)" - :export-opml "Экспортировать как OPML" - :export-public-pages "Экспорт публичных страниц" - :export-json "Экспортировать как JSON" - :export-roam-json "Экспортировать как Roam JSON" - :export-edn "Экспортировать как EDN" - :all-graphs "Все графы" - :all-pages "Все страницы" - :all-whiteboards "Все интерактивные доски" - :all-files "Все файлы" - :remove-orphaned-pages "Удалить страницы без родителя" - :all-journals "Все журналы" - :settings "Настройки" - :settings-of-plugins "Расширения" - :plugins "Расширения" - :themes "Темы" - :relaunch-confirm-to-work "Необходимо перезапустить приложение, чтобы оно заработало. Перезапустить его сейчас?" - :import "Импорт" - :importing "Импортирование" - :join-community "Присоединиться к сообществу" - :discourse-title "Наш форум!" - :help-shortcut-title "Нажмите для просмотра горячих клавиш и других советов" - :loading "Загрузка" - :parsing-files "Анализ файлов" - :loading-files "Загрузка файлов" - :login "Вход в систему" - :logout "Выйти" - :download "Скачать" - :language "Язык" - :remove-background "Удалить фон" - :remove-heading "Удалить заголовок" - :heading "Заголовок {1}" - :auto-heading "Автоматический заголовок" - :open-a-directory "Открыть локальный каталог" + :submit "Подтвердить" + :cancel "Отмена" + :close "Закрыть" + :delete "Удалить" + :save "Сохранить" + :type "Тип" + :host "Хост" + :port "Порт" + :re-index "Переиндексация" + :re-index-detail "Переиндексировать граф" + :re-index-multiple-windows-warning "Перед переиндексацией этого графа необходимо закрыть другие окна." + :re-index-discard-unsaved-changes-warning "Переиндексация удалит текущий граф, а затем снова обработает все файлы в том виде, в каком они в данный момент хранятся на диске. Вы потеряете несохраненные изменения, и это может занять некоторое время. Продолжить?" + :open-new-window "Новое окно" + :sync-from-local-files "Обновить" + :sync-from-local-files-detail "Импортировать изменения из локальных файлов" + :sync-from-local-changes-detected "При обновлении будут найдены и обработаны файлы, изменённые на диске и отличающиеся от текущего содержимого страниц Logseq. Продолжить?" + + :search/publishing "Искать" + :search "Искать или создать страницу" + :whiteboard/link-whiteboard-or-block "Ссылка на доску/страницу/блок" + :whiteboard/align-left "Выровнять по левому краю" + :whiteboard/align-center-horizontally "Центрировать по горизонтали" + :whiteboard/align-right "Выровнять по правому краю" + :whiteboard/distribute-horizontally "Распределить по горизонтали" + :whiteboard/align-top "Выровнять по верхнему краю" + :whiteboard/align-center-vertically "Центрировать по вертикали" + :whiteboard/align-bottom "Выровнять по нижнему краю" + :whiteboard/distribute-vertically "Распределить по вертикали" + :whiteboard/pack-into-rectangle "Упаковать в прямоугольник" + :whiteboard/zoom-to-fit "Масштабировать, показав все элементы" + :whiteboard/ungroup "Разгруппировать" + :whiteboard/group "Группировать" + :whiteboard/cut "Вырезать" + :whiteboard/copy "Копировать" + :whiteboard/paste "Вставить" + :whiteboard/paste-as-link "Вставить как ссылку" + :whiteboard/export "Экспорт" + :whiteboard/select-all "Выбрать всё" + :whiteboard/deselect-all "Отменить всё" + :whiteboard/lock "Заблокировать" + :whiteboard/unlock "Разблокировать" + :whiteboard/delete "Удалить" + :whiteboard/flip-horizontally "Отразить по горизонтали" + :whiteboard/flip-vertically "Отразить по вертикали" + :whiteboard/move-to-front "Переместить на передний план" + :whiteboard/move-to-back "Переместить на задний план" + :whiteboard/dev-print-shape-props "(Dev) Вывести свойства элемента" + :whiteboard/auto-resize "Автоматическое изменение размера" + :whiteboard/expand "Раскрыть" + :whiteboard/collapse "Свернуть" + :whiteboard/website-url "URL-адрес сайта" + :whiteboard/reload "Перезагрузить" + :whiteboard/open-website-url "Открыть URL-адрес сайта" + :whiteboard/youtube-url "URL-адрес YouTube" + :whiteboard/open-youtube-url "Открыть URL-адрес YouTube" + :whiteboard/twitter-url "URL-адрес Twitter" + :whiteboard/open-twitter-url "Открыть URL-адрес Twitter" + :whiteboard/fill "Заливка" + :whiteboard/stroke-type "Тип обводки" + :whiteboard/arrow-head "Тип указателя" + :whiteboard/bold "Жирный" + :whiteboard/italic "Курсив" + :whiteboard/undo "Отменить" + :whiteboard/redo "Вернуть" + :whiteboard/zoom-in "Увеличить" + :whiteboard/zoom-out "Уменьшить" + :whiteboard/select "Выделение" + :whiteboard/pan "Рука" + :whiteboard/add-block-or-page "Добавить блок или страницу" + :whiteboard/draw "Рисовать" + :whiteboard/highlight "Маркер" + :whiteboard/eraser "Ластик" + :whiteboard/connector "Соединительная стрелка" + :whiteboard/text "Текст" + :whiteboard/color "Цвет" + :whiteboard/select-custom-color "Выбрать пользовательский цвет" + :whiteboard/opacity "Непрозрачность" + :whiteboard/extra-small "Очень маленький" + :whiteboard/small "Маленький" + :whiteboard/medium "Средний" + :whiteboard/large "Большой" + :whiteboard/extra-large "Очень большой" + :whiteboard/huge "Огромный" + :whiteboard/scale-level "Изменение размера" + :whiteboard/rectangle "Прямоугольник" + :whiteboard/circle "Круг" + :whiteboard/triangle "Треугольник" + :whiteboard/shape "Фигура" + :whiteboard/open-page "Открыть страницу" + :whiteboard/open-page-in-sidebar "Открыть страницу на боковой панели" + :whiteboard/remove-link "Удалить ссылку" + :whiteboard/link "Ссылка" + :whiteboard/references "Связанные страницы" + :whiteboard/link-to-any-page-or-block "Ссылка на любую страницу или блок" + :whiteboard/start-typing-to-search "Начните вводить текст для поиска..." + :whiteboard/new-block-no-colon "Новый блок" + :whiteboard/new-block "Новый блок:" + :whiteboard/new-page "Новая страница:" + :whiteboard/new-whiteboard "Новая интерактивная доска" + :whiteboard/search-only-blocks "Поиск только по блокам" + :whiteboard/search-only-pages "Поиск только по страницам" + :whiteboard/cache-outdated "Кэш устарел. Пожалуйста, нажмите кнопку 'Переиндексировать' в выпадающем меню графов." + :whiteboard/shape-quick-links "Быстрые ссылки элемента" + :page-search "Искать на текущей странице" + :graph-search "Искать граф" + :home "Домой" + :new-page "Новая страница:" + :whiteboard "Интерактивная доска" + :whiteboards "Интерактивные доски" + :new-whiteboard "Новая интерактивная доска:" + :new-graph "Добавить новый граф" + :graph "Граф" + :graph/persist "Logseq синхронизирует внутреннее состояние, пожалуйста, подождите несколько секунд." + :graph/persist-error "Не удалось выполнить внутреннюю синхронизацию состояния." + :graph/save "Сохранение..." + :graph/save-success "Успешно сохранено" + :graph/save-error "Сохранить не удалось" + :graph/all-graphs "Все графы" + :graph/local-graphs "Локальные графы:" + :graph/remote-graphs "Удаленные(remote) графы:" + :export "Экспорт" + :export-graph "Экспортировать граф" + :export-page "Экспортировать страницу" + :export-markdown "Экспортировать как стандартный Markdown (без свойств блока)" + :export-opml "Экспортировать как OPML" + :export-public-pages "Экспорт публичных страниц" + :export-json "Экспортировать как JSON" + :export-roam-json "Экспортировать как Roam JSON" + :export-edn "Экспортировать как EDN" + :all-graphs "Все графы" + :all-pages "Все страницы" + :all-whiteboards "Все интерактивные доски" + :all-files "Все файлы" + :remove-orphaned-pages "Удалить страницы без родителя?" + :all-journals "Все журналы" + :settings "Настройки" + :settings-of-plugins "Расширения" + :plugins "Расширения" + :themes "Темы" + :relaunch-confirm-to-work "Необходимо перезапустить приложение, чтобы изменения вступили в силу. Перезапустить сейчас?" + :import "Импорт" + :importing "Импортирование" + :join-community "Присоединиться к сообществу" + :discourse-title "Наш форум!" + :help-shortcut-title "Нажмите для просмотра горячих клавиш и других советов" + :loading "Загрузка..." + :parsing-files "Анализ файлов" + :loading-files "Загрузка файлов" + :login "Вход" + :logout "Выйти" + :logout-user "Выйти ({1})" + :download "Скачать" + :language "Язык" + :remove-background "Удалить фон" + :remove-heading "Удалить заголовок" + :heading "Заголовок {1}" + :auto-heading "Автоматический заголовок" + :open-a-directory "Открыть локальный каталог" + :toggle-theme "Переключить тему" - :help/shortcut-page-title "Сочетания клавиш" + :help/shortcut-page-title "Сочетания клавиш" - :plugin/installed "Установлено" - :plugin/not-installed "Не установлено" - :plugin/installing "Установка" - :plugin/install "Установить" - :plugin/reload "Перезагрузить" - :plugin/update "Обновить" - :plugin/check-update "Проверить обновления" - :plugin/check-all-updates "Проверить все обновления" - :plugin/found-updates "Новые обновления" - :plugin/found-n-updates "Найдено обновлений {1}" - :plugin/update-all-selected "Обновить все выбранные" - :plugin/updates-downloading "Загрузка обновлений" - :plugin/refresh-lists "Обновить списки" - :plugin/enabled "Включено" - :plugin/disabled "Отключено" - :plugin/update-available "Доступно обновление" - :plugin/updating "Обновление" - :plugin/uninstall "Удаление" - :plugin/marketplace "Каталог расширений" - :plugin/downloads "Загрузки" - :plugin/stars "Звёзды" - :plugin/title "Название" - :plugin/all "Все" - :plugin/unpacked "Распаковано" - :plugin/delete-alert "Вы уверены, что хотите удалить расширение [{1}]?" - :plugin/open-settings "Открыть настройки" - :plugin/open-package "Открыть пакет" - :plugin/load-unpacked "Загрузить распакованное расширение" - :plugin/restart "Перезапустить приложение" - :plugin/unpacked-tips "Выбрать папку для расширений" - :plugin/contribute "✨ Написать и отправить новое расширение" - :plugin/up-to-date "Обновлено" - :plugin/custom-js-alert "Найден файл custom.js, выполнить его? (Если вы не понимаете содержание этого файла, рекомендуется не разрешать его выполнение, поскольку оно сопряжено с определенными рисками для безопасности)." - :plugin.install-from-file/menu-title "Установить из plugins.edn" - :plugin.install-from-file/title "Установить расширения из plugins.edn" - :plugin.install-from-file/notice "Следующие плагины заменят ваши плагины:" - :plugin.install-from-file/success "Все расширения установлены!" + :plugin/installed "Установлено" + :plugin/installed-plugin "Установлено расширение: {1}" + :plugin/not-installed "Не установлено" + :plugin/installing "Установка" + :plugin/install "Установить" + :plugin/reload "Перезагрузить" + :plugin/update "Обновить" + :plugin/update-plugin "Обновлено расширение: {1} - {2}" + :plugin/check-update "Проверить обновления" + :plugin/check-all-updates "Проверить все обновления" + :plugin/found-updates "Новые обновления" + :plugin/found-n-updates "Найдено обновлений: {1}" + :plugin/update-all-selected "Обновить выбранные" + :plugin/all-updated "Все расширения обновлены!" + :plugin/updates-downloading "Загрузка обновлений" + :plugin/refresh-lists "Обновить списки" + :plugin/enabled "Включено" + :plugin/disabled "Отключено" + :plugin/update-available "Доступно обновление" + :plugin/updating "Обновление" + :plugin/uninstall "Удаление" + :plugin/marketplace "Каталог расширений" + :plugin/downloads "Загрузки" + :plugin/stars "Звёзды" + :plugin/title "Название ({1})" + :plugin/all "Все" + :plugin/unpacked "Распаковано" + :plugin/delete-alert "Вы уверены, что хотите удалить расширение [{1}]?" + :plugin/open-settings "Открыть настройки" + :plugin/open-package "Открыть пакет" + :plugin/load-unpacked "Загрузить распакованное расширение" + :plugin/restart "Перезапустить приложение" + :plugin/unpacked-tips "Выбрать папку для расширений" + :plugin/contribute "✨ Написать и отправить новое расширение" + :plugin/up-to-date "Обновлено {1}" + :plugin/custom-js-alert "Найден файл custom.js, выполнить его? (Если вы не понимаете содержание этого файла, рекомендуется не разрешать его выполнение, поскольку оно сопряжено с определенными рисками для безопасности)." + :plugin/security-warning "Расширения могут получать доступ к вашему графу и локальным файлам, а также отправлять сетевые запросы. Кроме того, они могут стать причиной повреждения или потери данных. Мы работаем над наилучшими правилами доступа к вашим графам. Тем не менее, убедитесь, что у вас имеются регулярные резервные копии ваших графов. Старайтесь устанавливать расширения только тогда, когда вы можете прочитать и понять исходный код." + :plugin/search-plugin "Найти расширения" + :plugin/open-preferences "Открыть настройки" + :plugin/open-logseq-dir "Открыть" + :plugin/remote-error "Сетевая ошибка: " + :plugin/checking-for-updates "Проверка обновлений расширения..." + :plugin/list-of-updates "Обновления расширений: " + :plugin.install-from-file/menu-title "Установить из plugins.edn" + :plugin.install-from-file/title "Установить расширения из plugins.edn" + :plugin.install-from-file/notice "Следующие расширения заменят уже установленные:" + :plugin.install-from-file/success "Все расширения установлены!" - :pdf/copy-ref "Копировать ссылку" - :pdf/copy-text "Копировать текст" - :pdf/linked-ref "Связанные ссылки" - :pdf/toggle-dashed "Пунктирный стиль для выделения области" - :pdf/hl-block-colored "Цветная метка для выделенного блока" - :pdf/doc-metadata "Метаданные документа" + :pdf/copy-ref "Копировать ссылку" + :pdf/copy-text "Копировать текст" + :pdf/linked-ref "Связанные ссылки" + :pdf/toggle-dashed "Пунктирный стиль для выделения области" + :pdf/hl-block-colored "Цветная метка для выделенного блока" + :pdf/doc-metadata "Метаданные документа" - :updater/new-version-install "Была загружена новая версия" - :updater/quit-and-install "Перезапустить для установки" + :updater/new-version-install "Была загружена новая версия" + :updater/quit-and-install "Перезапустить для установки" - :paginates/pages "Всего {1} страниц(а)" - :paginates/prev "Предыдущая" - :paginates/next "Следующая" + :paginates/pages "Всего {1} страниц(а)" + :paginates/prev "Предыдущая" + :paginates/next "Следующая" - :tips/all-done "Всё готово" + :tips/all-done "Всё готово!" - :command-palette/prompt "Введите команду" - :select/default-prompt "Выберите" - :select/default-select-multiple "Выберите один или несколько" - :select.graph/prompt "Выберите граф" - :select.graph/empty-placeholder-description "Нет подходящих графов. Хотите добавить другой?" - :select.graph/add-graph "Да, добавить другой граф" + :command-palette/prompt "Введите команду" + :select/default-prompt "Выберите" + :select/default-select-multiple "Выберите один или несколько" + :select.graph/prompt "Выберите граф" + :select.graph/empty-placeholder-description "Нет подходящих графов. Хотите добавить другой?" + :select.graph/add-graph "Да, добавить другой граф" - :file-sync/other-user-graph "Текущий локальный граф привязан к удаленному графу другого пользователя. Поэтому синхронизацию начать нельзя." - :file-sync/graph-deleted "Текущий удаленный граф был удален" - :file-sync/rsapi-cannot-upload-err "Невозможно начать синхронизацию, пожалуйста, проверьте правильное ли установлено локальное время." + :file-sync/other-user-graph "Текущий локальный граф привязан к удаленному графу другого пользователя. Поэтому синхронизацию начать нельзя." + :file-sync/graph-deleted "Текущий удаленный граф был удален" + :file-sync/rsapi-cannot-upload-err "Не удалось начать синхронизацию, пожалуйста, проверьте, правильно ли установлено локальное время." - :notification/clear-all "Очистить всё" + :notification/clear-all "Очистить всё" - :shortcut.category/basics "Базовые" - :shortcut.category/formatting "Форматирование" - :shortcut.category/navigating "Навигация" - :shortcut.category/block-editing "Общее редактирование блока" - :shortcut.category/block-command-editing "Команды редактирования блока" - :shortcut.category/block-selection "Выделение блоков (нажмите Esc для отмены)" - :shortcut.category/toggle "Переключатели" - :shortcut.category/whiteboard "Интерактивная доска" - :shortcut.category/others "Разное" - :command.date-picker/complete "Выбор даты: Выбрать указанный день" - :command.date-picker/prev-day "Выбор даты: Выбрать предыдущий день" - :command.date-picker/next-day "Выбор даты: Выбрать следующий день" - :command.date-picker/prev-week "Выбор даты: Выбрать предыдущую неделю" - :command.date-picker/next-week "Выбор даты: Выбрать следующую неделю" - :command.pdf/previous-page "PDF: Предыдущая страница текущего PDF" - :command.pdf/next-page "PDF: Следующая страница текущего PDF" - :command.pdf/close "PDF: Закрыть текущий просмотр PDF" - :command.pdf/find "PDF: Поиск текста в текущем PDF-документе" - :command.auto-complete/complete "Автодополнение: Использовать выбранный элемент" - :command.auto-complete/prev "Автодополнение: Выбрать предыдущий" - :command.auto-complete/next "Автодополнение: Выбрать следующий" - :command.auto-complete/shift-complete "Автодополнение: Открыть выбранный элемент в боковой панели" - :command.auto-complete/open-link "Автодополнение: Открыть выбранный элемент в браузере" - :command.cards/toggle-answers "Карточки: показать/скрыть ответы/clozes" - :command.cards/next-card "Карточки: следующая карточка" - :command.cards/forgotten "Карточки: забытая" - :command.cards/remembered "Карточки: запомненная" - :command.cards/recall "Карточки: нужно время, чтобы вспомнить" - :command.editor/escape-editing "Выйти из режима редактирования" - :command.editor/backspace "Удалить перед курсором" - :command.editor/delete "Удалить после курсора" - :command.editor/new-block "Создать новый блок" - :command.editor/new-line "Новая строка в блоке" - :command.editor/new-whiteboard "Новая интерактивная доска" - :command.editor/follow-link "Перейти по ссылке под курсором" - :command.editor/open-link-in-sidebar "Открыть ссылку в боковой панели" - :command.editor/bold "Жирный" - :command.editor/italics "Курсив" - :command.editor/highlight "Выделение" - :command.editor/strike-through "Перечёркнутый" - :command.editor/clear-block "Удалить содержимое блока" - :command.editor/kill-line-before "Удалить строку до курсора" - :command.editor/copy-embed "Копировать вставку, ссылающуюся на текущий блок" - :command.editor/kill-line-after "Удалить строку после курсора" - :command.editor/beginning-of-block "Переместить курсор в начало блока" - :command.editor/end-of-block "Переместить курсор в конец блока" - :command.editor/forward-word "Переместить курсор на одно слово вперед" - :command.editor/backward-word "Переместить курсор на одно слово назад" - :command.editor/forward-kill-word "Удалить следующее слово" - :command.editor/backward-kill-word "Удалить предыдущее слово" - :command.editor/replace-block-reference-at-point "Заменить ссылку на блок своим содержимым в указанном месте" - :command.editor/paste-text-in-one-block-at-point "Вставить текст в один блок в указанном месте" - :command.editor/insert-youtube-timestamp "Вставить временную метку на Youtube" - :command.editor/cycle-todo "Изменить статус TODO текущего элемента" - :command.editor/up "Переместить курсор вверх / Выбрать вверх" - :command.editor/down "Переместить курсор вниз / Выбрать вниз" - :command.editor/left "Переместить курсор влево / Открыть выбранный блок в начале" - :command.editor/right "Переместить курсор вправо / Открыть выбранный блок в конце" - :command.editor/select-up "Выбрать контент выше" - :command.editor/select-down "Выбрать контент ниже" - :command.editor/move-block-up "Передвинуть блок выше" - :command.editor/move-block-down "Передвинуть блок ниже" - :command.editor/open-edit "Редактировать выбранный блок" - :command.editor/select-block-up "Выбрать блок выше" - :command.editor/select-block-down "Выбрать блок ниже" - :command.editor/delete-selection "Удалить выбранные блоки" - :command.editor/expand-block-children "Раскрыть" - :command.editor/collapse-block-children "Свернуть" - :command.editor/indent "Увеличить отступ блока" - :command.editor/outdent "Уменьшить отступ блока" - :command.editor/copy "Копировать (выделенное либо ссылку на блок)" - :command.editor/copy-text "Копировать как текст" - :command.editor/cut "Вырезать" - :command.editor/undo "Отменить" - :command.editor/redo "Вернуть" - :command.editor/insert-link "HTML ссылка" - :command.editor/select-all-blocks "Выбрать все блоки" - :command.editor/select-parent "Выбрать родительский блок" - :command.editor/zoom-in "Увеличить / Вперед" - :command.editor/zoom-out "Уменьшить / Назад" - :command.editor/toggle-undo-redo-mode "Переключить режим отменить/повторить (глобально или только на странице)" - :command.editor/toggle-number-list "Переключить режим нумерованный список" - :command.whiteboard/select "Выбрать инструмент" - :command.whiteboard/pan "Прокруктка" - :command.whiteboard/portal "Добавить блок или страницу" - :command.whiteboard/pencil "Карандаш" - :command.whiteboard/highlighter "Маркер" - :command.whiteboard/eraser "Ластик" - :command.whiteboard/connector "Соединитель" - :command.whiteboard/text "Текст" - :command.whiteboard/rectangle "Прямоугольник" - :command.whiteboard/ellipse "Эллипс" - :command.whiteboard/reset-zoom "Сбросить масштаб" - :command.whiteboard/zoom-to-fit "Показать все элементы" - :command.whiteboard/zoom-to-selection "Показать элемент" - :command.whiteboard/zoom-out "Уменьшить" - :command.whiteboard/zoom-in "Увеличить" - :command.whiteboard/send-backward "Переместить назад" - :command.whiteboard/send-to-back "На задний план" - :command.whiteboard/bring-forward "Переместить вперёд" - :command.whiteboard/bring-to-front "На передний план" - :command.whiteboard/lock "Блокировать" - :command.whiteboard/unlock "Разблокировать" - :command.whiteboard/group "Группировать" - :command.whiteboard/ungroup "Разгруппировать" - :command.whiteboard/toggle-grid "Переключить отображение сетки" - :command.ui/toggle-brackets "Переключить отображение скобок" - :command.go/search-in-page "Поиск блоков на текущей странице" - :command.go/electron-find-in-page "Поиск текста на странице" - :command.go/electron-jump-to-the-next "Перейти к следующему совпадению в строке поиска" - :command.go/electron-jump-to-the-previous "Перейти к предыдущему совпадению в строке поиска" - :command.go/search "Поиск страниц и блоков" - :command.go/journals "Перейти в журналы" - :command.go/backward "Назад" - :command.go/forward "Вперёд" - :command.search/re-index "Переиндексация поиска" - :command.sidebar/open-today-page "Открыть сегодняшнюю страницу в правой боковой панели" - :command.sidebar/close-top "Закрыть верхний элемент в правой боковой панели" - :command.sidebar/clear "Очистить правую панель" - :command.misc/copy "mod+c" - :command.command-palette/toggle "Показать палитру команд" - :command.graph/export-as-html "Экспорт публичных страниц графов в формате html" - :command.graph/open "Выберите граф для открытия" - :command.graph/remove "Удалить граф" - :command.graph/add "Добавить граф" - :command.graph/save "Сохранить текущий граф на диск" - :command.graph/re-index "Переиндексировать текущий граф" - :command.command/run "Выполнить команду git" - :command.go/home "Домой" - :command.go/all-graphs "Перейти ко всем графам" - :command.go/whiteboards "Перейти к интерактивным доскам" - :command.go/all-pages "Перейти ко всем страницам" - :command.go/graph-view "Перейти к просмотру графа" - :command.go/keyboard-shortcuts "Перейти к горячим клавишам" - :command.go/tomorrow "перейти к завтрашнему дню" - :command.go/next-journal "Перейти к следующему журналу" - :command.go/prev-journal "Перейти к предыдущему журналу" - :command.go/flashcards "Переключить карточки" - :command.ui/toggle-document-mode "Переключить режим документа" - :command.ui/toggle-settings "Переключить параметры" - :command.ui/toggle-right-sidebar "Переключить правую панель" - :command.ui/toggle-left-sidebar "Переключить левую панель" - :command.ui/toggle-help "Переключить помощь" - :command.ui/toggle-theme "Переключение между темной/светлой темой" - :command.ui/toggle-contents "Переключить Контент на боковой панели" - ;; :command.ui/open-new-window "Открыть новое окно" - :command.command/toggle-favorite "Добавить или удалить из избранного" - :command.editor/open-file-in-default-app "Открыть файл в программе по умолчанию" - :command.editor/open-file-in-directory "Открыть файл в родительском каталоге" - :command.editor/copy-current-file "Копировать текущий файл" - :command.editor/copy-page-url "Скопировать URL страницы" - :command.ui/toggle-wide-mode "Переключить широкоформатный режим" - :command.ui/select-theme-color "Выбрать доступные цвета темы" - :command.ui/goto-plugins "Перейдите в панель управления расширениями" - :command.ui/install-plugins-from-file "Установить расширения из plugins.edn" - :command.editor/toggle-open-blocks "Переключить открытые блоки (свернуть или развернуть все блоки)" - :command.ui/toggle-cards "Переключить карточки" - :command.ui/clear-all-notifications "Очистить все уведомления" - :command.git/commit "Создать git-коммит с сообщением" - :command.dev/show-block-data "(Dev) Показать данные блока" - :command.dev/show-block-ast "(Dev) Показать AST блока" - :command.dev/show-page-data "(Dev) Показать данные страницы" - :command.dev/show-page-ast "(Dev) Показать AST страницы"} \ No newline at end of file + :shortcut.category/basics "Базовые" + :shortcut.category/formatting "Форматирование" + :shortcut.category/navigating "Навигация" + :shortcut.category/block-editing "Общее редактирование блока" + :shortcut.category/block-command-editing "Команды редактирования блока" + :shortcut.category/block-selection "Выделение блоков (Esc для отмены)" + :shortcut.category/toggle "Переключатели" + :shortcut.category/whiteboard "Интерактивная доска" + :shortcut.category/others "Разное" + :shortcut.category/plugins "Расширения" + :window/minimize "Свернуть" + :window/maximize "Развернуть" + :window/restore "Свернуть в окно" + :window/close "Закрыть" + :window/exit-fullscreen "Выйти из полноэкранного режима" + + :header/toggle-left-sidebar "Переключить левую панель" + :header/search "Поиск" + :header/more "Больше" + :header/go-back "Назад" + :header/go-forward "Вперёд" + :command.date-picker/complete "Выбор даты: Выбрать указанный день" + :command.date-picker/prev-day "Выбор даты: Выбрать предыдущий день" + :command.date-picker/next-day "Выбор даты: Выбрать следующий день" + :command.date-picker/prev-week "Выбор даты: Выбрать предыдущую неделю" + :command.date-picker/next-week "Выбор даты: Выбрать следующую неделю" + :command.pdf/previous-page "PDF: Предыдущая страница текущего PDF-документа" + :command.pdf/next-page "PDF: Следующая страница текущего PDF-документа" + :command.pdf/close "PDF: Закрыть просмотр текущего PDF-документа" + :command.pdf/find "PDF: Поиск текста в текущем PDF-документе" + :command.auto-complete/complete "Автодополнение: Использовать выбранный элемент" + :command.auto-complete/prev "Автодополнение: Выбрать предыдущий" + :command.auto-complete/next "Автодополнение: Выбрать следующий" + :command.auto-complete/shift-complete "Автодополнение: Открыть выбранный элемент на боковой панели" + :command.auto-complete/open-link "Автодополнение: Открыть выбранный элемент в браузере" + :command.cards/toggle-answers "Карточки: показать/скрыть ответы/clozes" + :command.cards/next-card "Карточки: следующая карточка" + :command.cards/forgotten "Карточки: забытая" + :command.cards/remembered "Карточки: запомненная" + :command.cards/recall "Карточки: нужно время, чтобы вспомнить" + :command.editor/escape-editing "Выйти из режима редактирования" + :command.editor/backspace "Удалить перед курсором" + :command.editor/delete "Удалить после курсора" + :command.editor/new-block "Создать новый блок" + :command.editor/new-line "Новая строка в блоке" + :command.editor/new-whiteboard "Новая интерактивная доска" + :command.editor/follow-link "Перейти по ссылке под курсором" + :command.editor/open-link-in-sidebar "Открыть ссылку на боковой панели" + :command.editor/bold "Жирный" + :command.editor/italics "Курсив" + :command.editor/highlight "Выделение" + :command.editor/strike-through "Перечёркнутый" + :command.editor/clear-block "Удалить содержимое блока" + :command.editor/kill-line-before "Удалить строку до курсора" + :command.editor/copy-embed "Копировать встраиваемый блок, указывающий на текущий блок" + :command.editor/kill-line-after "Удалить строку после курсора" + :command.editor/beginning-of-block "Переместить курсор в начало блока" + :command.editor/end-of-block "Переместить курсор в конец блока" + :command.editor/forward-word "Переместить курсор на одно слово вперёд" + :command.editor/backward-word "Переместить курсор на одно слово назад" + :command.editor/forward-kill-word "Удалить следующее слово" + :command.editor/backward-kill-word "Удалить предыдущее слово" + :command.editor/replace-block-reference-at-point "Заменить ссылку на блок своим содержимым в указанном месте" + :command.editor/paste-text-in-one-block-at-point "Вставить текст в один блок в указанном месте" + :command.editor/insert-youtube-timestamp "Вставить временную метку на Youtube" + :command.editor/cycle-todo "Сменить статус задачи текущего элемента" + :command.editor/up "Переместить курсор вверх / Выбрать вверх" + :command.editor/down "Переместить курсор вниз / Выбрать вниз" + :command.editor/left "Переместить курсор влево / Открыть выбранный блок в начале" + :command.editor/right "Переместить курсор вправо / Открыть выбранный блок в конце" + :command.editor/select-up "Выбрать контент выше" + :command.editor/select-down "Выбрать контент ниже" + :command.editor/move-block-up "Передвинуть блок выше" + :command.editor/move-block-down "Передвинуть блок ниже" + :command.editor/open-edit "Редактировать выбранный блок" + :command.editor/select-block-up "Выбрать блок выше" + :command.editor/select-block-down "Выбрать блок ниже" + :command.editor/delete-selection "Удалить выбранные блоки" + :command.editor/expand-block-children "Раскрыть" + :command.editor/collapse-block-children "Свернуть" + :command.editor/indent "Увеличить отступ блока" + :command.editor/outdent "Уменьшить отступ блока" + :command.editor/copy "Копировать (выделенное либо ссылку на блок)" + :command.editor/copy-text "Копировать как текст" + :command.editor/cut "Вырезать" + :command.editor/undo "Отменить" + :command.editor/redo "Вернуть" + :command.editor/insert-link "HTML ссылка" + :command.editor/select-all-blocks "Выбрать все блоки" + :command.editor/select-parent "Выбрать родительский блок" + :command.editor/zoom-in "Войти в редактируемый блок / Иначе вперёд" + :command.editor/zoom-out "Выйти из редактируемого блока / Иначе назад" + :command.editor/toggle-undo-redo-mode "Переключить режим Отменить/Повторить (глобально или только на странице)" + :command.editor/toggle-number-list "Переключить формат нумерованного списка" + :command.whiteboard/select "Инструмент 'Выделение'" + :command.whiteboard/pan "Инструмент 'Рука'" + :command.whiteboard/portal "Инструмент 'портал'" + :command.whiteboard/pencil "Инструмент 'Карандаш'" + :command.whiteboard/highlighter "Инструмент 'Маркер'" + :command.whiteboard/eraser "Инструмент 'Ластик'" + :command.whiteboard/connector "Инструмент 'Соединительная стрелка'" + :command.whiteboard/text "Инструмент 'Текст'" + :command.whiteboard/rectangle "Инструмент 'Прямоугольник'" + :command.whiteboard/ellipse "Инструмент 'Эллипс'" + :command.whiteboard/reset-zoom "Сбросить масштаб" + :command.whiteboard/zoom-to-fit "Масштабировать, показав все элементы" + :command.whiteboard/zoom-to-selection "Масштабировать, показав выбранные элементы" + :command.whiteboard/zoom-out "Уменьшить" + :command.whiteboard/zoom-in "Увеличить" + :command.whiteboard/send-backward "Переместить назад" + :command.whiteboard/send-to-back "Переместить на задний план" + :command.whiteboard/bring-forward "Переместить вперёд" + :command.whiteboard/bring-to-front "Переместить на передний план" + :command.whiteboard/lock "Заблокировать выбранное" + :command.whiteboard/unlock "Разблокировать выбранное" + :command.whiteboard/group "Группировать выбранное" + :command.whiteboard/ungroup "Разгруппировать выбранное" + :command.whiteboard/toggle-grid "Переключить отображение сетки" + :command.ui/toggle-brackets "Переключить отображение скобок" + :command.go/search-in-page "Поиск блоков на текущей странице" + :command.go/electron-find-in-page "Поиск текста на странице" + :command.go/electron-jump-to-the-next "Перейти к следующему совпадению в строке поиска" + :command.go/electron-jump-to-the-previous "Перейти к предыдущему совпадению в строке поиска" + :command.go/search "Поиск страниц и блоков" + :command.go/journals "Перейти в журналы" + :command.go/backward "Назад" + :command.go/forward "Вперёд" + :command.search/re-index "Переиндексация поиска" + :command.sidebar/open-today-page "Открыть сегодняшнюю страницу на правой боковой панели" + :command.sidebar/close-top "Закрыть верхний элемент на правой боковой панели" + :command.sidebar/clear "Очистить всё на правой боковой панели" + :command.misc/copy "Копировать" + :command.command-palette/toggle "Показать палитру команд" + :command.graph/export-as-html "Экспорт публичных страниц графов в формате html" + :command.graph/open "Выберите граф для открытия" + :command.graph/remove "Удалить граф" + :command.graph/add "Добавить граф" + :command.graph/save "Сохранить текущий граф на диск" + :command.graph/re-index "Переиндексировать текущий граф" + :command.command/run "Выполнить команду git" + :command.go/home "Домой" + :command.go/all-graphs "Перейти ко всем графам" + :command.go/whiteboards "Перейти к интерактивным доскам" + :command.go/all-pages "Перейти ко всем страницам" + :command.go/graph-view "Перейти к просмотру графа" + :command.go/keyboard-shortcuts "Перейти к горячим клавишам" + :command.go/tomorrow "перейти к завтрашнему дню" + :command.go/next-journal "Перейти к следующему журналу" + :command.go/prev-journal "Перейти к предыдущему журналу" + :command.go/flashcards "Переключить карточки" + :command.ui/toggle-document-mode "Переключить режим документа" + :command.ui/toggle-settings "Переключить параметры" + :command.ui/toggle-right-sidebar "Переключить правую панель" + :command.ui/toggle-left-sidebar "Переключить левую панель" + :command.ui/toggle-help "Переключить помощь" + :command.ui/toggle-theme "Переключение между тёмной/светлой темой" + :command.ui/toggle-contents "Переключить Контент на боковой панели" + :command.command/toggle-favorite "Добавить или удалить из избранного" + :command.editor/open-file-in-default-app "Открыть файл в программе по умолчанию" + :command.editor/open-file-in-directory "Открыть файл в родительском каталоге" + :command.editor/copy-current-file "Копировать текущий файл" + :command.editor/copy-page-url "Копировать URL страницы" + :command.ui/toggle-wide-mode "Переключить широкоформатный режим" + :command.ui/select-theme-color "Выбрать доступные цвета темы" + :command.ui/goto-plugins "Перейдите в панель управления расширениями" + :command.ui/install-plugins-from-file "Установить расширения из plugins.edn" + :command.editor/toggle-open-blocks "Переключить открытые блоки (свернуть или развернуть все блоки)" + :command.ui/toggle-cards "Переключить карточки" + :command.ui/clear-all-notifications "Очистить все уведомления" + :command.git/commit "Создать git-коммит с сообщением" + :command.dev/show-block-data "(Dev) Показать данные блока" + :command.dev/show-block-ast "(Dev) Показать AST блока" + :command.dev/show-page-data "(Dev) Показать данные страницы" + :command.dev/show-page-ast "(Dev) Показать AST страницы"} \ No newline at end of file diff --git a/src/resources/dicts/sk.edn b/src/resources/dicts/sk.edn index ce9d777224c..fd767b06045 100644 --- a/src/resources/dicts/sk.edn +++ b/src/resources/dicts/sk.edn @@ -95,7 +95,6 @@ :file-rn/or-select-actions-2 ". Po zatvorení tohto panela nebudú tieto akcie dostupné." :file-rn/legend "🟢 Voliteľné akcie premenovania; 🟡 Vyžaduje sa akcia premenovania, aby sa zabránilo zmene názvu; 🔴 Nekompatibilná zmena." :file-rn/close-panel "Zatvoriť panel" - :file-rn/all-action "Použiť všetky akcie!" :file-rn/select-format "(Režimu vývojára, Nebezpečné!) Vybrať formát súboru" :file-rn/rename "premenovať súbor \"{1}\" na \"{2}\"" :file-rn/apply-rename "Použiť operáciu premenovania súboru" @@ -213,8 +212,6 @@ :whiteboard/link-whiteboard-or-block "Prepojiť tabuľu/stránku/blok" :page-search "Hľadať na aktuálnej stránke" :graph-search "Hľadať v grafe" - :new-page "Nová stránka" - :new-whiteboard "Nová tabuľa" :new-graph "Pridať nový graf" :graph "Graf" :graph/persist "Logseq synchronizuje interný stav, počkajte prosím niekoľko sekúnd." @@ -223,8 +220,6 @@ :graph/save-success "Úspešne uložené" :graph/save-error "Uloženie zlyhalo" :graph/all-graphs "Všetky grafy" - :graph/local-graphs "Lokálne grafy" - :graph/remote-graphs "Vzdialené grafy" :export-graph "Exportovať graf" :export-page "Exportovať stránku" :export-markdown "Exportovať ako štandardný Markdown (žiadne vlastnosti bloku)" @@ -237,7 +232,6 @@ :all-pages "Všetky stránky" :all-whiteboards "Všetky tabule" :all-files "Všetky súbory" - :remove-orphaned-pages "Odstrániť osamotené stránky" :all-journals "Všetky denníky" :settings "Nastavenia" :settings-of-plugins "Doplnky" @@ -249,7 +243,6 @@ :join-community "Pridať sa ku komunite" :discourse-title "Naše fórum!" :help-shortcut-title "Kliknutím zobrazíte skratky a ďalšie tipy" - :loading "Načítava sa" :parsing-files "Parsovanie súborov" :loading-files "Načítavajú sa súbory" :login "Prihlásiť sa" @@ -281,7 +274,6 @@ :plugin/marketplace "Obchod" :plugin/downloads "Počet stiahnutí" :plugin/stars "Počet hviezd" - :plugin/title "Názov" :plugin/all "Všetky" :plugin/unpacked "Rozbalené" :plugin/delete-alert "Naozaj chcete odinštalovať doplnok [{1}]?" @@ -291,7 +283,6 @@ :plugin/restart "Reštartovať aplikáciu" :plugin/unpacked-tips "Vyberte adresár doplnku" :plugin/contribute "✨ Vytvorte a odošlite nový doplnok" - :plugin/up-to-date "Je nainštalovaná najnovšia verzia" :plugin/custom-js-alert "Našiel sa súbor custom.js, je povolené jeho spustenie? (Ak nerozumiete obsahu tohto súboru, odporúčame nepovoliť jeho spustenie, ktoré má určité bezpečnostné riziká.)" :plugin.install-from-file/menu-title "Inštalovať z plugins.edn" :plugin.install-from-file/title "Inštalovať doplnky z plugins.edn" @@ -312,8 +303,6 @@ :paginates/prev "Predchádzajúca" :paginates/next "Ďalšia" - :tips/all-done "Hotovo" - :command-palette/prompt "Zadať príkaz" :select/default-prompt "Vybrať jeden" :select.graph/prompt "Vybrať graf" diff --git a/src/resources/dicts/tr.edn b/src/resources/dicts/tr.edn index 8be5f431277..21331f74421 100644 --- a/src/resources/dicts/tr.edn +++ b/src/resources/dicts/tr.edn @@ -17,6 +17,11 @@ :on-boarding/tour-whiteboard-home-description "Beyaz tahtalar uygulamada kendi bölümlerine sahiptir ve onları bir bakışta görebilir, kolayca yenilerini oluşturabilir veya silebilirsiniz." :on-boarding/tour-whiteboard-new "{1} Yeni beyaz tahta oluştur" :on-boarding/tour-whiteboard-new-description "Yeni bir beyaz tahta oluşturmanın birçok yolu vardır. Bunlardan biri her zaman tam burada bu panodadır." + :help/title-usage "Kullanım" + :help/title-community "Topluluk" + :help/title-development "Geliştirme" + :help/title-about "Hakkında" + :help/title-terms "Koşullar" :help/start "Başlarken" :help/about "Logseq hakkında" :help/roadmap "Yol haritası" @@ -41,6 +46,9 @@ :search/result-for "Arama sonucu: " :search/items "öğe" :search/page-names "Sayfa adlarında ara" + :search/recent "Son arama:" + :search/blocks-in-page "Blokları sayfada ara:" + :search/cache-outdated "Önbellek eski. Lütfen grafın açılır menüsündeki 'Yeniden dizin oluştur' düğmesini tıklayın." :search-item/whiteboard "Beyaz tahta" :search-item/page "Sayfa" :search-item/file "Dosya" @@ -67,6 +75,7 @@ :right-side-bar/new-page "Yeni sayfa" :right-side-bar/show-journals "Günlükleri Göster" :right-side-bar/separator "Sağ kenar çubuğu yeniden boyutlandırma işleyicisi" + :right-side-bar/toggle-right-sidebar "Sağ kenar çubuğunu aç/kapat" :left-side-bar/journals "Günlük" :left-side-bar/create "Oluştur" :left-side-bar/new-page "Yeni sayfa" @@ -93,6 +102,9 @@ :block/name "Sayfa adı" :page/earlier "Daha önce" :page/copy-page-url "Sayfa URL adresini kopyala" + :page/illegal-page-name "Geçersiz sayfa adı!" + :page/page-already-exists "“{1}” sayfası zaten var!" + :page/whiteboard-to-journal-error "Beyaz tahta sayfaları, günlük başlıkları olarak yeniden adlandırılamaz!" :file/name "Dosya adı" :file/last-modified-at "Son değiştirilme tarihi" :file/no-data "Veri yok" @@ -104,7 +116,7 @@ :file-rn/or-select-actions-2 ". Bu paneli kapattığınızda bu eylemler kullanılamaz." :file-rn/legend "🟢 İsteğe bağlı yeniden adlandırma eylemleri; 🟡 Başlık değişikliğini önlemek için gereken yeniden adlandırma eylemi; 🔴 Hataya neden olan değişiklik." :file-rn/close-panel "Paneli Kapat" - :file-rn/all-action "Tüm Eylemleri Uygula!" + :file-rn/all-action "Tüm Eylemleri Uygula! ({1})" :file-rn/select-format "(Geliştirici Modu Seçeneği, Tehlikeli!) Dosya adı biçimini seçin" :file-rn/rename "\"{1}\" dosyasını \"{2}\" olarak yeniden adlandır" :file-rn/apply-rename "Dosya yeniden adlandırma işlemini uygula" @@ -188,10 +200,14 @@ :settings-page/disable-sentry "Kullanım verilerini ve tanılamayı Logseq'e gönderin" :settings-page/disable-sentry-desc "Logseq asla yerel graf veritabanınızı toplamayacak veya verilerinizi satmayacaktır." :settings-page/preferred-outdenting "Mantıksal girinti" + :settings-page/preferred-outdenting-tip "Sol taraf varsayılan ayar ile olan girintiyi, sağ taraf ise mantıksal girinti etkinken olan girintiyi gösterir. " + :settings-page/preferred-outdenting-tip-more "→ Daha fazla bilgi edinin" :settings-page/show-full-blocks "Blok referansındaki tüm satırları göster" :settings-page/auto-expand-block-refs "Yakınlaştırdığınızda blok referanslarını otomatik olarak genişletin" + :settings-page/auto-expand-block-refs-tip "Bu seçenek, yakınlaştırma yapıldığında blok referanslarının otomatik olarak genişletilip genişletilmeyeceğini kontrol eder." :settings-page/custom-date-format "Tercih edilen tarih biçimi" :settings-page/custom-date-format-warning "Yeniden dizin oluşturma gerekli! Mevcut günlük referansları bozulabilir!" + :settings-page/preferred-pasting-file-hint "Etkinleştirildiğinde, internetten bir resim yapıştırmak görüntüyü indirir ve ekler. Devre dışı bırakıldığında, bağlantıyı görüntüye yapıştırır." :settings-page/preferred-file-format "Tercih edilen dosya biçimi" :settings-page/preferred-workflow "Tercih edilen iş akışı" :settings-page/preferred-pasting-file "Dosya yapıştırmayı tercih et" @@ -213,6 +229,7 @@ :settings-page/tab-general "Genel" :settings-page/tab-editor "Düzenleyici" :settings-page/tab-version-control "Sürüm denetimi" + :settings-page/tab-account "Hesap" :settings-page/tab-advanced "Gelişmiş" :settings-page/tab-assets "Varlıklar" :settings-page/tab-features "Özellikler" @@ -225,7 +242,15 @@ :settings-page/login-prompt "Yeni özelliklere herkesten önce erişmek için bir Open Collective Sponsoru veya Logseq'in Destekçisi olmanız ve oturum açmanız gerekir." :settings-page/sync "Eşitle" :settings-page/enable-whiteboards "Beyaz tahtalar" + :settings-page/native-titlebar "Yerel başlık çubuğu" + :settings-page/native-titlebar-desc "Windows ve Linux'ta yerel pencere başlık çubuğunu etkinleştirir." + :settings-page/check-for-updates "Güncellemeleri kontrol et" + :settings-page/checking "Kontrol ediliyor ..." + :settings-page/revision "Revizyon: " + :settings-page/changelog "Yenilikler nelerdir?" + :settings-page/app-updated "Uygulamanız güncel 🎉" :yes "Evet" + :submit "Onayla" :cancel "İptal" :close "Kapat" @@ -235,9 +260,9 @@ :host "Ana Bilgisayar" :port "Bağlantı Noktası" :re-index "Yeniden dizin oluştur" - :re-index-detail "Grafiği yeniden oluştur" + :re-index-detail "Grafı yeniden oluştur" :re-index-multiple-windows-warning "Bu graf için yeniden dizin oluşturmadan önce diğer pencereleri kapatmanız gerekiyor." - :re-index-discard-unsaved-changes-warning "Yeniden dizin oluşturmak mevcut grafiği siler ve ardından tüm dosyaları o anda diskte depolandıkları şekilde yeniden işler. Kaydedilmemiş değişiklikleri kaybedeceksiniz ve bu biraz zaman alabilir. Devam edilsin mi?" + :re-index-discard-unsaved-changes-warning "Yeniden dizin oluşturmak mevcut grafı siler ve ardından tüm dosyaları o anda diskte depolandıkları şekilde yeniden işler. Kaydedilmemiş değişiklikleri kaybedeceksiniz ve bu biraz zaman alabilir. Devam edilsin mi?" :open-new-window "Yeni pencere" :sync-from-local-files "Yenile" :sync-from-local-files-detail "Yerel dosyalardan değişiklikleri içeri aktarın" @@ -246,20 +271,106 @@ :search/publishing "Ara" :search "Ara veya sayfa oluştur" :whiteboard/link-whiteboard-or-block "Beyaz tahta/sayfa/blok bağlantısı" + :whiteboard/align-left "Sola hizala" + :whiteboard/align-center-horizontally "Merkeze yatay olarak hizala" + :whiteboard/align-right "Sağa hizala" + :whiteboard/distribute-horizontally "Yatay olarak dağıt" + :whiteboard/align-top "Üste hizala" + :whiteboard/align-center-vertically "Merkeze dikey olarak hizala" + :whiteboard/align-bottom "Alta hizala" + :whiteboard/distribute-vertically "Dikey olarak dağıt" + :whiteboard/pack-into-rectangle "Dikdörtgen halinde paketleyin" + :whiteboard/zoom-to-fit "Sığdırmak için yakınlaştır" + :whiteboard/ungroup "Grubu çöz" + :whiteboard/group "Grupla" + :whiteboard/cut "Kes" + :whiteboard/copy "Kopyala" + :whiteboard/paste "Yapıştır" + :whiteboard/paste-as-link "Bağlantı olarak yapıştır" + :whiteboard/export "Dışarı aktar" + :whiteboard/select-all "Tümünü seç" + :whiteboard/deselect-all "Tümünün seçimini kaldır" + :whiteboard/lock "Kilitle" + :whiteboard/unlock "Kilidi aç" + :whiteboard/delete "Sil" + :whiteboard/flip-horizontally "Yatay olarak çevir" + :whiteboard/flip-vertically "Dikey olarak çevir" + :whiteboard/move-to-front "Öne taşı" + :whiteboard/move-to-back "Geriye taşı" + :whiteboard/dev-print-shape-props "(Dev) Şekil aksesuarlarını yazdır" + :whiteboard/auto-resize "Otomatik yeniden boyutlandır" + :whiteboard/expand "Genişlet" + :whiteboard/collapse "Daralt" + :whiteboard/website-url "Web sitesi bağlantısı" + :whiteboard/reload "Yeniden yükle" + :whiteboard/open-website-url "Web sitesi bağlantısını aç" + :whiteboard/youtube-url "YouTube bağlantısı" + :whiteboard/open-youtube-url "YouTube bağlantısını aç" + :whiteboard/twitter-url "Twitter bağlantısı" + :whiteboard/open-twitter-url "Twitter bağlantısını aç" + :whiteboard/fill "Doldur" + :whiteboard/stroke-type "Vuruş türü" + :whiteboard/arrow-head "Ok başı" + :whiteboard/bold "Kalın" + :whiteboard/italic "İtalik" + :whiteboard/undo "Geri al" + :whiteboard/redo "Yinele" + :whiteboard/zoom-in "Yakınlaştır" + :whiteboard/zoom-out "Uzaklaştır" + :whiteboard/select "Seç" + :whiteboard/pan "Kaydır" + :whiteboard/add-block-or-page "Blok veya sayfa ekle" + :whiteboard/draw "Çiz" + :whiteboard/highlight "Vurgula" + :whiteboard/eraser "Silgi" + :whiteboard/connector "Bağlayıcı" + :whiteboard/text "Metin" + :whiteboard/color "Renk" + :whiteboard/select-custom-color "Özel renk seç" + :whiteboard/opacity "Opaklık" + :whiteboard/extra-small "Çok Küçük" + :whiteboard/small "Küçük" + :whiteboard/medium "Orta" + :whiteboard/large "Büyük" + :whiteboard/extra-large "Çok Büyük" + :whiteboard/huge "Kocaman" + :whiteboard/scale-level "Ölçek düzeyi" + :whiteboard/rectangle "Dikdörtgen" + :whiteboard/circle "Daire" + :whiteboard/triangle "Üçgen" + :whiteboard/shape "Şekil" + :whiteboard/open-page "Sayfayı aç" + :whiteboard/open-page-in-sidebar "Sayfayı kenar çubuğunda aç" + :whiteboard/remove-link "Bağlantıyı kaldır" + :whiteboard/link "Bağlantı" + :whiteboard/references "Referanslar" + :whiteboard/link-to-any-page-or-block "Herhangi bir sayfaya veya bloğa bağlantı ver" + :whiteboard/start-typing-to-search "Aramak için yazmaya başlayın..." + :whiteboard/new-block-no-colon "Yeni blok" + :whiteboard/new-block "Yeni blok:" + :whiteboard/new-page "Yeni sayfa:" + :whiteboard/new-whiteboard "Yeni beyaz tahta" + :whiteboard/search-only-blocks "Yalnızca blokları ara" + :whiteboard/search-only-pages "Yalnızca sayfaları ara" + :whiteboard/cache-outdated "Önbellek eski. Lütfen grafın açılır menüsündeki 'Yeniden dizin oluştur' düğmesini tıklayın." + :whiteboard/shape-quick-links "Hızlı Bağlantıları Şekillendir" :page-search "Geçerli sayfada ara" :graph-search "Grafta ara" - :new-page "Yeni sayfa" - :new-whiteboard "Yeni beyaz tahta" + :home "Başlangıç" + :new-page "Yeni sayfa:" + :whiteboard "Beyaz tahta" + :whiteboards "Beyaz tahtalar" + :new-whiteboard "Yeni beyaz tahta:" :new-graph "Yeni graf ekle" :graph "Graf" - :graph/persist "Logseq dahili durumu senkronize ediyor, lütfen birkaç saniye bekleyin." - :graph/persist-error "Dahili durum senkronize edilemedi." + :graph/persist "Logseq dahili durumu eşitlenemiyor, lütfen birkaç saniye bekleyin." + :graph/persist-error "Dahili durum eşitlenemedi." :graph/save "Kaydediliyor..." :graph/save-success "Başarıyla Kaydedildi" :graph/save-error "Kaydedilemedi" :graph/all-graphs "Tüm graflar" - :graph/local-graphs "Yerel graflar" - :graph/remote-graphs "Uzak graflar" + :graph/local-graphs "Yerel graflar:" + :graph/remote-graphs "Uzak graflar:" :export "Dışarı aktar" :export-graph "Grafı dışarı aktar" :export-page "Sayfayı dışarı aktar" @@ -273,7 +384,7 @@ :all-pages "Tüm sayfalar" :all-whiteboards "Tüm beyaz tahtalar" :all-files "Tüm dosyalar" - :remove-orphaned-pages "Yalnız bırakılmış sayfaları kaldır" + :remove-orphaned-pages "Yalnız bırakılmış sayfalar kaldırılsın mı?" :all-journals "Bütün günlükler" :settings "Ayarlar" :settings-of-plugins "Eklenti ayarları" @@ -285,11 +396,12 @@ :join-community "Topluluğa katıl" :discourse-title "Forum sayfamız!" :help-shortcut-title "Kısayolları ve diğer ipuçlarını kontrol etmek için tıklayın" - :loading "Yükleniyor" + :loading "Yükleniyor..." :parsing-files "Dosyalar ayrıştırılıyor" :loading-files "Dosyalar yükleniyor" :login "Oturum aç" :logout "Oturumu kapat" + :logout-user "Oturumu kapat ({1})" :download "İndir" :language "Dil" :remove-background "Arka planı kaldır" @@ -297,20 +409,24 @@ :heading "Başlık {1}" :auto-heading "Otomatik başlık" :open-a-directory "Yerel bir dizin aç" + :toggle-theme "Temayı değiştir" :help/shortcut-page-title "Klavye kısayolları" :plugin/installed "Yüklü" + :plugin/installed-plugin "Yüklü eklenti: {1}" :plugin/not-installed "Yüklü olmayan" :plugin/installing "Yükleniyor" :plugin/install "Yükle" :plugin/reload "Yeniden yükle" :plugin/update "Güncelle" + :plugin/update-plugin "Eklentiyi güncelle: {1} - {2}" :plugin/check-update "Güncellemeyi denetle" :plugin/check-all-updates "Tüm güncellemeleri denetle" :plugin/found-updates "Yeni güncellemeler" :plugin/found-n-updates "{1} güncelleme bulundu" :plugin/update-all-selected "Seçilenlerin hepsini güncelle" + :plugin/all-updated "Hepsi güncellendi!" :plugin/updates-downloading "Güncellemeler indiriliyor" :plugin/refresh-lists "Listeleri yenile" :plugin/enabled "Etkin" @@ -321,7 +437,7 @@ :plugin/marketplace "Market" :plugin/downloads "İndirilme" :plugin/stars "Yıldızlar" - :plugin/title "Başlık" + :plugin/title "Başlık ({1})" :plugin/all "Tümü" :plugin/unpacked "Çıkarılmamış" :plugin/delete-alert "[{1}] eklentisini kaldırmak istediğinizden emin misiniz?" @@ -331,8 +447,18 @@ :plugin/restart "Uygulamayı Yeniden Başlat" :plugin/unpacked-tips "Eklenti dizinini seçin" :plugin/contribute "✨ Yeni eklenti yaz ve gönder" - :plugin/up-to-date "Güncel" + :plugin/up-to-date "Güncel {1}" :plugin/custom-js-alert "custom.js dosyası bulundu, çalıştırılmasına izin veriliyor mu? (Bu dosyanın içeriğini anlamadıysanız, belirli güvenlik riskleri olduğu için çalıştırmaya izin vermemeniz önerilir.)" + :plugin/security-warning "Eklentiler grafınıza ve yerel dosyalarınıza erişebilir, ağ istekleri yayınlayabilir. + Ayrıca veri bozulmasına veya kaybına neden olabilirler. Graflarınız için uygun erişim kuralları üzerinde çalışıyoruz. + Bu arada, graflarınızı düzenli olarak yedeklediğinizden emin olun ve eklentileri yalnızca okuyabildiğiniz ve + kaynak kodunu anlayabildiğiniz zaman yükleyin." + :plugin/search-plugin "Eklenti ara" + :plugin/open-preferences "Tercihleri aç" + :plugin/open-logseq-dir "Aç" + :plugin/remote-error "Uzak hata: " + :plugin/checking-for-updates "Eklenti güncellemeleri kontrol ediliyor ..." + :plugin/list-of-updates "Eklenti güncellemeleri: " :plugin.install-from-file/menu-title "plugins.edn dosyasından yükle" :plugin.install-from-file/title "Eklentileri plugins.edn dosyasından yükle" :plugin.install-from-file/notice "Aşağıdaki eklentiler yüklü olan eklentilerinizin yerini alacak:" @@ -351,8 +477,8 @@ :paginates/pages "Toplam {1} sayfa" :paginates/prev "Önceki" :paginates/next "Sonraki" - - :tips/all-done "Tamamlandı" + + :tips/all-done "Tamamlandı!" :command-palette/prompt "Bir komut yazın" :select/default-prompt "Birini seçin" @@ -361,8 +487,9 @@ :select.graph/empty-placeholder-description "Eşleşen graf yok. Bir tane daha eklemek ister misin?" :select.graph/add-graph "Evet, başka bir graf ekle" - :file-sync/other-user-graph "Geçerli yerel graf, diğer kullanıcının uzak grafına bağlıdır. Bu yüzden senkronizasyon başlatılamıyor." + :file-sync/other-user-graph "Geçerli yerel graf, diğer kullanıcının uzak grafına bağlıdır. Bu yüzden eşitleme başlatılamıyor." :file-sync/graph-deleted "Geçerli uzak graf silindi" + :file-sync/rsapi-cannot-upload-err "Eşitleme başlatılamıyor, lütfen yerel saatin doğru olup olmadığını kontrol edin." :notification/clear-all "Tümünü temizle" @@ -375,6 +502,19 @@ :shortcut.category/toggle "Aç/Kapat" :shortcut.category/whiteboard "Beyaz tahta" :shortcut.category/others "Diğer" + :shortcut.category/plugins "Eklentiler" + :window/minimize "Simge durumuna küçült" + :window/maximize "Ekranı kapla" + :window/restore "Pencere durumuna dön" + :window/close "Kapat" + :window/exit-fullscreen "Tam ekrandan çık" + + :header/toggle-left-sidebar "Sol kenar çubuğunu aç/kapat" + :header/search "Ara" + :header/more "Diğer" + :header/go-back "Geri git" + :header/go-forward "İleri git" + :command.date-picker/complete "Tarih seçici: Seçilen günü seç" :command.date-picker/prev-day "Tarih seçici: Önceki günü seç" :command.date-picker/next-day "Tarih seçici: Sonraki günü seç" @@ -440,7 +580,7 @@ :command.editor/copy-text "Seçimleri metin olarak kopyala" :command.editor/cut "Kes" :command.editor/undo "Geri al" - :command.editor/redo "Tinele" + :command.editor/redo "Yinele" :command.editor/insert-link "HTML Bağlantısı" :command.editor/select-all-blocks "Tüm blokları seç" :command.editor/zoom-in "Düzenlenen bloğu yakınlaştır / Aksi takdirde ileri git" @@ -484,7 +624,7 @@ :command.sidebar/open-today-page "Sağ kenar çubuğunda bugünün sayfasını açın" :command.sidebar/close-top "Sağ kenar çubuğunun en üst öğesini kapatır" :command.sidebar/clear "Sağ kenar çubuğundaki herşeyi temizle" - :command.misc/copy "mod+c" + :command.misc/copy "Kopyala" :command.command-palette/toggle "Komut paletini aç" :command.graph/export-as-html "Herkese açık graf sayfalarını html olarak dışarı aktar" :command.graph/open "Açılacak grafı seçin" @@ -510,7 +650,6 @@ :command.ui/toggle-help "Yardımı aç/kapat" :command.ui/toggle-theme "Koyu ve açık tema arasında geçiş yap" :command.ui/toggle-contents "Kenar çubuğundaki içeriği aç/kapat" - ;; :command.ui/open-new-window "Başka bir pencere aç" :command.command/toggle-favorite "Sık kullanılanlara ekle/çıkar" :command.editor/open-file-in-default-app "Dosyayı varsayılan uygulamada aç" :command.editor/open-file-in-directory "Dosyayı üst dizinde aç" @@ -528,4 +667,4 @@ :command.dev/show-block-data "(Dev) Blok verilerini göster" :command.dev/show-block-ast "(Dev) Blok AST'sini göster" :command.dev/show-page-data "(Dev) Sayfa verilerini göster" - :command.dev/show-page-ast "(Dev) Sayfa AST'sini göster"} \ No newline at end of file + :command.dev/show-page-ast "(Dev) Sayfa AST'sini göster"} diff --git a/src/resources/dicts/uk.edn b/src/resources/dicts/uk.edn index 648717bf89f..f076df4cdc8 100644 --- a/src/resources/dicts/uk.edn +++ b/src/resources/dicts/uk.edn @@ -58,6 +58,7 @@ :right-side-bar/switch-theme "Режим теми" :right-side-bar/contents "Зміст" :right-side-bar/page-graph "Графік сторінки" + :right-side-bar/history "(Dev) Скасувати/Повторити історію" :right-side-bar/block-ref "Посилання на блоки" :right-side-bar/graph-view "Вигляд графіка" :right-side-bar/all-pages "Всі сторінки" @@ -103,7 +104,6 @@ :file-rn/or-select-actions-2 ". Ці дії недоступні, якщо ви закриєте цю панель." :file-rn/legend "🟢 Додаткові дії перейменування; 🟡 Щоб уникнути зміни назви, потрібна дія перейменування; 🔴 Порушення змін." :file-rn/close-panel "Закрити панель" - :file-rn/all-action "Застосувати всі дії!" :file-rn/select-format "(Режим розробника, небезпечно!) Виберіть формат назви файлу" :file-rn/rename "перейменувати файл \"{1}\" на \"{2}\"" :file-rn/apply-rename "Застосувати операцію перейменування файлу" @@ -144,10 +144,31 @@ :color/pink "Рожевий" :editor/copy "Копіювати" :editor/cut "Вирізати" + :editor/expand-block-children "Розгорнути все" + :editor/collapse-block-children "Згорнути все" + :editor/delete-selection "Видалити вибрані блоки" + :editor/cycle-todo "Змінити статус TODO для поточного елемента" + :dev/show-page-data "(Dev) Показати дані сторінки" + :dev/show-block-data "(Dev) Показати дані блоку" + :dev/show-block-ast "(Dev) Показати блок AST" + :dev/show-page-ast "(Dev) Показати сторінку AST" + :content/copy-export-as "Копіювати / Експортувати як.." + :content/copy-block-url "Копіювати URL блоку" :content/copy-block-ref "Копіювати посилання блоку" :content/copy-block-emebed "Копіювати вбудовування блоку" + :content/copy-ref "Копіювати це посилання" + :content/delete-ref "Видалити це посилання" + :content/replace-with-text "Замінити на текст" + :content/replace-with-embed "Замінити на вбудованний елемент" :content/open-in-sidebar "Відкрити у боковій панелі" :content/click-to-edit "Натисніть для редагування" + :context-menu/make-a-flashcard "Зробити Картку" + :context-menu/toggle-number-list "Переключити номерний список" + :context-menu/preview-flashcard "Попередній перегляд Картки" + :context-menu/make-a-template "Зробити шаблон" + :context-menu/input-template-name "Як назвемо шаблон?" + :context-menu/template-include-parent-block "Включити батьківський блок у шаблон?" + :context-menu/template-exists-warning "Шаблон вже існує!" :settings-page/git-confirm "Вам потрібно перезапустити програму після оновлення налаштувань Git." :settings-page/git-switcher-label "Увімкнути Git авто commit" :settings-page/git-commit-delay "Секунди Git авто commit" @@ -227,8 +248,6 @@ :whiteboard/link-whiteboard-or-block "Зв'язати дошку/сторінку/блок" :page-search "Пошук у поточній сторінці" :graph-search "Пошук графіку" - :new-page "Нова сторінка" - :new-whiteboard "Нова дошка" :new-graph "Додати новий графік" :graph "Графік" :graph/persist "Logseq синхронізує внутрішінй стан, будь ласка, почекайте кілька секунд." @@ -237,8 +256,6 @@ :graph/save-success "Успішно збережено" :graph/save-error "Збереження невдале" :graph/all-graphs "Всі графіки" - :graph/local-graphs "Локальні графіки" - :graph/remote-graphs "Дистанційні графіки" :export "Експортувати" :export-graph "Експортувати графік" :export-page "Експортувати сторінку" @@ -252,7 +269,6 @@ :all-pages "Всі сторінки" :all-whiteboards "Всі дошки" :all-files "Всі файли" - :remove-orphaned-pages "Видалити осиротілі сторінки" :all-journals "Всі журнали" :settings "Налаштування" :settings-of-plugins "Плагіни" @@ -264,7 +280,6 @@ :join-community "Приєднатися до нас" :discourse-title "Наш форум!" :help-shortcut-title "Клацніть, щоб перевірити комбінації і інші підказки" - :loading "Загрузка" :parsing-files "Розбір файлів" :loading-files "Загрузка файлів" :login "Увіти" @@ -287,6 +302,10 @@ :plugin/update "Оновити" :plugin/check-update "Перевірити оновлення" :plugin/check-all-updates "Перевірити всі оновлення" + :plugin/found-updates "Нові оновлення" + :plugin/found-n-updates "Знайдено оновлень {1}" + :plugin/update-all-selected "Оновити всі вибрані" + :plugin/updates-downloading "Завантаження оновлень" :plugin/refresh-lists "Оновити списки" :plugin/enabled "Ввімкнено" :plugin/disabled "Вимкнено" @@ -296,7 +315,6 @@ :plugin/marketplace "Маркетплейс" :plugin/downloads "Завантаження" :plugin/stars "Оцінка" - :plugin/title "Назва" :plugin/all "Все" :plugin/unpacked "Розпаковано" :plugin/delete-alert "Ви впевнені, що хочете видалити плагін [{1}]?" @@ -306,7 +324,6 @@ :plugin/restart "Перезапустити додаток" :plugin/unpacked-tips "Виберіть директорію із плагінами" :plugin/contribute "✨ Написати і відправити новий плагін" - :plugin/up-to-date "Все оновлено" :plugin/custom-js-alert "Знайденно custom.js файл, це дозволенно до запуску? (Якщо ви не розумієте що знаходитья у файлі, це не рекомедовано до запуску, як може мати певні проблеми із безпекою.)" :plugin.install-from-file/menu-title "Встановити з plugins.edn" :plugin.install-from-file/title "Встановити плагіни з plugins.edn" @@ -327,8 +344,6 @@ :paginates/prev "Попередня" :paginates/next "Наступна" - :tips/all-done "Готово" - :command-palette/prompt "Введіть команду" :select/default-prompt "Виберіть один" :select/default-select-multiple "Виберіть один або кілька" @@ -338,6 +353,7 @@ :file-sync/other-user-graph "Поточний локальний графік зв'язаний з графіком іншого користувача. Тому неможливо почати синхронізацію." :file-sync/graph-deleted "Поточний дистанційний графік був видалений" + :file-sync/rsapi-cannot-upload-err "Неможливо розпочати синхронізацію, будь ласка, перевірте чи місцевий час встановлено коректно." :notification/clear-all "Очистити все" @@ -348,6 +364,7 @@ :shortcut.category/block-command-editing "Редагування команди блоку" :shortcut.category/block-selection "Вибір блоку (натисніть Esc щоб вийти із вибірки)" :shortcut.category/toggle "Перемкнути" + :shortcut.category/whiteboard "Дошка" :shortcut.category/others "Інші" :command.date-picker/complete "Вибір дати: підтвердити обраний день" @@ -421,6 +438,32 @@ :command.editor/select-parent "Вибрати батьківський блок" :command.editor/zoom-in "Збільшити" :command.editor/zoom-out "Зменшити" + :command.editor/toggle-undo-redo-mode "Переключити режим скасування/повтору (глобально чи лише на сторінці)" + :command.editor/toggle-number-list "Переключити номерний список" + :command.whiteboard/select "Вибрати інструмент" + :command.whiteboard/pan "Прокрутка" + :command.whiteboard/portal "Додати блок або сторінку" + :command.whiteboard/pencil "Олівець" + :command.whiteboard/highlighter "Маркер" + :command.whiteboard/eraser "Гумка" + :command.whiteboard/connector "З'єднувач" + :command.whiteboard/text "Текст" + :command.whiteboard/rectangle "Прямокутник" + :command.whiteboard/ellipse "Еліпс" + :command.whiteboard/reset-zoom "Скинути масштаб" + :command.whiteboard/zoom-to-fit "Показати всі елементи" + :command.whiteboard/zoom-to-selection "Показати елемент" + :command.whiteboard/zoom-out "Зменшити" + :command.whiteboard/zoom-in "Збільшити" + :command.whiteboard/send-backward "Перемістити назад" + :command.whiteboard/send-to-back "На задній план" + :command.whiteboard/bring-forward "Перемістити вперед" + :command.whiteboard/bring-to-front "На передній план" + :command.whiteboard/lock "Блокувати" + :command.whiteboard/unlock "Розблокувати" + :command.whiteboard/group "Групувати" + :command.whiteboard/ungroup "Розгрупувати" + :command.whiteboard/toggle-grid "Переключити відображення сітки" :command.ui/toggle-brackets "Показати/Сховати квадратні дужки" :command.go/search-in-page "Пошук блоків на поточній сторінці" :command.go/electron-find-in-page "Знайти текст на сторінці" @@ -455,15 +498,17 @@ :command.go/flashcards "Показати/Сховати картки" :command.ui/toggle-document-mode "Показати/Сховати режим документа" :command.ui/toggle-settings "Налаштування перемикача" - :command.ui/toggle-right-sidebar "Показати/сховати праву бічну панель" + :command.ui/toggle-right-sidebar "Показати/Сховати праву бічну панель" :command.ui/toggle-left-sidebar "Показати/Сховати ліву бічну панель" :command.ui/toggle-help "Показати/Сховати помічника" :command.ui/toggle-theme "Перемикання між темною та світлою темою" :command.ui/toggle-contents "Показати/Приховати вміст бічної панелі" + ;; :command.ui/open-new-window "Відкрити інше вікно" :command.command/toggle-favorite "Додати/Видалити з вибраного" :command.editor/open-file-in-default-app "Відкрити файл у програмі за замовчуванням" :command.editor/open-file-in-directory "Відкрити файл у папці" :command.editor/copy-current-file "Копіювати поточний файл" + :command.editor/copy-page-url "Копіювати URL-адресу сторінки" :command.ui/toggle-wide-mode "Перейти у ширококутний режим" :command.ui/select-theme-color "Вибрати доступні кольори теми" :command.ui/goto-plugins "Перейти до списку плагінів" @@ -472,7 +517,6 @@ :command.ui/toggle-cards "Показати/Сховати карти" :command.git/commit "Виконати команду git commit із повідомленням" :command.ui/clear-all-notifications "Очистити всі сповіщення" - :command.editor/copy-page-url "Копіювати URL-адресу сторінки" :command.dev/show-block-ast "(Dev) Показати блок AST" :command.dev/show-block-data "(Dev) Показати дані блоку" :command.dev/show-page-ast "(Dev) Показати сторінку AST" diff --git a/src/resources/dicts/zh-cn.edn b/src/resources/dicts/zh-cn.edn index 0bc0b68940a..9300162247d 100644 --- a/src/resources/dicts/zh-cn.edn +++ b/src/resources/dicts/zh-cn.edn @@ -106,7 +106,6 @@ :file-rn/or-select-actions-2 "。关闭面板后,这些功能将不可用。" :file-rn/legend "🟢 可选的重命名操作; 🟡 需要重命名以避免标题的改变; 🔴 重大改变。" :file-rn/close-panel "关闭面板" - :file-rn/all-action "应用所有操作!" :file-rn/select-format "(开发者模式选项,危险!) 选择文件名格式" :file-rn/rename "重命名文件 \"{1}\" 到 \"{2}\"" :file-rn/apply-rename "应用文件重命名操作" @@ -205,7 +204,6 @@ :search "搜索或者创建新页面" :page-search "在当前页面搜索" :graph-search "搜索图谱" - :new-page "新页面" :graph "图谱" :graph/persist "打开新窗口前,Logseq正在同步内部状态,请等待片刻。" :graph/persist-error "内部状态同步失败。无法打开新窗口。" @@ -213,14 +211,11 @@ :graph/save-success "保存成功" :graph/save-error "保存失败" :graph/all-graphs "所有图谱" - :graph/local-graphs "本地图谱" - :graph/remote-graphs "同步图谱" :all-journals "日记" :export "导出" :all-graphs "所有图谱" :all-pages "所有页面" :all-files "所有文件" - :remove-orphaned-pages "删除空页面" :settings "设置" :settings-of-plugins "插件设置" :plugins "插件" @@ -230,7 +225,6 @@ :importing "导入中" :join-community "加入社区" :help-shortcut-title "点此查看快捷方式和更多有用帮助" - :loading "加载中" :close "关闭" :delete "删除" :save "保存" @@ -245,10 +239,8 @@ :language "语言" :remove-background "去除背景" :remove-heading "移除 heading" - :heading "Heading {1}" :auto-heading "自动转为 heading" :open-a-directory "打开本地文件夹" - :new-whiteboard "新建白板" :all-whiteboards "所有白板" :plugin/installed "已安装" @@ -273,7 +265,6 @@ :plugin/marketplace "插件市场" :plugin/downloads "下载量" :plugin/stars "收藏数" - :plugin/title "名称" :plugin/all "全部" :plugin/unpacked "未打包" :plugin/open-settings "打开配置项" @@ -281,9 +272,20 @@ :plugin/load-unpacked "手动载入插件" :plugin/restart "重启应用" :plugin/unpacked-tips "用于开发目的或者从本地磁盘载入可信的社区插件。" - :plugin/up-to-date "已经是最新了" :plugin/custom-js-alert "发现 custom.js 自定义脚本,是否允许执行?(如果您对该文件的内容不了解 或 来源不可靠,建议不要允许执行)" + :plugin/search-plugin "搜索插件" + :plugin/open-preferences "打开插件偏好设置" + :plugin/open-logseq-dir "打开" + :plugin/remote-error "远端错误: " + :plugin/checking-for-updates "正在检查插件更新 ..." + :plugin/list-of-updates "可用的插件更新: " + :plugin/auto-check-for-updates "是否自动检查更新" + :plugin.install-from-file/menu-title "从 plugins.edn 安装" + :plugin.install-from-file/title "从 plugins.edn 配置中安装插件" + :plugin.install-from-file/notice "以下插件会替换已安装的插件:" + :plugin.install-from-file/success "插件全部安装完毕!" + :pdf/copy-ref "复制引用" :pdf/copy-text "复制文本" :pdf/linked-ref "转到注解" @@ -314,8 +316,6 @@ :paginates/prev "上一页" :paginates/next "下一页" - :tips/all-done "处理完成" - :command-palette/prompt "输入指令" :file-sync/other-user-graph "当前本地图谱绑定在其他用户的远程图谱上。因此无法启动同步。" @@ -381,7 +381,6 @@ :command.graph/re-index "重建索引" :command.graph/remove "移除图谱" :command.graph/save "保存" - :command.misc/copy "Ctrl/Command + c" :command.sidebar/clear "清除侧边栏" :command.sidebar/open-today-page "在侧边栏打开今日" :command.ui/goto-plugins "插件" diff --git a/src/resources/dicts/zh-hant.edn b/src/resources/dicts/zh-hant.edn index 9107c7b34c5..0f00853eade 100644 --- a/src/resources/dicts/zh-hant.edn +++ b/src/resources/dicts/zh-hant.edn @@ -101,7 +101,6 @@ :file-rn/or-select-actions-2 "。一旦您關閉此面板,這些操作將無法更動。" :file-rn/legend "🟢 可選重新命名;🟡 須進行重命名以避免標題更動;🔴 破壞性更動" :file-rn/close-panel "關閉控制面板" - :file-rn/all-action "確認所有操作" :file-rn/select-format "(開發者模式專用)選擇文件名稱格式" :file-rn/rename "將文件 \"{1}\" 改名為 \"{2}\"" :file-rn/apply-rename "確定更改文件名稱" @@ -174,7 +173,6 @@ :settings-page/enable-timetracking "啟用時間追蹤" :settings-page/enable-tooltip "啟用提示" :settings-page/enable-journals "啟用日記頁面" - :settings-page/enable-all-pages-public "All pages public when publishing" :settings-page/customize-shortcuts "個人化快捷鍵" :settings-page/shortcut-settings "設定快捷鍵" :settings-page/home-default-page "設定預設首頁" @@ -185,7 +183,6 @@ :settings-page/developer-mode "開發者模式" :settings-page/developer-mode-desc "開發者模式可以協助貢獻者及擴充套件開發人員更有效率地測試 Logseq。" :settings-page/current-version "目前版本" - :settings-page/tab-general "General" :settings-page/tab-editor "編輯器" :settings-page/tab-version-control "版本控制" :settings-page/tab-advanced "進階功能" @@ -224,8 +221,6 @@ :whiteboard/link-whiteboard-or-block "連結白板/頁面/區塊" :page-search "在目前頁面搜尋" :graph-search "搜尋圖表" - :new-page "新分頁" - :new-whiteboard "新白板" :new-graph "新圖表" :graph "圖表" :graph/persist "Logseq 正在同步網路資料,請稍候。" @@ -234,8 +229,6 @@ :graph/save-success "儲存成功。" :graph/save-error "儲存失敗。" :graph/all-graphs "所有圖表" - :graph/local-graphs "本機圖表" - :graph/remote-graphs "線上圖表" :export "匯出" :export-graph "匯出圖表" :export-page "匯出頁面" @@ -249,7 +242,6 @@ :all-pages "所有分頁" :all-whiteboards "所有白板" :all-files "所有資料" - :remove-orphaned-pages "移除孤立頁面" :all-journals "所有日記" :settings "設定" :settings-of-plugins "外掛設定" @@ -261,7 +253,6 @@ :join-community "加入社群" :discourse-title "我們的論壇!" :help-shortcut-title "點擊查看快捷鍵和其他提示。" - :loading "讀取中" :parsing-files "爬取資料" :loading-files "讀取資料" :login "登入" @@ -293,7 +284,6 @@ :plugin/marketplace "市集" :plugin/downloads "下載" :plugin/stars "星星" - :plugin/title "標題" :plugin/all "所有" :plugin/unpacked "未壓縮的" :plugin/delete-alert "你確定要卸載外掛 [{1}] 嗎?" @@ -303,7 +293,6 @@ :plugin/restart "重新啟動應用程式" :plugin/unpacked-tips "選擇外掛資料夾" :plugin/contribute "✨ 貢獻外掛" - :plugin/up-to-date "已經是最新版本" :plugin/custom-js-alert "已找到 custom.js ,確定要執行它嗎?(如果您不了解此檔案的內容,建議不要允許執行,因為這具有一定的安全風險。)" :plugin.install-from-file/menu-title "正在從 plugins.edn 下載" :plugin.install-from-file/title "正在安裝 plugins.edn 的外掛" @@ -324,8 +313,6 @@ :paginates/prev "上一頁" :paginates/next "下一頁" - :tips/all-done "全部完成" - :command-palette/prompt "請輸入指令" :select/default-prompt "請選擇提示" :select.graph/prompt "請選擇圖表" diff --git a/src/main/grammar/calc.bnf b/src/resources/grammar/calc.bnf similarity index 100% rename from src/main/grammar/calc.bnf rename to src/resources/grammar/calc.bnf diff --git a/templates/config.edn b/src/resources/templates/config.edn similarity index 100% rename from templates/config.edn rename to src/resources/templates/config.edn diff --git a/templates/contents.md b/src/resources/templates/contents.md similarity index 100% rename from templates/contents.md rename to src/resources/templates/contents.md diff --git a/templates/contents.org b/src/resources/templates/contents.org similarity index 100% rename from templates/contents.org rename to src/resources/templates/contents.org diff --git a/templates/global-config.edn b/src/resources/templates/global-config.edn similarity index 100% rename from templates/global-config.edn rename to src/resources/templates/global-config.edn diff --git a/src/resources/tutorials/dummy-notes-ru.md b/src/resources/tutorials/dummy-notes-ru.md index 5c5b29ffbce..5eec82758d3 100644 --- a/src/resources/tutorials/dummy-notes-ru.md +++ b/src/resources/tutorials/dummy-notes-ru.md @@ -7,8 +7,8 @@ title: Как создать образец заметки? :id: 5f713e91-8a3c-4b04-a33a-c39482428e2d :END: - Я дочерний блок! - - Я очередной дочерний блок! -- Эй, я другой блок! + - Я следующий дочерний блок! +- Эй, а я другой блок! :PROPERTIES: :id: 5f713ea8-8cba-403d-ac00-9964b1ec7190 :END: diff --git a/src/resources/tutorials/tutorial-ru.md b/src/resources/tutorials/tutorial-ru.md index 68b59789663..3081ecfcdbb 100644 --- a/src/resources/tutorials/tutorial-ru.md +++ b/src/resources/tutorials/tutorial-ru.md @@ -1,5 +1,5 @@ -## Привет, добро пожаловать в Logseq! -- Logseq - это платформа [с открытым исходным кодом](https://github.com/logseq/logseq), _ориентированная на конфиденциальность_, для управления _знаниями_ и совместной работы. +## Привет и добро пожаловать в Logseq! +- Logseq - это платформа с [открытым исходным кодом](https://github.com/logseq/logseq), _ориентированная на конфиденциальность_, для управления _знаниями_ и совместной работы. - Это 3-минутное руководство по использованию Logseq. Приступим! - Вот несколько советов, которые могут оказаться полезными. #+BEGIN_TIP @@ -8,12 +8,12 @@ Нажмите `Shift+Enter`, чтобы начать писать с новой строки в блоке. Введите `/` для просмотра всех доступных команд. #+END_TIP -- 1. Давайте создадим страницу под названием [[Как создать образец заметки?]]. Вы можете кликнуть на нее, чтобы перейти на эту страницу, или кликнуть, удерживая нажатой клавишу `Shift`, чтобы открыть ее на правой боковой панели! После этого вы увидите как _связанные ссылки_, так и _несвязанные ссылки_. -- 2. Давайте обратимся к некоторым блокам страницы [[Как создать образец заметки?]]. Кликните, удерживая нажатой клавишу `Shift`, на любую ссылку на блок, чтобы открыть его на правой боковой панели. Попробуйте внести некоторые изменения на правой боковой панели, эти блоки также будут изменены! +- 1. Давайте создадим страницу под названием [[Как создать образец заметки?]]. Вы можете кликнуть на неё, чтобы перейти на эту страницу, или кликнуть, удерживая нажатой клавишу `Shift`, чтобы открыть её на правой боковой панели! После этого вы увидите как _связанные ссылки_, так и _несвязанные ссылки_. +- 2. Давайте обратимся к некоторым блокам страницы [[Как создать образец заметки?]]. Кликните, удерживая нажатой клавишу `Shift`, на любые ссылки на блоки, чтобы открыть их на правой боковой панели. Попробуйте внести некоторые изменения на правой боковой панели, эти блоки также будут изменены! - ((5f713e91-8a3c-4b04-a33a-c39482428e2d)) : Это ссылка на блок. - - ((5f713ea8-8cba-403d-ac00-9964b1ec7190)) : Это еще одна ссылка на блок. + - ((5f713ea8-8cba-403d-ac00-9964b1ec7190)) : Это ещё одна ссылка на блок. - 3. Поддерживаются ли теги? - - Разумеется! например, добавим тег #образец. + - Разумеется! Например, добавим тег #образец. - 4. Поддерживаются ли задачи todo/doing/done и их приоритеты? - Да, введите `/` и выберите подходящее ключевое todo-слово или приоритет (A/B/C). - NOW [#A] Руководство для начинающих "Как создать образец заметки?" @@ -21,7 +21,7 @@ {{youtube https://www.youtube.com/watch?v=BhHfF0P9A80&ab_channel=ShuOmi}} - DONE Создать страницу - - CANCELED [#C] Создать страницу с более чем 1000 блоков -- Вот и все! Теперь вы можете создать больше пунктов маркированного списка или открыть локальный каталог, чтобы импортировать заметки! + - CANCELED [#C] Создать страницу с более чем тысячью блоков +- Вот и всё! Теперь вы можете создать больше пунктов нумерованного списка или открыть локальный каталог, чтобы импортировать заметки! - Вы также можете загрузить наше приложение для настольных компьютеров по адресу https://github.com/logseq/logseq/releases \ No newline at end of file diff --git a/templates/zotero-items.edn b/src/resources/zotero-items.edn similarity index 100% rename from templates/zotero-items.edn rename to src/resources/zotero-items.edn diff --git a/src/test/frontend/components/block/macros_test.cljs b/src/test/frontend/components/block/macros_test.cljs new file mode 100644 index 00000000000..d40fbbf2013 --- /dev/null +++ b/src/test/frontend/components/block/macros_test.cljs @@ -0,0 +1,46 @@ +(ns frontend.components.block.macros-test + (:require [frontend.components.block.macros :as block-macros] + [frontend.db.utils :as db-utils] + [clojure.test :refer [deftest are testing is]])) + +(deftest macro-function + (testing "Default functions as an argument" + (are [user-input result] + (= result + (block-macros/function-macro + (mapv #(hash-map :block/properties %) [{:total 10} {:total 20} {:total 30}]) + [user-input])) + "(sum :total)" 60 + "(average :total)" 20 + "(max :total)" 30 + "(min :total)" 10 + "(count :total)" 3)) + + (testing "Custom clojure function as an argument" + (is (= 130 + (block-macros/function-macro + (mapv #(hash-map :block/properties %) + [{:total 10 :qty 3} {:total 20 :qty 5}]) + ["(sum (map (fn [x] (* (:total x) (:qty x))) result))"])))) + + (testing "When query results are in page view" + (is (= 60 + (block-macros/function-macro + (db-utils/group-by-page + [{:block/properties {:total 10} :block/page 1} + {:block/properties {:total 20} :block/page 2} + {:block/properties {:total 30} :block/page 1}]) + ["(sum :total)"])) + "Default function works like in query table view")) + + (testing "Edge cases" + (is (= 40 + (block-macros/function-macro + (mapv #(hash-map :block/properties %) [{:total 10} {} {:total 30}]) + ["(sum :total)"])) + "Function still works when some results are missing property") + (is (= 0 + (block-macros/function-macro + (mapv #(hash-map :block/properties %) [{:total 10} {} {:total 30}]) + ["(sum :totally)"])) + "Function gives back 0 when given wrong property"))) diff --git a/src/test/frontend/components/query/result_test.cljs b/src/test/frontend/components/query/result_test.cljs index 99528502572..d83ad36f3c7 100644 --- a/src/test/frontend/components/query/result_test.cljs +++ b/src/test/frontend/components/query/result_test.cljs @@ -8,11 +8,11 @@ (defn- mock-get-query-result "Mocks get-query-result assuming custom queries are being tested. Db calls are mocked to minimize setup" - [result query {:keys [table? current-block-uuid]}] + [result query-m {:keys [table? current-block-uuid config] :or {config {}}}] (with-redefs [db/custom-query (constantly (atom result)) model/with-pages identity] (binding [rum/*reactions* (volatile! #{})] - (#'query-result/get-query-result {} {} (atom nil) (atom nil) current-block-uuid query {:table? table?})))) + (#'query-result/get-query-result config query-m (atom nil) current-block-uuid {:table? table?})))) (deftest get-query-result-with-transforms-and-grouping (let [result (mapv @@ -22,8 +22,8 @@ {:block/uuid (random-uuid) :block/scheduled 20230417}]) sorted-result (sort-by :block/scheduled result)] (testing "For list view" - (are [query expected] - (= expected (mock-get-query-result result query {:table? false})) + (are [query-m expected] + (= expected (mock-get-query-result result query-m {:table? false})) ;; Default list behavior is to group result {} @@ -75,3 +75,11 @@ (is (= result (mock-get-query-result result {:remove-block-children? false} {:table? true})) "Doesn't remove children when :remove-block-children? is false"))) + +(deftest get-query-result-sets-result-in-config + (let [result [{:db/id 1 :block/content "parent" :block/uuid 1}] + config {:query-result (atom nil)}] + (is (= result + (mock-get-query-result result {} {:table? true :config config}))) + (is (= result @(:query-result config)) + "Result is set in config for downstream use e.g. query table fn"))) \ No newline at end of file diff --git a/src/test/frontend/handler/common/config_edn_test.cljs b/src/test/frontend/handler/common/config_edn_test.cljs index c96e0be9cc4..d8eb56d6238 100644 --- a/src/test/frontend/handler/common/config_edn_test.cljs +++ b/src/test/frontend/handler/common/config_edn_test.cljs @@ -60,7 +60,7 @@ (deftest detect-deprecations (is (re-find - #":editor/command-trigger.*Will" + #":editor/command-trigger.*is" (deprecation-warnings-for "{:preferred-workflow :todo :editor/command-trigger \",\"}")) "Warning when there is a deprecation") diff --git a/src/test/frontend/handler/editor_test.cljs b/src/test/frontend/handler/editor_test.cljs index d30d6f31ed1..daba691e75d 100644 --- a/src/test/frontend/handler/editor_test.cljs +++ b/src/test/frontend/handler/editor_test.cljs @@ -6,7 +6,9 @@ [frontend.test.helper :as test-helper :refer [load-test-files]] [frontend.db.model :as model] [frontend.state :as state] - [frontend.util.cursor :as cursor])) + [frontend.util.cursor :as cursor] + [goog.dom :as gdom] + [frontend.util :as util])) (use-fixtures :each test-helper/start-and-destroy-db) @@ -255,3 +257,69 @@ (editor/save-block! repo block-uuid "# bar") (is (= "# bar" (:block/content (model/query-block-by-uuid block-uuid))))))) + +(defn- delete-block + [db block {:keys [embed?]}] + (let [sibling-block (d/entity db (get-in block [:block/left :db/id])) + first-block (d/entity db (get-in sibling-block [:block/left :db/id])) + block-dom-id "ls-block-block-to-delete"] + (with-redefs [editor/get-state (constantly {:block-id (:block/uuid block) + :block-parent-id block-dom-id + :config {:embed? embed?}}) + ;; stub for delete-block + gdom/getElement (constantly #js {:id block-dom-id}) + ;; stub since not testing moving + editor/edit-block! (constantly nil) + util/get-blocks-noncollapse (constantly (mapv + (fn [m] + #js {:id (:id m) + ;; for dom/attr + :getAttribute #({"blockid" (str (:block-uuid m)) + "data-embed" (if embed? "true" "false")} %)}) + [{:id "ls-block-first-block" + :block-uuid (:block/uuid first-block)} + {:id "ls-block-sibling-block" + :block-uuid (:block/uuid sibling-block)} + {:id block-dom-id + :block-uuid (:block/uuid block)}]))] + (editor/delete-block! test-helper/test-db false)))) + +(deftest delete-block! + (testing "backspace deletes empty block" + (load-test-files [{:file/path "pages/page1.md" + :file/content "\n +- b1 +- b2 +-"}]) + (let [conn (db/get-db test-helper/test-db false) + block (->> (d/q '[:find (pull ?b [*]) + :where [?b :block/content ""] [?b :block/page [:block/name "page1"]]] + @conn) + ffirst) + _ (delete-block @conn block {}) + updated-blocks (->> (d/q '[:find (pull ?b [*]) + :where [?b :block/content] [(missing? $ ?b :block/pre-block?)]] + @conn) + (map (comp :block/content first)))] + (is (= ["b1" "b2"] updated-blocks) "Block is deleted")) + (test-helper/reset-test-db!)) + + (testing "backspace deletes empty block in embedded context" + ;; testing embed at this layer doesn't require an embed block since + ;; delete-block handles all the embed setup + (load-test-files [{:file/path "pages/page1.md" + :file/content "\n +- b1 +- b2 +-"}]) + (let [conn (db/get-db test-helper/test-db false) + block (->> (d/q '[:find (pull ?b [*]) + :where [?b :block/content ""] [?b :block/page [:block/name "page1"]]] + @conn) + ffirst) + _ (delete-block @conn block {:embed? true}) + updated-blocks (->> (d/q '[:find (pull ?b [*]) + :where [?b :block/content] [(missing? $ ?b :block/pre-block?)]] + @conn) + (map (comp :block/content first)))] + (is (= ["b1" "b2"] updated-blocks) "Block is deleted")))) \ No newline at end of file diff --git a/src/test/frontend/handler/paste_test.cljs b/src/test/frontend/handler/paste_test.cljs index 0718a1b6c8e..c03046e33c1 100644 --- a/src/test/frontend/handler/paste_test.cljs +++ b/src/test/frontend/handler/paste_test.cljs @@ -6,6 +6,7 @@ [frontend.state :as state] [frontend.commands :as commands] [frontend.util :as util] + [frontend.util.cursor :as cursor] [promesa.core :as p] [frontend.extensions.html-parser :as html-parser] [frontend.handler.editor :as editor-handler] @@ -105,21 +106,58 @@ (reset))))) (deftest-async editor-on-paste-with-link - (testing "Formatted paste for link should paste macro wrapped link" + (testing "Formatted paste for special link should paste macro wrapped link" (let [clipboard "https://www.youtube.com/watch?v=xu9p5ynlhZk" expected-paste "{{video https://www.youtube.com/watch?v=xu9p5ynlhZk}}"] (test-helper/with-reset reset - [state/get-input (constantly #js {:value "block"}) - ;; paste-copied-blocks-or-text mocks below + [;; paste-copied-blocks-or-text mocks below commands/delete-selection! (constantly nil) commands/simple-insert! (fn [_input text] (p/resolved text)) util/stop (constantly nil) + util/get-selected-text (constantly "") html-parser/convert (constantly nil)] (p/let [result ((paste-handler/editor-on-paste! nil) #js {:clipboardData #js {:getData (constantly clipboard)}})] - (is (= expected-paste result)) - (reset)))))) + (is (= expected-paste result)) + (reset)))))) + +(deftest-async editor-on-paste-with-selected-text-and-special-link + (testing "Formatted paste with special link on selected text pastes a formatted link" + (let [actual-text (atom nil) + clipboard "https://www.youtube.com/watch?v=xu9p5ynlhZk" + selected-text "great song" + block-content (str selected-text " - Obaluaê!") + expected-paste "[great song](https://www.youtube.com/watch?v=xu9p5ynlhZk) - Obaluaê!"] + (test-helper/with-reset + reset + [;; paste-copied-blocks-or-text mocks below + util/stop (constantly nil) + util/get-selected-text (constantly selected-text) + editor-handler/get-selection-and-format + (constantly {:selection-start 0 :selection-end (count selected-text) + :selection selected-text :format :markdown :value block-content}) + state/set-edit-content! (fn [_ new-value] (reset! actual-text new-value)) + cursor/move-cursor-to (constantly nil)] + (p/let [_ ((paste-handler/editor-on-paste! nil) + #js {:clipboardData #js {:getData (constantly clipboard)}})] + (is (= expected-paste @actual-text)) + (reset)))))) + +(deftest-async editor-on-paste-with-block-ref-in-between-parens + (let [clipboard "((647f90f4-d733-4ee2-bbf5-907e820a23d3))" + expected-paste "647f90f4-d733-4ee2-bbf5-907e820a23d3"] + (test-helper/with-reset + reset + [;; paste-copied-blocks-or-text mocks below + util/stop (constantly nil) + state/get-input (constantly #js {:value "(())"}) + cursor/pos (constantly 2) + commands/simple-insert! (fn [_input text] (p/resolved text))] + (p/let [result ((paste-handler/editor-on-paste! nil) + #js {:clipboardData #js {:getData (constantly clipboard)}})] + (is (= expected-paste result)) + (reset))))) (deftest-async editor-on-paste-with-copied-blocks (let [actual-blocks (atom nil) @@ -129,15 +167,14 @@ clipboard "- Test node\n\t- Notes\nid:: 6422ec75-85c7-4e09-9a4d-2a1639a69b2f"] (test-helper/with-reset reset - [state/get-input (constantly #js {:value "block"}) - ;; paste-copied-blocks-or-text mocks below + [;; paste-copied-blocks-or-text mocks below util/stop (constantly nil) paste-handler/get-copied-blocks (constantly (p/resolved expected-blocks)) editor-handler/paste-blocks (fn [blocks _] (reset! actual-blocks blocks))] (p/let [_ ((paste-handler/editor-on-paste! nil) - #js {:clipboardData #js {:getData (constantly clipboard)}})] - (is (= expected-blocks @actual-blocks)) - (reset))))) + #js {:clipboardData #js {:getData (constantly clipboard)}})] + (is (= expected-blocks @actual-blocks)) + (reset))))) (deftest-async editor-on-paste-with-selection-in-property (let [clipboard "after" @@ -183,8 +220,7 @@ text "- Test node\n\t- Notes\nid:: 6422ec75-85c7-4e09-9a4d-2a1639a69b2f"] (test-helper/with-reset reset - [state/get-input (constantly #js {:value "block"}) - ;; paste-copied-blocks-or-text mocks below + [;; paste-copied-blocks-or-text mocks below util/stop (constantly nil) html-parser/convert (constantly "**bold text**") paste-handler/get-copied-blocks (constantly (p/resolved nil)) diff --git a/src/test/frontend/modules/outliner/core_test.cljs b/src/test/frontend/modules/outliner/core_test.cljs index 43c7498f84e..b33ef86022a 100644 --- a/src/test/frontend/modules/outliner/core_test.cljs +++ b/src/test/frontend/modules/outliner/core_test.cljs @@ -245,7 +245,7 @@ :db/id 147, :block/parent #:db{:id 144}, :block/page #:db{:id 144}}]] - (= blocks (outliner-core/fix-top-level-blocks blocks))))) + (is (= blocks (outliner-core/fix-top-level-blocks blocks)))))) (deftest test-outdent-blocks (testing " @@ -734,41 +734,42 @@ tags:: tag1, tag2 :block/uuid #uuid "62f4b8c6-072e-4133-90e2-0591021a7fea", :block/parent #:db{:id 2333}, :db/id 2334}]] - (= (tree/non-consecutive-blocks->vec-tree blocks) - '({:db/id 2315, - :block/uuid #uuid "62f49b4c-f9f0-4739-9985-8bd55e4c68d4", - :block/parent #:db{:id 2313}, - :block/page #:db{:id 2313}, - :block/level 1, - :block/children - [{:db/id 2316, - :block/uuid #uuid "62f49b4c-aa84-416e-9554-b486b4e59b1b", - :block/parent #:db{:id 2315}, - :block/page #:db{:id 2313}, - :block/level 2, - :block/children - [{:db/id 2317, - :block/uuid #uuid "62f49b4c-f80c-49b4-ae83-f78c4520c071", - :block/parent #:db{:id 2316}, - :block/page #:db{:id 2313}, - :block/level 3, - :block/children - [{:db/id 2318, - :block/uuid #uuid "62f49b4c-8f5b-4a04-b749-68d34b28bcf2", - :block/parent #:db{:id 2317}, - :block/page #:db{:id 2313}, - :block/level 4}]}]} - {:db/id 2333, - :block/uuid #uuid "62f4b8c1-a99b-434f-84c3-011d6afc48ba", - :block/parent #:db{:id 2315}, - :block/page #:db{:id 2313}, - :block/level 2, - :block/children - [{:db/id 2334, - :block/uuid #uuid "62f4b8c6-072e-4133-90e2-0591021a7fea", - :block/parent #:db{:id 2333}, - :block/page #:db{:id 2313}, - :block/level 3}]}]})))) + (is + (= (tree/non-consecutive-blocks->vec-tree blocks) + '({:db/id 2315, + :block/uuid #uuid "62f49b4c-f9f0-4739-9985-8bd55e4c68d4", + :block/parent #:db{:id 2313}, + :block/page #:db{:id 2313}, + :block/level 1, + :block/children + [{:db/id 2316, + :block/uuid #uuid "62f49b4c-aa84-416e-9554-b486b4e59b1b", + :block/parent #:db{:id 2315}, + :block/page #:db{:id 2313}, + :block/level 2, + :block/children + [{:db/id 2317, + :block/uuid #uuid "62f49b4c-f80c-49b4-ae83-f78c4520c071", + :block/parent #:db{:id 2316}, + :block/page #:db{:id 2313}, + :block/level 3, + :block/children + [{:db/id 2318, + :block/uuid #uuid "62f49b4c-8f5b-4a04-b749-68d34b28bcf2", + :block/parent #:db{:id 2317}, + :block/page #:db{:id 2313}, + :block/level 4}]}]} + {:db/id 2333, + :block/uuid #uuid "62f4b8c1-a99b-434f-84c3-011d6afc48ba", + :block/parent #:db{:id 2315}, + :block/page #:db{:id 2313}, + :block/level 2, + :block/children + [{:db/id 2334, + :block/uuid #uuid "62f4b8c6-072e-4133-90e2-0591021a7fea", + :block/parent #:db{:id 2333}, + :block/page #:db{:id 2313}, + :block/level 3}]}]}))))) (comment (dotimes [i 5] diff --git a/src/test/frontend/test/helper.cljs b/src/test/frontend/test/helper.cljs index e4c3d6e52a8..1befc262fc2 100644 --- a/src/test/frontend/test/helper.cljs +++ b/src/test/frontend/test/helper.cljs @@ -14,6 +14,11 @@ [] (conn/destroy-all!)) +(defn reset-test-db! + [] + (destroy-test-db!) + (start-test-db!)) + (defn load-test-files "Given a collection of file maps, loads them into the current test-db. This can be called in synchronous contexts as no async fns should be invoked" diff --git a/src/test/frontend/util/clocktime_test.cljs b/src/test/frontend/util/clocktime_test.cljs index d57ac849a2c..481309766d8 100644 --- a/src/test/frontend/util/clocktime_test.cljs +++ b/src/test/frontend/util/clocktime_test.cljs @@ -14,4 +14,4 @@ [0, 17, 45, 53], [5, 14, 41, 22], [27, 17, 8, 23]]] - (map #(is (= (clock/s->dhms-util %1) %2)) inputs want))) \ No newline at end of file + (mapv #(is (= (clock/s->dhms-util %1) %2)) inputs want))) \ No newline at end of file diff --git a/src/test/frontend/util/property_test.cljs b/src/test/frontend/util/property_test.cljs index 2e556223ce1..5ff988b8b38 100644 --- a/src/test/frontend/util/property_test.cljs +++ b/src/test/frontend/util/property_test.cljs @@ -200,16 +200,49 @@ SCHEDULED: <2021-10-25 Mon>\n:PROPERTIES:\n:a: b\n:END:\nworld\n" "c" "d") (let [org-property ":PROPERTIES:\n:query-table: true\n:END:"] (are [x y] (= (property/with-built-in-properties {:query-table true} x :org) y) - content - (str org-property "\n" content) - - "title" - (str "title\n" org-property) - - "title\nbody" - (str "title\n" org-property "\nbody") - - "1. list" - (str org-property "\n1. list"))))) - -#_(cljs.test/run-tests) + content + (str org-property "\n" content) + + "title" + (str "title\n" org-property) + + "title\nbody" + (str "title\n" org-property "\nbody") + + "1. list" + (str org-property "\n1. list"))))) + +(deftest get-visible-ordered-properties + (testing "basic cases" + (are [x y expected] (= expected (property/get-visible-ordered-properties x y {})) + ;; returns in property order + {:prop "val" :prop2 "val2"} [:prop2 :prop] + [[:prop2 "val2"] [:prop "val"]] + ;; returns empty non-nil value if properties is non-nil + {} [:prop] + '() + ;; returns nil if properties is nil + nil [] + nil)) + + (testing "hidden properties" + (are [x y z expected] (= expected (property/get-visible-ordered-properties x y z)) + ;; page block + {:logseq.order-list-type "number" :foo "bar"} [:logseq.order-list-type :foo] {:pre-block false} + [[:foo "bar"]] + ;; normal block + {:logseq.order-list-type "number" :foo "bar"} [:logseq.order-list-type :foo] {:pre-block false} + [[:foo "bar"]])) + + (testing "hidden editable properties" + (are [x y z expected] (= expected (property/get-visible-ordered-properties x y z)) + ;; page block + {:title "foo"} [:title] {:pre-block? true} + '() + {:title "foo" :foo "bar"} [:title :foo] {:pre-block? true} + [[:foo "bar"]] + ;; normal block + {:logseq.table.version 2} [:logseq.table.version] {:pre-block? false} + '() + {:logseq.table.version 2 :foo "bar"} [:logseq.table.version :foo] {:pre-block? false} + [[:foo "bar"]]))) \ No newline at end of file diff --git a/static/yarn.lock b/static/yarn.lock index adaeecd7bd5..54fa8937071 100644 --- a/static/yarn.lock +++ b/static/yarn.lock @@ -1344,13 +1344,6 @@ chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1: ansi-styles "^4.1.0" supports-color "^7.1.0" -checksum@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/checksum/-/checksum-0.1.1.tgz#dc6527d4c90be8560dbd1ed4cecf3297d528e9e9" - integrity sha512-xWkkJpoWQ6CptWw2GvtoQbScL3xtvGjoqvHpALE7B0tSHxSw0ex0tlsKOKkbETaOYGBhMliAyscestDyAZIN9g== - dependencies: - optimist "~0.3.5" - chokidar@^3.5.1: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" @@ -1366,7 +1359,7 @@ chokidar@^3.5.1: optionalDependencies: fsevents "~2.3.2" -chownr@^1.1.1, chownr@^1.1.4: +chownr@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== @@ -1812,17 +1805,13 @@ ds-store@^0.1.5: macos-alias "~0.2.5" tn1150 "^0.1.0" -dugite@1.108.0: - version "1.108.0" - resolved "https://registry.yarnpkg.com/dugite/-/dugite-1.108.0.tgz#85f3ad9c4c209d2cd4dbfe24687ad40f49c8c4a4" - integrity sha512-2wwkZM2mJuoxuePFlfNh+UhWWLoorz5kud3L5qjBWQ0ZQi99OUZGtnDesJwc8e9WHtpwHjYGbl1MEgYi1GEgiA== +dugite@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/dugite/-/dugite-2.5.0.tgz#8b235564fdf8692688283c714149a59d9da79865" + integrity sha512-sYsSOqV7NidthDtMUPgKCvqMGqswKkcyAxOMhwEswlcGZ+kHadT2SEDFUJOy0AVR/yTJL6wBF7q1OiySfU0gGA== dependencies: - checksum "^0.1.1" - got "^9.6.0" - mkdirp "^0.5.1" progress "^2.0.3" - rimraf "^2.5.4" - tar "^4.4.7" + tar "^6.1.11" duplexer3@^0.1.4: version "0.1.5" @@ -2500,13 +2489,6 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-minipass@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== - dependencies: - minipass "^2.6.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" @@ -3557,14 +3539,6 @@ minipass-sized@^1.0.3: dependencies: minipass "^3.0.0" -minipass@^2.6.0, minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - minipass@^3.0.0, minipass@^3.1.1, minipass@^3.1.6: version "3.3.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.4.tgz#ca99f95dd77c43c7a76bf51e6d200025eee0ffae" @@ -3572,13 +3546,6 @@ minipass@^3.0.0, minipass@^3.1.1, minipass@^3.1.6: dependencies: yallist "^4.0.0" -minizlib@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== - dependencies: - minipass "^2.9.0" - minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" @@ -3592,7 +3559,7 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp@^0.5.1, mkdirp@^0.5.5: +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== @@ -3811,13 +3778,6 @@ open@7.3.1: is-docker "^2.0.0" is-wsl "^2.1.1" -optimist@~0.3.5: - version "0.3.7" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9" - integrity sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ== - dependencies: - wordwrap "~0.0.2" - ora@^5.0.0, ora@^5.1.0: version "5.4.1" resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" @@ -4381,7 +4341,7 @@ rfdc@^1.2.0, rfdc@^1.3.0: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== -rimraf@^2.5.4, rimraf@^2.6.3: +rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -4428,7 +4388,7 @@ rxjs@^7.5.7: dependencies: tslib "^2.1.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, 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== @@ -4804,19 +4764,6 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" -tar@^4.4.7: - version "4.4.19" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" - integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== - dependencies: - chownr "^1.1.4" - fs-minipass "^1.2.7" - minipass "^2.9.0" - minizlib "^1.3.3" - mkdirp "^0.5.5" - safe-buffer "^5.2.1" - yallist "^3.1.1" - tar@^6.0.5, tar@^6.1.11, tar@^6.1.2: version "6.1.11" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" @@ -5164,11 +5111,6 @@ word-wrap@^1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw== - wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -5227,11 +5169,6 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yallist@^3.0.0, yallist@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" diff --git a/tailwind.config.js b/tailwind.config.js index 40a34dc7596..c5a2fb14df8 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -213,6 +213,11 @@ module.exports = { '250': '2.5', '300': '3', '400': '4', + }, + width: { + 'lsm': '600px', + 'lmd': '728px', + 'llg': '960px' } }, colors: { diff --git a/templates/favorites.md b/templates/favorites.md deleted file mode 100644 index 39cdd0ded6d..00000000000 --- a/templates/favorites.md +++ /dev/null @@ -1 +0,0 @@ -- diff --git a/templates/favorites.org b/templates/favorites.org deleted file mode 100644 index 72e8ffc0db8..00000000000 --- a/templates/favorites.org +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/tldraw/apps/tldraw-logseq/src/components/ActionBar/ActionBar.tsx b/tldraw/apps/tldraw-logseq/src/components/ActionBar/ActionBar.tsx index 86bf68cb60a..430783b6a08 100644 --- a/tldraw/apps/tldraw-logseq/src/components/ActionBar/ActionBar.tsx +++ b/tldraw/apps/tldraw-logseq/src/components/ActionBar/ActionBar.tsx @@ -6,11 +6,16 @@ import * as React from 'react' import type { Shape } from '../../lib' import { TablerIcon } from '../icons' import { Button } from '../Button' +import { ToggleInput } from '../inputs/ToggleInput' import { ZoomMenu } from '../ZoomMenu' import * as Separator from '@radix-ui/react-separator' +import { LogseqContext } from '../../lib/logseq-context' export const ActionBar = observer(function ActionBar(): JSX.Element { const app = useApp() + const { + handlers: { t }, + } = React.useContext(LogseqContext) const undo = React.useCallback(() => { app.api.undo() @@ -28,29 +33,61 @@ export const ActionBar = observer(function ActionBar(): JSX.Element { app.api.zoomOut() }, [app]) + const toggleGrid = React.useCallback(() => { + app.api.toggleGrid() + }, [app]) + + const toggleSnapToGrid = React.useCallback(() => { + app.api.toggleSnapToGrid() + }, [app]) + return (
{!app.readOnly && (
- -
)}
- -
+ +
+ + + + + {!app.readOnly && ( + + + + )} +
) }) diff --git a/tldraw/apps/tldraw-logseq/src/components/ContextBar/contextBarActionFactory.tsx b/tldraw/apps/tldraw-logseq/src/components/ContextBar/contextBarActionFactory.tsx index ce6f2197f1b..d560f53840c 100644 --- a/tldraw/apps/tldraw-logseq/src/components/ContextBar/contextBarActionFactory.tsx +++ b/tldraw/apps/tldraw-logseq/src/components/ContextBar/contextBarActionFactory.tsx @@ -92,13 +92,16 @@ function filterShapeByAction(type: ContextBarActionType) { const AutoResizingAction = observer(() => { const app = useApp() + const { + handlers: { t }, + } = React.useContext(LogseqContext) const shapes = filterShapeByAction('AutoResizing') const pressed = shapes.every(s => s.props.isAutoResizing) return ( s.props.type === 'logseq-portal')} className="tl-button" pressed={pressed} @@ -122,6 +125,9 @@ const AutoResizingAction = observer(() => { const LogseqPortalViewModeAction = observer(() => { const app = useApp() + const { + handlers: { t }, + } = React.useContext(LogseqContext) const shapes = filterShapeByAction('LogseqPortalViewMode') const collapsed = shapes.every(s => s.collapsed) @@ -131,7 +137,7 @@ const LogseqPortalViewModeAction = observer(() => { const tooltip = (
- {collapsed ? 'Expand' : 'Collapse'} + {collapsed ? t('whiteboard/expand') : t('whiteboard/collapse')} @@ -164,6 +170,9 @@ const ScaleLevelAction = observer(() => { const IFrameSourceAction = observer(() => { const app = useApp() + const { + handlers: { t }, + } = React.useContext(LogseqContext) const shape = filterShapeByAction('IFrameSource')[0] const handleChange = React.useCallback((e: React.ChangeEvent) => { @@ -177,16 +186,20 @@ const IFrameSourceAction = observer(() => { return ( - - @@ -195,6 +208,9 @@ const IFrameSourceAction = observer(() => { const YoutubeLinkAction = observer(() => { const app = useApp() + const { + handlers: { t }, + } = React.useContext(LogseqContext) const shape = filterShapeByAction('YoutubeLink')[0] const handleChange = React.useCallback((e: React.ChangeEvent) => { shape.onYoutubeLinkChange(e.target.value) @@ -204,13 +220,13 @@ const YoutubeLinkAction = observer(() => { return (
)}