From 3d3f8b421781c13f6019cec0ca82453e2379a041 Mon Sep 17 00:00:00 2001 From: AgentStart1 <295559726+AgentStart1@users.noreply.github.com> Date: Sat, 3 Oct 2026 02:23:00 +0000 Subject: [PATCH] Build shared browser UI as an npm project --- .github/dependabot.yml | 9 + .github/workflows/release.yml | 10 + .github/workflows/test.yml | 22 + .gitignore | 6 +- DEVELOPMENT.md | 115 +- app/build.gradle.kts | 58 + app/src/main/resources/web/icons/LICENSE | 21 - .../main/resources/web/icons/chat-dots.svg | 1 - .../main/resources/web/icons/circle-fill.svg | 1 - app/src/main/resources/web/icons/copy.svg | 1 - .../resources/web/icons/download-simple.svg | 1 - .../main/resources/web/icons/file-image.svg | 1 - app/src/main/resources/web/icons/file-pdf.svg | 1 - app/src/main/resources/web/icons/file-ppt.svg | 1 - app/src/main/resources/web/icons/file-zip.svg | 1 - app/src/main/resources/web/icons/file.svg | 1 - .../resources/web/vendor/markdown-it/LICENSE | 22 - .../markdown-it/THIRD-PARTY-NOTICES.txt | 136 - .../markdown-it/markdown-it.esm.min.mjs | 3011 ----------------- .../com/storyteller_f/feiya/WebPagesTest.kt | 4 +- design-qa.md | 10 +- scripts/check-web-apk.py | 41 + tests/web/package-lock.json | 168 - tests/web/package.json | 16 - tests/web/vendor-markdown.mjs | 53 - web/.npmrc | 1 + web/.nvmrc | 1 + web/package-lock.json | 658 ++++ web/package.json | 24 + web/scripts/build.mjs | 89 + .../src/main/resources/web => web/src}/app.js | 0 .../main/resources/web => web/src}/host.js | 0 .../resources/web => web/src}/markdown.mjs | 2 +- .../feiya => web/src/pages}/chat.html | 0 .../feiya => web/src/pages}/index.html | 0 .../feiya => web/src/pages}/login.html | 0 .../main/resources/web => web/src}/style.css | 0 .../main/resources/web => web/src}/worker.js | 0 {tests/web => web/test}/browser.test.mjs | 0 web/test/build.test.mjs | 44 + {tests/web => web/test}/host.test.mjs | 12 +- {tests/web => web/test}/markdown.test.mjs | 2 +- {tests/web => web/test}/preview.mjs | 4 +- 43 files changed, 1040 insertions(+), 3508 deletions(-) delete mode 100644 app/src/main/resources/web/icons/LICENSE delete mode 100644 app/src/main/resources/web/icons/chat-dots.svg delete mode 100644 app/src/main/resources/web/icons/circle-fill.svg delete mode 100644 app/src/main/resources/web/icons/copy.svg delete mode 100644 app/src/main/resources/web/icons/download-simple.svg delete mode 100644 app/src/main/resources/web/icons/file-image.svg delete mode 100644 app/src/main/resources/web/icons/file-pdf.svg delete mode 100644 app/src/main/resources/web/icons/file-ppt.svg delete mode 100644 app/src/main/resources/web/icons/file-zip.svg delete mode 100644 app/src/main/resources/web/icons/file.svg delete mode 100644 app/src/main/resources/web/vendor/markdown-it/LICENSE delete mode 100644 app/src/main/resources/web/vendor/markdown-it/THIRD-PARTY-NOTICES.txt delete mode 100644 app/src/main/resources/web/vendor/markdown-it/markdown-it.esm.min.mjs create mode 100644 scripts/check-web-apk.py delete mode 100644 tests/web/package-lock.json delete mode 100644 tests/web/package.json delete mode 100644 tests/web/vendor-markdown.mjs create mode 100644 web/.npmrc create mode 100644 web/.nvmrc create mode 100644 web/package-lock.json create mode 100644 web/package.json create mode 100644 web/scripts/build.mjs rename {app/src/main/resources/web => web/src}/app.js (100%) rename {app/src/main/resources/web => web/src}/host.js (100%) rename {app/src/main/resources/web => web/src}/markdown.mjs (92%) rename {app/src/main/resources/feiya => web/src/pages}/chat.html (100%) rename {app/src/main/resources/feiya => web/src/pages}/index.html (100%) rename {app/src/main/resources/feiya => web/src/pages}/login.html (100%) rename {app/src/main/resources/web => web/src}/style.css (100%) rename {app/src/main/resources/web => web/src}/worker.js (100%) rename {tests/web => web/test}/browser.test.mjs (100%) create mode 100644 web/test/build.test.mjs rename {tests/web => web/test}/host.test.mjs (90%) rename {tests/web => web/test}/markdown.test.mjs (95%) rename {tests/web => web/test}/preview.mjs (97%) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 34b0305..41df9e5 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,5 +1,14 @@ version: 2 updates: + - package-ecosystem: npm + directory: "/web" + groups: + web-dependencies: + patterns: + - "*" + schedule: + interval: weekly + - package-ecosystem: gradle directory: "/" groups: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8b629bd..023e9de 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,6 +15,13 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Set up Node.js + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version-file: web/.nvmrc + cache: npm + cache-dependency-path: web/package-lock.json + - name: Set up JDK 21 uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: @@ -37,6 +44,9 @@ jobs: storyteller_f_sign_store_password: ${{ secrets.STORE_PASSWORD }} storyteller_f_sign_key_password: ${{ secrets.KEY_PASSWORD }} + - name: Verify packaged web resources + run: python3 scripts/check-web-apk.py web/dist app/build/outputs/apk/*/*.apk + - name: Upload artifact if: "!startsWith(github.ref, 'refs/tags/')" uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b19185c..075d166 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,6 +11,13 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Set up Node.js + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version-file: web/.nvmrc + cache: npm + cache-dependency-path: web/package-lock.json + - name: Set up JDK 21 uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: @@ -18,6 +25,18 @@ jobs: distribution: 'temurin' cache: gradle + - name: Install web dependencies + run: npm ci --prefix web + + - name: Test web state and Markdown + run: npm --prefix web test + + - name: Install Chromium + run: npm --prefix web exec -- playwright install --with-deps chromium + + - name: Test the bundled browser UI + run: npm --prefix web run test:browser + - name: Run tests run: ./gradlew test @@ -25,6 +44,9 @@ jobs: - name: Build minified APKs run: ./gradlew :app:assembleAlpha :app:assembleRelease + - name: Verify web resources in minified APKs + run: python3 scripts/check-web-apk.py web/dist app/build/outputs/apk/alpha/*.apk app/build/outputs/apk/release/*.apk + - name: Sign disposable minified APK copies run: scripts/sign-smoke-apks.sh "$RUNNER_TEMP/minified-smoke" app/build/outputs/apk/alpha/app-x86_64-alpha-unsigned.apk app/build/outputs/apk/release/app-x86_64-release-unsigned.apk diff --git a/.gitignore b/.gitignore index 7746743..d3001f3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,7 @@ local.properties /.idea/deploymentTargetDropDown.xml .kotlin # Browser development tools and screenshots -/tests/web/node_modules/ -/tests/web/artifacts/ +/web/node_modules/ +/web/test/artifacts/ + +/web/dist/ diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 53e0059..80a6157 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -1,7 +1,8 @@ # Development Use JDK 21 or later and an Android SDK with platform 37. Set `ANDROID_HOME` to the SDK -directory (or configure `sdk.dir` in your local `local.properties`). +directory (or configure `sdk.dir` in your local `local.properties`). Install Node.js +24 and npm on `PATH` as well; Android builds compile the shared browser UI automatically. ```sh ./gradlew :app:testDebugUnitTest :app:assembleDebug @@ -204,60 +205,76 @@ have a timeout and propagate failures instead of swallowing them. ## Shared browser UI -The production pages live in `app/src/main/resources/feiya`: `index.html`, `login.html`, -and `chat.html`. Shared styles, JavaScript, and icons live in the sibling `web/` directory. -The page namespace avoids collisions with dependency resources such as `index.html`. -Ktor serves -`/login` and `/web/*` before authentication, and `/` and `/messages` after session -validation. `/shares`, `/shares/{index}`, `/sse`, and `/chat` retain their existing -protocols. File downloads still use server list indices. +`web/` is a standalone npm project. HTML lives in `web/src/pages`, and the app, +Worker, Host, Markdown adapter, and stylesheet live in `web/src`. Runtime libraries +(`markdown-it` and `@phosphor-icons/core`) are declared in `web/package.json` and +locked in `web/package-lock.json`. Build/test tools are devDependencies. Dependabot +checks `/web` weekly, including transitive updates through the lockfile. -`web/host.js` owns asynchronous feature state and effects without DOM dependencies. -`web/worker.js` injects browser networking and timers in one dedicated Worker per -page. `web/app.js` renders snapshots and owns the immediately updated text draft. -Page exit terminates the Worker; a back/forward cache restore starts a fresh Host. -Messages are not automatically replayed after disconnect. Clipboard copying uses -the secure-context API when available and a user-gesture fallback for LAN HTTP. - -Run the isolated web checks with Node.js 22 or later: +Use Node.js 24 (`web/.nvmrc`) and npm: ```sh -npm ci --prefix tests/web -npm --prefix tests/web test -npm --prefix tests/web exec -- playwright install --with-deps chromium -npm --prefix tests/web run test:browser -npm --prefix tests/web run preview +npm ci --prefix web +npm --prefix web run build +npm --prefix web test +npm --prefix web exec -- playwright install --with-deps chromium +npm --prefix web run test:browser +npm --prefix web run preview ``` -The preview runs on `127.0.0.1:4173` with mock HTTP/SSE/WebSocket data; it is not an -Android end-to-end test. Browser tests save desktop/mobile screenshots to ignored -`tests/web/artifacts/`. `WebPagesTest` separately checks the real Ktor routes, -authentication redirects, login, and bundled assets using a JVM server. - -Icons are vendored from [Phosphor Icons core 2.1.1](https://github.com/phosphor-icons/core) -under its MIT license (`web/icons/LICENSE`). They need no runtime package or CDN. -Use upstream SVG assets when adding icons and retain the license. - -### Message Markdown - -The Worker injects `web/markdown.mjs` into the Host and parses each incoming -message once. It ignores any HTML supplied by the sender and publishes locally -generated HTML alongside the original text. The DOM layer renders that markup; -copying always uses the original text. Raw HTML stays disabled, and markdown-it's -default dangerous-URL validation remains enabled. Links open separately with -`noopener noreferrer`; Markdown images can load their referenced URLs. - -The browser bundle of markdown-it 15.0.2 and its license notices are checked in -under `web/vendor/markdown-it/`; there is no runtime CDN dependency. After updating -the pinned test-tool dependency and lockfile, regenerate the vendored files with: +`build` bundles JavaScript/CSS with esbuild, copies HTML and only referenced icon +assets, and derives third-party license notices from the actual bundled packages. +The output is `web/dist/feiya/*.html` and `web/dist/web/*`. Neither `dist` nor +`node_modules` is committed. No vendoring step is needed when dependencies change. +Update packages with npm and commit both `package.json` and `package-lock.json`. + +### Android packaging + +Every Android variant registers generated Java resources through the AGP variant +API. Gradle runs `:app:installWebDependencies` (`npm ci --include=dev`), then +`:app:buildWeb`, then copies the distribution into its variant-specific generated +resource directory. HTML, JS, CSS, icons, and notices enter the APK on the classpath; +source code, test fixtures, node_modules, and source maps do not. npm installation +and bundling use declared inputs/outputs so unchanged builds skip both tasks. +A deleted node_modules directory or changed lockfile causes a fresh install. +Build failures fail the Android build instead of packaging an old distribution. + +Normal commands such as `./gradlew :app:assembleDebug`, `:app:assembleAlpha`, +`:app:assembleRelease`, and `:app:testDebugUnitTest` generate the web resources +automatically. `./gradlew :app:buildWeb` runs just the web build through Gradle. +CI provisions Node.js for both test and release workflows; the PR workflow also +runs npm tests and Chromium checks against the bundled output. Both workflows +compare APK entries against the npm distribution using: ```sh -npm ci --prefix tests/web -npm --prefix tests/web run vendor:markdown -npm --prefix tests/web test -npm --prefix tests/web run test:browser +python3 scripts/check-web-apk.py web/dist app/build/outputs/apk/*/*.apk ``` -The vendoring script copies the official browser bundle and license files, omitting -only its source-map reference. Keep raw HTML disabled and run the malicious-input -fixtures when changing parser options or adding plugins. +This checks for missing, stale, unexpected, or duplicate web resources and excludes +node_modules from the APK. + +Ktor serves `/login` and `/web/*` before authentication, and `/` and `/messages` +after session validation. The `feiya/` output namespace avoids collisions with +dependency resources such as `index.html`. `/shares`, `/shares/{index}`, `/sse`, +and `/chat` retain their protocols. File downloads still use server list indices. + +### State, Markdown, and verification + +`web/src/host.js` owns asynchronous state and effects without DOM dependencies. +`web/src/worker.js` injects networking, timers, and the Markdown renderer in a +Worker per page. `web/src/app.js` renders snapshots and owns the synchronous draft. +Page exit terminates the Worker; back/forward cache restore starts a fresh Host. +Messages are not replayed after disconnect. Clipboard copying uses the secure API +when available and a user-gesture fallback for LAN HTTP. + +The Worker parses each message once, ignoring any sender-supplied HTML. The page +renders locally generated HTML; copying uses the original text. Raw HTML stays +disabled, and markdown-it's dangerous-URL validation remains enabled. Links open +separately with `noopener noreferrer`; message images can load their referenced +URLs. Run unsafe-input fixtures when changing parser options or adding plugins. + +The preview runs on `127.0.0.1:4173` with mock HTTP/SSE/WebSocket data and serves +the same distribution as the APK. It is not an Android end-to-end test. Browser +tests save screenshots to ignored `web/test/artifacts/`. `WebPagesTest` separately +checks real Ktor routes, session login, and generated JS/CSS/icon/notice resources +using a JVM server. The web build preserves local assets; no CDN is needed. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2275ecf..4047acf 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,7 @@ import com.google.gson.stream.JsonWriter import java.io.FileWriter import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import javax.inject.Inject plugins { alias(libs.plugins.android) @@ -9,6 +10,63 @@ plugins { alias(libs.plugins.compose.compiler) } +// The browser is an independent npm project. Only its distribution becomes Java +// resources; source files and node_modules never enter the APK. +val webDirectory = rootProject.layout.projectDirectory.dir("web") +val webDist = webDirectory.dir("dist") +val npmExecutable = if (System.getProperty("os.name").startsWith("Windows")) "npm.cmd" else "npm" +val installWebDependencies = tasks.register("installWebDependencies") { + group = "build" + description = "Install the browser project's locked npm dependencies." + workingDir(webDirectory) + commandLine(npmExecutable, "ci", "--include=dev", "--no-audit", "--no-fund") + inputs.files(webDirectory.file("package.json"), webDirectory.file("package-lock.json"), + webDirectory.file(".npmrc"), webDirectory.file(".nvmrc")) + inputs.property("nodeVersion", providers.exec { commandLine("node", "--version") }.standardOutput.asText) + inputs.property("npmVersion", providers.exec { commandLine(npmExecutable, "--version") }.standardOutput.asText) + outputs.dir(webDirectory.dir("node_modules")) +} +val buildWeb = tasks.register("buildWeb") { + group = "build" + description = "Bundle the browser UI and npm dependencies." + dependsOn(installWebDependencies) + workingDir(webDirectory) + commandLine(npmExecutable, "run", "build") + inputs.dir(webDirectory.dir("src")) + inputs.dir(webDirectory.dir("scripts")) + inputs.files(webDirectory.file("package.json"), webDirectory.file("package-lock.json")) + inputs.files(installWebDependencies.map { it.outputs.files }) + outputs.dir(webDist) +} + +abstract class SyncWebResources : DefaultTask() { + @get:InputDirectory + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val distribution: DirectoryProperty + + @get:OutputDirectory + abstract val outputDirectory: DirectoryProperty + + @get:Inject + abstract val fileSystemOperations: FileSystemOperations + + @TaskAction + fun copyDistribution() { + fileSystemOperations.sync { + from(distribution) + into(outputDirectory) + } + } +} + +androidComponents.onVariants { variant -> + val webResources = tasks.register("generate${variant.name.replaceFirstChar { it.uppercase() }}WebResources") { + dependsOn(buildWeb) + distribution.set(webDist) + } + variant.sources.resources?.addGeneratedSourceDirectory(webResources, SyncWebResources::outputDirectory) +} + val signPath: String? = System.getenv("storyteller_f_sign_path") val signFile = signPath?.let(rootProject::file) val signAlias: String? = System.getenv("storyteller_f_sign_alias") diff --git a/app/src/main/resources/web/icons/LICENSE b/app/src/main/resources/web/icons/LICENSE deleted file mode 100644 index 78c9810..0000000 --- a/app/src/main/resources/web/icons/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Phosphor Icons - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/app/src/main/resources/web/icons/chat-dots.svg b/app/src/main/resources/web/icons/chat-dots.svg deleted file mode 100644 index f058b2d..0000000 --- a/app/src/main/resources/web/icons/chat-dots.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/src/main/resources/web/icons/circle-fill.svg b/app/src/main/resources/web/icons/circle-fill.svg deleted file mode 100644 index ef26a83..0000000 --- a/app/src/main/resources/web/icons/circle-fill.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/src/main/resources/web/icons/copy.svg b/app/src/main/resources/web/icons/copy.svg deleted file mode 100644 index 8f3dd2e..0000000 --- a/app/src/main/resources/web/icons/copy.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/src/main/resources/web/icons/download-simple.svg b/app/src/main/resources/web/icons/download-simple.svg deleted file mode 100644 index 631dcde..0000000 --- a/app/src/main/resources/web/icons/download-simple.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/src/main/resources/web/icons/file-image.svg b/app/src/main/resources/web/icons/file-image.svg deleted file mode 100644 index 112edc3..0000000 --- a/app/src/main/resources/web/icons/file-image.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/src/main/resources/web/icons/file-pdf.svg b/app/src/main/resources/web/icons/file-pdf.svg deleted file mode 100644 index e7940a7..0000000 --- a/app/src/main/resources/web/icons/file-pdf.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/src/main/resources/web/icons/file-ppt.svg b/app/src/main/resources/web/icons/file-ppt.svg deleted file mode 100644 index 9eb650b..0000000 --- a/app/src/main/resources/web/icons/file-ppt.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/src/main/resources/web/icons/file-zip.svg b/app/src/main/resources/web/icons/file-zip.svg deleted file mode 100644 index d056e0e..0000000 --- a/app/src/main/resources/web/icons/file-zip.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/src/main/resources/web/icons/file.svg b/app/src/main/resources/web/icons/file.svg deleted file mode 100644 index f2e7629..0000000 --- a/app/src/main/resources/web/icons/file.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/src/main/resources/web/vendor/markdown-it/LICENSE b/app/src/main/resources/web/vendor/markdown-it/LICENSE deleted file mode 100644 index 7ffa058..0000000 --- a/app/src/main/resources/web/vendor/markdown-it/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2014 Vitaly Puzrin, Alex Kocharin. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/app/src/main/resources/web/vendor/markdown-it/THIRD-PARTY-NOTICES.txt b/app/src/main/resources/web/vendor/markdown-it/THIRD-PARTY-NOTICES.txt deleted file mode 100644 index de7a944..0000000 --- a/app/src/main/resources/web/vendor/markdown-it/THIRD-PARTY-NOTICES.txt +++ /dev/null @@ -1,136 +0,0 @@ -entities -======== -Copyright (c) Felix Böhm -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -linkify-it -========== -Copyright (c) 2015 Vitaly Puzrin. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - - -mdurl -===== -Copyright (c) 2015 Vitaly Puzrin, Alex Kocharin. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - --------------------------------------------------------------------------------- - -.parse() is based on Joyent's node.js `url` code: - -Copyright Joyent, Inc. and other Node contributors. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - - -punycode.js -=========== -Copyright Mathias Bynens - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -uc.micro -======== -Copyright Mathias Bynens - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/app/src/main/resources/web/vendor/markdown-it/markdown-it.esm.min.mjs b/app/src/main/resources/web/vendor/markdown-it/markdown-it.esm.min.mjs deleted file mode 100644 index a244657..0000000 --- a/app/src/main/resources/web/vendor/markdown-it/markdown-it.esm.min.mjs +++ /dev/null @@ -1,3011 +0,0 @@ -/*! markdown-it 15.0.2 https://github.com/markdown-it/markdown-it @license MIT */ -//#region \0rolldown/runtime.js -var e = Object.defineProperty, t = (t, n) => { - let r = {}; - for (var i in t) e(r, i, { - get: t[i], - enumerable: !0 - }); - return n || e(r, Symbol.toStringTag, { value: "Module" }), r; -}, n = {}; -function r(e) { - let t = n[e]; - if (t) return t; - t = n[e] = []; - for (let e = 0; e < 128; e++) { - let n = String.fromCharCode(e); - t.push(n); - } - for (let n = 0; n < e.length; n++) { - let r = e.charCodeAt(n); - t[r] = "%" + ("0" + r.toString(16).toUpperCase()).slice(-2); - } - return t; -} -function i(e, t) { - typeof t != "string" && (t = i.defaultChars); - let n = r(t); - return e.replace(/(%[a-f0-9]{2})+/gi, function(e) { - let t = ""; - for (let r = 0, i = e.length; r < i; r += 3) { - let a = parseInt(e.slice(r + 1, r + 3), 16); - if (a < 128) { - t += n[a]; - continue; - } - if ((a & 224) == 192 && r + 3 < i) { - let n = parseInt(e.slice(r + 4, r + 6), 16); - if ((n & 192) == 128) { - let e = a << 6 & 1984 | n & 63; - t += e < 128 ? "��" : String.fromCharCode(e), r += 3; - continue; - } - } - if ((a & 240) == 224 && r + 6 < i) { - let n = parseInt(e.slice(r + 4, r + 6), 16), i = parseInt(e.slice(r + 7, r + 9), 16); - if ((n & 192) == 128 && (i & 192) == 128) { - let e = a << 12 & 61440 | n << 6 & 4032 | i & 63; - t += e < 2048 || e >= 55296 && e <= 57343 ? "���" : String.fromCharCode(e), r += 6; - continue; - } - } - if ((a & 248) == 240 && r + 9 < i) { - let n = parseInt(e.slice(r + 4, r + 6), 16), i = parseInt(e.slice(r + 7, r + 9), 16), o = parseInt(e.slice(r + 10, r + 12), 16); - if ((n & 192) == 128 && (i & 192) == 128 && (o & 192) == 128) { - let e = a << 18 & 1835008 | n << 12 & 258048 | i << 6 & 4032 | o & 63; - e < 65536 || e > 1114111 ? t += "����" : (e -= 65536, t += String.fromCharCode(55296 + (e >> 10), 56320 + (e & 1023))), r += 9; - continue; - } - } - t += "�"; - } - return t; - }); -} -i.defaultChars = ";/?:@&=+$,#", i.componentChars = ""; -//#endregion -//#region node_modules/mdurl/lib/encode.mjs -var a = {}; -function o(e) { - let t = a[e]; - if (t) return t; - t = a[e] = []; - for (let e = 0; e < 128; e++) { - let n = String.fromCharCode(e); - /^[0-9a-z]$/i.test(n) ? t.push(n) : t.push("%" + ("0" + e.toString(16).toUpperCase()).slice(-2)); - } - for (let n = 0; n < e.length; n++) t[e.charCodeAt(n)] = e[n]; - return t; -} -function s(e, t, n) { - typeof t != "string" && (n = t, t = s.defaultChars), n === void 0 && (n = !0); - let r = o(t), i = ""; - for (let t = 0, a = e.length; t < a; t++) { - let o = e.charCodeAt(t); - if (n && o === 37 && t + 2 < a && /^[0-9a-f]{2}$/i.test(e.slice(t + 1, t + 3))) { - i += e.slice(t, t + 3), t += 2; - continue; - } - if (o < 128) { - i += r[o]; - continue; - } - if (o >= 55296 && o <= 57343) { - if (o >= 55296 && o <= 56319 && t + 1 < a) { - let n = e.charCodeAt(t + 1); - if (n >= 56320 && n <= 57343) { - i += encodeURIComponent(e[t] + e[t + 1]), t++; - continue; - } - } - i += "%EF%BF%BD"; - continue; - } - i += encodeURIComponent(e[t]); - } - return i; -} -s.defaultChars = ";/?:@&=+$,-_.!~*'()#", s.componentChars = "-_.!~*'()"; -//#endregion -//#region node_modules/mdurl/lib/format.mjs -function c(e) { - let t = ""; - return t += e.protocol || "", t += e.slashes ? "//" : "", t += e.auth ? e.auth + "@" : "", e.hostname && e.hostname.indexOf(":") !== -1 ? t += "[" + e.hostname + "]" : t += e.hostname || "", t += e.port ? ":" + e.port : "", t += e.pathname || "", t += e.search || "", t += e.hash || "", t; -} -//#endregion -//#region node_modules/mdurl/lib/parse.mjs -function l() { - this.protocol = null, this.slashes = null, this.auth = null, this.port = null, this.hostname = null, this.hash = null, this.search = null, this.pathname = null; -} -var u = /^([a-z0-9.+-]+:)/i, d = /:[0-9]*$/, f = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/, p = [ - "%", - "/", - "?", - ";", - "#", - "'", - "{", - "}", - "|", - "\\", - "^", - "`", - "<", - ">", - "\"", - "`", - " ", - "\r", - "\n", - " " -], m = [ - "/", - "?", - "#" -], h = 255, g = /^[+a-z0-9A-Z_-]{0,63}$/, _ = /^([+a-z0-9A-Z_-]{0,63})(.*)$/, v = { - javascript: !0, - "javascript:": !0 -}, y = { - http: !0, - https: !0, - ftp: !0, - gopher: !0, - file: !0, - "http:": !0, - "https:": !0, - "ftp:": !0, - "gopher:": !0, - "file:": !0 -}; -function b(e, t) { - if (e && e instanceof l) return e; - let n = new l(); - return n.parse(e, t), n; -} -l.prototype.parse = function(e, t) { - let n, r, i, a = e; - if (a = a.trim(), !t && e.split("#").length === 1) { - let e = f.exec(a); - if (e) return this.pathname = e[1], e[2] && (this.search = e[2]), this; - } - let o = u.exec(a); - if (o && (o = o[0], n = o.toLowerCase(), this.protocol = o, a = a.substr(o.length)), (t || o || a.match(/^\/\/[^@\/]+@[^@\/]+/)) && (i = a.substr(0, 2) === "//", i && !(o && v[o]) && (a = a.substr(2), this.slashes = !0)), !v[o] && (i || o && !y[o])) { - let e = -1; - for (let t = 0; t < m.length; t++) r = a.indexOf(m[t]), r !== -1 && (e === -1 || r < e) && (e = r); - let t, n; - n = e === -1 ? a.lastIndexOf("@") : a.lastIndexOf("@", e), n !== -1 && (t = a.slice(0, n), a = a.slice(n + 1), this.auth = t), e = -1; - for (let t = 0; t < p.length; t++) r = a.indexOf(p[t]), r !== -1 && (e === -1 || r < e) && (e = r); - e === -1 && (e = a.length), a[e - 1] === ":" && e--; - let i = a.slice(0, e); - a = a.slice(e), this.parseHost(i), this.hostname = this.hostname || ""; - let o = this.hostname[0] === "[" && this.hostname[this.hostname.length - 1] === "]"; - if (!o) { - let e = this.hostname.split(/\./); - for (let t = 0, n = e.length; t < n; t++) { - let n = e[t]; - if (n && !n.match(g)) { - let r = ""; - for (let e = 0, t = n.length; e < t; e++) n.charCodeAt(e) > 127 ? r += "x" : r += n[e]; - if (!r.match(g)) { - let r = e.slice(0, t), i = e.slice(t + 1), o = n.match(_); - o && (r.push(o[1]), i.unshift(o[2])), i.length && (a = i.join(".") + a), this.hostname = r.join("."); - break; - } - } - } - } - this.hostname.length > h && (this.hostname = ""), o && (this.hostname = this.hostname.substr(1, this.hostname.length - 2)); - } - let s = a.indexOf("#"); - s !== -1 && (this.hash = a.substr(s), a = a.slice(0, s)); - let c = a.indexOf("?"); - return c !== -1 && (this.search = a.substr(c), a = a.slice(0, c)), a && (this.pathname = a), y[n] && this.hostname && !this.pathname && (this.pathname = ""), this; -}, l.prototype.parseHost = function(e) { - let t = d.exec(e); - t && (t = t[0], t !== ":" && (this.port = t.substr(1)), e = e.substr(0, e.length - t.length)), e && (this.hostname = e); -}; -//#endregion -//#region node_modules/mdurl/index.mjs -var ee = /* @__PURE__ */ t({ - decode: () => i, - encode: () => s, - format: () => c, - parse: () => b -}), te = /* @__PURE__ */ t({ - Any: () => x, - Cc: () => ne, - Cf: () => re, - P: () => S, - S: () => ie, - Z: () => ae -}), x = /[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/, ne = /[\0-\x1F\x7F-\x9F]/, re = /[\xAD\u0600-\u0605\u061C\u06DD\u070F\u0890\u0891\u08E2\u180E\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u206F\uFEFF\uFFF9-\uFFFB]|\uD804[\uDCBD\uDCCD]|\uD80D[\uDC30-\uDC3F]|\uD82F[\uDCA0-\uDCA3]|\uD834[\uDD73-\uDD7A]|\uDB40[\uDC01\uDC20-\uDC7F]/, S = /[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061D-\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B4E\u1B4F\u1B5A-\u1B60\u1B7D-\u1B7F\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u2E52-\u2E5D\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDD6E\uDEAD\uDED0\uDF55-\uDF59\uDF86-\uDF89]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9\uDFD4\uDFD5\uDFD7\uDFD8]|\uD805[\uDC4B-\uDC4F\uDC5A\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDEB9\uDF3C-\uDF3E]|\uD806[\uDC3B\uDD44-\uDD46\uDDE2\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2\uDF00-\uDF09\uDFE1]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8\uDF43-\uDF4F\uDFFF]|\uD809[\uDC70-\uDC74]|\uD80B[\uDFF1\uDFF2]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDD6D-\uDD6F\uDE97-\uDE9A\uDFE2]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD839\uDDFF|\uD83A[\uDD5E\uDD5F]/, ie = /[\$\+<->\^`\|~\xA2-\xA6\xA8\xA9\xAC\xAE-\xB1\xB4\xB8\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0384\u0385\u03F6\u0482\u058D-\u058F\u0606-\u0608\u060B\u060E\u060F\u06DE\u06E9\u06FD\u06FE\u07F6\u07FE\u07FF\u0888\u09F2\u09F3\u09FA\u09FB\u0AF1\u0B70\u0BF3-\u0BFA\u0C7F\u0D4F\u0D79\u0E3F\u0F01-\u0F03\u0F13\u0F15-\u0F17\u0F1A-\u0F1F\u0F34\u0F36\u0F38\u0FBE-\u0FC5\u0FC7-\u0FCC\u0FCE\u0FCF\u0FD5-\u0FD8\u109E\u109F\u1390-\u1399\u166D\u17DB\u1940\u19DE-\u19FF\u1B61-\u1B6A\u1B74-\u1B7C\u1FBD\u1FBF-\u1FC1\u1FCD-\u1FCF\u1FDD-\u1FDF\u1FED-\u1FEF\u1FFD\u1FFE\u2044\u2052\u207A-\u207C\u208A-\u208C\u20A0-\u20C1\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F\u218A\u218B\u2190-\u2307\u230C-\u2328\u232B-\u2429\u2440-\u244A\u249C-\u24E9\u2500-\u2767\u2794-\u27C4\u27C7-\u27E5\u27F0-\u2982\u2999-\u29D7\u29DC-\u29FB\u29FE-\u2B73\u2B76-\u2BFF\u2CE5-\u2CEA\u2E50\u2E51\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFF\u3004\u3012\u3013\u3020\u3036\u3037\u303E\u303F\u309B\u309C\u3190\u3191\u3196-\u319F\u31C0-\u31E5\u31EF\u3200-\u321E\u322A-\u3247\u3250\u3260-\u327F\u328A-\u32B0\u32C0-\u33FF\u4DC0-\u4DFF\uA490-\uA4C6\uA700-\uA716\uA720\uA721\uA789\uA78A\uA828-\uA82B\uA836-\uA839\uAA77-\uAA79\uAB5B\uAB6A\uAB6B\uFB29\uFBB2-\uFBD2\uFD40-\uFD4F\uFD90\uFD91\uFDC8-\uFDCF\uFDFC-\uFDFF\uFE62\uFE64-\uFE66\uFE69\uFF04\uFF0B\uFF1C-\uFF1E\uFF3E\uFF40\uFF5C\uFF5E\uFFE0-\uFFE6\uFFE8-\uFFEE\uFFFC\uFFFD]|\uD800[\uDD37-\uDD3F\uDD79-\uDD89\uDD8C-\uDD8E\uDD90-\uDD9C\uDDA0\uDDD0-\uDDFC]|\uD802[\uDC77\uDC78\uDEC8]|\uD803[\uDD8E\uDD8F\uDED1-\uDED8]|\uD805\uDF3F|\uD807[\uDFD5-\uDFF1]|\uD81A[\uDF3C-\uDF3F\uDF45]|\uD82F\uDC9C|\uD833[\uDC00-\uDCEF\uDCFA-\uDCFC\uDD00-\uDEB3\uDEBA-\uDED0\uDEE0-\uDEF0\uDF50-\uDFC3]|\uD834[\uDC00-\uDCF5\uDD00-\uDD26\uDD29-\uDD64\uDD6A-\uDD6C\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDDEA\uDE00-\uDE41\uDE45\uDF00-\uDF56]|\uD835[\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85\uDE86]|\uD838[\uDD4F\uDEFF]|\uD83B[\uDCAC\uDCB0\uDD2E\uDEF0\uDEF1]|\uD83C[\uDC00-\uDC2B\uDC30-\uDC93\uDCA0-\uDCAE\uDCB1-\uDCBF\uDCC1-\uDCCF\uDCD1-\uDCF5\uDD0D-\uDDAD\uDDE6-\uDE02\uDE10-\uDE3B\uDE40-\uDE48\uDE50\uDE51\uDE60-\uDE65\uDF00-\uDFFF]|\uD83D[\uDC00-\uDED8\uDEDC-\uDEEC\uDEF0-\uDEFC\uDF00-\uDFD9\uDFE0-\uDFEB\uDFF0]|\uD83E[\uDC00-\uDC0B\uDC10-\uDC47\uDC50-\uDC59\uDC60-\uDC87\uDC90-\uDCAD\uDCB0-\uDCBB\uDCC0\uDCC1\uDCD0-\uDCD8\uDD00-\uDE57\uDE60-\uDE6D\uDE70-\uDE7C\uDE80-\uDE8A\uDE8E-\uDEC6\uDEC8\uDECD-\uDEDC\uDEDF-\uDEEA\uDEEF-\uDEF8\uDF00-\uDF92\uDF94-\uDFEF\uDFFA]/, ae = /[ \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/, oe = /* @__PURE__ */ new Map([ - [0, 65533], - [128, 8364], - [130, 8218], - [131, 402], - [132, 8222], - [133, 8230], - [134, 8224], - [135, 8225], - [136, 710], - [137, 8240], - [138, 352], - [139, 8249], - [140, 338], - [142, 381], - [145, 8216], - [146, 8217], - [147, 8220], - [148, 8221], - [149, 8226], - [150, 8211], - [151, 8212], - [152, 732], - [153, 8482], - [154, 353], - [155, 8250], - [156, 339], - [158, 382], - [159, 376] -]); -function se(e) { - var t; - return e >= 55296 && e <= 57343 || e > 1114111 ? 65533 : (t = oe.get(e)) == null ? e : t; -} -//#endregion -//#region node_modules/entities/dist/internal/decode-shared.js -function ce(e) { - let t = atob(e), n = t.length & -2, r = new Uint16Array(n / 2); - for (let e = 0, i = 0; e < n; e += 2) { - let n = t.charCodeAt(e), a = t.charCodeAt(e + 1); - r[i++] = n | a << 8; - } - return r; -} -//#endregion -//#region node_modules/entities/dist/generated/decode-data-html.js -var le = /* #__PURE__ */ ce("QR08ALkAAgH6AYsDNQR2BO0EPgXZBQEGLAbdBxMISQrvCmQLfQurDKQNLw4fD4YPpA+6D/IPAAAAAAAAAAAAAAAAKhBMEY8TmxUWF2EYLBkxGuAa3RsJHDscWR8YIC8jSCSIJcMl6ie3Ku8rEC0CLjoupS7kLgAIRU1hYmNmZ2xtbm9wcnN0dVQAWgBeAGUAaQBzAHcAfgCBAIQAhwCSAJoAoACsALMAbABpAGcAO4DGAMZAUAA7gCYAJkBjAHUAdABlADuAwQDBQHIiZXZlAAJhAAFpeW0AcgByAGMAO4DCAMJAEGRyAADgNdgE3XIAYQB2AGUAO4DAAMBA8CFoYZFj4SFjcgBhZAAAoFMqAAFncIsAjgBvAG4ABGFmAADgNdg43fAlbHlGdW5jdGlvbgCgYSBpAG4AZwA7gMUAxUAAAWNzpACoAHIAAOA12Jzc6SFnbgCgVCJpAGwAZABlADuAwwDDQG0AbAA7gMQAxEAABGFjZWZvcnN1xQDYANoA7QDxAPYA+QD8AAABY3LJAM8AayNzbGFzaAAAoBYidgHTANUAAKDnKmUAZAAAoAYjeQARZIABY3J0AOAA5QDrAGEidXNlAACgNSLuI291bGxpcwCgLCFhAJJjcgAA4DXYBd1wAGYAAOA12Dnd5SF2ZdhiYwDyAOoAbSJwZXEAAKBOIgAHSE9hY2RlZmhpbG9yc3UXARoBHwE6AVIBVQFiAWQBZgGCAakB6QHtAfIBYwB5ACdkUABZADuAqQCpQIABY3B5ACUBKAE1AfUhdGUGYWmg0iJ0KGFsRGlmZmVyZW50aWFsRAAAoEUhbCJleXMAAKAtIQACYWVpb0EBRAFKAU0B8iFvbgxhZABpAGwAO4DHAMdAcgBjAAhhbiJpbnQAAKAwIm8AdAAKYQABZG5ZAV0BaSJsbGEAuGB0I2VyRG90ALdg8gA5AWkAp2NyImNsZQAAAkRNUFRwAXQBeQF9AW8AdAAAoJkiaSJudXMAAKCWIuwhdXMAoJUiaSJtZXMAAKCXIm8AAAFjc4cBlAFrKndpc2VDb250b3VySW50ZWdyYWwAAKAyImUjQ3VybHkAAAFEUZwBpAFvJXVibGVRdW90ZQAAoB0gdSJvdGUAAKAZIAACbG5wdbABtgHNAdgBbwBuAGWgNyIAoHQqgAFnaXQAvAHBAcUB8iJ1ZW50AKBhIm4AdAAAoC8i7yV1ckludGVncmFsAKAuIgABZnLRAdMBAKACIe8iZHVjdACgECJuLnRlckNsb2Nrd2lzZUNvbnRvdXJJbnRlZ3JhbAAAoDMi7yFzcwCgLypjAHIAAOA12J7ccABDoNMiYQBwAACgTSKABURKU1phY2VmaW9zAAsCEgIVAhgCGwIsAjQCOQI9AnMCfwNvoEUh9CJyYWhkAKARKWMAeQACZGMAeQAFZGMAeQAPZIABZ3JzACECJQIoAuchZXIAoCEgcgAAoKEhaAB2AACg5CoAAWF5MAIzAvIhb24OYRRkbAB0oAciYQCUY3IAAOA12AfdAAFhZkECawIAAWNtRQJnAvIjaXRpY2FsAAJBREdUUAJUAl8CYwJjInV0ZQC0YG8AdAFZAloC2WJiJGxlQWN1dGUA3WJyImF2ZQBgYGkibGRlANxi7yFuZACgxCJmJWVyZW50aWFsRAAAoEYhcAR9AgAAAAAAAIECjgIAABoDZgAA4DXYO91EoagAhQKJAm8AdAAAoNwgcSJ1YWwAAKBQIuIhbGUAA0NETFJVVpkCqAK1Au8C/wIRA28AbgB0AG8AdQByAEkAbgB0AGUAZwByAGEA7ADEAW8AdAKvAgAAAACwAqhgbiNBcnJvdwAAoNMhAAFlb7kC0AJmAHQAgAFBUlQAwQLGAs0CciJyb3cAAKDQIekkZ2h0QXJyb3cAoNQhZQDlACsCbgBnAAABTFLWAugC5SFmdAABQVLcAuECciJyb3cAAKD4J+kkZ2h0QXJyb3cAoPon6SRnaHRBcnJvdwCg+SdpImdodAAAAUFU9gL7AnIicm93AACg0iFlAGUAAKCoInAAQQIGAwAAAAALA3Iicm93AACg0SFvJHduQXJyb3cAAKDVIWUlcnRpY2FsQmFyAACgJSJuAAADQUJMUlRhJAM2AzoDWgNxA3oDciJyb3cAAKGTIUJVLAMwA2EAcgAAoBMpcCNBcnJvdwAAoPUhciJldmUAEWPlIWZ00gJDAwAASwMAAFIDaSVnaHRWZWN0b3IAAKBQKWUkZVZlY3RvcgAAoF4p5SJjdG9yQqC9IWEAcgAAoFYpaSJnaHQA1AFiAwAAaQNlJGVWZWN0b3IAAKBfKeUiY3RvckKgwSFhAHIAAKBXKWUAZQBBoKQiciJyb3cAAKCnIXIAcgBvAPcAtAIAAWN0gwOHA3IA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YwAAoN8i4SFycnCgtiEAoD0pgKIqImJjZG9zACsVMBU6FT4VQRVyImNhcAAAoEgqAAFhdTQVNxVwAACgRipwAACgSipvAHQAAKCNInIAAKBFKgDgKiIA/gACYWxydksVURVuFXMVcgByAG2gtyEAoDwpeQCAAWV2dwBYFWUVaRVxAHACXxUAAAAAYxVyAGUA4wAXFXUA4wAZFWUAZQAAoM4iZSJkZ2UAAKDPImUAbgA7gKQApEBlI2Fycm93AAABbHJ7FX8V5SFmdACgtiFpImdodAAAoLchZQDkAG0VAAFjaYsVkRVvAG4AaQBuAPQAkwFuAHQAAKAxImwiY3R5AACgLSOACUFIYWJjZGVmaGlqbG9yc3R1d3oAuBW7Fb8V1RXgFegV+RUKFhUWHxZUFlcWZRbFFtsW7xb7FgUXChdyAPIAtAJhAHIAAKBlKQACZ2xyc8YVyhXOFdAV5yFlcgCgICDlIXRoAKA4IfIA9QxoAHagECAAoKMiawHZFd4VYSJyb3cAAKAPKWEA4wBfAgABYXnkFecV8iFvbg9hNGQAoUYhYW/tFfQVAAFnciEC8RVyAACgyiF0InNlcQAAoHcqgAFnbG0A/xUCFgUWO4CwALBAdABhALRjcCJ0eXYAAKCxKQABaXIOFhIW8yFodACgfykA4DXYId1hAHIAAAFschsWHRYAoMMhAKDCIYACYWVnc3YAKBauAjYWOhY+Fm0AAKHEIm9zLhY0Fm4AZABzoMQi9SFpdACgZiZhIm1tYQDdY2kAbgAAoPIiAKH3AGlvQxZRFmQAZQAAgfcAO29KFksW90BuI3RpbWVzAACgxyJuAPgAUBZjAHkAUmRjAG8CXhYAAAAAYhZyAG4AAKAeI28AcAAAoA0jgAJscHR1dwBuFnEWdRaSFp4W7CFhciRgZgAA4DXYVd0AotkCZW1wc30WhBaJFo0WcQBkoFAibwB0AACgUSJpIm51cwAAoDgi7CF1cwCgFCLxInVhcmUAoKEiYgBsAGUAYgBhAHIAdwBlAGQAZwDlANcAbgCAAWFkaAClFqoWtBZyAHIAbwD3APUMbwB3AG4AYQByAHIAbwB3APMA8xVhI3Jwb29uAAABbHK8FsAWZQBmAPQAHBZpAGcAaAD0AB4WYgHJFs8WawBhAHIAbwD3AJILbwLUFgAAAADYFnIAbgAAoB8jbwBwAACgDCOAAWNvdADhFukW7BYAAXJ55RboFgDgNdi53FVkbAAAoPYp8iFvaxFhAAFkcvMW9xZvAHQAAKDxImkA5qC/JVsSAAFhaP8WAhdyAPIANQNhAPIA1wvhIm5nbGUAoKYpAAFjaQ4XEBd5AF9k5yJyYXJyAKD/JwAJRGFjZGVmZ2xtbm9wcXJzdHV4MRc4F0YXWxcyBF4XaRd5F40XrBe0F78X2RcVGCEYLRg1GEAYAAFEbzUXgRZvAPQA+BUAAWNzPBdCF3UAdABlADuA6QDpQPQhZXIAoG4qAAJhaW95TRdQF1YXWhfyIW9uG2FyAGOgViI7gOoA6kDsIW9uAKBVIk1kbwB0ABdhAAFEcmIXZhdvAHQAAKBSIgDgNdgi3XKhmipuF3QXYQB2AGUAO4DoAOhAZKCWKm8AdAAAoJgqgKGZKmlscwCAF4UXhxfuInRlcnMAoOcjAKATIWSglSpvAHQAAKCXKoABYXBzAJMXlheiF2MAcgATYXQAeQBzogUinxcAAAAAoRdlAHQAAKAFInAAMaADIDMBqRerFwCgBCAAoAUgAAFnc7AXsRdLYXAAAKACIAABZ3C4F7sXbwBuABlhZgAA4DXYVt2AAWFscwDFF8sXzxdyAHOg1SJsAACg4yl1AHMAAKBxKmkAAKG1A2x21RfYF28AbgC1Y/VjAAJjc3V24BfoF/0XEBgAAWlv5BdWF3IAYwAAoFYiaQLuFwAAAADwF+0ADQThIW50AAFnbPUX+Rd0AHIAAKCWKuUhc3MAoJUqgAFhZWkAAxgGGAoYbABzAD1gcwB0AACgXyJ2AESgYSJEAACgeCrwImFyc2wAoOUpAAFEYRkYHRhvAHQAAKBTInIAcgAAoHEpgAFjZGkAJxgqGO0XcgAAoC8hbwD0AIwCAAFhaDEYMhi3YzuA8ADwQAABbXI5GD0YbAA7gOsA60BvAACgrCCAAWNpcABGGEgYSxhsACFgcwD0ACwEAAFlb08YVxhjAHQAYQB0AGkAbwDuABoEbgBlAG4AdABpAGEAbADlADME4Ql1GAAAgRgAAIMYiBgAAAAAoRilGAAAqhgAALsYvhjRGAAA1xgnGWwAbABpAG4AZwBkAG8AdABzAGUA8QBlF3kARGRtImFsZQAAoEAmgAFpbHIAjRiRGJ0Y7CFpZwCgA/tpApcYAAAAAJoYZwAAoAD7aQBnAACgBPsA4DXYI93sIWlnAKAB++whaWcA4GYAagCAAWFsdACvGLIYthh0AACgbSZpAGcAAKAC+24AcwAAoLElbwBmAJJh8AHCGAAAxhhmAADgNdhX3QABYWvJGMwYbADsAGsEdqDUIgCg2SphI3J0aW50AACgDSoAAWFv2hgiGQABY3PeGB8ZsQPnGP0YBRkSGRUZAAAdGbID7xjyGPQY9xj5GAAA+xg7gL0AvUAAoFMhO4C8ALxAAKBVIQCgWSEAoFshswEBGQAAAxkAoFQhAKBWIbQCCxkOGQAAAAAQGTuAvgC+QACgVyEAoFwhNQAAoFghtgEZGQAAGxkAoFohAKBdITgAAKBeIWwAAKBEIHcAbgAAoCIjYwByAADgNdi73IAIRWFiY2RlZmdpamxub3JzdHYARhlKGVoZXhlmGWkZkhmWGZkZnRmgGa0ZxhnLGc8Z4BkjGmygZyIAoIwqgAFjbXAAUBlTGVgZ9SF0ZfVhbQBhAOSgswM6FgCghipyImV2ZQAfYQABaXliGWUZcgBjAB1hM2RvAHQAIWGAoWUibHFzAMYEcBl6GfGhZSLOBAAAdhlsAGEAbgD0AN8EgKF+KmNkbACBGYQZjBljAACgqSpvAHQAb6CAKmyggioAoIQqZeDbIgD+cwAAoJQqcgAA4DXYJN3noGsirATtIWVsAKA3IWMAeQBTZIChdyJFYWoApxmpGasZAKCSKgCgpSoAoKQqAAJFYWVztBm2Gb0ZwhkAoGkicABwoIoq8iFveACgiipxoIgq8aCIKrUZaQBtAACg5yJwAGYAAOA12FjdYQB2AOUAYwIAAWNp0xnWGXIAAKAKIW0AAKFzImVs3BneGQCgjioAoJAqAIM+ADtjZGxxco0E6xn0GfgZ/BkBGgABY2nvGfEZAKCnKnIAAKB6Km8AdAAAoNci0CFhcgCglSl1ImVzdAAAoHwqgAJhZGVscwAKGvQZFhrVBCAa8AEPGgAAFBpwAHIAbwD4AFkZcgAAoHgpcQAAAWxxxAQbGmwAZQBzAPMASRlpAO0A5AQAAWVuJxouGnIjdG5lcXEAAOBpIgD+xQAsGgAFQWFiY2Vma29zeUAaQxpmGmoabRqDGocalhrCGtMacgDyAMwCAAJpbG1yShpOGlAaVBpyAHMA8ABxD2YAvWBpAGwA9AASBQABZHJYGlsaYwB5AEpkAKGUIWN3YBpkGmkAcgAAoEgpAKCtIWEAcgAAoA8h6SFyYyVhgAFhbHIAcxp7Gn8a8iF0c3WgZSZpAHQAAKBlJuwhaXAAoCYg4yFvbgCguSJyAADgNdgl3XMAAAFld4wakRphInJvdwAAoCUpYSJyb3cAAKAmKYACYW1vcHIAnxqjGqcauhq+GnIAcgAAoP8h9CFodACgOyJrAAABbHKsGrMaZSRmdGFycm93AACgqSHpJGdodGFycm93AKCqIWYAAOA12Fnd4iFhcgCgFSCAAWNsdADIGswa0BpyAADgNdi93GEAcwDoAGka8iFvaydhAAFicNca2xr1IWxsAKBDIOghZW4AoBAg4Qr2GgAA/RoAAAgbExsaGwAAIRs7GwAAAAA+G2IbmRuVG6sbAACyG80b0htjAHUAdABlADuA7QDtQAChYyBpeQEbBhtyAGMAO4DuAO5AOGQAAWN4CxsNG3kANWRjAGwAO4ChAKFAAAFmcssCFhsA4DXYJt1yAGEAdgBlADuA7ADsQIChSCFpbm8AJxsyGzYbAAFpbisbLxtuAHQAAKAMKnQAAKAtIuYhaW4AoNwpdABhAACgKSHsIWlnM2GAAWFvcABDG1sbXhuAAWNndABJG0sbWRtyACthgAFlbHAAcQVRG1UbaQBuAOUAyAVhAHIA9AByBWgAMWFmAACgtyJlAGQAtWEAoggiY2ZvdGkbbRt1G3kb4SFyZQCgBSFpAG4AdKAeImkAZQAAoN0pZABvAPQAWxsAoisiY2VscIEbhRuPG5QbYQBsAACguiIAAWdyiRuNG2UAcgDzACMQ4wCCG2EicmhrAACgFyryIW9kAKA8KgACY2dwdJ8boRukG6gbeQBRZG8AbgAvYWYAAOA12FrdYQC5Y3UAZQBzAHQAO4C/AL9AAAFjabUbuRtyAADgNdi+3G4AAKIIIkVkc3bCG8QbyBvQAwCg+SJvAHQAAKD1Inag9CIAoPMiaaBiIOwhZGUpYesB1hsAANkbYwB5AFZkbAA7gO8A70AAA2NmbW9zdeYb7hvyG/Ub+hsFHAABaXnqG+0bcgBjADVhOWRyAADgNdgn3eEhdGg3YnAAZgAA4DXYW93jAf8bAAADHHIAAOA12L/c8iFjeVhk6yFjeVRkAARhY2ZnaGpvcxUcGhwiHCYcKhwtHDAcNRzwIXBhdqC6A/BjAAFleR4cIRzkIWls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ZmdobG1vcHJzdHV3CiwNLBEsHSwnLDEsQCxLLFIsYix6LIQsjyzLLOgs7Sz/LAotcgDyAAkDYQByAACgYykAAWNyFSwbLHUAdABlADuA+gD6QPIACQ1yAOMBIywAACUseQBeZHYAZQBtYQABaXkrLDAscgBjADuA+wD7QENkgAFhYmgANyw6LD0scgDyANEO7CFhY3FhYQDyAOAOAAFpckQsSCzzIWh0AKB+KQDgNdgy3XIAYQB2AGUAO4D5APlAYQFWLF8scgAAAWxyWixcLACgvyEAoL4hbABrAACggCUAAWN0Zix2LG8CbCwAAAAAcyxyAG4AZaAcI3IAAKAcI28AcAAAoA8jcgBpAACg+CUAAWFsfiyBLGMAcgBrYTuAqACoQAABZ3CILIssbwBuAHNhZgAA4DXYZt0AA2FkaGxzdZksniynLLgsuyzFLHIAcgBvAPcACQ1vAHcAbgBhAHIAcgBvAPcA2A5hI3Jwb29uAAABbHKvLLMsZQBmAPQAWyxpAGcAaAD0AF0sdQDzAKYOaQAAocUDaGzBLMIs0mNvAG4AxWPwI2Fycm93cwCgyCGAAWNpdADRLOEs5CxvAtcsAAAAAN4scgBuAGWgHSNyAACgHSNvAHAAAKAOI24AZwBvYXIAaQAAoPklYwByAADgNdjK3IABZGlyAPMs9yz6LG8AdAAAoPAi7CFkZWlhaQBmoLUlAKC0JQABYW0DLQYtcgDyAMosbAA7gPwA/EDhIm5nbGUAoKcpgAdBQkRhY2RlZmxub3Byc3oAJy0qLTAtNC2bLZ0toS2/LcMtxy3TLdgt3C3gLfwtcgDyABADYQByAHag6CoAoOkqYQBzAOgA/gIAAW5yOC08LechcnQAoJwpgANla25wcnN0AJkpSC1NLVQtXi1iLYItYQBwAHAA4QAaHG8AdABoAGkAbgDnAKEXgAFoaXIAoSmzJFotbwBwAPQAdCVooJUh7wD4JgABaXVmLWotZwBtAOEAuygAAWJwbi14LXMjZXRuZXEAceCKIgD+AODLKgD+cyNldG5lcQBx4IsiAP4A4MwqAP4AAWhyhi2KLWUAdADhABIraSNhbmdsZQAAAWxyki2WLeUhZnQAoLIiaSJnaHQAAKCzInkAMmThIXNoAKCiIoABZWxyAKcttC24LWKiKCKuLQAAAACyLWEAcgAAoLsicQAAoFoi7CFpcACg7iIAAWJ0vC1eD2EA8gBfD3IAAOA12DPddAByAOkAlS1zAHUAAAFicM0t0C0A4IIi0iAA4IMi0iBwAGYAAOA12GfdcgBvAPAAWQt0AHIA6QCaLQABY3XkLegtcgAA4DXYy9wAAWJw7C30LW4AAAFFZXUt8S0A4IoiAP5uAAABRWV/LfktAOCLIgD+6SJnemFnAKCaKYADY2Vmb3BycwANLhAuJS4pLiMuLi40LukhcmN1YQABZGkULiEuAAFiZxguHC5hAHIAAKBfKmUAcaAnIgCgWSLlIXJwAKAYIXIAAOA12DTdcABmAADgNdho3WWgQCJhAHQA6ABqD2MAcgAA4DXYzNzjCuQRUC4AAFQuAABYLmIuAAAAAGMubS5wLnQuAAAAAIguki4AAJouJxIqEnQAcgDpAB0ScgAA4DXYNd0AAUFhWy5eLnIA8gDnAnIA8gCTB75jAAFBYWYuaS5yAPIA4AJyAPIAjAdhAPAAeh5pAHMAAKD7IoABZHB0APgReS6DLgABZmx9LoAuAOA12GnddQDzAP8RaQBtAOUABBIAAUFhiy6OLnIA8gDuAnIA8gCaBwABY3GVLgoScgAA4DXYzdwAAXB0nS6hLmwAdQDzACUScgDpACASAARhY2VmaW9zdbEuvC7ELsguzC7PLtQu2S5jAAABdXm2LrsudABlADuA/QD9QE9kAAFpecAuwy5yAGMAd2FLZG4AO4ClAKVAcgAA4DXYNt1jAHkAV2RwAGYAAOA12GrdYwByAADgNdjO3AABY23dLt8ueQBOZGwAO4D/AP9AAAVhY2RlZmhpb3N38y73Lv8uAi8MLxAvEy8YLx0vIi9jInV0ZQB6YQABYXn7Lv4u8iFvbn5hN2RvAHQAfGEAAWV0Bi8KL3QAcgDmAB8QYQC2Y3IAAOA12DfdYwB5ADZk5yJyYXJyAKDdIXAAZgAA4DXYa91jAHIAAOA12M/cAAFqbiYvKC8AoA0gagAAoAwg"), C; -(function(e) { - e[e.VALUE_LENGTH = 49152] = "VALUE_LENGTH", e[e.FLAG13 = 8192] = "FLAG13", e[e.BRANCH_LENGTH = 8064] = "BRANCH_LENGTH", e[e.JUMP_TABLE = 127] = "JUMP_TABLE"; -})(C || (C = {})); -//#endregion -//#region \0@oxc-project+runtime@0.142.0/helpers/esm/typeof.js -function w(e) { - "@babel/helpers - typeof"; - return w = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(e) { - return typeof e; - } : function(e) { - return e && typeof Symbol == "function" && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e; - }, w(e); -} -//#endregion -//#region \0@oxc-project+runtime@0.142.0/helpers/esm/toPrimitive.js -function ue(e, t) { - if (w(e) != "object" || !e) return e; - var n = e[Symbol.toPrimitive]; - if (n !== void 0) { - var r = n.call(e, t || "default"); - if (w(r) != "object") return r; - throw TypeError("@@toPrimitive must return a primitive value."); - } - return (t === "string" ? String : Number)(e); -} -//#endregion -//#region \0@oxc-project+runtime@0.142.0/helpers/esm/toPropertyKey.js -function de(e) { - var t = ue(e, "string"); - return w(t) == "symbol" ? t : t + ""; -} -//#endregion -//#region \0@oxc-project+runtime@0.142.0/helpers/esm/defineProperty.js -function T(e, t, n) { - return (t = de(t)) in e ? Object.defineProperty(e, t, { - value: n, - enumerable: !0, - configurable: !0, - writable: !0 - }) : e[t] = n, e; -} -//#endregion -//#region node_modules/entities/dist/decode.js -var E; -(function(e) { - e[e.NUM = 35] = "NUM", e[e.SEMI = 59] = "SEMI", e[e.EQUALS = 61] = "EQUALS", e[e.ZERO = 48] = "ZERO", e[e.NINE = 57] = "NINE", e[e.LOWER_A = 97] = "LOWER_A", e[e.LOWER_F = 102] = "LOWER_F", e[e.LOWER_X = 120] = "LOWER_X", e[e.LOWER_Z = 122] = "LOWER_Z", e[e.UPPER_A = 65] = "UPPER_A", e[e.UPPER_F = 70] = "UPPER_F", e[e.UPPER_Z = 90] = "UPPER_Z"; -})(E || (E = {})); -var fe = 32; -function D(e) { - return e >= E.ZERO && e <= E.NINE; -} -function pe(e) { - return e >= E.UPPER_A && e <= E.UPPER_F || e >= E.LOWER_A && e <= E.LOWER_F; -} -function me(e) { - return e >= E.UPPER_A && e <= E.UPPER_Z || e >= E.LOWER_A && e <= E.LOWER_Z || D(e); -} -function he(e) { - return e === E.EQUALS || me(e); -} -var O; -(function(e) { - e[e.EntityStart = 0] = "EntityStart", e[e.NumericStart = 1] = "NumericStart", e[e.NumericDecimal = 2] = "NumericDecimal", e[e.NumericHex = 3] = "NumericHex", e[e.NamedEntity = 4] = "NamedEntity"; -})(O || (O = {})); -var k; -(function(e) { - e[e.Legacy = 0] = "Legacy", e[e.Strict = 1] = "Strict", e[e.Attribute = 2] = "Attribute"; -})(k || (k = {})); -var ge = class { - constructor(e, t, n) { - T(this, "decodeTree", void 0), T(this, "emitCodePoint", void 0), T(this, "errors", void 0), T(this, "state", O.EntityStart), T(this, "consumed", 1), T(this, "result", 0), T(this, "treeIndex", 0), T(this, "excess", 1), T(this, "decodeMode", k.Strict), T(this, "runConsumed", 0), this.decodeTree = e, this.emitCodePoint = t, this.errors = n; - } - startEntity(e) { - this.decodeMode = e, this.state = O.EntityStart, this.result = 0, this.treeIndex = 0, this.excess = 1, this.consumed = 1, this.runConsumed = 0; - } - write(e, t) { - switch (this.state) { - case O.EntityStart: return e.charCodeAt(t) === E.NUM ? (this.state = O.NumericStart, this.consumed += 1, this.stateNumericStart(e, t + 1)) : (this.state = O.NamedEntity, this.stateNamedEntity(e, t)); - case O.NumericStart: return this.stateNumericStart(e, t); - case O.NumericDecimal: return this.stateNumericDecimal(e, t); - case O.NumericHex: return this.stateNumericHex(e, t); - case O.NamedEntity: return this.stateNamedEntity(e, t); - } - } - stateNumericStart(e, t) { - return t >= e.length ? -1 : (e.charCodeAt(t) | fe) === E.LOWER_X ? (this.state = O.NumericHex, this.consumed += 1, this.stateNumericHex(e, t + 1)) : (this.state = O.NumericDecimal, this.stateNumericDecimal(e, t)); - } - stateNumericHex(e, t) { - for (; t < e.length;) { - let n = e.charCodeAt(t); - if (D(n) || pe(n)) { - let e = n <= E.NINE ? n - E.ZERO : (n | fe) - E.LOWER_A + 10; - this.result = this.result * 16 + e, this.consumed++, t++; - } else return this.emitNumericEntity(n, 3); - } - return -1; - } - stateNumericDecimal(e, t) { - for (; t < e.length;) { - let n = e.charCodeAt(t); - if (D(n)) this.result = this.result * 10 + (n - E.ZERO), this.consumed++, t++; - else return this.emitNumericEntity(n, 2); - } - return -1; - } - emitNumericEntity(e, t) { - if (this.consumed <= t) { - var n; - return (n = this.errors) == null || n.absenceOfDigitsInNumericCharacterReference(this.consumed), 0; - } - if (e === E.SEMI) this.consumed += 1; - else if (this.decodeMode === k.Strict) return 0; - return this.emitCodePoint(se(this.result), this.consumed), this.errors && (e !== E.SEMI && this.errors.missingSemicolonAfterCharacterReference(), this.errors.validateNumericCharacterReference(this.result)), this.consumed; - } - stateNamedEntity(e, t) { - let { decodeTree: n } = this, r = n[this.treeIndex], i = (r & C.VALUE_LENGTH) >> 14; - for (; t < e.length;) { - if (i === 0 && (r & C.FLAG13) !== 0) { - let a = (r & C.BRANCH_LENGTH) >> 7; - if (this.runConsumed === 0) { - let n = r & C.JUMP_TABLE; - if (e.charCodeAt(t) !== n) return this.result === 0 ? 0 : this.emitNotTerminatedNamedEntity(); - t++, this.excess++, this.runConsumed++; - } - for (; this.runConsumed < a;) { - if (t >= e.length) return -1; - let r = this.runConsumed - 1, i = n[this.treeIndex + 1 + (r >> 1)], a = r % 2 == 0 ? i & 255 : i >> 8 & 255; - if (e.charCodeAt(t) !== a) return this.runConsumed = 0, this.result === 0 ? 0 : this.emitNotTerminatedNamedEntity(); - t++, this.excess++, this.runConsumed++; - } - this.runConsumed = 0, this.treeIndex += 1 + (a >> 1), r = n[this.treeIndex], i = (r & C.VALUE_LENGTH) >> 14; - } - if (t >= e.length) break; - let a = e.charCodeAt(t); - if (a === E.SEMI && i !== 0 && (r & C.FLAG13) !== 0) return this.emitNamedEntityData(this.treeIndex, i, this.consumed + this.excess); - if (this.treeIndex = ve(n, r, this.treeIndex + Math.max(1, i), a), this.treeIndex < 0) return this.result === 0 || this.decodeMode === k.Attribute && (i === 0 || he(a)) ? 0 : this.emitNotTerminatedNamedEntity(); - if (r = n[this.treeIndex], i = (r & C.VALUE_LENGTH) >> 14, i !== 0) { - if (a === E.SEMI) return this.emitNamedEntityData(this.treeIndex, i, this.consumed + this.excess); - this.decodeMode !== k.Strict && (r & C.FLAG13) === 0 && (this.result = this.treeIndex, this.consumed += this.excess, this.excess = 0); - } - t++, this.excess++; - } - return -1; - } - emitNotTerminatedNamedEntity() { - var e; - let { result: t, decodeTree: n } = this, r = (n[t] & C.VALUE_LENGTH) >> 14; - return this.emitNamedEntityData(t, r, this.consumed), (e = this.errors) == null || e.missingSemicolonAfterCharacterReference(), this.consumed; - } - emitNamedEntityData(e, t, n) { - let { decodeTree: r } = this; - return this.emitCodePoint(t === 1 ? r[e] & ~(C.VALUE_LENGTH | C.FLAG13) : r[e + 1], n), t === 3 && this.emitCodePoint(r[e + 2], n), n; - } - end() { - switch (this.state) { - case O.NamedEntity: return this.result !== 0 && (this.decodeMode !== k.Attribute || this.result === this.treeIndex) ? this.emitNotTerminatedNamedEntity() : 0; - case O.NumericDecimal: return this.emitNumericEntity(0, 2); - case O.NumericHex: return this.emitNumericEntity(0, 3); - case O.NumericStart: - var e; - return (e = this.errors) == null || e.absenceOfDigitsInNumericCharacterReference(this.consumed), 0; - case O.EntityStart: return 0; - } - } -}; -function _e(e) { - let t = "", n = new ge(e, (e) => t += String.fromCodePoint(e)); - return function(e, r) { - let i = 0, a = 0; - for (; (a = e.indexOf("&", a)) >= 0;) { - t += e.slice(i, a), n.startEntity(r); - let o = n.write(e, a + 1); - if (o < 0) { - i = a + n.end(); - break; - } - i = a + o, a = o === 0 ? i + 1 : i; - } - let o = t + e.slice(i); - return t = "", o; - }; -} -function ve(e, t, n, r) { - let i = (t & C.BRANCH_LENGTH) >> 7, a = t & C.JUMP_TABLE; - if (i === 0) return a !== 0 && r === a ? n : -1; - if (a) { - let t = r - a; - return t < 0 || t >= i ? -1 : e[n + t] - 1; - } - let o = i + 1 >> 1, s = 0, c = i - 1; - for (; s <= c;) { - let t = s + c >>> 1, i = e[n + (t >> 1)] >> (t & 1) * 8 & 255; - if (i < r) s = t + 1; - else if (i > r) c = t - 1; - else return e[n + o + t]; - } - return -1; -} -var ye = /* #__PURE__ */ _e(le); -function be(e) { - return ye(e, k.Strict); -} -//#endregion -//#region src/common/utils.ts -var xe = /* @__PURE__ */ t({ - arrayReplaceAt: () => Ce, - asciiTrim: () => R, - callable: () => Se, - escapeHtml: () => M, - escapeRE: () => Fe, - fromCodePoint: () => A, - isMdAsciiPunct: () => I, - isPunctChar: () => Ie, - isPunctCharCode: () => F, - isSpace: () => N, - isValidEntityCode: () => we, - isWhiteSpace: () => P, - lib: () => Re, - normalizeReference: () => L, - unescapeAll: () => j, - unescapeMd: () => ke -}); -function Se(e) { - let t = function(...n) { - return Reflect.construct(e, n, new.target && new.target !== t ? new.target : e); - }; - return Object.defineProperty(t, "name", { value: e.name }), Object.setPrototypeOf(t, e), t.prototype = e.prototype, t; -} -function Ce(e, t, n) { - return [].concat(e.slice(0, t), n, e.slice(t + 1)); -} -function we(e) { - return !(e >= 55296 && e <= 57343 || e >= 64976 && e <= 65007 || (e & 65535) == 65535 || (e & 65535) == 65534 || e >= 0 && e <= 8 || e === 11 || e >= 14 && e <= 31 || e >= 127 && e <= 159 || e > 1114111); -} -function A(e) { - if (e > 65535) { - e -= 65536; - let t = 55296 + (e >> 10), n = 56320 + (e & 1023); - return String.fromCharCode(t, n); - } - return String.fromCharCode(e); -} -var Te = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g, Ee = RegExp(`${Te.source}|&([a-z#][a-z0-9]{1,31});`, "gi"), De = /^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))$/i; -function Oe(e, t) { - if (t.charCodeAt(0) === 35 && De.test(t)) { - let n = t[1].toLowerCase() === "x" ? parseInt(t.slice(2), 16) : parseInt(t.slice(1), 10); - return we(n) ? A(n) : e; - } - let n = be(e); - return n === e ? e : n; -} -function ke(e) { - return e.indexOf("\\") < 0 ? e : e.replace(Te, "$1"); -} -function j(e) { - return e.indexOf("\\") < 0 && e.indexOf("&") < 0 ? e : e.replace(Ee, function(e, t, n) { - return t || Oe(e, n); - }); -} -var Ae = /[&<>"]/, je = /[&<>"]/g, Me = { - "&": "&", - "<": "<", - ">": ">", - "\"": """ -}; -function Ne(e) { - return Me[e]; -} -function M(e) { - return Ae.test(e) ? e.replace(je, Ne) : e; -} -var Pe = /[.?*+^$[\]\\(){}|-]/g; -function Fe(e) { - return e.replace(Pe, "\\$&"); -} -function N(e) { - switch (e) { - case 9: - case 32: return !0; - } - return !1; -} -function P(e) { - if (e >= 8192 && e <= 8202) return !0; - switch (e) { - case 9: - case 10: - case 11: - case 12: - case 13: - case 32: - case 160: - case 5760: - case 8239: - case 8287: - case 12288: return !0; - } - return !1; -} -function Ie(e) { - return S.test(e) || ie.test(e); -} -function F(e) { - return Ie(A(e)); -} -function I(e) { - switch (e) { - case 33: - case 34: - case 35: - case 36: - case 37: - case 38: - case 39: - case 40: - case 41: - case 42: - case 43: - case 44: - case 45: - case 46: - case 47: - case 58: - case 59: - case 60: - case 61: - case 62: - case 63: - case 64: - case 91: - case 92: - case 93: - case 94: - case 95: - case 96: - case 123: - case 124: - case 125: - case 126: return !0; - default: return !1; - } -} -function L(e) { - return e = e.trim().replace(/\s+/g, " "), e.toLowerCase().toUpperCase(); -} -function Le(e) { - return e === 32 || e === 9 || e === 10 || e === 13; -} -function R(e) { - let t = 0; - for (; t < e.length && Le(e.charCodeAt(t)); t++); - let n = e.length - 1; - for (; n >= t && Le(e.charCodeAt(n)); n--); - return e.slice(t, n + 1); -} -var Re = { - mdurl: ee, - ucmicro: te -}; -//#endregion -//#region src/helpers/parse_link_label.ts -function ze(e, t, n) { - let r, i, a, o, s = e.posMax, c = e.pos; - for (e.pos = t + 1, r = 1; e.pos < s;) { - if (a = e.src.charCodeAt(e.pos), a === 93 && (r--, r === 0)) { - i = !0; - break; - } - if (o = e.pos, e.md.inline.skipToken(e), a === 91) { - if (o === e.pos - 1) r++; - else if (n) return e.pos = c, -1; - } - } - let l = -1; - return i && (l = e.pos), e.pos = c, l; -} -//#endregion -//#region src/helpers/parse_link_destination.ts -function Be(e, t, n) { - let r, i = t, a = { - ok: !1, - pos: 0, - str: "" - }; - if (e.charCodeAt(i) === 60) { - for (i++; i < n;) { - if (r = e.charCodeAt(i), r === 10 || r === 60) return a; - if (r === 62) return a.pos = i + 1, a.str = j(e.slice(t + 1, i)), a.ok = !0, a; - if (r === 92 && i + 1 < n) { - i += 2; - continue; - } - i++; - } - return a; - } - let o = 0; - for (; i < n && (r = e.charCodeAt(i), !(r === 32 || r < 32 || r === 127));) { - if (r === 92 && i + 1 < n) { - if (e.charCodeAt(i + 1) === 32) { - i++; - continue; - } - i += 2; - continue; - } - if (r === 40 && (o++, o > 32)) return a; - if (r === 41) { - if (o === 0) break; - o--; - } - i++; - } - return t === i || o !== 0 ? a : (a.str = j(e.slice(t, i)), a.pos = i, a.ok = !0, a); -} -//#endregion -//#region src/helpers/parse_link_title.ts -function Ve(e, t, n, r) { - let i, a = t, o = { - ok: !1, - can_continue: !1, - pos: 0, - str: "", - marker: 0 - }; - if (r) o.str = r.str, o.marker = r.marker; - else { - if (a >= n) return o; - let r = e.charCodeAt(a); - if (r !== 34 && r !== 39 && r !== 40) return o; - t++, a++, r === 40 && (r = 41), o.marker = r; - } - for (; a < n;) { - if (i = e.charCodeAt(a), i === o.marker) return o.pos = a + 1, o.str += j(e.slice(t, a)), o.ok = !0, o; - if (i === 40 && o.marker === 41) return o; - i === 92 && a + 1 < n && a++, a++; - } - return o.can_continue = !0, o.str += j(e.slice(t, a)), o; -} -//#endregion -//#region src/helpers/index.ts -var He = /* @__PURE__ */ t({ - parseLinkDestination: () => Be, - parseLinkLabel: () => ze, - parseLinkTitle: () => Ve -}), z = class { - constructor(e, t, n) { - T(this, "map", null), T(this, "level", 0), T(this, "children", null), T(this, "content", ""), T(this, "markup", ""), T(this, "info", ""), T(this, "block", !1), T(this, "hidden", !1), this.type = e, this.tag = t, this.attrs = null, this.nesting = n, this.meta = null; - } - attrIndex(e) { - if (!this.attrs) return -1; - let t = this.attrs; - for (let n = 0, r = t.length; n < r; n++) if (t[n][0] === e) return n; - return -1; - } - attrPush(e) { - this.attrs ? this.attrs.push(e) : this.attrs = [e]; - } - attrSet(e, t) { - let n = this.attrIndex(e), r = [e, t]; - n < 0 ? this.attrPush(r) : this.attrs[n] = r; - } - attrGet(e) { - let t = this.attrIndex(e), n = null; - return t >= 0 && (n = this.attrs[t][1]), n; - } - attrJoin(e, t) { - let n = this.attrIndex(e); - n < 0 ? this.attrPush([e, t]) : this.attrs[n][1] = `${this.attrs[n][1]} ${t}`; - } -}, B = class { - constructor() { - T(this, "__rules__", []), T(this, "__cache__", null); - } - __find__(e) { - for (let t = 0; t < this.__rules__.length; t++) if (this.__rules__[t].name === e) return t; - return -1; - } - __compile__() { - let e = /* @__PURE__ */ new Set(); - this.__rules__.forEach((t) => { - t.enabled && t.alt.forEach((t) => { - t && e.add(t); - }); - }), this.__cache__ = Object.create(null), this.__cache__[""] = [], this.__rules__.forEach((e) => { - e.enabled && this.__cache__[""].push(e.fn); - }), e.forEach((e) => { - this.__cache__[e] = [], this.__rules__.forEach((t) => { - t.enabled && t.alt.indexOf(e) >= 0 && this.__cache__[e].push(t.fn); - }); - }); - } - at(e, t, n = {}) { - let r = this.__find__(e); - if (r === -1) throw Error(`Parser rule not found: ${e}`); - this.__rules__[r].fn = t, this.__rules__[r].alt = n.alt || [], this.__cache__ = null; - } - before(e, t, n, r = {}) { - let i = this.__find__(e); - if (i === -1) throw Error(`Parser rule not found: ${e}`); - this.__rules__.splice(i, 0, { - name: t, - enabled: !0, - fn: n, - alt: r.alt || [] - }), this.__cache__ = null; - } - after(e, t, n, r = {}) { - let i = this.__find__(e); - if (i === -1) throw Error(`Parser rule not found: ${e}`); - this.__rules__.splice(i + 1, 0, { - name: t, - enabled: !0, - fn: n, - alt: r.alt || [] - }), this.__cache__ = null; - } - push(e, t, n = {}) { - this.__rules__.push({ - name: e, - enabled: !0, - fn: t, - alt: n.alt || [] - }), this.__cache__ = null; - } - enable(e, t = !1) { - Array.isArray(e) || (e = [e]); - let n = []; - return e.forEach((e) => { - let r = this.__find__(e); - if (r < 0) { - if (t) return; - throw Error(`Rules manager: invalid rule name ${e}`); - } - this.__rules__[r].enabled = !0, n.push(e); - }), this.__cache__ = null, n; - } - enableOnly(e, t = !1) { - Array.isArray(e) || (e = [e]), this.__rules__.forEach((e) => { - e.enabled = !1; - }), this.enable(e, t); - } - disable(e, t = !1) { - Array.isArray(e) || (e = [e]); - let n = []; - return e.forEach((e) => { - let r = this.__find__(e); - if (r < 0) { - if (t) return; - throw Error(`Rules manager: invalid rule name ${e}`); - } - this.__rules__[r].enabled = !1, n.push(e); - }), this.__cache__ = null, n; - } - getRules(e) { - return this.__cache__ || this.__compile__(), this.__cache__[e] || []; - } -}, V = {}; -V.code_inline = function(e, t, n, r, i) { - let a = e[t]; - return `${M(a.content)}`; -}, V.code_block = function(e, t, n, r, i) { - let a = e[t]; - return `${M(e[t].content)}\n`; -}, V.fence = function(e, t, n, r, i) { - let a = e[t], o = a.info ? j(a.info).trim() : "", s = "", c = ""; - if (o) { - let e = o.split(/(\s+)/g); - s = e[0], c = e.slice(2).join(""); - } - let l; - if (l = n.highlight && n.highlight(a.content, s, c) || M(a.content), l.indexOf("${l}\n`; - } - return `
${l}
\n`; -}, V.image = function(e, t, n, r, i) { - let a = e[t]; - return a.attrs[a.attrIndex("alt")][1] = i.renderInlineAsText(a.children, n, r), i.renderToken(e, t, n); -}, V.hardbreak = function(e, t, n) { - return n.xhtmlOut ? "
\n" : "
\n"; -}, V.softbreak = function(e, t, n) { - return n.breaks ? n.xhtmlOut ? "
\n" : "
\n" : "\n"; -}, V.text = function(e, t) { - return M(e[t].content); -}, V.html_block = function(e, t) { - return e[t].content; -}, V.html_inline = function(e, t) { - return e[t].content; -}; -var Ue = class { - constructor() { - T(this, "rules", Object.assign({}, V)); - } - renderAttrs(e) { - let t, n, r; - if (!e.attrs) return ""; - for (r = "", t = 0, n = e.attrs.length; t < n; t++) r += ` ${M(e.attrs[t][0])}="${M(String(e.attrs[t][1]))}"`; - return r; - } - renderToken(e, t, n) { - let r = e[t], i = ""; - if (r.hidden) return ""; - let a = t - 1; - for (; a >= 0 && e[a].hidden && e[a].nesting === 0;) a--; - r.block && r.nesting !== -1 && a >= 0 && e[a].hidden && e[a].nesting === -1 && (i += "\n"), i += (r.nesting === -1 ? "\n" : ">", i; - } - renderInline(e, t, n) { - let r = "", i = this.rules; - for (let a = 0, o = e.length; a < o; a++) { - let o = e[a].type; - i[o] === void 0 ? r += this.renderToken(e, a, t) : r += i[o](e, a, t, n, this); - } - return r; - } - renderInlineAsText(e, t, n) { - let r = ""; - for (let i = 0, a = e.length; i < a; i++) switch (e[i].type) { - case "text": - case "code_inline": - r += e[i].content; - break; - case "image": - r += this.renderInlineAsText(e[i].children, t, n); - break; - case "html_inline": - case "html_block": - r += e[i].content; - break; - case "softbreak": - case "hardbreak": r += "\n"; - } - return r; - } - render(e, t, n) { - let r = "", i = this.rules; - for (let a = 0, o = e.length; a < o; a++) { - let o = e[a].type; - o === "inline" ? r += this.renderInline(e[a].children, t, n) : i[o] === void 0 ? r += this.renderToken(e, a, t) : r += i[o](e, a, t, n, this); - } - return r; - } -}, We = class { - constructor(e, t, n) { - T(this, "tokens", []), T(this, "inlineMode", !1), T(this, "Token", z), this.src = e, this.env = n, this.md = t; - } -}, Ge = /\r\n?/g, Ke = /\0/g; -function qe(e) { - let t; - t = e.src.replace(Ge, "\n"), t = t.replace(Ke, "�"), e.src = t; -} -//#endregion -//#region src/rules_core/block.ts -function Je(e) { - let t; - e.inlineMode ? (t = new e.Token("inline", "", 0), t.content = e.src, t.map = [0, 1], t.children = [], e.tokens.push(t)) : e.md.block.parse(e.src, e.md, e.env, e.tokens); -} -//#endregion -//#region src/rules_core/strip_references.ts -function Ye(e) { - let t = e.tokens, n = 0; - for (let e = 0; e < t.length; e++) t[e].type !== "reference_definition" && (e !== n && (t[n] = t[e]), n++); - t.length !== n && (t.length = n); -} -//#endregion -//#region src/rules_core/inline.ts -function Xe(e) { - let t = e.tokens; - for (let n = 0, r = t.length; n < r; n++) { - let r = t[n]; - r.type === "inline" && e.md.inline.parse(r.content, e.md, e.env, r.children); - } -} -//#endregion -//#region src/rules_core/linkify.ts -function Ze(e) { - return /^\s]/i.test(e); -} -function Qe(e) { - return /^<\/a\s*>/i.test(e); -} -function $e(e) { - let t = e.tokens; - if (e.md.options.linkify) for (let n = 0, r = t.length; n < r; n++) { - if (t[n].type !== "inline" || !e.md.linkify.test(t[n].content)) continue; - let r = t[n].children, i = [], a = 0; - for (let t = r.length - 1; t >= 0; t--) { - let n = r[t]; - if (n.type === "link_close") { - for (t--; r[t].level !== n.level && r[t].type !== "link_open";) t--; - continue; - } - if (n.type === "html_inline" && (Ze(n.content) && a > 0 && a--, Qe(n.content) && a++), !(a > 0) && n.type === "text" && e.md.linkify.test(n.content)) { - let a = n.content, o = e.md.linkify.match(a), s = [], c = n.level, l = 0; - o.length > 0 && o[0].index === 0 && t > 0 && r[t - 1].type === "text_special" && (o = o.slice(1)); - for (let t = 0; t < o.length; t++) { - let n = o[t].url, r = e.md.normalizeLink(n); - if (!e.md.validateLink(r)) continue; - let i = o[t].text; - i = o[t].schema ? o[t].schema === "mailto:" && !/^mailto:/i.test(i) ? e.md.normalizeLinkText(`mailto:${i}`).replace(/^mailto:/, "") : e.md.normalizeLinkText(i) : e.md.normalizeLinkText(`http://${i}`).replace(/^http:\/\//, ""); - let u = o[t].index; - if (u > l) { - let t = new e.Token("text", "", 0); - t.content = a.slice(l, u), t.level = c, s.push(t); - } - let d = new e.Token("link_open", "a", 1); - d.attrs = [["href", r]], d.level = c++, d.markup = "linkify", d.info = "auto", s.push(d); - let f = new e.Token("text", "", 0); - f.content = i, f.level = c, s.push(f); - let p = new e.Token("link_close", "a", -1); - p.level = --c, p.markup = "linkify", p.info = "auto", s.push(p), l = o[t].lastIndex; - } - if (l < a.length) { - let t = new e.Token("text", "", 0); - t.content = a.slice(l), t.level = c, s.push(t); - } - i.push({ - index: t, - nodes: s - }); - } - } - if (i.length > 0) { - let e = r.length; - for (let t of i) e += t.nodes.length - 1; - let a = Array(e), o = 0, s = 0; - i.reverse(); - for (let e = 0; e < r.length; e++) { - let t = i[o]; - if ((t == null ? void 0 : t.index) === e) { - for (let e of t.nodes) a[s++] = e; - o++; - } else a[s++] = r[e]; - } - t[n].children = a; - } - } -} -//#endregion -//#region src/rules_core/replacements.ts -var et = /\+-|\.\.|\?\?\?\?|!!!!|,,|--/, tt = /\((c|tm|r)\)/i, nt = /\((c|tm|r)\)/gi, rt = { - c: "©", - r: "®", - tm: "™" -}; -function it(e, t) { - return rt[t.toLowerCase()]; -} -function at(e) { - let t = 0; - for (let n = e.length - 1; n >= 0; n--) { - let r = e[n]; - r.type === "text" && !t && (r.content = r.content.replace(nt, it)), r.type === "link_open" && r.info === "auto" && t--, r.type === "link_close" && r.info === "auto" && t++; - } -} -function ot(e) { - let t = 0; - for (let n = e.length - 1; n >= 0; n--) { - let r = e[n]; - r.type === "text" && !t && et.test(r.content) && (r.content = r.content.replace(/\+-/g, "±").replace(/\.{2,}/g, "…").replace(/([?!])…/g, "$1..").replace(/([?!]){4,}/g, "$1$1$1").replace(/,{2,}/g, ",").replace(/(^|[^-])---(?=[^-]|$)/gm, "$1—").replace(/(^|\s)--(?=\s|$)/gm, "$1–").replace(/(^|[^-\s])--(?=[^-\s]|$)/gm, "$1–")), r.type === "link_open" && r.info === "auto" && t--, r.type === "link_close" && r.info === "auto" && t++; - } -} -function st(e) { - let t; - if (e.md.options.typographer) for (t = e.tokens.length - 1; t >= 0; t--) e.tokens[t].type === "inline" && (tt.test(e.tokens[t].content) && at(e.tokens[t].children), et.test(e.tokens[t].content) && ot(e.tokens[t].children)); -} -//#endregion -//#region src/rules_core/smartquotes.ts -var ct = /['"]/, lt = /['"]/g, ut = "’", dt = 1e3; -function ft(e, t, n) { - for (; e.length > n;) { - let n = e.pop(); - n.isSingleQuote ? t.single = n.prevSameQuoteIdx : t.double = n.prevSameQuoteIdx; - } -} -function H(e, t, n, r) { - e[t] || (e[t] = []), e[t].push({ - pos: n, - ch: r - }); -} -function pt(e, t) { - let n = "", r = 0; - t.sort((e, t) => e.pos - t.pos); - for (let i = 0; i < t.length; i++) { - let a = t[i]; - n += e.slice(r, a.pos) + a.ch, r = a.pos + 1; - } - return n + e.slice(r); -} -function mt(e, t) { - let n, r = [], i = { - single: -1, - double: -1 - }, a = {}; - for (let o = 0; o < e.length; o++) { - let s = e[o], c = e[o].level; - for (n = r.length - 1; n >= 0 && !(r[n].level <= c); n--); - if (ft(r, i, n + 1), s.type !== "text") continue; - let l = s.content, u = 0, d = l.length; - OUTER: for (; u < d;) { - lt.lastIndex = u; - let s = lt.exec(l); - if (!s) break; - let f = !0, p = !0; - u = s.index + 1; - let m = s[0] === "'", h = 32; - if (s.index - 1 >= 0) h = l.charCodeAt(s.index - 1); - else for (n = o - 1; n >= 0 && e[n].type !== "softbreak" && e[n].type !== "hardbreak"; n--) if (e[n].content) { - h = e[n].content.charCodeAt(e[n].content.length - 1); - break; - } - let g = 32; - if (u < d) g = l.charCodeAt(u); - else for (n = o + 1; n < e.length && e[n].type !== "softbreak" && e[n].type !== "hardbreak"; n++) if (e[n].content) { - g = e[n].content.charCodeAt(0); - break; - } - let _ = I(h) || F(h), v = I(g) || F(g), y = P(h), b = P(g); - if (b ? f = !1 : v && (y || _ || (f = !1)), y ? p = !1 : _ && (b || v || (p = !1)), g === 34 && s[0] === "\"" && h >= 48 && h <= 57 && (p = f = !1), f && p && (f = _, p = v), !f && !p) { - m && H(a, o, s.index, ut); - continue; - } - if (p && (n = m ? i.single : i.double, n >= 0 && r[n].level === c)) { - let e = r[n], c, l; - m ? (c = t.md.options.quotes[2], l = t.md.options.quotes[3]) : (c = t.md.options.quotes[0], l = t.md.options.quotes[1]), H(a, o, s.index, l), H(a, e.tokenIdx, e.contentPos, c), ft(r, i, n); - continue OUTER; - } - if (f) { - if (r.length >= dt) return; - r.push({ - tokenIdx: o, - contentPos: s.index, - isSingleQuote: m, - level: c, - prevSameQuoteIdx: m ? i.single : i.double - }), m ? i.single = r.length - 1 : i.double = r.length - 1; - } else p && m && H(a, o, s.index, ut); - } - } - Object.keys(a).forEach(function(t) { - let n = Number(t); - e[n].content = pt(e[n].content, a[t]); - }); -} -function ht(e) { - if (e.md.options.typographer) for (let t = e.tokens.length - 1; t >= 0; t--) e.tokens[t].type !== "inline" || !ct.test(e.tokens[t].content) || mt(e.tokens[t].children, e); -} -//#endregion -//#region src/rules_core/text_join.ts -function gt(e) { - let t, n, r = e.length; - for (t = 0; t < r; t++) e[t].type === "text_special" && (e[t].type = "text"); - for (t = n = 0; t < r; t++) e[t].type === "text" && t + 1 < r && e[t + 1].type === "text" ? e[t + 1].content = e[t].content + e[t + 1].content : (t !== n && (e[n] = e[t]), n++); - t !== n && (e.length = n); -} -function _t(e) { - let t, n, r = e.tokens, i = r.length; - for (let e = 0; e < i; e++) { - if (r[e].type !== "inline") continue; - let i = r[e].children, a = i.length; - for (t = 0; t < a; t++) i[t].type === "text_special" && (i[t].type = "text"), i[t].children && gt(i[t].children); - for (t = n = 0; t < a; t++) i[t].type === "text" && t + 1 < a && i[t + 1].type === "text" ? i[t + 1].content = i[t].content + i[t + 1].content : (t !== n && (i[n] = i[t]), n++); - t !== n && (i.length = n); - } -} -//#endregion -//#region src/parser_core.ts -var U = [ - ["normalize", qe], - ["block", Je], - ["strip_references", Ye], - ["inline", Xe], - ["linkify", $e], - ["replacements", st], - ["smartquotes", ht], - ["text_join", _t] -], vt = class { - constructor() { - T(this, "ruler", new B()), T(this, "State", We); - for (let e = 0; e < U.length; e++) this.ruler.push(U[e][0], U[e][1]); - } - process(e) { - let t = this.ruler.getRules(""); - for (let n = 0, r = t.length; n < r; n++) t[n](e); - } -}, yt = class { - constructor(e, t, n, r) { - T(this, "bMarks", []), T(this, "eMarks", []), T(this, "tShift", []), T(this, "sCount", []), T(this, "bsCount", []), T(this, "blkIndent", 0), T(this, "line", 0), T(this, "lineMax", 0), T(this, "tight", !1), T(this, "listIndent", -1), T(this, "parentType", "root"), T(this, "level", 0), T(this, "Token", z), this.src = e, this.md = t, this.env = n, this.tokens = r; - let i = this.src; - for (let e = 0, t = 0, n = 0, r = 0, a = i.length, o = !1; t < a; t++) { - let s = i.charCodeAt(t); - if (!o) if (N(s)) { - n++, s === 9 ? r += 4 - r % 4 : r++; - continue; - } else o = !0; - (s === 10 || t === a - 1) && (s !== 10 && t++, this.bMarks.push(e), this.eMarks.push(t), this.tShift.push(n), this.sCount.push(r), this.bsCount.push(0), o = !1, n = 0, r = 0, e = t + 1); - } - this.bMarks.push(i.length), this.eMarks.push(i.length), this.tShift.push(0), this.sCount.push(0), this.bsCount.push(0), this.lineMax = this.bMarks.length - 1; - } - push(e, t, n) { - let r = new z(e, t, n); - return r.block = !0, n < 0 && this.level--, r.level = this.level, n > 0 && this.level++, this.tokens.push(r), r; - } - isEmpty(e) { - return this.bMarks[e] + this.tShift[e] >= this.eMarks[e]; - } - skipEmptyLines(e) { - for (let t = this.lineMax; e < t && !(this.bMarks[e] + this.tShift[e] < this.eMarks[e]); e++); - return e; - } - skipSpaces(e) { - for (let t = this.src.length; e < t && N(this.src.charCodeAt(e)); e++); - return e; - } - skipSpacesBack(e, t) { - if (e <= t) return e; - for (; e > t;) if (!N(this.src.charCodeAt(--e))) return e + 1; - return e; - } - skipChars(e, t) { - for (let n = this.src.length; e < n && this.src.charCodeAt(e) === t; e++); - return e; - } - skipCharsBack(e, t, n) { - if (e <= n) return e; - for (; e > n;) if (t !== this.src.charCodeAt(--e)) return e + 1; - return e; - } - getLines(e, t, n, r) { - if (e >= t) return ""; - let i = Array(t - e); - for (let a = 0, o = e; o < t; o++, a++) { - let e = 0, s = this.bMarks[o], c = s, l; - for (l = o + 1 < t || r ? this.eMarks[o] + 1 : this.eMarks[o]; c < l && e < n;) { - let t = this.src.charCodeAt(c); - if (N(t)) t === 9 ? e += 4 - (e + this.bsCount[o]) % 4 : e++; - else if (c - s < this.tShift[o]) e++; - else break; - c++; - } - e > n ? i[a] = Array(e - n + 1).join(" ") + this.src.slice(c, l) : i[a] = this.src.slice(c, l); - } - return i.join(""); - } -}, bt = 65536; -function W(e, t) { - let n = e.bMarks[t] + e.tShift[t], r = e.eMarks[t]; - return e.src.slice(n, r); -} -function xt(e) { - let t = [], n = e.length, r = 0, i = e.charCodeAt(r), a = !1, o = 0, s = ""; - for (; r < n;) i === 124 && (a ? (s += e.substring(o, r - 1), o = r) : (t.push(s + e.substring(o, r)), s = "", o = r + 1)), a = i === 92, r++, i = e.charCodeAt(r); - return t.push(s + e.substring(o)), t; -} -function St(e, t, n, r) { - if (t + 2 > n) return !1; - let i = t + 1; - if (e.sCount[i] < e.blkIndent || e.sCount[i] - e.blkIndent >= 4) return !1; - let a = e.bMarks[i] + e.tShift[i]; - if (a >= e.eMarks[i]) return !1; - let o = e.src.charCodeAt(a++); - if (o !== 124 && o !== 45 && o !== 58 || a >= e.eMarks[i]) return !1; - let s = e.src.charCodeAt(a++); - if (s !== 124 && s !== 45 && s !== 58 && !N(s) || o === 45 && N(s)) return !1; - for (; a < e.eMarks[i];) { - let t = e.src.charCodeAt(a); - if (t !== 124 && t !== 45 && t !== 58 && !N(t)) return !1; - a++; - } - let c = W(e, t + 1), l = c.split("|"), u = []; - for (let e = 0; e < l.length; e++) { - let t = l[e].trim(); - if (!t) { - if (e === 0 || e === l.length - 1) continue; - return !1; - } - if (!/^:?-+:?$/.test(t)) return !1; - t.charCodeAt(t.length - 1) === 58 ? u.push(t.charCodeAt(0) === 58 ? "center" : "right") : t.charCodeAt(0) === 58 ? u.push("left") : u.push(""); - } - if (c = W(e, t).trim(), c.indexOf("|") === -1 || e.sCount[t] - e.blkIndent >= 4) return !1; - l = xt(c), l.length && l[0] === "" && l.shift(), l.length && l[l.length - 1] === "" && l.pop(); - let d = l.length; - if (d === 0 || d !== u.length) return !1; - if (r) return !0; - let f = e.parentType; - e.parentType = "table"; - let p = e.md.block.ruler.getRules("blockquote"), m = e.push("table_open", "table", 1), h = [t, 0]; - m.map = h; - let g = e.push("thead_open", "thead", 1); - g.map = [t, t + 1]; - let _ = e.push("tr_open", "tr", 1); - _.map = [t, t + 1]; - for (let t = 0; t < l.length; t++) { - let n = e.push("th_open", "th", 1); - u[t] && (n.attrs = [["style", `text-align:${u[t]}`]]); - let r = e.push("inline", "", 0); - r.content = l[t].trim(), r.children = [], e.push("th_close", "th", -1); - } - e.push("tr_close", "tr", -1), e.push("thead_close", "thead", -1); - let v, y = 0; - for (i = t + 2; i < n && !(e.sCount[i] < e.blkIndent); i++) { - let r = !1; - for (let t = 0, a = p.length; t < a; t++) if (p[t](e, i, n, !0)) { - r = !0; - break; - } - if (r || (c = W(e, i).trim(), !c) || e.sCount[i] - e.blkIndent >= 4 || (l = xt(c), l.length && l[0] === "" && l.shift(), l.length && l[l.length - 1] === "" && l.pop(), y += d - l.length, y > bt)) break; - if (i === t + 2) { - let n = e.push("tbody_open", "tbody", 1); - n.map = v = [t + 2, 0]; - } - let a = e.push("tr_open", "tr", 1); - a.map = [i, i + 1]; - for (let t = 0; t < d; t++) { - let n = e.push("td_open", "td", 1); - u[t] && (n.attrs = [["style", `text-align:${u[t]}`]]); - let r = e.push("inline", "", 0); - r.content = l[t] ? l[t].trim() : "", r.children = [], e.push("td_close", "td", -1); - } - e.push("tr_close", "tr", -1); - } - return v && (e.push("tbody_close", "tbody", -1), v[1] = i), e.push("table_close", "table", -1), h[1] = i, e.parentType = f, e.line = i, !0; -} -//#endregion -//#region src/rules_block/code.ts -function Ct(e, t, n) { - if (e.sCount[t] - e.blkIndent < 4) return !1; - let r = t + 1, i = r; - for (; r < n;) { - if (e.isEmpty(r)) { - r++; - continue; - } - if (e.sCount[r] - e.blkIndent >= 4) { - r++, i = r; - continue; - } - break; - } - e.line = i; - let a = e.push("code_block", "code", 0); - return a.content = e.getLines(t, i, 4 + e.blkIndent, !1) + "\n", a.map = [t, e.line], !0; -} -//#endregion -//#region src/rules_block/fence.ts -function wt(e, t, n, r) { - let i = e.bMarks[t] + e.tShift[t], a = e.eMarks[t]; - if (e.sCount[t] - e.blkIndent >= 4 || i + 3 > a) return !1; - let o = e.src.charCodeAt(i); - if (o !== 126 && o !== 96) return !1; - let s = i; - i = e.skipChars(i, o); - let c = i - s; - if (c < 3) return !1; - let l = e.src.slice(s, i), u = e.src.slice(i, a); - if (o === 96 && u.indexOf(String.fromCharCode(o)) >= 0) return !1; - if (r) return !0; - let d = t, f = !1; - for (; d++, !(d >= n || (i = s = e.bMarks[d] + e.tShift[d], a = e.eMarks[d], i < a && e.sCount[d] < e.blkIndent));) if (e.src.charCodeAt(i) === o && !(e.sCount[d] - e.blkIndent >= 4) && (i = e.skipChars(i, o), !(i - s < c) && (i = e.skipSpaces(i), !(i < a)))) { - f = !0; - break; - } - c = e.sCount[t], e.line = d + +!!f; - let p = e.push("fence", "code", 0); - return p.info = u, p.content = e.getLines(t + 1, d, c, !0), p.markup = l, p.map = [t, e.line], !0; -} -//#endregion -//#region src/rules_block/blockquote.ts -function Tt(e, t, n, r) { - let i = e.bMarks[t] + e.tShift[t], a = e.eMarks[t], o = e.lineMax; - if (e.sCount[t] - e.blkIndent >= 4 || e.src.charCodeAt(i) !== 62) return !1; - if (r) return !0; - let s = [], c = [], l = [], u = [], d = e.md.block.ruler.getRules("blockquote"), f = e.parentType; - e.parentType = "blockquote"; - let p = !1, m; - for (m = t; m < n; m++) { - let t = e.sCount[m] < e.blkIndent; - if (i = e.bMarks[m] + e.tShift[m], a = e.eMarks[m], i >= a) break; - if (e.src.charCodeAt(i++) === 62 && !t) { - let t = e.sCount[m] + 1, n, r; - e.src.charCodeAt(i) === 32 ? (i++, t++, r = !1, n = !0) : e.src.charCodeAt(i) === 9 ? (n = !0, (e.bsCount[m] + t) % 4 == 3 ? (i++, t++, r = !1) : r = !0) : n = !1; - let o = t; - for (s.push(e.bMarks[m]), e.bMarks[m] = i; i < a;) { - let t = e.src.charCodeAt(i); - if (N(t)) t === 9 ? o += 4 - (o + e.bsCount[m] + +!!r) % 4 : o++; - else break; - i++; - } - p = i >= a, c.push(e.bsCount[m]), e.bsCount[m] = e.sCount[m] + 1 + +!!n, l.push(e.sCount[m]), e.sCount[m] = o - t, u.push(e.tShift[m]), e.tShift[m] = i - e.bMarks[m]; - continue; - } - if (p) break; - let r = !1; - for (let t = 0, i = d.length; t < i; t++) if (d[t](e, m, n, !0)) { - r = !0; - break; - } - if (r) { - e.lineMax = m, e.blkIndent !== 0 && (s.push(e.bMarks[m]), c.push(e.bsCount[m]), u.push(e.tShift[m]), l.push(e.sCount[m]), e.sCount[m] -= e.blkIndent); - break; - } - s.push(e.bMarks[m]), c.push(e.bsCount[m]), u.push(e.tShift[m]), l.push(e.sCount[m]), e.sCount[m] = -1; - } - let h = e.blkIndent; - e.blkIndent = 0; - let g = e.push("blockquote_open", "blockquote", 1); - g.markup = ">"; - let _ = [t, 0]; - g.map = _, e.md.block.tokenize(e, t, m); - let v = e.push("blockquote_close", "blockquote", -1); - v.markup = ">", e.lineMax = o, e.parentType = f, _[1] = e.line; - for (let n = 0; n < u.length; n++) e.bMarks[n + t] = s[n], e.tShift[n + t] = u[n], e.sCount[n + t] = l[n], e.bsCount[n + t] = c[n]; - return e.blkIndent = h, !0; -} -//#endregion -//#region src/rules_block/hr.ts -function Et(e, t, n, r) { - let i = e.eMarks[t]; - if (e.sCount[t] - e.blkIndent >= 4) return !1; - let a = e.bMarks[t] + e.tShift[t], o = e.src.charCodeAt(a++); - if (o !== 42 && o !== 45 && o !== 95) return !1; - let s = 1; - for (; a < i;) { - let t = e.src.charCodeAt(a++); - if (t !== o && !N(t)) return !1; - t === o && s++; - } - if (s < 3) return !1; - if (r) return !0; - e.line = t + 1; - let c = e.push("hr", "hr", 0); - return c.map = [t, e.line], c.markup = Array(s + 1).join(String.fromCharCode(o)), !0; -} -//#endregion -//#region src/rules_block/list.ts -function Dt(e, t) { - let n = e.eMarks[t], r = e.bMarks[t] + e.tShift[t], i = e.src.charCodeAt(r++); - return i !== 42 && i !== 45 && i !== 43 || r < n && !N(e.src.charCodeAt(r)) ? -1 : r; -} -function Ot(e, t) { - let n = e.bMarks[t] + e.tShift[t], r = e.eMarks[t], i = n; - if (i + 1 >= r) return -1; - let a = e.src.charCodeAt(i++); - if (a < 48 || a > 57) return -1; - for (;;) { - if (i >= r) return -1; - if (a = e.src.charCodeAt(i++), a >= 48 && a <= 57) { - if (i - n >= 10) return -1; - continue; - } - if (a === 41 || a === 46) break; - return -1; - } - return i < r && (a = e.src.charCodeAt(i), !N(a)) ? -1 : i; -} -function kt(e, t) { - let n = e.level + 2; - for (let r = t + 2, i = e.tokens.length - 2; r < i; r++) e.tokens[r].level === n && e.tokens[r].type === "paragraph_open" && (e.tokens[r + 2].hidden = !0, e.tokens[r].hidden = !0, r += 2); -} -function At(e, t, n, r) { - let i, a, o, s, c = t, l = !0; - if (e.sCount[c] - e.blkIndent >= 4 || e.listIndent >= 0 && e.sCount[c] - e.listIndent >= 4 && e.sCount[c] < e.blkIndent) return !1; - let u = !1; - r && e.parentType === "paragraph" && e.sCount[c] >= e.blkIndent && (u = !0); - let d, f, p; - if ((p = Ot(e, c)) >= 0) { - if (d = !0, o = e.bMarks[c] + e.tShift[c], f = Number(e.src.slice(o, p - 1)), u && f !== 1) return !1; - } else if ((p = Dt(e, c)) >= 0) d = !1; - else return !1; - if (u && e.skipSpaces(p) >= e.eMarks[c]) return !1; - if (r) return !0; - let m = e.src.charCodeAt(p - 1), h = e.tokens.length; - d ? (s = e.push("ordered_list_open", "ol", 1), f !== 1 && (s.attrs = [["start", f]])) : s = e.push("bullet_list_open", "ul", 1); - let g = [c, 0]; - s.map = g, s.markup = String.fromCharCode(m); - let _ = !1, v = e.md.block.ruler.getRules("list"), y = e.parentType; - for (e.parentType = "list"; c < n;) { - a = p, i = e.eMarks[c]; - let t = e.sCount[c] + p - (e.bMarks[c] + e.tShift[c]), r = t; - for (; a < i;) { - let t = e.src.charCodeAt(a); - if (t === 9) r += 4 - (r + e.bsCount[c]) % 4; - else if (t === 32) r++; - else break; - a++; - } - let u = a, f; - f = u >= i ? 1 : r - t, f > 4 && (f = 1); - let h = t + f; - s = e.push("list_item_open", "li", 1), s.markup = String.fromCharCode(m); - let g = [c, 0]; - s.map = g, d && (s.info = e.src.slice(o, p - 1)); - let y = e.tight, b = e.tShift[c], ee = e.sCount[c], te = e.listIndent; - if (e.listIndent = e.blkIndent, e.blkIndent = h, e.tight = !0, e.tShift[c] = u - e.bMarks[c], e.sCount[c] = r, u >= i && e.isEmpty(c + 1) ? e.line = Math.min(e.line + 2, n) : e.md.block.tokenize(e, c, n), (!e.tight || _) && (l = !1), _ = e.line - c > 1 && e.isEmpty(e.line - 1), e.blkIndent = e.listIndent, e.listIndent = te, e.tShift[c] = b, e.sCount[c] = ee, e.tight = y, s = e.push("list_item_close", "li", -1), s.markup = String.fromCharCode(m), c = e.line, g[1] = c, c >= n || e.sCount[c] < e.blkIndent || e.sCount[c] - e.blkIndent >= 4) break; - let x = !1; - for (let t = 0, r = v.length; t < r; t++) if (v[t](e, c, n, !0)) { - x = !0; - break; - } - if (x) break; - if (d) { - if (p = Ot(e, c), p < 0) break; - o = e.bMarks[c] + e.tShift[c]; - } else if (p = Dt(e, c), p < 0) break; - if (m !== e.src.charCodeAt(p - 1)) break; - } - return s = d ? e.push("ordered_list_close", "ol", -1) : e.push("bullet_list_close", "ul", -1), s.markup = String.fromCharCode(m), g[1] = c, e.line = c, e.parentType = y, l && kt(e, h), !0; -} -//#endregion -//#region src/rules_block/reference.ts -function jt(e, t, n, r) { - let i = e.bMarks[t] + e.tShift[t], a = e.eMarks[t], o = t + 1; - if (e.sCount[t] - e.blkIndent >= 4 || e.src.charCodeAt(i) !== 91) return !1; - function s(t) { - let n = e.lineMax; - if (t >= n || e.isEmpty(t)) return null; - let r = !1; - if (e.sCount[t] - e.blkIndent > 3 && (r = !0), e.sCount[t] < 0 && (r = !0), !r) { - let r = e.md.block.ruler.getRules("reference"), i = e.parentType; - e.parentType = "reference"; - let a = !1; - for (let i = 0, o = r.length; i < o; i++) if (r[i](e, t, n, !0)) { - a = !0; - break; - } - if (e.parentType = i, a) return null; - } - let i = e.bMarks[t] + e.tShift[t], a = e.eMarks[t]; - return e.src.slice(i, a + 1); - } - let c = e.src.slice(i, a + 1); - a = c.length; - let l = -1; - for (i = 1; i < a; i++) { - let e = c.charCodeAt(i); - if (e === 91) return !1; - if (e === 93) { - l = i; - break; - } - if (e === 10) { - let e = s(o); - e !== null && (c += e, a = c.length, o++); - } else if (e === 92 && (i++, i < a && c.charCodeAt(i) === 10)) { - let e = s(o); - e !== null && (c += e, a = c.length, o++); - } - } - if (l < 0 || c.charCodeAt(l + 1) !== 58) return !1; - for (i = l + 2; i < a; i++) { - let e = c.charCodeAt(i); - if (e === 10) { - let e = s(o); - e !== null && (c += e, a = c.length, o++); - } else if (!N(e)) break; - } - let u = e.md.helpers.parseLinkDestination(c, i, a); - if (!u.ok) return !1; - let d = e.md.normalizeLink(u.str); - if (!e.md.validateLink(d)) return !1; - i = u.pos; - let f = i, p = o, m = i; - for (; i < a; i++) { - let e = c.charCodeAt(i); - if (e === 10) { - let e = s(o); - e !== null && (c += e, a = c.length, o++); - } else if (!N(e)) break; - } - let h = e.md.helpers.parseLinkTitle(c, i, a); - for (; h.can_continue;) { - let t = s(o); - if (t === null) break; - c += t, i = a, a = c.length, o++, h = e.md.helpers.parseLinkTitle(c, i, a, h); - } - let g; - for (i < a && m !== i && h.ok ? (g = h.str, i = h.pos) : (g = "", i = f, o = p); i < a && N(c.charCodeAt(i));) i++; - if (i < a && c.charCodeAt(i) !== 10 && g) for (g = "", i = f, o = p; i < a && N(c.charCodeAt(i));) i++; - if (i < a && c.charCodeAt(i) !== 10) return !1; - let _ = L(c.slice(1, l)); - if (!_) return !1; - /* istanbul ignore if */ - if (r) return !0; - e.env.references === void 0 && (e.env.references = {}), e.env.references[_] === void 0 && (e.env.references[_] = { - title: g, - href: d - }); - let v = e.push("reference_definition", "", 0); - v.map = [t, o], v.hidden = !0; - let y = Object.create(null); - return y.label = _, v.meta = y, e.line = o, !0; -} -//#endregion -//#region src/common/html_blocks.ts -var Mt = /* @__PURE__ */ "address.article.aside.base.basefont.blockquote.body.caption.center.col.colgroup.dd.details.dialog.dir.div.dl.dt.fieldset.figcaption.figure.footer.form.frame.frameset.h1.h2.h3.h4.h5.h6.head.header.hr.html.iframe.legend.li.link.main.menu.menuitem.nav.noframes.ol.optgroup.option.p.param.search.section.summary.table.tbody.td.tfoot.th.thead.title.tr.track.ul".split("."), Nt = "<[A-Za-z][A-Za-z0-9\\-]*(?:\\s+[a-zA-Z_:][a-zA-Z0-9:._-]*(?:\\s*=\\s*(?:[^\"'=<>`\\x00-\\x20]+|'[^']*'|\"[^\"]*\"))?)*\\s*\\/?>", Pt = "<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>", Ft = RegExp(`^(?:${Nt}|${Pt}||<[?][\\s\\S]*?[?]>|]*>|)`), It = RegExp(`^(?:${Nt}|${Pt})`), G = [ - [ - /^<(script|pre|style|textarea)(?=(\s|>|$))/i, - /<\/(script|pre|style|textarea)>/i, - !0 - ], - [ - /^/, - !0 - ], - [ - /^<\?/, - /\?>/, - !0 - ], - [ - /^/, - !0 - ], - [ - /^/, - !0 - ], - [ - RegExp(`^|$))`, "i"), - /^$/, - !0 - ], - [ - RegExp(`${It.source}\\s*$`), - /^$/, - !1 - ] -]; -function Lt(e, t, n, r) { - let i = e.bMarks[t] + e.tShift[t], a = e.eMarks[t]; - if (e.sCount[t] - e.blkIndent >= 4 || !e.md.options.html || e.src.charCodeAt(i) !== 60) return !1; - let o = e.src.slice(i, a), s = 0; - for (; s < G.length && !G[s][0].test(o); s++); - if (s === G.length) return !1; - if (r) return G[s][2]; - let c = t + 1, l = G[s][1].test(""); - if (!G[s][1].test(o)) { - for (; c < n && !(e.sCount[c] < e.blkIndent && (l || !e.isEmpty(c))); c++) if (i = e.bMarks[c] + e.tShift[c], a = e.eMarks[c], o = e.src.slice(i, a), G[s][1].test(o)) { - o.length !== 0 && c++; - break; - } - } - e.line = c; - let u = e.push("html_block", "", 0); - return u.map = [t, c], u.content = e.getLines(t, c, e.blkIndent, !0), !0; -} -//#endregion -//#region src/rules_block/heading.ts -function Rt(e, t, n, r) { - let i = e.bMarks[t] + e.tShift[t], a = e.eMarks[t]; - if (e.sCount[t] - e.blkIndent >= 4) return !1; - let o = e.src.charCodeAt(i); - if (o !== 35 || i >= a) return !1; - let s = 1; - for (o = e.src.charCodeAt(++i); o === 35 && i < a && s <= 6;) s++, o = e.src.charCodeAt(++i); - if (s > 6 || i < a && !N(o)) return !1; - if (r) return !0; - a = e.skipSpacesBack(a, i); - let c = e.skipCharsBack(a, 35, i); - c > i && N(e.src.charCodeAt(c - 1)) && (a = c), e.line = t + 1; - let l = e.push("heading_open", `h${s}`, 1); - l.markup = "########".slice(0, s), l.map = [t, e.line]; - let u = e.push("inline", "", 0); - u.content = R(e.src.slice(i, a)), u.map = [t, e.line], u.children = []; - let d = e.push("heading_close", `h${s}`, -1); - return d.markup = "########".slice(0, s), !0; -} -//#endregion -//#region src/rules_block/lheading.ts -function zt(e, t, n) { - let r = e.md.block.ruler.getRules("paragraph"); - if (e.sCount[t] - e.blkIndent >= 4) return !1; - let i = e.parentType; - e.parentType = "paragraph"; - let a = 0, o, s = t + 1; - for (; s < n && !e.isEmpty(s); s++) { - if (e.sCount[s] - e.blkIndent > 3) continue; - if (e.sCount[s] >= e.blkIndent) { - let t = e.bMarks[s] + e.tShift[s], n = e.eMarks[s]; - if (t < n && (o = e.src.charCodeAt(t), (o === 45 || o === 61) && (t = e.skipChars(t, o), t = e.skipSpaces(t), t >= n))) { - a = o === 61 ? 1 : 2; - break; - } - } - if (e.sCount[s] < 0) continue; - let t = !1; - for (let i = 0, a = r.length; i < a; i++) if (r[i](e, s, n, !0)) { - t = !0; - break; - } - if (t) break; - } - if (!a) return e.parentType = i, !1; - let c = R(e.getLines(t, s, e.blkIndent, !1)); - e.line = s + 1; - let l = e.push("heading_open", `h${a}`, 1); - l.markup = String.fromCharCode(o), l.map = [t, e.line]; - let u = e.push("inline", "", 0); - u.content = c, u.map = [t, e.line - 1], u.children = []; - let d = e.push("heading_close", `h${a}`, -1); - return d.markup = String.fromCharCode(o), e.parentType = i, !0; -} -//#endregion -//#region src/rules_block/paragraph.ts -function Bt(e, t, n) { - let r = e.md.block.ruler.getRules("paragraph"), i = e.parentType, a = t + 1; - for (e.parentType = "paragraph"; a < n && !e.isEmpty(a); a++) { - if (e.sCount[a] - e.blkIndent > 3 || e.sCount[a] < 0) continue; - let t = !1; - for (let i = 0, o = r.length; i < o; i++) if (r[i](e, a, n, !0)) { - t = !0; - break; - } - if (t) break; - } - let o = R(e.getLines(t, a, e.blkIndent, !1)); - e.line = a; - let s = e.push("paragraph_open", "p", 1); - s.map = [t, e.line]; - let c = e.push("inline", "", 0); - return c.content = o, c.map = [t, e.line], c.children = [], e.push("paragraph_close", "p", -1), e.parentType = i, !0; -} -//#endregion -//#region src/parser_block.ts -var K = [ - [ - "table", - St, - ["paragraph", "reference"] - ], - ["code", Ct], - [ - "fence", - wt, - [ - "paragraph", - "reference", - "blockquote", - "list" - ] - ], - [ - "blockquote", - Tt, - [ - "paragraph", - "reference", - "blockquote", - "list" - ] - ], - [ - "hr", - Et, - [ - "paragraph", - "reference", - "blockquote", - "list" - ] - ], - [ - "list", - At, - [ - "paragraph", - "reference", - "blockquote" - ] - ], - ["reference", jt], - [ - "html_block", - Lt, - [ - "paragraph", - "reference", - "blockquote" - ] - ], - [ - "heading", - Rt, - [ - "paragraph", - "reference", - "blockquote" - ] - ], - ["lheading", zt], - ["paragraph", Bt] -], Vt = class { - constructor() { - T(this, "ruler", new B()), T(this, "State", yt); - for (let e = 0; e < K.length; e++) this.ruler.push(K[e][0], K[e][1], { alt: (K[e][2] || []).slice() }); - } - tokenize(e, t, n) { - let r = this.ruler.getRules(""), i = r.length, a = e.md.options.maxNesting, o = t, s = !1; - for (; o < n && (e.line = o = e.skipEmptyLines(o), !(o >= n || e.sCount[o] < e.blkIndent));) { - if (e.level >= a) { - e.line = n; - break; - } - let t = e.line, c = !1; - for (let a = 0; a < i; a++) if (c = r[a](e, o, n, !1), c) { - if (t >= e.line) throw Error("block rule didn't increment state.line"); - break; - } - if (!c) throw Error("none of the block rules matched"); - e.tight = !s, e.isEmpty(e.line - 1) && (s = !0), o = e.line, o < n && e.isEmpty(o) && (s = !0, o++, e.line = o); - } - } - parse(e, t, n, r) { - if (!e) return; - let i = new this.State(e, t, n, r); - this.tokenize(i, i.line, i.lineMax); - } -}, Ht = class { - constructor(e, t, n, r) { - T(this, "pos", 0), T(this, "level", 0), T(this, "pending", ""), T(this, "pendingLevel", 0), T(this, "cache", {}), T(this, "backticks", {}), T(this, "backticksScanned", !1), T(this, "linkLevel", 0), T(this, "delimiters", []), T(this, "_prev_delimiters", []), T(this, "Token", z), this.src = e, this.env = n, this.md = t, this.tokens = r, this.tokens_meta = Array(r.length), this.posMax = this.src.length; - } - pushPending() { - let e = new z("text", "", 0); - return e.content = this.pending, e.level = this.pendingLevel, this.tokens.push(e), this.pending = "", e; - } - push(e, t, n) { - this.pending && this.pushPending(); - let r = new z(e, t, n), i; - return n < 0 && (this.level--, this.delimiters = this._prev_delimiters.pop()), r.level = this.level, n > 0 && (this.level++, this._prev_delimiters.push(this.delimiters), this.delimiters = [], i = { delimiters: this.delimiters }), this.pendingLevel = this.level, this.tokens.push(r), this.tokens_meta.push(i), r; - } - scanDelims(e, t) { - let n = this.posMax, r = this.src.charCodeAt(e), i; - if (e === 0) i = 32; - else if (e === 1) i = this.src.charCodeAt(0), (i & 63488) == 55296 && (i = 65533); - else if (i = this.src.charCodeAt(e - 1), (i & 64512) == 56320) { - let t = this.src.charCodeAt(e - 2); - i = (t & 64512) == 55296 ? 65536 + (t - 55296 << 10) + (i - 56320) : 65533; - } else (i & 64512) == 55296 && (i = 65533); - let a = e; - for (; a < n && this.src.charCodeAt(a) === r;) a++; - let o = a - e, s = a < n ? this.src.charCodeAt(a) : 32; - if ((s & 64512) == 55296) { - let e = this.src.charCodeAt(a + 1); - s = (e & 64512) == 56320 ? 65536 + (s - 55296 << 10) + (e - 56320) : 65533; - } else (s & 64512) == 56320 && (s = 65533); - let c = I(i) || F(i), l = I(s) || F(s), u = P(i), d = P(s), f = !d && (!l || u || c), p = !u && (!c || d || l); - return { - can_open: f && (t || !p || c), - can_close: p && (t || !f || l), - length: o - }; - } -}; -//#endregion -//#region src/rules_inline/text.ts -function Ut(e) { - switch (e) { - case 10: - case 33: - case 35: - case 36: - case 37: - case 38: - case 42: - case 43: - case 45: - case 58: - case 60: - case 61: - case 62: - case 64: - case 91: - case 92: - case 93: - case 94: - case 95: - case 96: - case 123: - case 125: - case 126: return !0; - default: return !1; - } -} -function Wt(e, t) { - let n = e.pos; - for (; n < e.posMax && !Ut(e.src.charCodeAt(n));) n++; - return n !== e.pos && (t || (e.pending += e.src.slice(e.pos, n)), e.pos = n, !0); -} -//#endregion -//#region src/rules_inline/linkify.ts -function Gt(e) { - return e >= 65 && e <= 90 || e >= 97 && e <= 122; -} -function Kt(e) { - return e >= 65 && e <= 90 || e >= 97 && e <= 122 || e >= 48 && e <= 57 || e === 43 || e === 45 || e === 46; -} -function qt(e, t) { - if (!e.md.options.linkify || e.linkLevel > 0) return !1; - let n = e.pos, r = e.posMax; - if (n + 3 > r || e.src.charCodeAt(n) !== 58 || e.src.charCodeAt(n + 1) !== 47 || e.src.charCodeAt(n + 2) !== 47) return !1; - let i = n - Math.min(10, e.pending.length, n), a = n; - for (; a > i && Kt(e.src.charCodeAt(a - 1));) a--; - if (a === n || !Gt(e.src.charCodeAt(a))) return !1; - let o = n - a, s = e.md.linkify.matchAtStart(e.src.slice(a)); - if (!s) return !1; - let c = s.url; - if (c.length <= o) return !1; - let l = c.length; - for (; l > 0 && c.charCodeAt(l - 1) === 42;) l--; - l !== c.length && (c = c.slice(0, l)); - let u = e.md.normalizeLink(c); - if (!e.md.validateLink(u)) return !1; - if (!t) { - e.pending = e.pending.slice(0, -o); - let t = e.push("link_open", "a", 1); - t.attrs = [["href", u]], t.markup = "linkify", t.info = "auto"; - let n = e.push("text", "", 0); - n.content = e.md.normalizeLinkText(c); - let r = e.push("link_close", "a", -1); - r.markup = "linkify", r.info = "auto"; - } - return e.pos += c.length - o, !0; -} -//#endregion -//#region src/rules_inline/newline.ts -function Jt(e, t) { - let n = e.pos; - if (e.src.charCodeAt(n) !== 10) return !1; - let r = e.pending.length - 1, i = e.posMax; - if (!t) if (r >= 0 && e.pending.charCodeAt(r) === 32) if (r >= 1 && e.pending.charCodeAt(r - 1) === 32) { - let t = r - 1; - for (; t >= 1 && e.pending.charCodeAt(t - 1) === 32;) t--; - e.pending = e.pending.slice(0, t), e.push("hardbreak", "br", 0); - } else e.pending = e.pending.slice(0, -1), e.push("softbreak", "br", 0); - else e.push("softbreak", "br", 0); - for (n++; n < i && N(e.src.charCodeAt(n));) n++; - return e.pos = n, !0; -} -//#endregion -//#region src/rules_inline/escape.ts -var q = []; -for (let e = 0; e < 256; e++) q.push(0); -"\\!\"#$%&'()*+,./:;<=>?@[]^_`{|}~-".split("").forEach(function(e) { - q[e.charCodeAt(0)] = 1; -}); -function Yt(e, t) { - let n = e.pos, r = e.posMax; - if (e.src.charCodeAt(n) !== 92 || (n++, n >= r)) return !1; - let i = e.src.charCodeAt(n); - if (i === 10) { - for (t || e.push("hardbreak", "br", 0), n++; n < r && (i = e.src.charCodeAt(n), N(i));) n++; - return e.pos = n, !0; - } - if (i === 32) { - if (!t) { - let t = e.push("text_special", "", 0); - t.content = "\\", t.markup = "\\", t.info = "escape"; - } - return e.pos = n, !0; - } - let a = e.src[n]; - if (i >= 55296 && i <= 56319 && n + 1 < r) { - let t = e.src.charCodeAt(n + 1); - t >= 56320 && t <= 57343 && (a += e.src[n + 1], n++); - } - let o = "\\" + a; - if (!t) { - let t = e.push("text_special", "", 0); - t.content = i < 256 && q[i] !== 0 ? a : o, t.markup = o, t.info = "escape"; - } - return e.pos = n + 1, !0; -} -//#endregion -//#region src/rules_inline/backticks.ts -function Xt(e) { - let t = {}, n = 0; - for (; (n = e.indexOf("`", n)) !== -1;) { - let r = n; - for (; e.charCodeAt(++n) === 96;); - t[n - r] = r; - } - return t; -} -function Zt(e, t) { - var n; - let r = e.pos; - if (e.src.charCodeAt(r) !== 96) return !1; - let i = e.posMax, a = r + 1; - for (; a < i && e.src.charCodeAt(a) === 96;) a++; - let o = e.src.slice(r, a), s = o.length; - if (e.backticksScanned || (e.backticks = Xt(e.src), e.backticksScanned = !0), ((n = e.backticks[s]) == null ? -1 : n) >= a) { - let n = a, r; - for (; (r = e.src.indexOf("`", n)) !== -1 && r < i;) { - for (n = r + 1; e.src.charCodeAt(n) === 96;) n++; - if (n > i) break; - if (n - r === s) { - if (!t) { - let t = e.push("code_inline", "code", 0); - t.markup = o; - let n = e.src.slice(a, r).replace(/\n/g, " "); - n.startsWith(" ") && n.endsWith(" ") && /[^ ]/.test(n) && (n = n.slice(1, -1)), t.content = n; - } - return e.pos = n, !0; - } - } - } - return t || (e.pending += o), e.pos = a, !0; -} -//#endregion -//#region src/rules_inline/strikethrough.ts -function Qt(e, t) { - let n = e.pos, r = e.src.charCodeAt(n); - if (t || r !== 126) return !1; - let i = e.scanDelims(e.pos, !0), a = i.length, o = String.fromCharCode(r); - if (a < 2) return !1; - let s; - a % 2 && (s = e.push("text", "", 0), s.content = o, a--); - for (let t = 0; t < a; t += 2) s = e.push("text", "", 0), s.content = o + o, e.delimiters.push({ - marker: r, - length: 0, - token: e.tokens.length - 1, - end: -1, - open: i.can_open, - close: i.can_close - }); - return e.pos += i.length, !0; -} -function $t(e, t) { - let n, r = [], i = t.length; - for (let a = 0; a < i; a++) { - let i = t[a]; - if (i.marker !== 126 || i.end === -1) continue; - let o = t[i.end]; - n = e.tokens[i.token], n.type = "s_open", n.tag = "s", n.nesting = 1, n.markup = "~~", n.content = "", n = e.tokens[o.token], n.type = "s_close", n.tag = "s", n.nesting = -1, n.markup = "~~", n.content = "", e.tokens[o.token - 1].type === "text" && e.tokens[o.token - 1].content === "~" && r.push(o.token - 1); - } - for (; r.length;) { - let t = r.pop(), i = t + 1; - for (; i < e.tokens.length && e.tokens[i].type === "s_close";) i++; - i--, t !== i && (n = e.tokens[i], e.tokens[i] = e.tokens[t], e.tokens[t] = n); - } -} -function en(e) { - let t = e.tokens_meta, n = e.tokens_meta.length; - $t(e, e.delimiters); - for (let i = 0; i < n; i++) { - var r; - let n = (r = t[i]) == null ? void 0 : r.delimiters; - n && $t(e, n); - } -} -var tn = { - tokenize: Qt, - postProcess: en -}; -//#endregion -//#region src/rules_inline/emphasis.ts -function nn(e, t) { - let n = e.pos, r = e.src.charCodeAt(n); - if (t || r !== 95 && r !== 42) return !1; - let i = e.scanDelims(e.pos, r === 42); - for (let t = 0; t < i.length; t++) { - let t = e.push("text", "", 0); - t.content = String.fromCharCode(r), e.delimiters.push({ - marker: r, - length: i.length, - token: e.tokens.length - 1, - end: -1, - open: i.can_open, - close: i.can_close - }); - } - return e.pos += i.length, !0; -} -function rn(e, t) { - let n = t.length; - for (let r = n - 1; r >= 0; r--) { - let n = t[r]; - if (n.marker !== 95 && n.marker !== 42 || n.end === -1) continue; - let i = t[n.end], a = r > 0 && t[r - 1].end === n.end + 1 && t[r - 1].marker === n.marker && t[r - 1].token === n.token - 1 && t[n.end + 1].token === i.token + 1, o = String.fromCharCode(n.marker), s = e.tokens[n.token]; - s.type = a ? "strong_open" : "em_open", s.tag = a ? "strong" : "em", s.nesting = 1, s.markup = a ? o + o : o, s.content = ""; - let c = e.tokens[i.token]; - c.type = a ? "strong_close" : "em_close", c.tag = a ? "strong" : "em", c.nesting = -1, c.markup = a ? o + o : o, c.content = "", a && (e.tokens[t[r - 1].token].content = "", e.tokens[t[n.end + 1].token].content = "", r--); - } -} -function an(e) { - let t = e.tokens_meta, n = e.tokens_meta.length; - rn(e, e.delimiters); - for (let i = 0; i < n; i++) { - var r; - let n = (r = t[i]) == null ? void 0 : r.delimiters; - n && rn(e, n); - } -} -var on = { - tokenize: nn, - postProcess: an -}; -//#endregion -//#region src/rules_inline/link.ts -function sn(e, t) { - let n, r, i, a, o = "", s = "", c = e.pos, l = !0; - if (e.src.charCodeAt(e.pos) !== 91) return !1; - let u = e.pos, d = e.posMax, f = e.pos + 1, p = e.md.helpers.parseLinkLabel(e, e.pos, !0); - if (p < 0) return !1; - let m = p + 1; - if (m < d && e.src.charCodeAt(m) === 40) { - for (l = !1, m++; m < d && (n = e.src.charCodeAt(m), !(!N(n) && n !== 10)); m++); - if (m >= d) return !1; - if (c = m, i = e.md.helpers.parseLinkDestination(e.src, m, e.posMax), i.ok) { - for (o = e.md.normalizeLink(i.str), e.md.validateLink(o) ? m = i.pos : o = "", c = m; m < d && (n = e.src.charCodeAt(m), !(!N(n) && n !== 10)); m++); - if (i = e.md.helpers.parseLinkTitle(e.src, m, e.posMax), m < d && c !== m && i.ok) for (s = i.str, m = i.pos; m < d && (n = e.src.charCodeAt(m), !(!N(n) && n !== 10)); m++); - } - (m >= d || e.src.charCodeAt(m) !== 41) && (l = !0), m++; - } - if (l) { - if (e.env.references === void 0) return !1; - if (m < d && e.src.charCodeAt(m) === 91 ? (c = m + 1, m = e.md.helpers.parseLinkLabel(e, m), m >= 0 ? r = e.src.slice(c, m++) : m = p + 1) : m = p + 1, r || (r = e.src.slice(f, p)), r = L(r), a = e.env.references[r], !a) return e.pos = u, !1; - o = a.href, s = a.title; - } - if (!t) { - e.pos = f, e.posMax = p; - let t = e.push("link_open", "a", 1), n = [["href", o]]; - if (t.attrs = n, s && n.push(["title", s]), r) { - let e = Object.create(null); - e.label = r, t.meta = e; - } - e.linkLevel++, e.md.inline.tokenize(e), e.linkLevel--, e.push("link_close", "a", -1); - } - return e.pos = m, e.posMax = d, !0; -} -//#endregion -//#region src/rules_inline/image.ts -function cn(e, t) { - let n, r, i, a, o, s, c, l, u = "", d = e.pos, f = e.posMax; - if (e.src.charCodeAt(e.pos) !== 33 || e.src.charCodeAt(e.pos + 1) !== 91) return !1; - let p = e.pos + 2, m = e.md.helpers.parseLinkLabel(e, e.pos + 1, !1); - if (m < 0) return !1; - if (a = m + 1, a < f && e.src.charCodeAt(a) === 40) { - for (a++; a < f && (n = e.src.charCodeAt(a), !(!N(n) && n !== 10)); a++); - if (a >= f) return !1; - for (l = a, s = e.md.helpers.parseLinkDestination(e.src, a, e.posMax), s.ok && (u = e.md.normalizeLink(s.str), e.md.validateLink(u) ? a = s.pos : u = ""), l = a; a < f && (n = e.src.charCodeAt(a), !(!N(n) && n !== 10)); a++); - if (s = e.md.helpers.parseLinkTitle(e.src, a, e.posMax), a < f && l !== a && s.ok) for (c = s.str, a = s.pos; a < f && (n = e.src.charCodeAt(a), !(!N(n) && n !== 10)); a++); - else c = ""; - if (a >= f || e.src.charCodeAt(a) !== 41) return e.pos = d, !1; - a++; - } else { - if (e.env.references === void 0) return !1; - if (a < f && e.src.charCodeAt(a) === 91 ? (l = a + 1, a = e.md.helpers.parseLinkLabel(e, a), a >= 0 ? i = e.src.slice(l, a++) : a = m + 1) : a = m + 1, i || (i = e.src.slice(p, m)), i = L(i), o = e.env.references[i], !o) return e.pos = d, !1; - u = o.href, c = o.title; - } - if (!t) { - r = e.src.slice(p, m); - let t = []; - e.md.inline.parse(r, e.md, e.env, t); - let n = e.push("image", "img", 0), a = [["src", u], ["alt", ""]]; - if (n.attrs = a, n.children = t, n.content = r, c && a.push(["title", c]), i) { - let e = Object.create(null); - e.label = i, n.meta = e; - } - } - return e.pos = a, e.posMax = f, !0; -} -//#endregion -//#region src/rules_inline/autolink.ts -var ln = /^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/, un = /^([a-zA-Z][a-zA-Z0-9+.-]{1,31}):([^<>\x00-\x20]*)$/; -function dn(e, t) { - let n = e.pos; - if (e.src.charCodeAt(n) !== 60) return !1; - let r = e.pos, i = e.posMax; - for (;;) { - if (++n >= i) return !1; - let t = e.src.charCodeAt(n); - if (t === 60) return !1; - if (t === 62) break; - } - let a = e.src.slice(r + 1, n); - if (un.test(a)) { - let n = e.md.normalizeLink(a); - if (!e.md.validateLink(n)) return !1; - if (!t) { - let t = e.push("link_open", "a", 1); - t.attrs = [["href", n]], t.markup = "autolink", t.info = "auto"; - let r = e.push("text", "", 0); - r.content = e.md.normalizeLinkText(a); - let i = e.push("link_close", "a", -1); - i.markup = "autolink", i.info = "auto"; - } - return e.pos += a.length + 2, !0; - } - if (ln.test(a)) { - let n = e.md.normalizeLink(`mailto:${a}`); - if (!e.md.validateLink(n)) return !1; - if (!t) { - let t = e.push("link_open", "a", 1); - t.attrs = [["href", n]], t.markup = "autolink", t.info = "auto"; - let r = e.push("text", "", 0); - r.content = e.md.normalizeLinkText(a); - let i = e.push("link_close", "a", -1); - i.markup = "autolink", i.info = "auto"; - } - return e.pos += a.length + 2, !0; - } - return !1; -} -//#endregion -//#region src/rules_inline/html_inline.ts -function fn(e) { - return /^\s]/i.test(e); -} -function pn(e) { - return /^<\/a\s*>/i.test(e); -} -function mn(e) { - let t = e | 32; - return t >= 97 && t <= 122; -} -function hn(e, t) { - if (!e.md.options.html) return !1; - let n = e.posMax, r = e.pos; - if (e.src.charCodeAt(r) !== 60 || r + 2 >= n) return !1; - let i = e.src.charCodeAt(r + 1); - if (i !== 33 && i !== 63 && i !== 47 && !mn(i)) return !1; - let a = e.src.slice(r).match(Ft); - if (!a) return !1; - if (!t) { - let t = e.push("html_inline", "", 0); - t.content = a[0], fn(t.content) && e.linkLevel++, pn(t.content) && e.linkLevel--; - } - return e.pos += a[0].length, !0; -} -//#endregion -//#region src/rules_inline/entity.ts -var gn = /^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i, _n = /^&([a-z][a-z0-9]{1,31});/i; -function vn(e, t) { - let n = e.pos, r = e.posMax; - if (e.src.charCodeAt(n) !== 38 || n + 1 >= r) return !1; - if (e.src.charCodeAt(n + 1) === 35) { - let r = e.src.slice(n).match(gn); - if (r) { - if (!t) { - let t = r[1][0].toLowerCase() === "x" ? parseInt(r[1].slice(1), 16) : parseInt(r[1], 10), n = e.push("text_special", "", 0); - n.content = we(t) ? A(t) : A(65533), n.markup = r[0], n.info = "entity"; - } - return e.pos += r[0].length, !0; - } - } else { - let r = e.src.slice(n).match(_n); - if (r) { - let n = be(r[0]); - if (n !== r[0]) { - if (!t) { - let t = e.push("text_special", "", 0); - t.content = n, t.markup = r[0], t.info = "entity"; - } - return e.pos += r[0].length, !0; - } - } - } - return !1; -} -//#endregion -//#region src/rules_inline/balance_pairs.ts -function yn(e) { - let t = {}, n = e.length; - if (!n) return; - let r = 0, i = -2, a = []; - for (let o = 0; o < n; o++) { - let n = e[o]; - if (a.push(0), (e[r].marker !== n.marker || i !== n.token - 1) && (r = o), i = n.token, n.length = n.length || 0, !n.close) continue; - t.hasOwnProperty(n.marker) || (t[n.marker] = [ - -1, - -1, - -1, - -1, - -1, - -1 - ]); - let s = t[n.marker][(n.open ? 3 : 0) + n.length % 3], c = r - a[r] - 1, l = c; - for (; c > s; c -= a[c] + 1) { - let t = e[c]; - if (t.marker === n.marker && t.open && t.end < 0) { - let r = !1; - if ((t.close || n.open) && (t.length + n.length) % 3 == 0 && (t.length % 3 != 0 || n.length % 3 != 0) && (r = !0), !r) { - let r = c > 0 && !e[c - 1].open ? a[c - 1] + 1 : 0; - a[o] = o - c + r, a[c] = r, n.open = !1, t.end = o, t.close = !1, l = -1, i = -2; - break; - } - } - } - l !== -1 && (t[n.marker][(n.open ? 3 : 0) + (n.length || 0) % 3] = l); - } -} -function bn(e) { - let t = e.tokens_meta, n = e.tokens_meta.length; - yn(e.delimiters); - for (let e = 0; e < n; e++) { - var r; - let n = (r = t[e]) == null ? void 0 : r.delimiters; - n && yn(n); - } -} -//#endregion -//#region src/rules_inline/fragments_join.ts -function xn(e) { - let t, n, r = 0, i = e.tokens, a = e.tokens.length; - for (t = n = 0; t < a; t++) i[t].nesting < 0 && r--, i[t].level = r, i[t].nesting > 0 && r++, i[t].type === "text" && t + 1 < a && i[t + 1].type === "text" ? i[t + 1].content = i[t].content + i[t + 1].content : (t !== n && (i[n] = i[t]), n++); - t !== n && (i.length = n); -} -//#endregion -//#region src/parser_inline.ts -var Sn = [ - ["text", Wt], - ["linkify", qt], - ["newline", Jt], - ["escape", Yt], - ["backticks", Zt], - ["strikethrough", tn.tokenize], - ["emphasis", on.tokenize], - ["link", sn], - ["image", cn], - ["autolink", dn], - ["html_inline", hn], - ["entity", vn] -], Cn = [ - ["balance_pairs", bn], - ["strikethrough", tn.postProcess], - ["emphasis", on.postProcess], - ["fragments_join", xn] -], wn = class { - constructor() { - T(this, "ruler", new B()), T(this, "ruler2", new B()), T(this, "State", Ht); - for (let e = 0; e < Sn.length; e++) this.ruler.push(Sn[e][0], Sn[e][1]); - for (let e = 0; e < Cn.length; e++) this.ruler2.push(Cn[e][0], Cn[e][1]); - } - skipToken(e) { - let t = e.pos, n = this.ruler.getRules(""), r = n.length, i = e.md.options.maxNesting, a = e.cache; - if (a[t] !== void 0) { - e.pos = a[t]; - return; - } - let o = !1; - if (e.level < i) { - for (let i = 0; i < r; i++) if (e.level++, o = n[i](e, !0), e.level--, o) { - if (t >= e.pos) throw Error("inline rule didn't increment state.pos"); - break; - } - } else e.pos = e.posMax; - o || e.pos++, a[t] = e.pos; - } - tokenize(e) { - let t = this.ruler.getRules(""), n = t.length, r = e.posMax, i = e.md.options.maxNesting; - for (; e.pos < r;) { - let a = e.pos, o = !1; - if (e.level < i) { - for (let r = 0; r < n; r++) if (o = t[r](e, !1), o) { - if (a >= e.pos) throw Error("inline rule didn't increment state.pos"); - break; - } - } - if (o) { - if (e.pos >= r) break; - continue; - } - e.pending += e.src[e.pos++]; - } - e.pending && e.pushPending(); - } - parse(e, t, n, r) { - let i = new this.State(e, t, n, r); - this.tokenize(i); - let a = this.ruler2.getRules(""), o = a.length; - for (let e = 0; e < o; e++) a[e](i); - } -}, Tn = class { - constructor(e = {}) { - T(this, "src_Any", x.source), T(this, "src_Cc", ne.source), T(this, "src_Z", ae.source), T(this, "src_P", S.source), T(this, "src_ZPCc", [ - this.src_Z, - this.src_P, - this.src_Cc - ].join("|")), T(this, "src_ZCc", [this.src_Z, this.src_Cc].join("|")), T(this, "cache", {}), T(this, "opts", { - maxLength: 1e4, - urlAuth: !1, - schema_names: [] - }), this.opts = { - ...this.opts, - ...e - }; - } - set(e = {}) { - return this.opts = { - ...this.opts, - ...e - }, this.cache = {}, this; - } - escapeRE(e) { - return e.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&"); - } - nestedPairRE(e, t, n = 4) { - let r = this.escapeRE(e), i = this.escapeRE(t), a = `(?:(?!${this.src_ZCc}|${r}|${i}).)`, o = `${r}${a}{0,1000}${i}`; - for (let e = 2; e <= n; e++) o = `${r}(?:${a}|${o}){0,1000}${i}`; - return o; - } - get_text_separators() { - var e, t; - return (t = (e = this.cache).text_separators) == null ? e.text_separators = /[><\uff5c]/ : t; - } - get_pseudo_letter() { - var e, t; - return (t = (e = this.cache).src_pseudo_letter) == null ? e.src_pseudo_letter = RegExp(`(?:(?!${this.get_text_separators().source}|${this.src_ZPCc})${this.src_Any})`) : t; - } - get_ipv4_addr() { - var e, t; - return (t = (e = this.cache).src_ip4) == null ? e.src_ip4 = /* @__PURE__ */ RegExp("(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])[.]){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])") : t; - } - get_ipv6_addr() { - var e, t; - let n = "[0-9A-Fa-f]{1,4}", r = `(?:(?:${n}:${n})|${this.get_ipv4_addr().source})`; - return (t = (e = this.cache).src_ip6_addr) == null ? e.src_ip6_addr = RegExp(`(?:(?:${n}:){6}${r}|::(?:${n}:){5}${r}|(?:${n})?::(?:${n}:){4}${r}|(?:(?:${n}:){0,1}${n})?::(?:${n}:){3}${r}|(?:(?:${n}:){0,2}${n})?::(?:${n}:){2}${r}|(?:(?:${n}:){0,3}${n})?::${n}:${r}|(?:(?:${n}:){0,4}${n})?::${r}|(?:(?:${n}:){0,5}${n})?::${n}|(?:(?:${n}:){0,6}${n})?::)`) : t; - } - get_ipv6_url_host() { - var e, t; - return (t = (e = this.cache).src_ip6_host) == null ? e.src_ip6_host = RegExp(`\\[${this.get_ipv6_addr().source}\\]`) : t; - } - get_ipv6_mail_host() { - var e, t; - return (t = (e = this.cache).src_ipv6_mail_host) == null ? e.src_ipv6_mail_host = RegExp(`\\[IPv6:${this.get_ipv6_addr().source}\\]`) : t; - } - get_auth() { - var e, t; - return (t = (e = this.cache).src_auth) == null ? e.src_auth = RegExp(`(?:(?:(?!${this.src_ZCc}|[@/\\[\\]()]).){1,50}@)?`) : t; - } - get_port() { - var e, t; - return (t = (e = this.cache).src_port) == null ? e.src_port = /* @__PURE__ */ RegExp("(?::(?:6(?:[0-4]\\d{3}|5(?:[0-4]\\d{2}|5(?:[0-2]\\d|3[0-5])))|[1-5]?\\d{1,4}))?") : t; - } - get_host_terminator() { - var e, t; - return (t = (e = this.cache).src_host_terminator) == null ? e.src_host_terminator = RegExp(`(?=$|${this.get_text_separators().source}|${this.src_ZPCc})(?!${this.opts["---"] ? "-(?!--)|" : "-|"}_|:\\d|\\.-|\\.(?!$|${this.src_ZPCc}))`) : t; - } - get_path_terminator() { - var e, t; - return (t = (e = this.cache).src_path_terminator) == null ? e.src_path_terminator = RegExp(`${this.src_ZPCc}|${this.get_text_separators().source}`) : t; - } - get_path() { - var e, t; - return (t = (e = this.cache).src_path) == null ? e.src_path = RegExp(`(?:[/?#](?:${this.nestedPairRE("[", "]")}|${this.nestedPairRE("(", ")")}|${this.nestedPairRE("{", "}")}|\\"(?:(?!${this.src_ZCc}|["]).){1,100}\\"|\\'(?:(?!${this.src_ZCc}|[']).){1,100}\\'|\\'(?=${this.get_pseudo_letter().source}|[-])|\\.{2,20}[:]?[a-zA-Z0-9%/&]|\\.(?!${this.src_ZCc}|[.]|$)|` + (this.opts["---"] ? "\\-(?!--(?:[^-]|$))(?:-{0,19})|" : "\\-{1,20}|") + `,(?!${this.src_ZCc}|$)|;(?!${this.src_ZCc}|$)|\\!{1,20}(?!${this.src_ZCc}|[!]|$)|\\?(?!${this.src_ZCc}|[?]|$)|` + this.get_path_extra().source + `[\\\\/:%@#&=_~*]|(?!${this.get_path_terminator().source}).){1,${this.opts.maxLength}}|\\/)?`) : t; - } - get_mail_name() { - var e, t; - return (t = (e = this.cache).src_mail_name) == null ? e.src_mail_name = /* @__PURE__ */ RegExp("[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9](?:[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9]|[.](?=[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9])){0,63}") : t; - } - get_xn() { - var e, t; - return (t = (e = this.cache).src_xn) == null ? e.src_xn = /* @__PURE__ */ RegExp("xn--[a-z0-9\\-]{1,59}") : t; - } - get_tld() { - if (this.cache.tld) return this.cache.tld; - let e = [...new Set(this.opts.tlds || [])].sort().reverse().join("|"); - return this.cache.tld = RegExp(`${e || "$#none#$"}|${this.get_xn().source}`), this.cache.tld; - } - get_domain_root() { - var e, t; - return (t = (e = this.cache).src_domain_root) == null ? e.src_domain_root = RegExp("(?:" + this.get_xn().source + `|${this.get_pseudo_letter().source}{1,63})`) : t; - } - get_domain() { - var e, t; - return (t = (e = this.cache).src_domain) == null ? e.src_domain = RegExp("(?:" + this.get_xn().source + `|(?:${this.get_pseudo_letter().source})|(?:${this.get_pseudo_letter().source}(?:-|${this.get_pseudo_letter().source}){0,61}${this.get_pseudo_letter().source}))`) : t; - } - get_url_host_port() { - var e, t; - return (t = (e = this.cache).url_host_port) == null ? e.url_host_port = RegExp("(?:" + this.get_ipv6_url_host().source + `|(?:(?:(?:${this.get_domain().source})\\.){0,10}${this.get_domain().source}))` + this.get_port().source + this.get_host_terminator().source) : t; - } - get_fuzzy_url_host_port() { - var e, t; - return (t = (e = this.cache).fuzzy_url_host_port) == null ? e.fuzzy_url_host_port = RegExp("(?:" + (this.opts.fuzzyIP ? this.get_ipv4_addr().source + "|" : "") + `(?:(?:(?:${this.get_domain().source})\\.){1,10}(?:${this.get_tld().source})))` + this.get_host_terminator().source) : t; - } - get_mail_host() { - var e, t; - return (t = (e = this.cache).src_mail_host) == null ? e.src_mail_host = RegExp("(?:" + this.get_ipv6_mail_host().source + `|(?:(?:(?:${this.get_domain().source})\\.){0,4}${this.get_domain().source}))` + this.get_host_terminator().source) : t; - } - get_fuzzy_mail_host() { - var e, t; - return (t = (e = this.cache).src_fuzzy_mail_host) == null ? e.src_fuzzy_mail_host = RegExp("(?:" + this.get_ipv6_mail_host().source + `|(?:(?:(?:${this.get_domain().source})[.]){1,4}${this.get_domain_root().source}))` + this.get_host_terminator().source) : t; - } - get_path_extra() { - var e, t; - return (t = (e = this.cache).src_path_extra) == null ? e.src_path_extra = /* @__PURE__ */ RegExp("") : t; - } - get_fuzzy_mail_host_search() { - var e, t; - return (t = (e = this.cache).mail_fuzzy_host_search) == null ? e.mail_fuzzy_host_search = RegExp(`@${this.get_fuzzy_mail_host().source}`, "ig") : t; - } - get_fuzzy_link_search() { - var e, t; - return (t = (e = this.cache).link_fuzzy_search) == null ? e.link_fuzzy_search = RegExp(`(^|(?![.:/\\-_@])(?:[$+<=>^\`|\uff5c]|${this.src_ZPCc}))(?:(?![$+<=>^\`|\uff5c])${this.get_fuzzy_url_host_port().source}${this.get_path().source})`, "ig") : t; - } - get_http_validator() { - var e, t; - return (t = (e = this.cache).http_validator) == null ? e.http_validator = RegExp("\\/\\/" + (this.opts.urlAuth ? this.get_auth().source : "") + this.get_url_host_port().source + this.get_path().source, "iy") : t; - } - get_relative_proto_validator() { - var e, t; - return (t = (e = this.cache).relative_proto_validator) == null ? e.relative_proto_validator = RegExp((this.opts.urlAuth ? this.get_auth().source : "") + `(?:localhost|${this.get_ipv6_url_host().source}|(?:(?:${this.get_domain().source})[.]){1,10}${this.get_domain_root().source})` + this.get_port().source + this.get_host_terminator().source + this.get_path().source, "iy") : t; - } - get_mail_name_validator() { - var e, t; - return (t = (e = this.cache).mail_name_validator) == null ? e.mail_name_validator = RegExp(`(?:^|${this.get_text_separators().source}|"|\\(|${this.src_ZCc})(${this.get_mail_name().source})$`) : t; - } - get_mailto_validator() { - var e, t; - return (t = (e = this.cache).mailto_validator) == null ? e.mailto_validator = RegExp(`${this.get_mail_name().source}@${this.get_mail_host().source}`, "iy") : t; - } - get_schema_names() { - var e, t; - return (t = (e = this.cache).schema_names) == null ? e.schema_names = new RegExp((this.opts.schema_names || []).map((e) => this.escapeRE(e)).join("|")) : t; - } - get_schema_search() { - var e, t; - return (t = (e = this.cache).schema_search) == null ? e.schema_search = RegExp(`(^|(?!_)(?:[><\uff5c]|${this.src_ZPCc}))(${this.get_schema_names().source})`, "ig") : t; - } - get_schema_at_start() { - var e, t; - return (t = (e = this.cache).schema_at_start) == null ? e.schema_at_start = RegExp(`^${this.get_schema_search().source}`, "i") : t; - } -}, En = { - validate: (e, t, n) => { - let r = n.re.get_http_validator(); - r.lastIndex = t; - let i = r.exec(e); - return i ? i[0].length : 0; - }, - normalize: (e, t) => t.normalize(e) -}, Dn = { - "http:": En, - "https:": En, - "ftp:": En, - "//": { - validate: function(e, t, n) { - let r = n.re.get_relative_proto_validator(); - r.lastIndex = t; - let i = r.exec(e); - return i ? t >= 3 && e[t - 3] === ":" || t >= 3 && e[t - 3] === "/" ? 0 : i[0].length : 0; - }, - normalize: (e, t) => t.normalize(e) - }, - "mailto:": { - validate: function(e, t, n) { - let r = n.re.get_mailto_validator(); - r.lastIndex = t; - let i = r.exec(e); - return i ? i[0].length : 0; - }, - normalize: (e, t) => t.normalize(e) - } -}, On = "a:cdefgilmnoqrstuwxz|b:abdefghijmnorstvwyz|c:acdfghiklmnoruvwxyz|d:ejkmoz|e:cegrstu|f:ijkmor|g:abdefghilmnpqrstuwy|h:kmnrtu|i:delmnoqrst|j:emop|k:eghimnprwyz|l:abcikrstuvy|m:acdeghklmnopqrstuvwxyz|n:acefgilopruz|o:m|p:aefghklmnrstwy|q:a|r:eosuw|s:abcdeghijklmnortuvxyz|t:cdfghjklmnortvwz|u:agksyz|v:aceginu|w:fs|y:et|z:amw", kn = "biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф"; -function An() { - let e = kn.split("|"); - return On.split("|").forEach((t) => { - let n = t.indexOf(":"), r = t.slice(0, n); - for (let i of t.slice(n + 1)) e.push(r + i); - }), e; -} -var jn = { - fuzzyLink: !1, - fuzzyEmail: !0, - fuzzyIP: !1, - "---": !1, - tlds: An(), - urlAuth: !1, - maxLength: 1e4 -}, Mn = class { - constructor(e, t, n, r) { - T(this, "schema", void 0), T(this, "index", void 0), T(this, "lastIndex", void 0), T(this, "raw", void 0), T(this, "text", void 0), T(this, "url", void 0); - let i = e.slice(n, r); - this.schema = t.toLowerCase(), this.index = n, this.lastIndex = r, this.raw = i, this.text = i, this.url = i; - } -}, Nn = class { - constructor(e = {}) { - T(this, "__opts__", void 0), T(this, "__schemas__", void 0), T(this, "re", void 0); - let { rebuilder: t, ...n } = e; - this.__opts__ = { - ...jn, - ...n - }, this.__schemas__ = { ...Dn }, this.re = t || new Tn(), this.re.set({ - ...this.__opts__, - schema_names: Object.keys(this.__schemas__) - }); - } - add(e, t = null) { - if (!t) delete this.__schemas__[e]; - else { - let n = { - normalize: (e, t) => t.normalize(e), - ...t - }; - this.__schemas__[e] = n; - } - return this.re.set({ - ...this.__opts__, - schema_names: Object.keys(this.__schemas__) - }), this; - } - set(e = {}) { - return this.__opts__ = { - ...this.__opts__, - ...e - }, this.re.set({ - ...this.__opts__, - schema_names: Object.keys(this.__schemas__) - }), this; - } - test(e) { - if (!e.length) return !1; - let t, n; - for (n = this.re.get_schema_search(), n.lastIndex = 0; (t = n.exec(e)) !== null;) if (this.testSchemaAt(e, t[2], n.lastIndex)) return !0; - if (this.__opts__.fuzzyLink && this.__schemas__["http:"] && (n = this.re.get_fuzzy_link_search(), n.lastIndex = 0, n.exec(e) !== null)) return !0; - if (this.__opts__.fuzzyEmail && this.__schemas__["mailto:"] && e.indexOf("@") >= 0) { - let n = this.re.get_fuzzy_mail_host_search(), r = this.re.get_mail_name_validator(); - for (n.lastIndex = 0; (t = n.exec(e)) !== null;) { - let n = e.slice(Math.max(0, t.index - 65), t.index); - if (r.test(n)) return !0; - } - } - return !1; - } - testSchemaAt(e, t, n) { - return this.__schemas__[t.toLowerCase()] ? this.__schemas__[t.toLowerCase()].validate(e.slice(0, n + this.__opts__.maxLength), n, this) : 0; - } - match(e) { - let t = [], n = this.re.get_schema_search(), r, i, a, o, s, c, l = !1, u = !1, d = !1, f = 0; - if (!e.length) return null; - for (n.lastIndex = 0, this.__opts__.fuzzyLink && this.__schemas__["http:"] && (r = this.re.get_fuzzy_link_search(), r.lastIndex = 0), this.__opts__.fuzzyEmail && this.__schemas__["mailto:"] && (i = this.re.get_fuzzy_mail_host_search(), i.lastIndex = 0, a = this.re.get_mail_name_validator());;) { - let p = Math.max(f - 1, 0); - if (i && a && !d && (!s || s.index < f)) for (i.lastIndex < p && (i.lastIndex = p);;) { - let t = i.exec(e); - if (!t) { - d = !0, s = void 0; - break; - } - let n = a.exec(e.slice(Math.max(0, t.index - 65), t.index)); - if (n) { - if (s = { - schema: "mailto:", - index: t.index - n[1].length, - lastIndex: t.index + t[0].length - }, s.index >= f) break; - i.lastIndex < p && (i.lastIndex = p); - } - } - if (r && !u && (!o || o.index < f)) for (r.lastIndex < p && (r.lastIndex = p);;) { - let t = r.exec(e); - if (!t) { - u = !0, o = void 0; - break; - } - if (o = { - schema: "", - index: t.index + t[1].length, - lastIndex: t.index + t[0].length - }, o.index >= f) break; - r.lastIndex < p && (r.lastIndex = p); - } - let m = s; - (!m || o && (o.index < m.index || o.index === m.index && o.lastIndex > m.lastIndex)) && (m = o); - let h; - if (!l) for (;;) { - if (!c) { - n.lastIndex < p && (n.lastIndex = p); - let t = n.exec(e); - if (!t) { - l = !0; - break; - } - c = { - schema: t[2], - index: t.index + t[1].length, - lastIndex: t.index + t[0].length - }; - } - if (c.index < f) { - c = void 0; - continue; - } - if (m && c.index > m.index) break; - let t = c; - c = void 0; - let r = this.testSchemaAt(e, t.schema, t.lastIndex); - if (r) { - h = { - schema: t.schema, - index: t.index, - lastIndex: t.lastIndex + r - }; - break; - } - } - let g = h; - if ((!g || s && (s.index < g.index || s.index === g.index && s.lastIndex > g.lastIndex)) && (g = s), (!g || o && (o.index < g.index || o.index === g.index && o.lastIndex > g.lastIndex)) && (g = o), !g) break; - g === s ? s = void 0 : g === o && (o = void 0); - let _ = new Mn(e, g.schema, g.index, g.lastIndex); - _.schema ? this.__schemas__[_.schema].normalize(_, this) : this.normalize(_), t.push(_), f = g.lastIndex; - } - return t.length ? t : null; - } - matchAtStart(e) { - if (!e.length) return null; - let t = this.re.get_schema_at_start().exec(e); - if (!t) return null; - let n = this.testSchemaAt(e, t[2], t[0].length); - if (!n) return null; - let r = new Mn(e, t[2], t.index + t[1].length, t.index + t[0].length + n); - return this.__schemas__[r.schema].normalize(r, this), r; - } - tlds(e, t = !1) { - return e = Array.isArray(e) ? e : [e], t ? this.__opts__.tlds = this.__opts__.tlds.concat(e) : this.__opts__.tlds = e, this.re.set({ - ...this.__opts__, - schema_names: Object.keys(this.__schemas__) - }), this; - } - normalize(e) { - e.schema || (e.url = `http://${e.url}`), e.schema === "mailto:" && !/^mailto:/i.test(e.url) && (e.url = `mailto:${e.url}`); - } -}, J = 2147483647, Y = 36, Pn = 1, X = 26, Fn = 38, In = 700, Ln = 72, Rn = 128, zn = "-", Bn = /^xn--/, Vn = /[^\0-\x7F]/, Hn = /[\x2E\u3002\uFF0E\uFF61]/g, Un = { - overflow: "Overflow: input needs wider integers to process", - "not-basic": "Illegal input >= 0x80 (not a basic code point)", - "invalid-input": "Invalid input" -}, Wn = 35, Z = Math.floor, Gn = String.fromCharCode; -function Q(e) { - throw RangeError(Un[e]); -} -function Kn(e, t) { - let n = [], r = e.length; - for (; r--;) n[r] = t(e[r]); - return n; -} -function qn(e, t) { - let n = e.split("@"), r = ""; - n.length > 1 && (r = n[0] + "@", e = n[1]), e = e.replace(Hn, "."); - let i = Kn(e.split("."), t).join("."); - return r + i; -} -function Jn(e) { - let t = [], n = 0, r = e.length; - for (; n < r;) { - let i = e.charCodeAt(n++); - if (i >= 55296 && i <= 56319 && n < r) { - let r = e.charCodeAt(n++); - (r & 64512) == 56320 ? t.push(((i & 1023) << 10) + (r & 1023) + 65536) : (t.push(i), n--); - } else t.push(i); - } - return t; -} -var Yn = (e) => String.fromCodePoint(...e), Xn = function(e) { - return e >= 48 && e < 58 ? 26 + (e - 48) : e >= 65 && e < 91 ? e - 65 : e >= 97 && e < 123 ? e - 97 : Y; -}, Zn = function(e, t) { - return e + 22 + 75 * (e < 26) - ((t != 0) << 5); -}, Qn = function(e, t, n) { - let r = 0; - for (e = n ? Z(e / In) : e >> 1, e += Z(e / t); e > 455; r += Y) e = Z(e / Wn); - return Z(r + 36 * e / (e + Fn)); -}, $n = function(e) { - let t = [], n = e.length, r = 0, i = Rn, a = Ln, o = e.lastIndexOf(zn); - o < 0 && (o = 0); - for (let n = 0; n < o; ++n) e.charCodeAt(n) >= 128 && Q("not-basic"), t.push(e.charCodeAt(n)); - for (let s = o > 0 ? o + 1 : 0; s < n;) { - let o = r; - for (let t = 1, i = Y;; i += Y) { - s >= n && Q("invalid-input"); - let o = Xn(e.charCodeAt(s++)); - o >= Y && Q("invalid-input"), o > Z((J - r) / t) && Q("overflow"), r += o * t; - let c = i <= a ? Pn : i >= a + X ? X : i - a; - if (o < c) break; - let l = Y - c; - t > Z(J / l) && Q("overflow"), t *= l; - } - let c = t.length + 1; - a = Qn(r - o, c, o == 0), Z(r / c) > J - i && Q("overflow"), i += Z(r / c), r %= c, t.splice(r++, 0, i); - } - return String.fromCodePoint(...t); -}, er = function(e) { - let t = []; - e = Jn(e); - let n = e.length, r = Rn, i = 0, a = Ln; - for (let n of e) n < 128 && t.push(Gn(n)); - let o = t.length, s = o; - for (o && t.push(zn); s < n;) { - let n = J; - for (let t of e) t >= r && t < n && (n = t); - let c = s + 1; - n - r > Z((J - i) / c) && Q("overflow"), i += (n - r) * c, r = n; - for (let n of e) if (n < r && ++i > J && Q("overflow"), n === r) { - let e = i; - for (let n = Y;; n += Y) { - let r = n <= a ? Pn : n >= a + X ? X : n - a; - if (e < r) break; - let i = e - r, o = Y - r; - t.push(Gn(Zn(r + i % o, 0))), e = Z(i / o); - } - t.push(Gn(Zn(e, 0))), a = Qn(i, c, s === o), i = 0, ++s; - } - ++i, ++r; - } - return t.join(""); -}, tr = { - version: "2.3.1", - ucs2: { - decode: Jn, - encode: Yn - }, - decode: $n, - encode: er, - toASCII: function(e) { - return qn(e, function(e) { - return Vn.test(e) ? "xn--" + er(e) : e; - }); - }, - toUnicode: function(e) { - return qn(e, function(e) { - return Bn.test(e) ? $n(e.slice(4).toLowerCase()) : e; - }); - } -}, nr = { - default: { - options: { - html: !1, - xhtmlOut: !1, - breaks: !1, - langPrefix: "language-", - linkify: !1, - typographer: !1, - quotes: "“”‘’", - highlight: null, - maxNesting: 100 - }, - components: { - core: {}, - block: {}, - inline: {} - } - }, - zero: { - options: { - html: !1, - xhtmlOut: !1, - breaks: !1, - langPrefix: "language-", - linkify: !1, - typographer: !1, - quotes: "“”‘’", - highlight: null, - maxNesting: 20 - }, - components: { - core: { rules: [ - "normalize", - "block", - "strip_references", - "inline", - "text_join" - ] }, - block: { rules: ["paragraph"] }, - inline: { - rules: ["text"], - rules2: ["balance_pairs", "fragments_join"] - } - } - }, - commonmark: { - options: { - html: !0, - xhtmlOut: !0, - breaks: !1, - langPrefix: "language-", - linkify: !1, - typographer: !1, - quotes: "“”‘’", - highlight: null, - maxNesting: 20 - }, - components: { - core: { rules: [ - "normalize", - "block", - "strip_references", - "inline", - "text_join" - ] }, - block: { rules: [ - "blockquote", - "code", - "fence", - "heading", - "hr", - "html_block", - "lheading", - "list", - "reference", - "paragraph" - ] }, - inline: { - rules: [ - "autolink", - "backticks", - "emphasis", - "entity", - "escape", - "html_inline", - "image", - "link", - "newline", - "text" - ], - rules2: [ - "balance_pairs", - "emphasis", - "fragments_join" - ] - } - } - } -}, rr = /^(vbscript|javascript|file|data):/, ir = /^data:image\/(gif|png|jpeg|webp);/, ar = [ - "http:", - "https:", - "mailto:" -], $ = class { - validateLink(e) { - let t = e.trim().toLowerCase(); - return !rr.test(t) || ir.test(t); - } - normalizeLink(e) { - let t = b(e, !0); - if (t.hostname && (!t.protocol || ar.indexOf(t.protocol) >= 0)) try { - t.hostname = tr.toASCII(t.hostname); - } catch (e) {} - return t.auth && (t.auth = s(t.auth)), t.hostname && (t.hostname = s(t.hostname)), t.pathname && (t.pathname = s(t.pathname)), t.search && (t.search = s(t.search)), t.hash && (t.hash = s(t.hash)), c(t); - } - normalizeLinkText(e) { - let t = b(e, !0); - if (t.hostname && (!t.protocol || ar.indexOf(t.protocol) >= 0)) try { - t.hostname = tr.toUnicode(t.hostname); - } catch (e) {} - return i(c(t), i.defaultChars + "%"); - } - constructor(...e) { - T(this, "inline", new wn()), T(this, "block", new Vt()), T(this, "core", new vt()), T(this, "renderer", new Ue()), T(this, "linkify", new Nn()), T(this, "utils", xe), T(this, "helpers", Object.assign({}, He)); - let [t, n] = e; - typeof t == "string" ? (this.configure(t), n && this.set(n)) : (this.configure("default"), this.set(t || {})); - } - set(e) { - return Object.assign(this.options, e), this; - } - configure(e) { - let t; - if (typeof e == "string") { - let n = e; - if (t = nr[n], !t) throw Error(`Wrong 'markdown-it' preset "${n}", check name`); - } else t = e; - if (!t) throw Error("Wrong `markdown-it` preset, can't be empty"); - t.options && (this.options = { ...t.options }); - let n = t.components; - if (n) { - var r; - [ - "core", - "block", - "inline" - ].forEach((e) => { - var t; - let r = (t = n[e]) == null ? void 0 : t.rules; - r && this[e].ruler.enableOnly(r); - }); - let e = (r = n.inline) == null ? void 0 : r.rules2; - e && this.inline.ruler2.enableOnly(e); - } - return this; - } - enable(e, t = !1) { - let n = []; - Array.isArray(e) || (e = [e]), [ - "core", - "block", - "inline" - ].forEach((t) => { - n = n.concat(this[t].ruler.enable(e, !0)); - }), n = n.concat(this.inline.ruler2.enable(e, !0)); - let r = e.filter((e) => n.indexOf(e) < 0); - if (r.length && !t) throw Error(`MarkdownIt. Failed to enable unknown rule(s): ${r}`); - return this; - } - disable(e, t = !1) { - let n = []; - Array.isArray(e) || (e = [e]), [ - "core", - "block", - "inline" - ].forEach((t) => { - n = n.concat(this[t].ruler.disable(e, !0)); - }), n = n.concat(this.inline.ruler2.disable(e, !0)); - let r = e.filter((e) => n.indexOf(e) < 0); - if (r.length && !t) throw Error(`MarkdownIt. Failed to disable unknown rule(s): ${r}`); - return this; - } - use(e, ...t) { - return e.apply(e, [this, ...t]), this; - } - parse(e, t) { - if (typeof e != "string") throw Error("Input data should be a String"); - let n = new this.core.State(e, this, t); - return this.core.process(n), n.tokens; - } - render(e, t = {}) { - return this.renderer.render(this.parse(e, t), this.options, t); - } - parseInline(e, t) { - let n = new this.core.State(e, this, t); - return n.inlineMode = !0, this.core.process(n), n.tokens; - } - renderInline(e, t = {}) { - return this.renderer.render(this.parseInline(e, t), this.options, t); - } -}; -T($, "Token", z), T($, "Ruler", B), T($, "Renderer", Ue), T($, "ParserCore", vt), T($, "StateCore", We), T($, "ParserBlock", Vt), T($, "StateBlock", yt), T($, "ParserInline", wn), T($, "StateInline", Ht); -//#endregion -//#region src/index.ts -var or = Se($); -//#endregion -export { or as default }; diff --git a/app/src/test/java/com/storyteller_f/feiya/WebPagesTest.kt b/app/src/test/java/com/storyteller_f/feiya/WebPagesTest.kt index 6622154..7a41a69 100644 --- a/app/src/test/java/com/storyteller_f/feiya/WebPagesTest.kt +++ b/app/src/test/java/com/storyteller_f/feiya/WebPagesTest.kt @@ -40,7 +40,7 @@ class WebPagesTest { connection.outputStream.use { it.write(form.toByteArray()) } } val status = connection.responseCode - if (path.endsWith(".mjs")) { + if (path.endsWith(".js")) { assertTrue(connection.contentType, connection.contentType.substringBefore(';') in listOf("text/javascript", "application/javascript")) } @@ -54,7 +54,7 @@ class WebPagesTest { val login = request("/login") assertEquals(200, login.first) assertTrue(login.second.contains("type=\"password\"")) - for (path in listOf("style.css", "app.js", "worker.js", "host.js", "markdown.mjs", "vendor/markdown-it/markdown-it.esm.min.mjs", "icons/file.svg")) { + for (path in listOf("style.css", "app.js", "worker.js", "icons/file.svg", "THIRD-PARTY-NOTICES.txt")) { val asset = request("/web/$path") assertEquals(path, 200, asset.first) assertFalse(path, asset.second.contains("")) diff --git a/design-qa.md b/design-qa.md index 207cfef..7e4e9f9 100644 --- a/design-qa.md +++ b/design-qa.md @@ -5,16 +5,16 @@ final result: passed ## Reference and evidence - Visual target: selected option 2, `/tmp/feiya-design-options/option-2.png`. -- Implementation: `tests/web/artifacts/files-desktop.png`. -- Side-by-side comparison: `tests/web/artifacts/comparison.png` (reference left, +- Implementation: `web/test/artifacts/files-desktop.png`. +- Side-by-side comparison: `web/test/artifacts/comparison.png` (reference left, implementation right); focused header/first-row comparison: - `tests/web/artifacts/comparison-top.png`. + `web/test/artifacts/comparison-top.png`. - Source and implementation: 1487 × 1058 pixels; browser viewport 1487 × 1058 CSS pixels, device scale factor 1. Both captures use the same four file names and connected state. No density conversion or browser frame was included. - Additional browser captures: `files-mobile.png`, `files-mobile-long.png`, `chat-mobile.png`, `chat-desktop.png`, `login-mobile.png`, `login-desktop.png` - in `tests/web/artifacts/`. Mobile viewport: 390 × 844 CSS pixels at scale 1. + in `web/test/artifacts/`. Mobile viewport: 390 × 844 CSS pixels at scale 1. - Captures are local verification artifacts, not bundled application resources. ## Findings and comparison history @@ -41,7 +41,7 @@ final result: passed a top navigation row so both destinations remain directly available. - Tokens: Feiya primary `#206c29`, page `#fcfdf6`, sage sidebar `#e8eedd`, muted text `#52634f`. Flat surfaces intentionally omit image-generation texture. -- Assets: vendored Phosphor 2.1.1 SVGs, retained MIT license, no external requests. +- Assets: Phosphor SVGs supplied by the npm build, retained MIT license, no external requests. Library file-type glyphs replace the mock's illustrative glyph shapes. They remain sharp at both sizes and preserve the reference's type colors. - Copy: the file page preserves the selected Chinese hierarchy and labels. diff --git a/scripts/check-web-apk.py b/scripts/check-web-apk.py new file mode 100644 index 0000000..afe4e52 --- /dev/null +++ b/scripts/check-web-apk.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +"""Check that APK classpath resources exactly match the npm web distribution.""" +import argparse +from pathlib import Path +from zipfile import ZipFile + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("distribution", type=Path) + parser.add_argument("apk", type=Path, nargs="+") + args = parser.parse_args() + expected = { + path.relative_to(args.distribution).as_posix(): path.read_bytes() + for path in args.distribution.rglob("*") if path.is_file() + } + required = {"feiya/index.html", "feiya/login.html", "feiya/chat.html", + "web/app.js", "web/worker.js", "web/style.css", + "web/THIRD-PARTY-NOTICES.txt"} + if not required <= expected.keys(): + parser.error("Web distribution is missing required entries; run the npm build first.") + for apk in args.apk: + with ZipFile(apk) as archive: + entries = [entry.filename for entry in archive.infolist() + if not entry.is_dir() and entry.filename.startswith(("web/", "feiya/"))] + if len(entries) != len(set(entries)): + raise SystemExit(f"{apk}: duplicate web resources") + missing = expected.keys() - set(entries) + extra = set(entries) - expected.keys() + if missing or extra: + raise SystemExit(f"{apk}: missing {sorted(missing)}, unexpected {sorted(extra)}") + for name, data in expected.items(): + if archive.read(name) != data: + raise SystemExit(f"{apk}: stale or changed resource {name}") + if any("node_modules/" in entry.filename for entry in archive.infolist()): + raise SystemExit(f"{apk}: contains node_modules") + print(f"PASS {apk}: {len(expected)} web resources match the npm distribution") + + +if __name__ == "__main__": + main() diff --git a/tests/web/package-lock.json b/tests/web/package-lock.json deleted file mode 100644 index 6c7afb6..0000000 --- a/tests/web/package-lock.json +++ /dev/null @@ -1,168 +0,0 @@ -{ - "name": "feiya-web-tests", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "feiya-web-tests", - "devDependencies": { - "markdown-it": "15.0.2", - "playwright": "1.63.0", - "ws": "8.22.0" - } - }, - "node_modules/argparse": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-3.0.2.tgz", - "integrity": "sha512-mFdDM6WqWKraGLsVb+C9CahPnzTXOefAOLq3jYcca2YZ8bEWpr++Tzj+zSaKW9+X9L5uSxcm1AZ3Y6aZJ09OhQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], - "license": "PSF-2.0" - }, - "node_modules/entities": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-8.1.0.tgz", - "integrity": "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=20.19.0" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/linkify-it": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-6.1.0.tgz", - "integrity": "sha512-wJ/TwpSDTLepCrQoYWYIExIKg5Zchex2Nn5yk2mFnB+6PtdkHtyLx742md9csRjjOnGkKIS/RrbY7l8D6gT9Vw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/markdown-it" - } - ], - "license": "MIT", - "dependencies": { - "uc.micro": "^3.0.0" - } - }, - "node_modules/markdown-it": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-15.0.2.tgz", - "integrity": "sha512-q4IGxMv56jCqT4OCRCADBoDP3LO4MhmTXjFbphHPXs4g3j9Xg5RDnxqN8IF/3vIWEU+VCnUq+7JUg/cfy2E6Qw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/markdown-it" - } - ], - "license": "MIT", - "dependencies": { - "argparse": "^3.0.0", - "entities": "^8.0.0", - "linkify-it": "^6.0.0", - "mdurl": "^2.1.0", - "punycode.js": "^2.3.1", - "uc.micro": "^3.0.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/mdurl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.1.0.tgz", - "integrity": "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==", - "dev": true, - "license": "MIT" - }, - "node_modules/playwright": { - "version": "1.63.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.63.0.tgz", - "integrity": "sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.63.0" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/playwright-core": { - "version": "1.63.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.63.0.tgz", - "integrity": "sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/uc.micro": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-3.0.0.tgz", - "integrity": "sha512-U3PppEkleoTnIfi8BozMx3yju3qc/L6SwqWo2Sw+54PX+PX0q9I+r1Um5HCmqD7n9VDX5/v3vQH/AjA6deDdtw==", - "dev": true, - "license": "MIT" - }, - "node_modules/ws": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.0.tgz", - "integrity": "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - } - } -} diff --git a/tests/web/package.json b/tests/web/package.json deleted file mode 100644 index 8886f34..0000000 --- a/tests/web/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "feiya-web-tests", - "private": true, - "type": "module", - "scripts": { - "test": "node --test host.test.mjs markdown.test.mjs", - "test:browser": "node browser.test.mjs", - "preview": "node preview.mjs", - "vendor:markdown": "node vendor-markdown.mjs" - }, - "devDependencies": { - "markdown-it": "15.0.2", - "playwright": "1.63.0", - "ws": "8.22.0" - } -} diff --git a/tests/web/vendor-markdown.mjs b/tests/web/vendor-markdown.mjs deleted file mode 100644 index 1601e7a..0000000 --- a/tests/web/vendor-markdown.mjs +++ /dev/null @@ -1,53 +0,0 @@ -import { createRequire } from "node:module"; -import { dirname, join } from "node:path"; -import { readFile, writeFile, mkdir } from "node:fs/promises"; -const require = createRequire(import.meta.url); -const root = dirname(require.resolve("markdown-it/package.json")); -const destination = new URL( - "../../app/src/main/resources/web/vendor/markdown-it/", - import.meta.url, -); -await mkdir(destination, { recursive: true }); -const bundle = await readFile( - join(root, "dist/browser/markdown-it.esm.min.mjs"), - "utf8", -); -// Source maps are not shipped with the app; preserve all executable upstream code. -await writeFile( - new URL("markdown-it.esm.min.mjs", destination), - bundle.split("//# sourceMappingURL=")[0].trimEnd() + "\n", -); -await writeFile( - new URL("LICENSE", destination), - await readFile(join(root, "LICENSE")), -); -const notices = []; -for (const [name, license] of [ - ["entities", "LICENSE"], - ["linkify-it", "LICENSE"], - ["mdurl", "LICENSE"], - ["punycode.js", "LICENSE-MIT.txt"], - ["uc.micro", "LICENSE.txt"], -]) { - let path = dirname(require.resolve(name)); - while (true) { - try { - const pkg = JSON.parse( - await readFile(join(path, "package.json"), "utf8"), - ); - if (pkg.name === name) break; - } catch { - /* The entry point can be inside a dist directory. */ - } - const parent = dirname(path); - if (parent === path) throw new Error(`Cannot locate license for ${name}`); - path = parent; - } - notices.push( - `${name}\n${"=".repeat(name.length)}\n${await readFile(join(path, license), "utf8")}`, - ); -} -await writeFile( - new URL("THIRD-PARTY-NOTICES.txt", destination), - notices.join("\n\n"), -); diff --git a/web/.npmrc b/web/.npmrc new file mode 100644 index 0000000..b6f27f1 --- /dev/null +++ b/web/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/web/.nvmrc b/web/.nvmrc new file mode 100644 index 0000000..a45fd52 --- /dev/null +++ b/web/.nvmrc @@ -0,0 +1 @@ +24 diff --git a/web/package-lock.json b/web/package-lock.json new file mode 100644 index 0000000..aa2d314 --- /dev/null +++ b/web/package-lock.json @@ -0,0 +1,658 @@ +{ + "name": "feiya-web", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "feiya-web", + "dependencies": { + "@phosphor-icons/core": "2.1.1", + "markdown-it": "15.0.2" + }, + "devDependencies": { + "esbuild": "0.28.2", + "playwright": "1.63.0", + "ws": "8.22.0" + }, + "engines": { + "node": ">=24 <25" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@phosphor-icons/core": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@phosphor-icons/core/-/core-2.1.1.tgz", + "integrity": "sha512-v4ARvrip4qBCImOE5rmPUylOEK4iiED9ZyKjcvzuezqMaiRASCHKcRIuvvxL/twvLpkfnEODCOJp5dM4eZilxQ==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-3.0.2.tgz", + "integrity": "sha512-mFdDM6WqWKraGLsVb+C9CahPnzTXOefAOLq3jYcca2YZ8bEWpr++Tzj+zSaKW9+X9L5uSxcm1AZ3Y6aZJ09OhQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "PSF-2.0" + }, + "node_modules/entities": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.1.0.tgz", + "integrity": "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/linkify-it": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-6.1.0.tgz", + "integrity": "sha512-wJ/TwpSDTLepCrQoYWYIExIKg5Zchex2Nn5yk2mFnB+6PtdkHtyLx742md9csRjjOnGkKIS/RrbY7l8D6gT9Vw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "uc.micro": "^3.0.0" + } + }, + "node_modules/markdown-it": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-15.0.2.tgz", + "integrity": "sha512-q4IGxMv56jCqT4OCRCADBoDP3LO4MhmTXjFbphHPXs4g3j9Xg5RDnxqN8IF/3vIWEU+VCnUq+7JUg/cfy2E6Qw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^3.0.0", + "entities": "^8.0.0", + "linkify-it": "^6.0.0", + "mdurl": "^2.1.0", + "punycode.js": "^2.3.1", + "uc.micro": "^3.0.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/mdurl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.1.0.tgz", + "integrity": "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==", + "license": "MIT" + }, + "node_modules/playwright": { + "version": "1.63.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.63.0.tgz", + "integrity": "sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.63.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/playwright-core": { + "version": "1.63.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.63.0.tgz", + "integrity": "sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/uc.micro": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-3.0.0.tgz", + "integrity": "sha512-U3PppEkleoTnIfi8BozMx3yju3qc/L6SwqWo2Sw+54PX+PX0q9I+r1Um5HCmqD7n9VDX5/v3vQH/AjA6deDdtw==", + "license": "MIT" + }, + "node_modules/ws": { + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.0.tgz", + "integrity": "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/web/package.json b/web/package.json new file mode 100644 index 0000000..cd85c7b --- /dev/null +++ b/web/package.json @@ -0,0 +1,24 @@ +{ + "name": "feiya-web", + "private": true, + "type": "module", + "scripts": { + "build": "node scripts/build.mjs", + "test": "node --test test/host.test.mjs test/markdown.test.mjs test/build.test.mjs", + "test:browser": "npm run build && node test/browser.test.mjs", + "preview": "npm run build && node test/preview.mjs", + "pretest": "npm run build" + }, + "devDependencies": { + "playwright": "1.63.0", + "ws": "8.22.0", + "esbuild": "0.28.2" + }, + "engines": { + "node": ">=24 <25" + }, + "dependencies": { + "@phosphor-icons/core": "2.1.1", + "markdown-it": "15.0.2" + } +} diff --git a/web/scripts/build.mjs b/web/scripts/build.mjs new file mode 100644 index 0000000..3355b4d --- /dev/null +++ b/web/scripts/build.mjs @@ -0,0 +1,89 @@ +import { build } from "esbuild"; +import { cp, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises"; +import { createRequire } from "node:module"; +import { dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +const root = fileURLToPath(new URL("../", import.meta.url)); +const output = join(root, "dist"); +const require = createRequire(import.meta.url); +await rm(output, { recursive: true, force: true }); +await mkdir(join(output, "web/icons"), { recursive: true }); +await cp(join(root, "src/pages"), join(output, "feiya"), { recursive: true }); + +const result = await build({ + absWorkingDir: root, + entryPoints: { + app: "src/app.js", + worker: "src/worker.js", + style: "src/style.css", + }, + outdir: join(output, "web"), + bundle: true, + format: "esm", + platform: "browser", + target: ["es2022"], + minify: true, + // Icons keep their stable, same-origin URLs in CSS. + external: ["/web/icons/*"], + metafile: true, + legalComments: "eof", +}); + +async function packageAt(path) { + let directory = dirname(path); + while (true) { + try { + const pkg = JSON.parse( + await readFile(join(directory, "package.json"), "utf8"), + ); + if (pkg.name) return { directory, ...pkg }; + } catch (error) { + if (error.code !== "ENOENT") throw error; + } + const parent = dirname(directory); + if (parent === directory) + throw new Error(`No package manifest for ${path}`); + directory = parent; + } +} + +const icons = await packageAt(require.resolve("@phosphor-icons/core")); +// Read the icon names from the production stylesheet instead of maintaining a second list. +const css = await readFile(join(root, "src/style.css"), "utf8"); +for (const [, name] of css.matchAll(/\/web\/icons\/([a-z-]+)\.svg/g)) { + const weight = name.endsWith("-fill") ? "fill" : "regular"; + await cp( + join(icons.directory, "assets", weight, `${name}.svg`), + join(output, "web/icons", `${name}.svg`), + ); +} + +// Derive notices from actual bundled modules, so transitive dependency updates +// cannot silently leave a hand-maintained license list behind. +const packages = new Map([[icons.directory, icons]]); +for (const input of Object.keys(result.metafile.inputs)) { + if (!input.includes("node_modules/")) continue; + const pkg = await packageAt(resolve(root, input)); + packages.set(pkg.directory, pkg); +} +const notices = []; +for (const pkg of [...packages.values()].sort((a, b) => + a.name.localeCompare(b.name), +)) { + const files = (await readdir(pkg.directory)) + .filter((name) => /^(licen[cs]e|copying)([.-]|$)/i.test(name)) + .sort(); + if (!files.length) throw new Error(`No license file found for ${pkg.name}`); + const licenses = await Promise.all( + files.map((name) => readFile(join(pkg.directory, name), "utf8")), + ); + notices.push(`${pkg.name} ${pkg.version}\n${licenses.join("\n")}`); +} +await writeFile( + join(output, "web/THIRD-PARTY-NOTICES.txt"), + notices.join("\n\n"), +); +console.log( + "Built web/dist (HTML, bundled JS/CSS, icons, and third-party notices).", +); diff --git a/app/src/main/resources/web/app.js b/web/src/app.js similarity index 100% rename from app/src/main/resources/web/app.js rename to web/src/app.js diff --git a/app/src/main/resources/web/host.js b/web/src/host.js similarity index 100% rename from app/src/main/resources/web/host.js rename to web/src/host.js diff --git a/app/src/main/resources/web/markdown.mjs b/web/src/markdown.mjs similarity index 92% rename from app/src/main/resources/web/markdown.mjs rename to web/src/markdown.mjs index 2fde9bb..6c6f259 100644 --- a/app/src/main/resources/web/markdown.mjs +++ b/web/src/markdown.mjs @@ -1,4 +1,4 @@ -import MarkdownIt from "./vendor/markdown-it/markdown-it.esm.min.mjs"; +import MarkdownIt from "markdown-it"; // Keep raw HTML disabled: only parser-generated markup reaches the DOM. const markdown = new MarkdownIt({ html: false, breaks: true, linkify: true }); diff --git a/app/src/main/resources/feiya/chat.html b/web/src/pages/chat.html similarity index 100% rename from app/src/main/resources/feiya/chat.html rename to web/src/pages/chat.html diff --git a/app/src/main/resources/feiya/index.html b/web/src/pages/index.html similarity index 100% rename from app/src/main/resources/feiya/index.html rename to web/src/pages/index.html diff --git a/app/src/main/resources/feiya/login.html b/web/src/pages/login.html similarity index 100% rename from app/src/main/resources/feiya/login.html rename to web/src/pages/login.html diff --git a/app/src/main/resources/web/style.css b/web/src/style.css similarity index 100% rename from app/src/main/resources/web/style.css rename to web/src/style.css diff --git a/app/src/main/resources/web/worker.js b/web/src/worker.js similarity index 100% rename from app/src/main/resources/web/worker.js rename to web/src/worker.js diff --git a/tests/web/browser.test.mjs b/web/test/browser.test.mjs similarity index 100% rename from tests/web/browser.test.mjs rename to web/test/browser.test.mjs diff --git a/web/test/build.test.mjs b/web/test/build.test.mjs new file mode 100644 index 0000000..b8fce5f --- /dev/null +++ b/web/test/build.test.mjs @@ -0,0 +1,44 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { readFile, readdir } from "node:fs/promises"; +const dist = new URL("../dist/", import.meta.url); + +test("the distribution includes every same-origin page and CSS asset reference", async () => { + const pages = await readdir(new URL("feiya/", dist)); + assert.deepEqual(pages.sort(), ["chat.html", "index.html", "login.html"]); + for (const page of pages) { + const html = await readFile(new URL(`feiya/${page}`, dist), "utf8"); + for (const [, path] of html.matchAll(/(?:src|href)="(\/web\/[^"#]+)"/g)) { + assert.ok( + (await readFile(new URL(path.slice(1), dist))).length > 0, + path, + ); + } + } + const css = await readFile(new URL("web/style.css", dist), "utf8"); + for (const [, path] of css.matchAll(/url\(["']?(\/web\/[^"')]+)["']?\)/g)) { + assert.ok((await readFile(new URL(path.slice(1), dist))).length > 0, path); + } + assert.ok((await readFile(new URL("web/worker.js", dist))).length > 0); +}); + +test("the runtime has no copied source modules, vendored tree or node_modules", async () => { + assert.deepEqual((await readdir(dist)).sort(), ["feiya", "web"]); + assert.deepEqual((await readdir(new URL("web/", dist))).sort(), [ + "THIRD-PARTY-NOTICES.txt", + "app.js", + "icons", + "style.css", + "worker.js", + ]); + const pkg = JSON.parse( + await readFile(new URL("../package.json", import.meta.url), "utf8"), + ); + const notices = await readFile( + new URL("web/THIRD-PARTY-NOTICES.txt", dist), + "utf8", + ); + for (const name of Object.keys(pkg.dependencies)) + assert.ok(notices.includes(name), name); + assert.ok(notices.includes("MIT License")); +}); diff --git a/tests/web/host.test.mjs b/web/test/host.test.mjs similarity index 90% rename from tests/web/host.test.mjs rename to web/test/host.test.mjs index 7266a9c..c8a5e23 100644 --- a/tests/web/host.test.mjs +++ b/web/test/host.test.mjs @@ -1,15 +1,7 @@ import test from "node:test"; -import { renderMarkdown } from "../../app/src/main/resources/web/markdown.mjs"; +import { renderMarkdown } from "../src/markdown.mjs"; import assert from "node:assert/strict"; -import { readFile } from "node:fs/promises"; -// Import the production Worker module without imposing a package type on Android resources. -const source = await readFile( - new URL("../../app/src/main/resources/web/host.js", import.meta.url), - "utf8", -); -const { WebHost } = await import( - `data:text/javascript;base64,${Buffer.from(source).toString("base64")}` -); +import { WebHost } from "../src/host.js"; function setup(overrides = {}) { const states = [], effects = [], diff --git a/tests/web/markdown.test.mjs b/web/test/markdown.test.mjs similarity index 95% rename from tests/web/markdown.test.mjs rename to web/test/markdown.test.mjs index 0e8deee..93b8189 100644 --- a/tests/web/markdown.test.mjs +++ b/web/test/markdown.test.mjs @@ -1,6 +1,6 @@ import test from "node:test"; import assert from "node:assert/strict"; -import { renderMarkdown } from "../../app/src/main/resources/web/markdown.mjs"; +import { renderMarkdown } from "../src/markdown.mjs"; test("renders common message formatting and multiline text", () => { const html = renderMarkdown( diff --git a/tests/web/preview.mjs b/web/test/preview.mjs similarity index 97% rename from tests/web/preview.mjs rename to web/test/preview.mjs index 7882d7a..627ae60 100644 --- a/tests/web/preview.mjs +++ b/web/test/preview.mjs @@ -2,7 +2,7 @@ import http from "node:http"; import { readFile } from "node:fs/promises"; import { fileURLToPath } from "node:url"; import { WebSocketServer } from "ws"; -const root = new URL("../../app/src/main/resources/", import.meta.url); +const root = new URL("../dist/", import.meta.url); export async function createPreview(port = 0) { const state = { files: [ @@ -59,7 +59,7 @@ export async function createPreview(port = 0) { "/messages": "feiya/chat.html", }[pathname] || pathname.slice(1); if ( - !/^(web\/[a-z0-9/.-]+|feiya\/(index.html|login.html|chat.html))$/.test( + !/^(web\/[a-z0-9/.-]+|feiya\/(index.html|login.html|chat.html))$/i.test( path, ) || path.includes("..")