From 23a55488fc9390caae6393562013ec961c285a26 Mon Sep 17 00:00:00 2001 From: "N. V. Lang" Date: Mon, 20 May 2024 03:10:31 +0200 Subject: [PATCH] feat(core): revamp escape mechanism --- .dockerignore | 10 + .github/workflows/jsr.yml | 15 + .github/workflows/nodejs.yml | 2 +- .github/workflows/playwright.yml | 16 +- .gitignore | 5 + Dockerfile | 22 + README.md | 14 +- docs/advanced/tex-texlive/caching.mdx | 4 +- docs/essentials/tex.mdx | 200 +- e2e/full-examples/markdown-it/README.md | 9 +- e2e/full-examples/markdown-it/basic.spec.ts | 35 + .../markdown-it-1-chrome-darwin.png | Bin 0 -> 115777 bytes e2e/full-examples/markdown-it/package.json | 4 +- e2e/full-examples/markdown-it/src/app.d.ts | 14 +- e2e/full-examples/markdown-it/src/app.html | 20 +- .../markdown-it/src/routes/+page.sveltex | 83 +- .../markdown-it/sveltex.config.js | 75 +- e2e/full-examples/marked/README.md | 9 +- e2e/full-examples/marked/basic.spec.ts | 35 + .../marked-1-chrome-darwin.png | Bin 0 -> 115267 bytes e2e/full-examples/marked/package.json | 4 +- e2e/full-examples/marked/src/app.d.ts | 14 +- e2e/full-examples/marked/src/app.html | 20 +- .../marked/src/routes/+page.sveltex | 81 +- .../marked/src/sveltex/tex/something.svelte | 9 - e2e/full-examples/marked/sveltex.config.js | 69 +- e2e/full-examples/micromark/README.md | 9 +- e2e/full-examples/micromark/basic.spec.ts | 35 + .../micromark-1-chrome-darwin.png | Bin 0 -> 112439 bytes e2e/full-examples/micromark/package.json | 18 +- e2e/full-examples/micromark/src/app.d.ts | 14 +- e2e/full-examples/micromark/src/app.html | 20 +- .../micromark/src/routes/+page.sveltex | 83 +- .../src/sveltex/tex/something.svelte | 11 + e2e/full-examples/micromark/sveltex.config.js | 108 +- e2e/full-examples/unified/basic.spec.ts | 17 +- .../unified-1-chrome-darwin.png | Bin 0 -> 113495 bytes e2e/full-examples/unified/src/app.html | 5 +- .../unified/src/routes/+page.sveltex | 69 +- .../unified/src/sveltex/tex/something.svelte | 28 - e2e/full-examples/unified/sveltex.config.js | 55 +- eslint.config.js | 2 + jsr.jsonc | 35 + map.json | 12 - out.html | 24 - package.json | 61 +- playwright.config.ts | 31 +- pnpm-lock.yaml | 1762 ++++++---------- screenshot.png | Bin 40063 -> 0 bytes src/README.md | 20 +- src/Sveltex.ts | 357 ++-- src/config/defaults.ts | 34 +- src/deps.ts | 88 +- src/handlers/CodeHandler.ts | 218 +- src/handlers/Handler.ts | 9 +- src/handlers/MarkdownHandler.ts | 8 +- src/handlers/TexHandler.ts | 87 +- src/handlers/VerbatimHandler.ts | 277 ++- src/type-guards/ast.ts | 98 - src/type-guards/code.ts | 12 +- src/types/SveltexConfiguration.ts | 22 +- src/types/handlers/AdvancedTex.ts | 7 +- src/types/handlers/Code.ts | 10 +- src/types/handlers/Handler.ts | 6 +- src/types/handlers/Tex.ts | 10 +- src/types/handlers/Verbatim.ts | 4 + src/types/utils/Ast.ts | 2 +- src/types/utils/Escape.ts | 255 +++ src/types/utils/MathjaxOptions.ts | 13 +- src/utils/README.md | 12 +- src/utils/TexComponent.ts | 51 +- src/utils/ast.ts | 338 +-- src/utils/cdn.ts | 25 +- src/utils/debug.ts | 92 +- src/utils/diagnosers/backendChoices.ts | 12 +- src/utils/env.ts | 107 + src/utils/escape.ts | 1259 +++++++----- src/utils/fs.ts | 14 + src/utils/globals.ts | 36 - src/utils/html.ts | 21 - src/utils/micromark/skip-flow.ts | 400 ++++ src/utils/micromark/syntax.ts | 28 + src/utils/misc.ts | 169 +- src/utils/parseComponent.ts | 168 +- tests/Sveltex/sveltex.commonmark.test.ts | 383 ++++ tests/Sveltex/sveltex.error.test.ts | 35 +- tests/Sveltex/sveltex.real.test.ts | 78 +- tests/Sveltex/sveltex.script.test.ts | 43 +- tests/Sveltex/sveltex.test.ts | 542 ++--- tests/config/defaults.test.ts | 14 +- tests/fixtures.ts | 21 +- .../AdvancedTexHandler.test.ts | 157 +- .../CodeHandler.escapeOnly.test.ts | 19 +- .../CodeHandler.highlight-js.test.ts | 159 +- .../CodeHandler/CodeHandler.none.test.ts | 139 +- .../CodeHandler/CodeHandler.prismjs.test.ts | 106 +- .../CodeHandler.starry-night.test.ts | 179 +- .../handlers/CodeHandler/CodeHandler.test.ts | 23 +- .../MarkdownHandler.custom.errors.test.ts | 4 +- .../MarkdownHandler.custom.test.ts | 106 +- .../MarkdownHandler.markdown-it.test.ts | 42 +- .../MarkdownHandler.marked.test.ts | 42 +- .../MarkdownHandler.micromark.test.ts | 18 +- .../MarkdownHandler.none.test.ts | 12 +- .../MarkdownHandler/MarkdownHandler.test.ts | 8 +- .../MarkdownHandler.unified.test.ts | 24 +- .../TexHandler.katex.errors.2.test.ts | 14 +- .../TexHandler.katex.errors.test.ts | 15 +- .../TexHandler/TexHandler.katex.test.ts | 45 +- .../TexHandler.mathjax.errors.test.ts | 5 +- .../TexHandler/TexHandler.mathjax.test.ts | 37 +- tests/handlers/TexHandler/TexHandler.test.ts | 34 +- .../VerbatimHandler/VerbatimHandler.test.ts | 325 ++- tests/type-guards/ast.test.ts | 68 - tests/utils.ts | 35 +- tests/utils/TexComponent.test.ts | 82 +- tests/utils/ast.test.ts | 498 +---- tests/utils/cache.test.ts | 20 +- tests/utils/cdn.error.test.ts | 16 +- tests/utils/cdn.test.ts | 29 +- tests/utils/cli.test.ts | 1 + tests/utils/debug.test.ts | 152 +- tests/utils/diagnosers/backendChoices.test.ts | 26 +- .../diagnosers/codeConfiguration.test.ts | 8 +- tests/utils/diagnosers/diagnosers.test.ts | 17 +- tests/utils/dvisvgm.test.ts | 663 +++--- tests/utils/env.test.ts | 160 ++ tests/utils/escape.test.ts | 1806 +++++++++++++---- tests/utils/fs.test.ts | 57 +- tests/utils/globals.test.ts | 42 - tests/utils/html.test.ts | 11 - tests/utils/misc.test.ts | 32 +- tests/utils/parseComponent.test.ts | 170 +- tsconfig.check.json | 10 +- tsconfig.json | 6 +- tsconfig.release.json | 2 +- vitest.config.ts | 6 +- 137 files changed, 7899 insertions(+), 6084 deletions(-) create mode 100644 .dockerignore create mode 100644 .github/workflows/jsr.yml create mode 100644 Dockerfile create mode 100644 e2e/full-examples/markdown-it/basic.spec.ts create mode 100644 e2e/full-examples/markdown-it/basic.spec.ts-snapshots/markdown-it-1-chrome-darwin.png create mode 100644 e2e/full-examples/marked/basic.spec.ts create mode 100644 e2e/full-examples/marked/basic.spec.ts-snapshots/marked-1-chrome-darwin.png delete mode 100644 e2e/full-examples/marked/src/sveltex/tex/something.svelte create mode 100644 e2e/full-examples/micromark/basic.spec.ts create mode 100644 e2e/full-examples/micromark/basic.spec.ts-snapshots/micromark-1-chrome-darwin.png create mode 100644 e2e/full-examples/micromark/src/sveltex/tex/something.svelte create mode 100644 e2e/full-examples/unified/basic.spec.ts-snapshots/unified-1-chrome-darwin.png delete mode 100644 e2e/full-examples/unified/src/sveltex/tex/something.svelte create mode 100644 jsr.jsonc delete mode 100644 map.json delete mode 100644 out.html delete mode 100644 screenshot.png create mode 100644 src/types/utils/Escape.ts create mode 100644 src/utils/env.ts delete mode 100644 src/utils/globals.ts delete mode 100644 src/utils/html.ts create mode 100644 src/utils/micromark/skip-flow.ts create mode 100644 src/utils/micromark/syntax.ts create mode 100644 tests/Sveltex/sveltex.commonmark.test.ts create mode 100644 tests/utils/env.test.ts delete mode 100644 tests/utils/globals.test.ts delete mode 100644 tests/utils/html.test.ts diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6543b8b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +node_modules +dist +ideas +external +legacy +docs +.VSCodeCounter +.github +.vscode +.husky diff --git a/.github/workflows/jsr.yml b/.github/workflows/jsr.yml new file mode 100644 index 0000000..b3e10c4 --- /dev/null +++ b/.github/workflows/jsr.yml @@ -0,0 +1,15 @@ +name: Publish to JSR + +on: + release: + types: [published] + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write # The OIDC ID token is used for authentication with JSR. + steps: + - uses: actions/checkout@v4 + - run: npx jsr publish diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 2acd2e3..98e9afa 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -13,6 +13,6 @@ jobs: node-version: '20.x' registry-url: 'https://registry.npmjs.org' - run: npm ci - - run: npm publish + - run: npm publish --provenance env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index ba18c2b..baf485d 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -1,20 +1,28 @@ name: Playwright Tests on: push: - branches: [main, master] + branches: [main] pull_request: - branches: [main, master] + branches: [main] jobs: test: timeout-minutes: 60 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - uses: xu-cheng/texlive-action@v2 + with: + scheme: small + run: | + apk add make + make - uses: actions/setup-node@v4 with: node-version: lts/* - - name: Install dependencies - run: npm install -g pnpm && pnpm install + - name: Install PNPM + run: npm install -g pnpm + - name: Install Node.js dependencies + run: pnpm install - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run Playwright tests diff --git a/.gitignore b/.gitignore index b38b7db..477ba3a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,12 +11,17 @@ dist examples external ideas +legacy node_modules playwright-report static test-results tmp +# Generated by Sveltex in E2E tests +**/sveltex/fonts/** +**/sveltex/*.css + .VSCodeCounter #——————————————————————————————————————————————————————————# diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1fc6261 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +# Extend the Playwright Docker image +FROM mcr.microsoft.com/playwright:v1.44.0-jammy + +# Set environment variables to skip interactive prompts +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Etc/UTC + +# Install TeX Live for LaTeX document compilation +RUN apt-get update && \ + apt-get install -y texlive tzdata && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Install Node.js dependencies (assuming package.json is present) +COPY package*.json ./ +RUN npm install + +# Copy the rest of your application +COPY . . + +# Entrypoint for your application (adjust as needed) +CMD ["npm", "run", "test:e2e"] diff --git a/README.md b/README.md index 515f2c2..f92586a 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,10 @@ -# Sveltex = Svelte + $\TeX$ +# Sveltex = Svelte + $\mathrm{\TeX}$ [![JSR](https://jsr.io/badges/@nvlang/sveltex?style=flat-square&labelColor=1A3644)](https://jsr.io/@nvlang/sveltex) [![NPM Version](https://img.shields.io/npm/v/sveltex-preprocess?style=flat-square&logo=npm&logoColor=white&label=&labelColor=BD453B&color=BD453B)](https://npmjs.com/sveltex-preprocess) [![GitHub Tag](https://img.shields.io/github/v/tag/nvlang/sveltex?style=flat-square&logo=GitHub&logoColor=aaa&label=&labelColor=333&color=333)](https://github.com/nvlang/sveltex) [![Codecov](https://img.shields.io/codecov/c/github/nvlang/sveltex?style=flat-square&logo=codecov&label=&logoColor=aaa&labelColor=333&color=333)]() -- NPM: [sveltex-preprocess](https://npmjs.com/sveltex-preprocess) -- JSR: [@nvlang/sveltex](https://jsr.io/@nvlang/sveltex) -- GitHub: [nvlang/sveltex](https://github.com/nvlang/sveltex) - ## Installation ```sh @@ -17,7 +13,12 @@ ## Documentation -TODO +### Quickstart + +```js +// svelte.config.js +import { sveltex } from 'sveltex-preprocess'; +``` ## How it works @@ -34,6 +35,7 @@ In alphabetical order: - Improve source map support. - Support preprocessing LaTeX content before passing it to MathJax/KaTeX. - VSCode extension for proper syntax highlighting of `.sveltex` files. +- Yeoman generator for scaffolding new Sveltex projects. ## Contributing diff --git a/docs/advanced/tex-texlive/caching.mdx b/docs/advanced/tex-texlive/caching.mdx index ca82a37..57e15bf 100644 --- a/docs/advanced/tex-texlive/caching.mdx +++ b/docs/advanced/tex-texlive/caching.mdx @@ -26,7 +26,9 @@ apply: ```js sveltex.config.js import { sveltex } from 'sveltex-preprocess'; -export const sveltexPreprocessor = await sveltex({ advancedTexBackend: 'local' }) +export const sveltexPreprocessor = await sveltex({ + advancedTexBackend: 'local', +}); await sveltexPreprocessor.configure({ advancedTex: { diff --git a/docs/essentials/tex.mdx b/docs/essentials/tex.mdx index f4be2f9..0a104aa 100644 --- a/docs/essentials/tex.mdx +++ b/docs/essentials/tex.mdx @@ -1,76 +1,50 @@ --- title: 'TeX' -description: 'Choose your markdown ecosystem' +description: 'Choose your TeX backend' icon: 'square-root-variable' mode: 'wide' --- -SvelTeX natively supports the following backends to render "basic" TeX (listed -in alphabetical order): +SvelTeX natively supports two backends to render "basic" TeX (listed in +alphabetical order): - [KaTeX](https://katex.org): "The fastest math typesetting library for the - web." + web." NPM: [`katex`](https://www.npmjs.com/package/katex). - [MathJax](http://mathjax.org): "Beautiful and accessible math in all - browsers." - - [MathJax-full](https://github.com/mathjax/MathJax-src): - - [MathJax-node](https://github.com/mathjax/MathJax-node): API to call - MathJax from Node.js. At the time of writing, it uses MathJax v2, which is - a bit outdated (MathJax v3 is mature, and v4 is in beta). - -Additionally, you can also provide a **custom** markdown backend. + browsers." NPM: [`mathjax-full`](https://github.com/mathjax/MathJax-src). ### Backend-specific setup - + ```bash pnpm - pnpm add -D markdown-it + pnpm add -D katex ``` ```bash bun - bun add -D markdown-it + bun add -D katex ``` ```bash npm - npm add -D markdown-it + npm add -D katex ``` ```bash yarn - yarn add -D markdown-it + yarn add -D katex ``` ```js sveltex.config.js import { sveltex } from 'sveltex-preprocess'; - // import multimdTablePlugin from 'markdown-it-multimd-table'; export const sveltexPreprocessor = await sveltex({ - markdownBackend: 'markdown-it', + texBackend: 'katex', }); await sveltexPreprocessor.configure({ - markdown: { - options: { - html: false, - xhtmlOut: false, - breaks: false, - linkify: false, - typographer: false, - quotes: '“”‘’', - }, - extensions: [ - // [ - // multimdTablePlugin, - // { - // multiline: false, - // rowspan: false, - // headerless: false, - // multibody: true, - // autolabel: true, - // }, - // ], - ], + tex: { + // ... (configuration possible, but not necessary) }, }); ``` @@ -78,170 +52,40 @@ Additionally, you can also provide a **custom** markdown backend. - + ```bash pnpm - pnpm add -D marked + pnpm add -D mathjax-full ``` ```bash bun - bun add -D marked + bun add -D mathjax-full ``` ```bash npm - npm add -D marked + npm add -D mathjax-full ``` ```bash yarn - yarn add -D marked + yarn add -D mathjax-full ``` - + ```js sveltex.config.js import { sveltex } from 'sveltex-preprocess'; - // import { gfmHeadingId } from 'marked-gfm-heading-id'; export const sveltexPreprocessor = await sveltex({ - markdownBackend: 'marked', - }); - - await sveltexPreprocessor.configure({ - markdown: { - options: { - async: false, - breaks: true, - gfm: true, - pedantic: false, - silent: false, - }, - extensions: [ - // gfmHeadingId() - ], - }, - }); - ``` - - - - - - - - - ```bash pnpm - pnpm add -D micromark - ``` - ```bash bun - bun add -D micromark - ``` - ```bash npm - npm add -D micromark - ``` - ```bash yarn - yarn add -D micromark - ``` - - - - ```js sveltex.config.js - import { sveltex } from 'sveltex-preprocess'; - - export const sveltexPreprocessor = await sveltex({ - 'micromark', - }); - - await sveltexPreprocessor.configure({ - markdown: { - options: { - gfm: true, - }, - extensions: [], - }, + texBackend: 'mathjax', }); - ``` - - - - - - - - - ```bash pnpm - pnpm add -D unified remark-parse remark-rehype rehype-stringify - ``` - ```bash bun - bun add -D unified remark-parse remark-rehype rehype-stringify - ``` - ```bash npm - npm add -D unified remark-parse remark-rehype rehype-stringify - ``` - ```bash yarn - yarn add -D unified remark-parse remark-rehype rehype-stringify - ``` - - - - ```js sveltex.config.js - import { sveltex } from 'sveltex-preprocess'; - - export const sveltexPreprocessor = await sveltex( - 'unified', // Markdown backend - 'none', // Code backend (syntax highlighting) - 'none', // TeX backend - 'none', // Advanced TeX backend - ); await sveltexPreprocessor.configure({ - markdown: { - options: { - gfm: true, - }, - extensions: [], + tex: { + // ... (configuration possible, but not necessary) }, }); ``` - - -By way of example, here is how you might set up a custom markdown backend to use -[Marked](https://github.com/markedjs/marked) if it weren't already supported: - -```js sveltex.config.js -import { sveltex, MarkdownHandler } from 'sveltex-preprocess'; -import { Marked } from 'marked'; - -export const sveltexPreprocessor = await sveltex({ - markdownBackend: 'custom', -}); - -sveltexPreprocessor.markdownHandler = await MarkdownHandler.create( - 'custom', - { - configuration: { extensions: [], options: {} }, - processor: new Marked(), - configure: (config, markdownHandler) => { - if (config.options) { - markdownHandler.processor.setOptions(config.options); - } - if (config.extensions) { - markdownHandler.processor.use(...config.extensions); - } - // Before calling the `configure` function you provide, the - // MarkdownHandler class will always do the following: - // markdownHandler.configuration = - // mergeConfigs(markdownHandler.configuration, config); - }, - process: (markdown: string, inline: boolean, markdownHandler) => { - return inline - ? await markdownHandler.processor.parseInline(markdown) - : await markdownHandler.processor.parse(markdown); - }, - } -) -``` - diff --git a/e2e/full-examples/markdown-it/README.md b/e2e/full-examples/markdown-it/README.md index 5ce6766..435a567 100644 --- a/e2e/full-examples/markdown-it/README.md +++ b/e2e/full-examples/markdown-it/README.md @@ -1,6 +1,7 @@ # create-svelte -Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte). +Everything you need to build a Svelte project, powered by +[`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte). ## Creating a project @@ -16,7 +17,8 @@ npm create svelte@latest my-app ## Developing -Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: +Once you've created a project and installed dependencies with `npm install` (or +`pnpm install` or `yarn`), start a development server: ```bash npm run dev @@ -35,4 +37,5 @@ npm run build You can preview the production build with `npm run preview`. -> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. +> To deploy your app, you may need to install an +> [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. diff --git a/e2e/full-examples/markdown-it/basic.spec.ts b/e2e/full-examples/markdown-it/basic.spec.ts new file mode 100644 index 0000000..53b212f --- /dev/null +++ b/e2e/full-examples/markdown-it/basic.spec.ts @@ -0,0 +1,35 @@ +import { test, expect } from '@playwright/test'; + +// test('has title', async ({ page }) => { +// await page.goto('https://playwright.dev/'); + +// // Expect a title "to contain" a substring. +// await expect(page).toHaveTitle(/Playwright/); +// }); + +/** + * - 3001 - markdown-it + * - 3002 - marked + * - 3003 - micromark + * - 3004 - unified + */ +test('markdown-it', async ({ page }) => { + await page.goto('http://localhost:3001/'); + + // Expects page to have a heading with the name of Installation. + await expect( + page.getByRole('heading', { name: 'Heading 1' }), + ).toBeVisible(); + + // expect + // + //

Welcome to SvelteKit

Visit kit.svelte.dev to read the documentation

+ // + + // Expects page to have a link with the href "https://kit.svelte.dev". + await expect( + page.getByRole('link', { name: 'kit.svelte.dev' }), + ).toHaveAttribute('href', 'https://kit.svelte.dev'); + + await expect(page).toHaveScreenshot({ fullPage: true }); +}); diff --git a/e2e/full-examples/markdown-it/basic.spec.ts-snapshots/markdown-it-1-chrome-darwin.png b/e2e/full-examples/markdown-it/basic.spec.ts-snapshots/markdown-it-1-chrome-darwin.png new file mode 100644 index 0000000000000000000000000000000000000000..e4c6c66ea4e75d14c2cab06a36805126c39d84b0 GIT binary patch literal 115777 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 WgyE}7=ndm&&)pw#+q=qi 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 - - - - - %sveltekit.head% - - -
%sveltekit.body%
- + + + + %sveltekit.head% + + +
%sveltekit.body%
+ diff --git a/e2e/full-examples/markdown-it/src/routes/+page.sveltex b/e2e/full-examples/markdown-it/src/routes/+page.sveltex index 4ef77f3..9d21561 100644 --- a/e2e/full-examples/markdown-it/src/routes/+page.sveltex +++ b/e2e/full-examples/markdown-it/src/routes/+page.sveltex @@ -1,7 +1,86 @@ -# Welcome to SvelteKit + -Visit [kit.svelte.dev](https://kit.svelte.dev) to read the documentation +# Heading 1 +###### Heading 6 +text **bold** text *italic (asterisks)* text _italic (underscores)_ text +[kit.svelte.dev](https://kit.svelte.dev) text `inline code` text $$ 1/n < \color{#fc0}\int_0^{1} \color{var(--some-color)}x^{x}\ dx < n. $$ + +Text: \[ 1/n < \color{#fc0}\int_0^{1} \color{var(--some-color)}x^{x}\ dx < n. \] Mustache tags: {1+1}, {`$1 + $${2 + +3} = $6`}. + +Regexes in mustache tags: {('a$b$c\(d\)e\[f\]g$$h$$'.match(/\$/g))}. + +` foo ` text $a$; +$ +b +$. + +
+> $x^{a}$ `monospaced $x$` +
+ + +Verbatim $$x^{2}\}$$ {{{ \[ \( + </Verb> < + + + + +$\texttt{}\}\\\{\ldots\text{\(f\)}$ + +\(\texttt{}\}\\\{\ldots\text{$f$}\) + +```ts +let a = { b: 3 }; +let b = `${2 + 2}a$b$c\(d\)\(e\[f\]\[g$$h$$i$` // { +let c = `{@html a} b {@debug c} d {@const e} f ` +``` + +text + +```html + + + + +``` + +An "advanced tex" block: + + +\begin{tikzpicture} + \draw (1,2) circle (2.4); + \draw[dashed, var(--some-color), thick] (-.5,0) rectangle (3, 3); + \draw[red, thick] (-1,1) rectangle (2.5, 4); + \node at (1,2) {\(\int_{0}^{1} \sum x_{i}^{3} \mathrm{d}\text{$x$}\)}; +\end{tikzpicture} + + +That same advanced tex block, referenced with a self-closing tag: + + + +some *more* text... diff --git a/e2e/full-examples/markdown-it/sveltex.config.js b/e2e/full-examples/markdown-it/sveltex.config.js index 13f7361..2b6f1f9 100644 --- a/e2e/full-examples/markdown-it/sveltex.config.js +++ b/e2e/full-examples/markdown-it/sveltex.config.js @@ -2,11 +2,80 @@ import { sveltex } from 'sveltex-preprocess'; export const sveltexPreprocessor = await sveltex({ markdownBackend: 'markdown-it', - codeBackend: 'none', - texBackend: 'none', - advancedTexBackend: 'none', + codeBackend: 'highlight.js', + texBackend: 'mathjax', + advancedTexBackend: 'local', }); await sveltexPreprocessor.configure({ markdown: {}, + code: { + escapeBraces: true, + escapeHtml: true, + wrap: undefined, + wrapClassPrefix: 'language-', + languages: ['ts'], + }, + tex: { + outputFormat: 'svg', + }, + verbatim: { + verbatimEnvironments: { + Verb: { + processInner: { + escapeBraces: true, + escapeHtml: true, + }, + component: 'p', + }, + }, + }, + advancedTex: { + components: { + tex: { + aliases: ['TikZ'], + preamble: [ + '\\usepackage{mathtools}', + '\\usepackage{amssymb}', + '\\usepackage{microtype}', + // '\\usepackage{fontspec}', + // '\\usepackage{unicode-math}', + // '\\usepackage{geometry}', + '\\usepackage{tikz}', + '\\usetikzlibrary{arrows.meta, calc, matrix, patterns, shadings, shadows, plotmarks, shapes.geometric, shapes.misc}', + '\\usepgflibrary{shadings}', + ].join('\n'), + overrides: { + engine: 'lualatex', + // overrideSvgPostprocess: null, + // svgoOptions: { + // plugins: [], + // }, + intermediateFiletype: 'dvi', + dvisvgmOptions: { + svg: { + // fontFormat: 'svg', + bbox: '3pt', + gradSimplify: null, + gradOverlap: null, + gradSegments: null, + bitmapFormat: null, + clipJoin: null, + comments: null, + currentColor: null, + optimize: null, + precision: null, + linkmark: null, + noStyles: null, + relative: null, + zip: null, + }, + processing: {}, + svgTransformations: {}, + }, + }, + documentClass: '\\documentclass{standalone}', + }, + }, + }, }); diff --git a/e2e/full-examples/marked/README.md b/e2e/full-examples/marked/README.md index 5ce6766..435a567 100644 --- a/e2e/full-examples/marked/README.md +++ b/e2e/full-examples/marked/README.md @@ -1,6 +1,7 @@ # create-svelte -Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte). +Everything you need to build a Svelte project, powered by +[`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte). ## Creating a project @@ -16,7 +17,8 @@ npm create svelte@latest my-app ## Developing -Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: +Once you've created a project and installed dependencies with `npm install` (or +`pnpm install` or `yarn`), start a development server: ```bash npm run dev @@ -35,4 +37,5 @@ npm run build You can preview the production build with `npm run preview`. -> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. +> To deploy your app, you may need to install an +> [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. diff --git a/e2e/full-examples/marked/basic.spec.ts b/e2e/full-examples/marked/basic.spec.ts new file mode 100644 index 0000000..33f6097 --- /dev/null +++ b/e2e/full-examples/marked/basic.spec.ts @@ -0,0 +1,35 @@ +import { test, expect } from '@playwright/test'; + +// test('has title', async ({ page }) => { +// await page.goto('https://playwright.dev/'); + +// // Expect a title "to contain" a substring. +// await expect(page).toHaveTitle(/Playwright/); +// }); + +/** + * - 3001 - markdown-it + * - 3002 - marked + * - 3003 - micromark + * - 3004 - unified + */ +test('marked', async ({ page }) => { + await page.goto('http://localhost:3002/'); + + // Expects page to have a heading with the name of Installation. + await expect( + page.getByRole('heading', { name: 'Heading 1' }), + ).toBeVisible(); + + // expect + // + //

Welcome to SvelteKit

Visit kit.svelte.dev to read the documentation

+ // + + // Expects page to have a link with the href "https://kit.svelte.dev". + await expect( + page.getByRole('link', { name: 'kit.svelte.dev' }), + ).toHaveAttribute('href', 'https://kit.svelte.dev'); + + await expect(page).toHaveScreenshot({ fullPage: true }); +}); diff --git a/e2e/full-examples/marked/basic.spec.ts-snapshots/marked-1-chrome-darwin.png b/e2e/full-examples/marked/basic.spec.ts-snapshots/marked-1-chrome-darwin.png new file mode 100644 index 0000000000000000000000000000000000000000..c4b739d9961e2aed85df02aa7bbee77516b6f1ba GIT binary patch literal 115267 zcmeFZWmHsO{5Oh?2!b?7ODH1UsYpqxAl*m{C=8v-hyqd~T_V!b-QXzQNS8==cRk;M z-~ZlMcipw_TFWBfFhq9s`30eN4Jok_m#1aKKdI+8JDlAi*0>mY!{(XJE<0HSDJ60V^SJs_brKqpTrIk#*Utz z!u#zuLHTrjFUNCgOibgQXQG@jH~Cb{k%!T~TDt#}-gwl0Q(a4|qO2@RKsl*vq};v*g+etqH_PWoM@P@h z%v9W;q9nk2udAzT<)Esjmf363BT`pacm4Wx0Re&8js!kZY~12cj$chX;*Sq^$McO_ zP^_5e_vXT4m+Y(qO@rD_2UaM>jS$7J4()YCMkJ+}z}Q zNCWB#m=p;K3DZMXh?)^Py=I3=d5V^uM{R^_-?sxM7UOk}EN{S&QTufI*graL7ndU~|^=FJ;KMRm2u zSfw*=(kIHv&HW&e9d!$fjFJ+*(WIw$P1lA6~C@UM0V~`LNk5z~}^kiw3v{F2H@L>AlU*6q4Jm25{rlzKD-I3xK6ck;`Kfmgu z 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 <}AUTYCVaA=Qsi|nl4ZV1jLfXTloP`2Y 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 literal 0 HcmV?d00001 diff --git a/e2e/full-examples/marked/package.json b/e2e/full-examples/marked/package.json index c1145bc..b2a4cbe 100644 --- a/e2e/full-examples/marked/package.json +++ b/e2e/full-examples/marked/package.json @@ -14,7 +14,6 @@ "@sveltejs/kit": "^2.5.5", "@sveltejs/vite-plugin-svelte": "^3.0.2", "esbuild": "0.20.2", - "katex": "^0.16.10", "marked": "^12.0.1", "svelte": "^4.2.12", "svelte-check": "^3.6.8", @@ -26,6 +25,7 @@ "type": "module", "dependencies": { "@types/unist": "^2.0.10", - "marked-gfm-heading-id": "^3.1.3" + "marked-gfm-heading-id": "^3.1.3", + "mathjax-full": "^3.2.2" } } diff --git a/e2e/full-examples/marked/src/app.d.ts b/e2e/full-examples/marked/src/app.d.ts index 743f07b..c7c0ed1 100644 --- a/e2e/full-examples/marked/src/app.d.ts +++ b/e2e/full-examples/marked/src/app.d.ts @@ -1,13 +1,13 @@ // See https://kit.svelte.dev/docs/types#app // for information about these interfaces declare global { - namespace App { - // interface Error {} - // interface Locals {} - // interface PageData {} - // interface PageState {} - // interface Platform {} - } + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface PageState {} + // interface Platform {} + } } export {}; diff --git a/e2e/full-examples/marked/src/app.html b/e2e/full-examples/marked/src/app.html index 77a5ff5..e499e56 100644 --- a/e2e/full-examples/marked/src/app.html +++ b/e2e/full-examples/marked/src/app.html @@ -1,12 +1,14 @@ - - - - - %sveltekit.head% - - -
%sveltekit.body%
- + + + + %sveltekit.head% + + +
%sveltekit.body%
+ diff --git a/e2e/full-examples/marked/src/routes/+page.sveltex b/e2e/full-examples/marked/src/routes/+page.sveltex index 962cddd..9d21561 100644 --- a/e2e/full-examples/marked/src/routes/+page.sveltex +++ b/e2e/full-examples/marked/src/routes/+page.sveltex @@ -1,15 +1,86 @@ + + + +# Heading 1 +###### Heading 6 + +text **bold** text *italic (asterisks)* text _italic (underscores)_ text +[kit.svelte.dev](https://kit.svelte.dev) text `inline code` text $$ 1/n < \color{#fc0}\int_0^{1} \color{var(--some-color)}x^{x}\ dx < n. $$ + +Text: \[ 1/n < \color{#fc0}\int_0^{1} \color{var(--some-color)}x^{x}\ dx < n. \] Mustache tags: {1+1}, {`$1 + $${2 + +3} = $6`}. + +Regexes in mustache tags: {('a$b$c\(d\)e\[f\]g$$h$$'.match(/\$/g))}. + +` foo ` text $a$; +$ +b +$. + +
+> $x^{a}$ `monospaced $x$` +
+ + +Verbatim $$x^{2}\}$$ {{{ \[ \( + </Verb> < + + + + +$\texttt{}\}\\\{\ldots\text{\(f\)}$ + +\(\texttt{}\}\\\{\ldots\text{$f$}\) + +```ts +let a = { b: 3 }; +let b = `${2 + 2}a$b$c\(d\)\(e\[f\]\[g$$h$$i$` // { +let c = `{@html a} b {@debug c} d {@const e} f ` +``` + +text + +```html + -test1 *italic* test2 +``` + +An "advanced tex" block: \begin{tikzpicture} - \draw (0,0) circle (3); - \draw (0,-1) circle (1.8); - \draw[var(--red), thick] (0,0) rectangle (3, 3); + \draw (1,2) circle (2.4); + \draw[dashed, var(--some-color), thick] (-.5,0) rectangle (3, 3); + \draw[red, thick] (-1,1) rectangle (2.5, 4); + \node at (1,2) {\(\int_{0}^{1} \sum x_{i}^{3} \mathrm{d}\text{$x$}\)}; \end{tikzpicture} -test3 **bold** test4 +That same advanced tex block, referenced with a self-closing tag: + + + +some *more* text... + + diff --git a/e2e/full-examples/marked/src/sveltex/tex/something.svelte b/e2e/full-examples/marked/src/sveltex/tex/something.svelte deleted file mode 100644 index 2b7097b..0000000 --- a/e2e/full-examples/marked/src/sveltex/tex/something.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/e2e/full-examples/marked/sveltex.config.js b/e2e/full-examples/marked/sveltex.config.js index 2c9a028..6a806cc 100644 --- a/e2e/full-examples/marked/sveltex.config.js +++ b/e2e/full-examples/marked/sveltex.config.js @@ -1,10 +1,10 @@ import { sveltex } from 'sveltex-preprocess'; import { gfmHeadingId } from 'marked-gfm-heading-id'; -export const sveltexPreprocessor = sveltex({ +export const sveltexPreprocessor = await sveltex({ markdownBackend: 'marked', - codeBackend: 'none', - texBackend: 'none', + codeBackend: 'highlight.js', + texBackend: 'mathjax', advancedTexBackend: 'local', }); @@ -19,11 +19,70 @@ await sveltexPreprocessor.configure({ }, extensions: [gfmHeadingId()], }, + code: { + escapeBraces: true, + escapeHtml: true, + wrap: undefined, + wrapClassPrefix: 'language-', + languages: ['ts'], + }, + tex: {}, + verbatim: { + verbatimEnvironments: { + Verb: { + processInner: { + escapeBraces: true, + escapeHtml: true, + }, + component: 'p', + }, + }, + }, advancedTex: { - // caching: false, components: { tex: { - documentClass: '\\documentclass[tikz]{standalone}', + aliases: ['TikZ'], + preamble: [ + '\\usepackage{mathtools}', + '\\usepackage{amssymb}', + '\\usepackage{microtype}', + // '\\usepackage{fontspec}', + // '\\usepackage{unicode-math}', + // '\\usepackage{geometry}', + '\\usepackage{tikz}', + '\\usetikzlibrary{arrows.meta, calc, matrix, patterns, shadings, shadows, plotmarks, shapes.geometric, shapes.misc}', + '\\usepgflibrary{shadings}', + ].join('\n'), + overrides: { + engine: 'lualatex', + // overrideSvgPostprocess: null, + // svgoOptions: { + // plugins: [], + // }, + intermediateFiletype: 'dvi', + dvisvgmOptions: { + svg: { + // fontFormat: 'svg', + bbox: '3pt', + gradSimplify: null, + gradOverlap: null, + gradSegments: null, + bitmapFormat: null, + clipJoin: null, + comments: null, + currentColor: null, + optimize: null, + precision: null, + linkmark: null, + noStyles: null, + relative: null, + zip: null, + }, + processing: {}, + svgTransformations: {}, + }, + }, + documentClass: '\\documentclass{standalone}', }, }, }, diff --git a/e2e/full-examples/micromark/README.md b/e2e/full-examples/micromark/README.md index 5ce6766..435a567 100644 --- a/e2e/full-examples/micromark/README.md +++ b/e2e/full-examples/micromark/README.md @@ -1,6 +1,7 @@ # create-svelte -Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte). +Everything you need to build a Svelte project, powered by +[`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte). ## Creating a project @@ -16,7 +17,8 @@ npm create svelte@latest my-app ## Developing -Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: +Once you've created a project and installed dependencies with `npm install` (or +`pnpm install` or `yarn`), start a development server: ```bash npm run dev @@ -35,4 +37,5 @@ npm run build You can preview the production build with `npm run preview`. -> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. +> To deploy your app, you may need to install an +> [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. diff --git a/e2e/full-examples/micromark/basic.spec.ts b/e2e/full-examples/micromark/basic.spec.ts new file mode 100644 index 0000000..e9071c7 --- /dev/null +++ b/e2e/full-examples/micromark/basic.spec.ts @@ -0,0 +1,35 @@ +import { test, expect } from '@playwright/test'; + +// test('has title', async ({ page }) => { +// await page.goto('https://playwright.dev/'); + +// // Expect a title "to contain" a substring. +// await expect(page).toHaveTitle(/Playwright/); +// }); + +/** + * - 3001 - markdown-it + * - 3002 - marked + * - 3003 - micromark + * - 3004 - unified + */ +test('micromark', async ({ page }) => { + await page.goto('http://localhost:3003/'); + + // Expects page to have a heading with the name of Installation. + await expect( + page.getByRole('heading', { name: 'Heading 1' }), + ).toBeVisible(); + + // expect + // + //

Welcome to SvelteKit

Visit kit.svelte.dev to read the documentation

+ // + + // Expects page to have a link with the href "https://kit.svelte.dev". + await expect( + page.getByRole('link', { name: 'kit.svelte.dev' }), + ).toHaveAttribute('href', 'https://kit.svelte.dev'); + + await expect(page).toHaveScreenshot({ fullPage: true }); +}); diff --git a/e2e/full-examples/micromark/basic.spec.ts-snapshots/micromark-1-chrome-darwin.png b/e2e/full-examples/micromark/basic.spec.ts-snapshots/micromark-1-chrome-darwin.png new file mode 100644 index 0000000000000000000000000000000000000000..b1080bcdd5effd74a8a700f8376ee040cf7383e3 GIT binary patch literal 112439 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 bT?v<{W=tPu81zg_T;)_7he_!ZJ%0W_9G0YU literal 0 HcmV?d00001 diff --git a/e2e/full-examples/micromark/package.json b/e2e/full-examples/micromark/package.json index 2017dd7..046144a 100644 --- a/e2e/full-examples/micromark/package.json +++ b/e2e/full-examples/micromark/package.json @@ -11,20 +11,22 @@ }, "devDependencies": { "@sveltejs/adapter-auto": "^3.2.0", - "@sveltejs/kit": "^2.5.5", - "@sveltejs/vite-plugin-svelte": "^3.0.2", + "@sveltejs/kit": "^2.5.9", + "@sveltejs/vite-plugin-svelte": "^3.1.0", "esbuild": "0.20.2", "katex": "^0.16.10", + "mathjax-full": "^3.2.2", "micromark": "^4.0.0", - "svelte": "^4.2.12", - "svelte-check": "^3.6.8", - "sveltex-preprocess": "file:../../../", + "svelte": "^4.2.17", + "svelte-check": "^3.7.1", + "sveltex-preprocess": "file:../../..", "tslib": "^2.6.2", - "typescript": "^5.4.3", - "vite": "^5.2.7" + "typescript": "^5.4.5", + "vite": "^5.2.11" }, "type": "module", "dependencies": { - "@types/unist": "^2.0.10" + "@types/unist": "^2.0.10", + "mathjax-node": "^2.1.1" } } diff --git a/e2e/full-examples/micromark/src/app.d.ts b/e2e/full-examples/micromark/src/app.d.ts index 743f07b..c7c0ed1 100644 --- a/e2e/full-examples/micromark/src/app.d.ts +++ b/e2e/full-examples/micromark/src/app.d.ts @@ -1,13 +1,13 @@ // See https://kit.svelte.dev/docs/types#app // for information about these interfaces declare global { - namespace App { - // interface Error {} - // interface Locals {} - // interface PageData {} - // interface PageState {} - // interface Platform {} - } + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface PageState {} + // interface Platform {} + } } export {}; diff --git a/e2e/full-examples/micromark/src/app.html b/e2e/full-examples/micromark/src/app.html index 77a5ff5..e499e56 100644 --- a/e2e/full-examples/micromark/src/app.html +++ b/e2e/full-examples/micromark/src/app.html @@ -1,12 +1,14 @@ - - - - - %sveltekit.head% - - -
%sveltekit.body%
- + + + + %sveltekit.head% + + +
%sveltekit.body%
+ diff --git a/e2e/full-examples/micromark/src/routes/+page.sveltex b/e2e/full-examples/micromark/src/routes/+page.sveltex index 4ef77f3..9d21561 100644 --- a/e2e/full-examples/micromark/src/routes/+page.sveltex +++ b/e2e/full-examples/micromark/src/routes/+page.sveltex @@ -1,7 +1,86 @@ -# Welcome to SvelteKit + -Visit [kit.svelte.dev](https://kit.svelte.dev) to read the documentation +# Heading 1 +###### Heading 6 +text **bold** text *italic (asterisks)* text _italic (underscores)_ text +[kit.svelte.dev](https://kit.svelte.dev) text `inline code` text $$ 1/n < \color{#fc0}\int_0^{1} \color{var(--some-color)}x^{x}\ dx < n. $$ + +Text: \[ 1/n < \color{#fc0}\int_0^{1} \color{var(--some-color)}x^{x}\ dx < n. \] Mustache tags: {1+1}, {`$1 + $${2 + +3} = $6`}. + +Regexes in mustache tags: {('a$b$c\(d\)e\[f\]g$$h$$'.match(/\$/g))}. + +` foo ` text $a$; +$ +b +$. + +
+> $x^{a}$ `monospaced $x$` +
+ + +Verbatim $$x^{2}\}$$ {{{ \[ \( + </Verb> < + + + + +$\texttt{}\}\\\{\ldots\text{\(f\)}$ + +\(\texttt{}\}\\\{\ldots\text{$f$}\) + +```ts +let a = { b: 3 }; +let b = `${2 + 2}a$b$c\(d\)\(e\[f\]\[g$$h$$i$` // { +let c = `{@html a} b {@debug c} d {@const e} f ` +``` + +text + +```html + + + + +``` + +An "advanced tex" block: + + +\begin{tikzpicture} + \draw (1,2) circle (2.4); + \draw[dashed, var(--some-color), thick] (-.5,0) rectangle (3, 3); + \draw[red, thick] (-1,1) rectangle (2.5, 4); + \node at (1,2) {\(\int_{0}^{1} \sum x_{i}^{3} \mathrm{d}\text{$x$}\)}; +\end{tikzpicture} + + +That same advanced tex block, referenced with a self-closing tag: + + + +some *more* text... diff --git a/e2e/full-examples/micromark/src/sveltex/tex/something.svelte b/e2e/full-examples/micromark/src/sveltex/tex/something.svelte new file mode 100644 index 0000000..e16ae5a --- /dev/null +++ b/e2e/full-examples/micromark/src/sveltex/tex/something.svelte @@ -0,0 +1,11 @@ +10x3idx \ No newline at end of file diff --git a/e2e/full-examples/micromark/sveltex.config.js b/e2e/full-examples/micromark/sveltex.config.js index 8aba0f8..ed24798 100644 --- a/e2e/full-examples/micromark/sveltex.config.js +++ b/e2e/full-examples/micromark/sveltex.config.js @@ -2,11 +2,113 @@ import { sveltex } from 'sveltex-preprocess'; export const sveltexPreprocessor = await sveltex({ markdownBackend: 'micromark', - codeBackend: 'none', - texBackend: 'none', - advancedTexBackend: 'none', + codeBackend: 'escapeOnly', + texBackend: 'mathjax', + advancedTexBackend: 'local', }); await sveltexPreprocessor.configure({ + general: { + tex: {}, + }, markdown: {}, + code: { + escapeBraces: true, + escapeHtml: true, + wrap: undefined, + wrapClassPrefix: 'language-', + }, + tex: { + // inputConfiguration: { + // svgNode: true, + // }, + outputFormat: 'chtml', + mathjaxConfiguration: { + svg: { + // displayIndent: '2em', + // displayAlign: 'center', + }, + chtml: { + adaptiveCSS: false, + fontURL: + 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/output/chtml/fonts/woff-v2', + }, + options: {}, + }, + + // inputConfiguration: { + // html: true, + // css: true, + // }, + // mathjaxNodeConfiguration: { + // fontURL: + // 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/output/chtml/fonts/woff-v2/', + // }, + // mathjaxConfiguration: { + // chtml: { + // fontURL: + // 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/output/chtml/fonts/woff-v2/', + // }, + // }, + // outputFormat: 'chtml', + }, + verbatim: { + verbatimEnvironments: { + Verb: { + processInner: { + escapeBraces: true, + escapeHtml: true, + }, + component: 'p', + }, + }, + }, + advancedTex: { + components: { + tex: { + aliases: ['TikZ'], + preamble: [ + '\\usepackage{mathtools}', + '\\usepackage{amssymb}', + '\\usepackage{microtype}', + // '\\usepackage{fontspec}', + // '\\usepackage{unicode-math}', + // '\\usepackage{geometry}', + '\\usepackage{tikz}', + '\\usetikzlibrary{arrows.meta, calc, matrix, patterns, shadings, shadows, plotmarks, shapes.geometric, shapes.misc}', + '\\usepgflibrary{shadings}', + ].join('\n'), + overrides: { + engine: 'lualatex', + // overrideSvgPostprocess: null, + // svgoOptions: { + // plugins: [], + // }, + intermediateFiletype: 'dvi', + dvisvgmOptions: { + svg: { + // fontFormat: 'svg', + bbox: '3pt', + gradSimplify: null, + gradOverlap: null, + gradSegments: null, + bitmapFormat: null, + clipJoin: null, + comments: null, + currentColor: null, + optimize: null, + precision: null, + linkmark: null, + noStyles: null, + relative: null, + zip: null, + }, + processing: {}, + svgTransformations: {}, + }, + }, + documentClass: '\\documentclass{standalone}', + }, + }, + }, }); diff --git a/e2e/full-examples/unified/basic.spec.ts b/e2e/full-examples/unified/basic.spec.ts index f5390fd..b7744f2 100644 --- a/e2e/full-examples/unified/basic.spec.ts +++ b/e2e/full-examples/unified/basic.spec.ts @@ -18,7 +18,7 @@ test('unified', async ({ page }) => { // Expects page to have a heading with the name of Installation. await expect( - page.getByRole('heading', { name: 'Welcome to SvelteKit' }), + page.getByRole('heading', { name: 'Heading 1' }), ).toBeVisible(); // expect @@ -26,14 +26,6 @@ test('unified', async ({ page }) => { //

Welcome to SvelteKit

Visit kit.svelte.dev to read the documentation

// - // Expects page to have a paragraph with the text "Visit kit.svelte.dev to read the documentation". - await expect( - page.getByText('Visit kit.svelte.dev to read the documentation'), - ).toBeVisible(); - - // Expects page to have a link with the text "kit.svelte.dev". - await expect(page.getByText('kit.svelte.dev')).toBeVisible(); - // Expects page to have a link with the href "https://kit.svelte.dev". await expect( page.getByRole('link', { name: 'kit.svelte.dev' }), @@ -41,9 +33,8 @@ test('unified', async ({ page }) => { // Expect H1 to have ID "welcome-to-sveltekit" await expect( - page.getByRole('heading', { name: 'Welcome to SvelteKit' }), - ).toHaveAttribute('id', 'welcome-to-sveltekit'); + page.getByRole('heading', { name: 'Heading 1' }), + ).toHaveAttribute('id', 'heading-1'); - // Expect there to be a strong "something" within a paragraph on the page - await expect(page.getByText('something')).toBeVisible(); + await expect(page).toHaveScreenshot({ fullPage: true }); }); diff --git a/e2e/full-examples/unified/basic.spec.ts-snapshots/unified-1-chrome-darwin.png b/e2e/full-examples/unified/basic.spec.ts-snapshots/unified-1-chrome-darwin.png new file mode 100644 index 0000000000000000000000000000000000000000..df6e134e3ead555783750d011d35bc627b841bf4 GIT binary patch literal 113495 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 CVd*{q literal 0 HcmV?d00001 diff --git a/e2e/full-examples/unified/src/app.html b/e2e/full-examples/unified/src/app.html index 1966776..e499e56 100644 --- a/e2e/full-examples/unified/src/app.html +++ b/e2e/full-examples/unified/src/app.html @@ -5,7 +5,10 @@ %sveltekit.head% - +
%sveltekit.body%
diff --git a/e2e/full-examples/unified/src/routes/+page.sveltex b/e2e/full-examples/unified/src/routes/+page.sveltex index 5c09370..9d21561 100644 --- a/e2e/full-examples/unified/src/routes/+page.sveltex +++ b/e2e/full-examples/unified/src/routes/+page.sveltex @@ -1,43 +1,86 @@ + # Heading 1 -## Heading 2 -### Heading 3 -#### Heading 4 -##### Heading 5 ###### Heading 6 text **bold** text *italic (asterisks)* text _italic (underscores)_ text -[svelte.dev](https://kit.svelte.dev) text `inline code` text $x^{x}$ text +[kit.svelte.dev](https://kit.svelte.dev) text `inline code` text $$ 1/n < \color{#fc0}\int_0^{1} \color{var(--some-color)}x^{x}\ dx < n. $$ -$$ 1/n < \int_0^{1} x^{x}\ dx < n. $$ +Text: \[ 1/n < \color{#fc0}\int_0^{1} \color{var(--some-color)}x^{x}\ dx < n. \] Mustache tags: {1+1}, {`$1 + $${2 + +3} = $6`}. -text +Regexes in mustache tags: {('a$b$c\(d\)e\[f\]g$$h$$'.match(/\$/g))}. + +` foo ` text $a$; +$ +b +$. + +
+> $x^{a}$ `monospaced $x$` +
+ + +Verbatim $$x^{2}\}$$ {{{ \[ \( + </Verb> < + + + + +$\texttt{}\}\\\{\ldots\text{\(f\)}$ + +\(\texttt{}\}\\\{\ldots\text{$f$}\) ```ts let a = { b: 3 }; +let b = `${2 + 2}a$b$c\(d\)\(e\[f\]\[g$$h$$i$` // { +let c = `{@html a} b {@debug c} d {@const e} f ` ``` text +```html + + + +``` + +An "advanced tex" block: + \begin{tikzpicture} - \draw (0,0) circle (3); - \draw[thin] (0,-1) circle (3.9); - \draw[var(--some-color), thick] (0,0) rectangle (3, 3); + \draw (1,2) circle (2.4); + \draw[dashed, var(--some-color), thick] (-.5,0) rectangle (3, 3); + \draw[red, thick] (-1,1) rectangle (2.5, 4); + \node at (1,2) {\(\int_{0}^{1} \sum x_{i}^{3} \mathrm{d}\text{$x$}\)}; \end{tikzpicture} -text +That same advanced tex block, referenced with a self-closing tag: -text +some *more* text... + + diff --git a/e2e/full-examples/unified/src/sveltex/tex/something.svelte b/e2e/full-examples/unified/src/sveltex/tex/something.svelte deleted file mode 100644 index 8cf89c2..0000000 --- a/e2e/full-examples/unified/src/sveltex/tex/something.svelte +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - diff --git a/e2e/full-examples/unified/sveltex.config.js b/e2e/full-examples/unified/sveltex.config.js index cac6240..83e8ac0 100644 --- a/e2e/full-examples/unified/sveltex.config.js +++ b/e2e/full-examples/unified/sveltex.config.js @@ -18,11 +18,62 @@ await sveltexPreprocessor.configure({ languages: 'common', }, tex: {}, + verbatim: { + verbatimEnvironments: { + Verb: { + processInner: { + escapeBraces: true, + escapeHtml: true, + }, + component: 'p', + }, + }, + }, advancedTex: { - // caching: false, components: { tex: { - documentClass: '\\documentclass[tikz]{standalone}', + aliases: ['TikZ'], + preamble: [ + '\\usepackage{mathtools}', + '\\usepackage{amssymb}', + '\\usepackage{microtype}', + // '\\usepackage{fontspec}', + // '\\usepackage{unicode-math}', + // '\\usepackage{geometry}', + '\\usepackage{tikz}', + '\\usetikzlibrary{arrows.meta, calc, matrix, patterns, shadings, shadows, plotmarks, shapes.geometric, shapes.misc}', + '\\usepgflibrary{shadings}', + ].join('\n'), + overrides: { + engine: 'lualatex', + // overrideSvgPostprocess: null, + // svgoOptions: { + // plugins: [], + // }, + intermediateFiletype: 'dvi', + dvisvgmOptions: { + svg: { + // fontFormat: 'svg', + bbox: '3pt', + gradSimplify: null, + gradOverlap: null, + gradSegments: null, + bitmapFormat: null, + clipJoin: null, + comments: null, + currentColor: null, + optimize: null, + precision: null, + linkmark: null, + noStyles: null, + relative: null, + zip: null, + }, + processing: {}, + svgTransformations: {}, + }, + }, + documentClass: '\\documentclass{standalone}', }, }, }, diff --git a/eslint.config.js b/eslint.config.js index 94eb5b0..1d270d6 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -20,6 +20,8 @@ export default tseslint.config( 'yarn.lock', 'external', 'examples', + 'legacy', + 'ideas', ], }, { diff --git a/jsr.jsonc b/jsr.jsonc new file mode 100644 index 0000000..7213b0e --- /dev/null +++ b/jsr.jsonc @@ -0,0 +1,35 @@ +{ + "name": "@nvl/sveltex", + "version": "0.1.0", + "exports": { + // Default entry point, which can be imported as `@nvlang/sveltex` + ".": "./src/mod.ts" + }, + "publish": { + "exclude": [ + // End-to-end tests + "**/e2e/**", + + // Unit tests + "**/tests/**", + + // JS distribution files (NPM uses these, but JSR doesn't need them) + "**/dist/**", + + // Node modules + "**/node_modules/**", + + // Documentation deployed with Mintlify + "**/docs/**", + + // GitHub Actions workflows + "**/.github/**", + + // Editor settings + "**/.vscode/**", + + // Git hooks + "**/.husky/**" + ] + } +} diff --git a/map.json b/map.json deleted file mode 100644 index 69e23d7..0000000 --- a/map.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "version": 3, - "file": "test.sveltex_final", - "sources": [ - "test.sveltex" - ], - "sourcesContent": [ - "hello\n\ntest1\ntest2\ntest3\ntest4\ntest5\ntest6\ntest7\ntest8\ntest9\n\nthere\n`1`\n{#if condition}\n*a* {mustache}\n{:else}\n**b**\n{/if}\n*italic*\n`code`\nor **bold**" - ], - "names": [], - "mappings": ";;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcA,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC;AAAA;AAEf,CAAC,CAAC,IAAI,CAAC;AAAA;AAEP,CAAC,CAAC,EAAE,CAAC;AAAA;AAAA;AAAA" -} \ No newline at end of file diff --git a/out.html b/out.html deleted file mode 100644 index 8e434c2..0000000 --- a/out.html +++ /dev/null @@ -1,24 +0,0 @@ - -hello - -test1 -test2 -test3 -test4 -test5 -test6 -test7 -test8 -test9 - -there -1 -{#if condition} -a {mustache} -{:else} -b -{/if} -italic -code -or bold diff --git a/package.json b/package.json index f6e75e8..d60f12a 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,8 @@ "build:release": "pnpm run clean && tsc -p tsconfig.release.json && tsc-alias -p tsconfig.release.json", "lint": "eslint . && tsc -p tsconfig.check.json", "test": "vitest run --coverage --watch --", - "test:e2e": "playwright test", + "test:e2e": "pnpm test:e2e:prepare && playwright test", + "test:e2e:prepare": "pnpm build:release && cd e2e/full-examples/unified && pnpm i && cd ../micromark && pnpm i && cd ../marked && pnpm i && cd ../markdown-it && pnpm i && cd ../../..", "format": "prettier --write .", "test:watch": "vitest --watch", "prepare": "husky" @@ -59,30 +60,26 @@ "devDependencies": { "@commitlint/config-conventional": "^19.2.2", "@commitlint/types": "^19.0.3", - "@playwright/test": "^1.43.1", - "@sveltejs/kit": "^2.5.7", + "@playwright/test": "^1.44.0", "@types/clean-css": "^4.2.11", "@types/estree": "^1.0.5", "@types/hast": "^3.0.4", - "@types/jsdom": "^21.1.6", "@types/katex": "^0.16.7", "@types/markdown-it": "^14.1.1", "@types/mathjax": "^0.0.40", - "@types/mathjax-node": "^2.1.0", - "@types/mdast": "^4.0.3", "@types/mock-fs": "^4.13.4", - "@types/node": "^20.12.8", - "@types/prismjs": "^1.26.3", - "@types/semver": "^7.5.8", + "@types/node": "^20.12.12", + "@types/prismjs": "^1.26.4", "@types/uuid": "^9.0.8", - "@typescript-eslint/eslint-plugin": "^7.8.0", - "@typescript-eslint/parser": "^7.8.0", + "@typescript-eslint/eslint-plugin": "8.0.0-alpha.13", + "@typescript-eslint/parser": "8.0.0-alpha.13", + "@typescript-eslint/utils": "8.0.0-alpha.13", "@vitest/coverage-v8": "^1.6.0", "@wooorm/starry-night": "^3.3.0", "commitlint": "^19.3.0", - "eslint": "^8.57.0", + "eslint": "^9.3.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-playwright": "^1.6.0", + "eslint-plugin-playwright": "^1.6.1", "eslint-plugin-tsdoc": "^0.2.17", "eslint-plugin-vitest": "^0.5.4", "hast-util-find-and-replace": "^5.0.1", @@ -96,7 +93,6 @@ "marked": "^12.0.2", "mathjax": "^3.2.2", "mathjax-full": "3.2.2", - "mathjax-node": "^2.1.1", "micromark": "^4.0.0", "mock-fs": "^5.2.0", "prettier": "^3.2.5", @@ -106,12 +102,10 @@ "rehype-stringify": "^10.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.0", - "source-map": "^0.7.4", - "svelte": "^4.2.15", "ts-node": "^10.9.2", - "tsc-alias": "^1.8.8", + "tsc-alias": "^1.8.10", "typescript": "^5.4.5", - "typescript-eslint": "^7.8.0", + "typescript-eslint": "8.0.0-alpha.13", "unified": "^11.0.4", "vite": "^5.2.11", "vite-tsconfig-paths": "^4.3.2", @@ -119,30 +113,42 @@ }, "dependencies": { "@types/html-escaper": "^3.0.2", + "@types/mdast": "^4.0.4", "@types/unist": "^3.0.2", "clean-css": "^5.3.3", "deepmerge-ts": "^5.1.0", "find-cache-dir": "^5.0.0", - "glob": "^10.3.12", + "glob": "^10.3.15", "html-escaper": "^3.0.3", "html-tag-names": "^2.1.0", "magic-string": "^0.30.10", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-math": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "micromark-core-commonmark": "^2.0.1", + "micromark-extension-math": "^3.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-util-character": "^2.1.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", "node-fetch": "^3.3.2", "ora": "^8.0.1", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "pretty-bytes": "^6.1.1", "radash": "^12.1.0", "rfdc": "^1.3.1", - "rimraf": "^5.0.5", - "semver": "^7.6.2", - "sorcery": "^0.11.0", - "svgo": "^3.2.0", + "rimraf": "^5.0.7", + "svelte": "^4.2.17", + "svgo": "^3.3.2", "tsafe": "^1.6.6", "uuid": "^9.0.1", + "xregexp": "^5.1.1", "yaml": "^2.4.2" }, "peerDependencies": { - "@types/mdast": "^4.0.3", "@wooorm/starry-night": "^3.3.0", "hast-util-find-and-replace": "^5.0.1", "hast-util-to-html": "^9.0.1", @@ -151,13 +157,11 @@ "markdown-it": "^14.1.0", "marked": "^12.0.1", "mathjax-full": "^3.2.2 || ^4.0.0", - "mathjax-node": "^2.1.1", "micromark": "^4.0.0", "prismjs": "^1.29.0", "rehype-stringify": "^10.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.0", - "svelte": ">=4", "unified": "^11.0.4" }, "peerDependenciesMeta": { @@ -185,9 +189,6 @@ "mathjax-full": { "optional": true }, - "mathjax-node": { - "optional": true - }, "markdown-it": { "optional": true }, diff --git a/playwright.config.ts b/playwright.config.ts index 16c3fed..8dcdf0d 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -61,18 +61,33 @@ export const config = defineConfig({ /* Run your local dev server before starting the tests */ webServer: [ - // { - // cwd: './e2e/full-examples/markdown-it', - // command: 'pnpm build && pnpm preview', - // url: 'http://127.0.0.1:3001', - // reuseExistingServer: !process.env['CI'], - // }, + { + cwd: './e2e/full-examples/markdown-it/', + command: 'pnpm build && pnpm preview', + url: 'http://localhost:3001', + reuseExistingServer: !process.env['CI'], + timeout: 40000, + }, + { + cwd: './e2e/full-examples/marked/', + command: 'pnpm build && pnpm preview', + url: 'http://localhost:3002', + reuseExistingServer: !process.env['CI'], + timeout: 40000, + }, + { + cwd: './e2e/full-examples/micromark/', + command: 'pnpm build && pnpm preview', + url: 'http://localhost:3003', + reuseExistingServer: !process.env['CI'], + timeout: 40000, + }, { cwd: './e2e/full-examples/unified/', command: 'pnpm build && pnpm preview', url: 'http://localhost:3004/', - // reuseExistingServer: !process.env['CI'], - timeout: 20000, + reuseExistingServer: !process.env['CI'], + timeout: 40000, }, ], }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f20692..ffeb471 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@types/html-escaper': specifier: ^3.0.2 version: 3.0.2 + '@types/mdast': + specifier: ^4.0.4 + version: 4.0.4 '@types/unist': specifier: ^3.0.2 version: 3.0.2 @@ -24,8 +27,8 @@ importers: specifier: ^5.0.0 version: 5.0.0 glob: - specifier: ^10.3.12 - version: 10.3.12 + specifier: ^10.3.15 + version: 10.3.15 html-escaper: specifier: ^3.0.3 version: 3.0.3 @@ -35,6 +38,42 @@ importers: magic-string: specifier: ^0.30.10 version: 0.30.10 + mdast-util-from-markdown: + specifier: ^2.0.0 + version: 2.0.0 + mdast-util-math: + specifier: ^3.0.0 + version: 3.0.0 + mdast-util-mdx-expression: + specifier: ^2.0.0 + version: 2.0.0 + micromark-core-commonmark: + specifier: ^2.0.1 + version: 2.0.1 + micromark-extension-math: + specifier: ^3.0.0 + version: 3.0.0 + micromark-extension-mdx-expression: + specifier: ^3.0.0 + version: 3.0.0 + micromark-extension-mdx-jsx: + specifier: ^3.0.0 + version: 3.0.0 + micromark-extension-mdx-md: + specifier: ^2.0.0 + version: 2.0.0 + micromark-util-character: + specifier: ^2.1.0 + version: 2.1.0 + micromark-util-html-tag-name: + specifier: ^2.0.0 + version: 2.0.0 + micromark-util-symbol: + specifier: ^2.0.0 + version: 2.0.0 + micromark-util-types: + specifier: ^2.0.0 + version: 2.0.0 node-fetch: specifier: ^3.3.2 version: 3.3.2 @@ -42,8 +81,8 @@ importers: specifier: ^8.0.1 version: 8.0.1 picocolors: - specifier: ^1.0.0 - version: 1.0.0 + specifier: ^1.0.1 + version: 1.0.1 pretty-bytes: specifier: ^6.1.1 version: 6.1.1 @@ -54,23 +93,23 @@ importers: specifier: ^1.3.1 version: 1.3.1 rimraf: - specifier: ^5.0.5 - version: 5.0.5 - semver: - specifier: ^7.6.2 - version: 7.6.2 - sorcery: - specifier: ^0.11.0 - version: 0.11.0 + specifier: ^5.0.7 + version: 5.0.7 + svelte: + specifier: ^4.2.17 + version: 4.2.17 svgo: - specifier: ^3.2.0 - version: 3.2.0 + specifier: ^3.3.2 + version: 3.3.2 tsafe: specifier: ^1.6.6 version: 1.6.6 uuid: specifier: ^9.0.1 version: 9.0.1 + xregexp: + specifier: ^5.1.1 + version: 5.1.1 yaml: specifier: ^2.4.2 version: 2.4.2 @@ -82,11 +121,8 @@ importers: specifier: ^19.0.3 version: 19.0.3 '@playwright/test': - specifier: ^1.43.1 - version: 1.43.1 - '@sveltejs/kit': - specifier: ^2.5.7 - version: 2.5.7(@sveltejs/vite-plugin-svelte@3.1.0(svelte@4.2.15)(vite@5.2.11(@types/node@20.12.8)))(svelte@4.2.15)(vite@5.2.11(@types/node@20.12.8)) + specifier: ^1.44.0 + version: 1.44.0 '@types/clean-css': specifier: ^4.2.11 version: 4.2.11 @@ -96,9 +132,6 @@ importers: '@types/hast': specifier: ^3.0.4 version: 3.0.4 - '@types/jsdom': - specifier: ^21.1.6 - version: 21.1.6 '@types/katex': specifier: ^0.16.7 version: 0.16.7 @@ -108,57 +141,51 @@ importers: '@types/mathjax': specifier: ^0.0.40 version: 0.0.40 - '@types/mathjax-node': - specifier: ^2.1.0 - version: 2.1.0 - '@types/mdast': - specifier: ^4.0.3 - version: 4.0.3 '@types/mock-fs': specifier: ^4.13.4 version: 4.13.4 '@types/node': - specifier: ^20.12.8 - version: 20.12.8 + specifier: ^20.12.12 + version: 20.12.12 '@types/prismjs': - specifier: ^1.26.3 - version: 1.26.3 - '@types/semver': - specifier: ^7.5.8 - version: 7.5.8 + specifier: ^1.26.4 + version: 1.26.4 '@types/uuid': specifier: ^9.0.8 version: 9.0.8 '@typescript-eslint/eslint-plugin': - specifier: ^7.8.0 - version: 7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) + specifier: 8.0.0-alpha.13 + version: 8.0.0-alpha.13(@typescript-eslint/parser@8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5))(eslint@9.3.0)(typescript@5.4.5) '@typescript-eslint/parser': - specifier: ^7.8.0 - version: 7.8.0(eslint@8.57.0)(typescript@5.4.5) + specifier: 8.0.0-alpha.13 + version: 8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5) + '@typescript-eslint/utils': + specifier: 8.0.0-alpha.13 + version: 8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5) '@vitest/coverage-v8': specifier: ^1.6.0 - version: 1.6.0(vitest@1.6.0(@types/node@20.12.8)(jsdom@24.0.0)) + version: 1.6.0(vitest@1.6.0(@types/node@20.12.12)(jsdom@24.0.0)) '@wooorm/starry-night': specifier: ^3.3.0 version: 3.3.0 commitlint: specifier: ^19.3.0 - version: 19.3.0(@types/node@20.12.8)(typescript@5.4.5) + version: 19.3.0(@types/node@20.12.12)(typescript@5.4.5) eslint: - specifier: ^8.57.0 - version: 8.57.0 + specifier: ^9.3.0 + version: 9.3.0 eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) + version: 9.1.0(eslint@9.3.0) eslint-plugin-playwright: - specifier: ^1.6.0 - version: 1.6.0(eslint@8.57.0) + specifier: ^1.6.1 + version: 1.6.1(eslint@9.3.0) eslint-plugin-tsdoc: specifier: ^0.2.17 version: 0.2.17 eslint-plugin-vitest: specifier: ^0.5.4 - version: 0.5.4(@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)(vitest@1.6.0(@types/node@20.12.8)(jsdom@24.0.0)) + version: 0.5.4(@typescript-eslint/eslint-plugin@8.0.0-alpha.13(@typescript-eslint/parser@8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5))(eslint@9.3.0)(typescript@5.4.5))(eslint@9.3.0)(typescript@5.4.5)(vitest@1.6.0(@types/node@20.12.12)(jsdom@24.0.0)) hast-util-find-and-replace: specifier: ^5.0.1 version: 5.0.1 @@ -192,9 +219,6 @@ importers: mathjax-full: specifier: 3.2.2 version: 3.2.2 - mathjax-node: - specifier: ^2.1.1 - version: 2.1.1 micromark: specifier: ^4.0.0 version: 4.0.0 @@ -222,36 +246,30 @@ importers: remark-rehype: specifier: ^11.1.0 version: 11.1.0 - source-map: - specifier: ^0.7.4 - version: 0.7.4 - svelte: - specifier: ^4.2.15 - version: 4.2.15 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.12.8)(typescript@5.4.5) + version: 10.9.2(@types/node@20.12.12)(typescript@5.4.5) tsc-alias: - specifier: ^1.8.8 - version: 1.8.8 + specifier: ^1.8.10 + version: 1.8.10 typescript: specifier: ^5.4.5 version: 5.4.5 typescript-eslint: - specifier: ^7.8.0 - version: 7.8.0(eslint@8.57.0)(typescript@5.4.5) + specifier: 8.0.0-alpha.13 + version: 8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5) unified: specifier: ^11.0.4 version: 11.0.4 vite: specifier: ^5.2.11 - version: 5.2.11(@types/node@20.12.8) + version: 5.2.11(@types/node@20.12.12) vite-tsconfig-paths: specifier: ^4.3.2 - version: 4.3.2(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.8)) + version: 4.3.2(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.12)) vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@20.12.8)(jsdom@24.0.0) + version: 1.6.0(@types/node@20.12.12)(jsdom@24.0.0) packages: @@ -280,6 +298,10 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/runtime-corejs3@7.24.5': + resolution: {integrity: sha512-GWO0mgzNMLWaSYM4z4NVIuY0Cd1fl8cPnuetuddu5w/qGuvt5Y7oUi/kvvQGK9xgOkFJDQX2heIvTRn/OQ1XTg==} + engines: {node: '>=6.9.0'} + '@babel/types@7.24.5': resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==} engines: {node: '>=6.9.0'} @@ -508,16 +530,16 @@ packages: resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/eslintrc@3.1.0': + resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@8.57.0': - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/js@9.3.0': + resolution: {integrity: sha512-niBqk8iwv96+yuTwjM6bWg8ovzAPF9qkICsGtcoa5/dmqcEMfdwNAX7+/OHcJHc7wj7XqPxH98oAHytFYlw6Sw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + '@humanwhocodes/config-array@0.13.0': + resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} '@humanwhocodes/module-importer@1.0.1': @@ -527,6 +549,10 @@ packages: '@humanwhocodes/object-schema@2.0.3': resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + '@humanwhocodes/retry@0.3.0': + resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} + engines: {node: '>=18.18'} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -582,14 +608,11 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@playwright/test@1.43.1': - resolution: {integrity: sha512-HgtQzFgNEEo4TE22K/X7sYTYNqEMMTZmFS8kTq6m8hXj+m1D8TgwgIbumHddJa9h4yl4GkKb8/bgAl2+g7eDgA==} + '@playwright/test@1.44.0': + resolution: {integrity: sha512-rNX5lbNidamSUorBhB4XZ9SQTjAqfe5M+p37Z8ic0jPFBMo5iCtQz1kRWkEMg+rYOKSlVycpQmpqjSFq7LXOfg==} engines: {node: '>=16'} hasBin: true - '@polka/url@1.0.0-next.25': - resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} - '@rollup/rollup-android-arm-eabi@4.17.2': resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} cpu: [arm] @@ -673,30 +696,6 @@ packages: '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - '@sveltejs/kit@2.5.7': - resolution: {integrity: sha512-6uedTzrb7nQrw6HALxnPrPaXdIN2jJJTzTIl96Z3P5NiG+OAfpdPbrWrvkJ3GN4CfWqrmU4dJqwMMRMTD/C7ow==} - engines: {node: '>=18.13'} - hasBin: true - peerDependencies: - '@sveltejs/vite-plugin-svelte': ^3.0.0 - svelte: ^4.0.0 || ^5.0.0-next.0 - vite: ^5.0.3 - - '@sveltejs/vite-plugin-svelte-inspector@2.1.0': - resolution: {integrity: sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==} - engines: {node: ^18.0.0 || >=20} - peerDependencies: - '@sveltejs/vite-plugin-svelte': ^3.0.0 - svelte: ^4.0.0 || ^5.0.0-next.0 - vite: ^5.0.0 - - '@sveltejs/vite-plugin-svelte@3.1.0': - resolution: {integrity: sha512-sY6ncCvg+O3njnzbZexcVtUqOBE3iYmQPJ9y+yXSkOwG576QI/xJrBnQSRXFLGwJNBa0T78JEKg5cIR0WOAuUw==} - engines: {node: ^18.0.0 || >=20} - peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.0 - vite: ^5.0.0 - '@trysound/sax@0.2.0': resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -713,18 +712,21 @@ packages: '@tsconfig/node16@1.0.4': resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@types/acorn@4.0.6': + resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} + '@types/clean-css@4.2.11': resolution: {integrity: sha512-Y8n81lQVTAfP2TOdtJJEsCoYl1AnOkqDqMvXb9/7pfgZZ7r8YrEyurrAvAoAjHOGXKRybay+5CsExqIH6liccw==} '@types/conventional-commits-parser@5.0.0': resolution: {integrity: sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==} - '@types/cookie@0.6.0': - resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} - '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@types/estree-jsx@1.0.5': + resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} + '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} @@ -734,9 +736,6 @@ packages: '@types/html-escaper@3.0.2': resolution: {integrity: sha512-A8vk09eyYzk8J/lFO4OUMKCmRN0rRzfZf4n3Olwapgox/PtTiU8zPYlL1UEkJ/WeHvV6v9Xnj3o/705PKz9r4Q==} - '@types/jsdom@21.1.6': - resolution: {integrity: sha512-/7kkMsC+/kMs7gAYmmBR9P0vGTnOoLhQhyhQJSlXGI5bzTHp6xdo0TtKWQAsz6pmSAeVqKSbqeyP6hytqr9FDw==} - '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -749,14 +748,11 @@ packages: '@types/markdown-it@14.1.1': resolution: {integrity: sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==} - '@types/mathjax-node@2.1.0': - resolution: {integrity: sha512-s1i5U1yVQBINaWuIa/950yxLRvF1DdaB+P4+hm+CjchbkjoufBnTQC91Rw7qFN2Z9UYvJQ4GPHdHlCcgiNx9oA==} - '@types/mathjax@0.0.40': resolution: {integrity: sha512-rHusx08LCg92WJxrsM3SPjvLTSvK5C+gealtSuhKbEOcUZfWlwigaFoPLf6Dfxhg4oryN5qP9Sj7zOQ4HYXINw==} - '@types/mdast@4.0.3': - resolution: {integrity: sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==} + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} '@types/mdurl@2.0.0': resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} @@ -767,65 +763,69 @@ packages: '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} - '@types/node@20.12.8': - resolution: {integrity: sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==} + '@types/node@20.12.12': + resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} - '@types/prismjs@1.26.3': - resolution: {integrity: sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw==} + '@types/prismjs@1.26.4': + resolution: {integrity: sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg==} '@types/semver@7.5.8': resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - '@types/tough-cookie@4.0.5': - resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - '@types/unist@3.0.2': resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} '@types/uuid@9.0.8': resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} - '@typescript-eslint/eslint-plugin@7.8.0': - resolution: {integrity: sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/eslint-plugin@8.0.0-alpha.13': + resolution: {integrity: sha512-FQeu2HGVZ6wDAn2m6MxpS+or7LyBEjjCXnFv79aCJtcJnxtgDQa0po88GHZv1tZwzIsgxQ3bnbz4vNgbPisMbA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/parser@7.8.0': - resolution: {integrity: sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/parser@8.0.0-alpha.13': + resolution: {integrity: sha512-CWFhVzrA6n7OeTHmvtxxUy+BSvUwHl8BcT6QsVi87MGcGQpLQZ1TeU0kYoIISkzFojoULF5q0de9hP/FbANi/g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/scope-manager@7.8.0': - resolution: {integrity: sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==} + '@typescript-eslint/scope-manager@7.9.0': + resolution: {integrity: sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/type-utils@7.8.0': - resolution: {integrity: sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/scope-manager@8.0.0-alpha.13': + resolution: {integrity: sha512-5XA+tfDumd6Y5GWVFMF2810HB8GIijMawdLgMptSeN3CeOfxQB1J3EBtmbgSWuValNSvV6jujIxKRVgnrZ/WpA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/type-utils@8.0.0-alpha.13': + resolution: {integrity: sha512-4Rkwf4YaQIqeF/l2/F9hqxiWlr9P5a0M7Ep0kK99WDYDAhABraIgvsScd2PAtKU1smJXdozbqKDywKCg6etH5Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/types@7.8.0': - resolution: {integrity: sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==} + '@typescript-eslint/types@7.9.0': + resolution: {integrity: sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/typescript-estree@7.8.0': - resolution: {integrity: sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==} + '@typescript-eslint/types@8.0.0-alpha.13': + resolution: {integrity: sha512-uJN8BSa8YHs9E/lFR9nkzLyaEijXGzMLgkh8DuQMlOP8epqJ9Jnzx+gOFUIyJV+C8uavpGp+YnCMvq4IDG9L+Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@7.9.0': + resolution: {integrity: sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' @@ -833,16 +833,35 @@ packages: typescript: optional: true - '@typescript-eslint/utils@7.8.0': - resolution: {integrity: sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==} + '@typescript-eslint/typescript-estree@8.0.0-alpha.13': + resolution: {integrity: sha512-p5SZlikPhHg4510ttfqwjwMgBG7ehzRj5dLk8JR5x9bV0D8zWNotqkWNa0vftbYHb+mdGV6D9zNrJwDjWVd4ag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@7.9.0': + resolution: {integrity: sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 - '@typescript-eslint/visitor-keys@7.8.0': - resolution: {integrity: sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==} + '@typescript-eslint/utils@8.0.0-alpha.13': + resolution: {integrity: sha512-BMAbK/fC7RgvRjGQh8AixfQErFXIpCqL1DfFmMnp+oBZvYLON/4/iIj0yPPpY3E8gbljT7s4LHVkNSu7K/MQug==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + + '@typescript-eslint/visitor-keys@7.9.0': + resolution: {integrity: sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/visitor-keys@8.0.0-alpha.13': + resolution: {integrity: sha512-q8r/RVc5AtAnnRGqKBIoWMwChET2hqydVGqAXlvXXnB6JOE3prpMLvnpUp7JK1jma3VPt2JieCGhzX3YZSLY/Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -873,36 +892,15 @@ packages: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true - abab@2.0.6: - resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} - deprecated: Use your platform's native atob() and btoa() methods instead - - acorn-globals@4.3.4: - resolution: {integrity: sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==} - acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn-walk@6.2.0: - resolution: {integrity: sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==} - engines: {node: '>=0.4.0'} - acorn-walk@8.3.2: resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} engines: {node: '>=0.4.0'} - acorn@5.7.4: - resolution: {integrity: sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==} - engines: {node: '>=0.4.0'} - hasBin: true - - acorn@6.4.2: - resolution: {integrity: sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==} - engines: {node: '>=0.4.0'} - hasBin: true - acorn@8.11.3: resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} engines: {node: '>=0.4.0'} @@ -955,9 +953,6 @@ packages: aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - array-equal@1.0.2: - resolution: {integrity: sha512-gUHx76KtnhEgB3HOuFYiCm3FIdEs6ocM2asHvNTkfu/Y09qQVrrVVaOKENmS2KkSaGoxgXNqC+ZVtR/n0MOkSA==} - array-ify@1.0.0: resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} @@ -965,28 +960,12 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - asn1@0.2.6: - resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} - - assert-plus@1.0.0: - resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} - engines: {node: '>=0.8'} - assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - async-limiter@1.0.1: - resolution: {integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==} - asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - aws-sign2@0.7.0: - resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} - - aws4@1.12.0: - resolution: {integrity: sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==} - axobject-query@4.0.0: resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==} @@ -996,9 +975,6 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - bcrypt-pbkdf@1.0.2: - resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} - binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -1016,12 +992,6 @@ packages: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} - browser-process-hrtime@1.0.0: - resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} - - buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -1030,9 +1000,6 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caseless@0.12.0: - resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -1153,12 +1120,8 @@ packages: engines: {node: '>=16'} hasBin: true - cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} - - core-util-is@1.0.2: - resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + core-js-pure@3.37.1: + resolution: {integrity: sha512-J/r5JTHSmzTxbiYYrzXg9w1VpqrYt+gexenBE9pugeyhwPZTAEJddyiReJWsLO6uNQ8xJZFbod6XC7KKwatCiA==} cosmiconfig-typescript-loader@5.0.0: resolution: {integrity: sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==} @@ -1203,12 +1166,6 @@ packages: resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - cssom@0.3.8: - resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} - - cssstyle@1.4.0: - resolution: {integrity: sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==} - cssstyle@4.0.1: resolution: {integrity: sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==} engines: {node: '>=18'} @@ -1217,17 +1174,10 @@ packages: resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} engines: {node: '>=12'} - dashdash@1.14.1: - resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} - engines: {node: '>=0.10'} - data-uri-to-buffer@4.0.1: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} - data-urls@1.1.0: - resolution: {integrity: sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==} - data-urls@5.0.0: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} @@ -1258,10 +1208,6 @@ packages: resolution: {integrity: sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==} engines: {node: '>=16.0.0'} - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -1270,9 +1216,6 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} - devalue@5.0.0: - resolution: {integrity: sha512-gO+/OMXF7488D+u3ue+G7Y4AA3ZmUnB3eHJXmBTgNHvr4ZNzl36A0ZtG+XCRNYCkYx/bFmw4qtkoFLa+wSrwAA==} - devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} @@ -1288,20 +1231,12 @@ packages: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} - doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - domexception@1.0.1: - resolution: {integrity: sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==} - deprecated: Use your platform's native DOMException instead - domhandler@5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} @@ -1316,9 +1251,6 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - ecc-jsbn@0.1.2: - resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} - emoji-regex@10.3.0: resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} @@ -1339,9 +1271,6 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - es6-promise@3.3.1: - resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} - esbuild@0.20.2: resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} engines: {node: '>=12'} @@ -1363,19 +1292,14 @@ packages: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} - escodegen@1.14.3: - resolution: {integrity: sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==} - engines: {node: '>=4.0'} - hasBin: true - eslint-config-prettier@9.1.0: resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} hasBin: true peerDependencies: eslint: '>=7.0.0' - eslint-plugin-playwright@1.6.0: - resolution: {integrity: sha512-tI1E/EDbHT4Fx5KvukUG3RTIT0gk44gvTP8bNwxLCFsUXVM98ZJG5zWU6Om5JOzH9FrmN4AhMu/UKyEsu0ZoDA==} + eslint-plugin-playwright@1.6.1: + resolution: {integrity: sha512-pfcaeAENH0jZEuUxynfVgMlLY9CSp68D9Ja2z32Xq5zhWCN1HoixSHOzhYVuh/N6fYwtBp4kLu/+IIUTXBTGZg==} engines: {node: '>=16.6.0'} peerDependencies: eslint: '>=8.40.0' @@ -1400,34 +1324,30 @@ packages: vitest: optional: true - eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-scope@8.0.1: + resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true + eslint-visitor-keys@4.0.0: + resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - esm-env@1.0.0: - resolution: {integrity: sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==} + eslint@9.3.0: + resolution: {integrity: sha512-5Iv4CsZW030lpUqHBapdPo3MJetAPtejVW8B84GIcIIv8+ohFaddXsrn1Gn8uD9ijDb+kcYKFUVmC8qG8B2ORQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true esm@3.2.25: resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==} engines: {node: '>=6'} - espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true + espree@10.0.1: + resolution: {integrity: sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} esquery@1.5.0: resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} @@ -1437,14 +1357,16 @@ packages: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} - estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-util-is-identifier-name@3.0.0: + resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + + estree-util-visit@2.0.0: + resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -1459,10 +1381,6 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - extsprintf@1.3.0: - resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} - engines: {'0': node >=0.6.0} - fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -1483,9 +1401,9 @@ packages: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} - file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} @@ -1507,9 +1425,9 @@ packages: resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} engines: {node: '>=18'} - flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} @@ -1518,13 +1436,6 @@ packages: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} - forever-agent@0.6.1: - resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} - - form-data@2.3.3: - resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} - engines: {node: '>= 0.12'} - form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -1564,9 +1475,6 @@ packages: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} - getpass@0.1.7: - resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} - git-raw-commits@4.0.0: resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} engines: {node: '>=16'} @@ -1580,9 +1488,9 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@10.3.12: - resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} - engines: {node: '>=16 || 14 >=14.17'} + glob@10.3.15: + resolution: {integrity: sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==} + engines: {node: '>=16 || 14 >=14.18'} hasBin: true glob@7.2.3: @@ -1596,8 +1504,9 @@ packages: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} - globalyzer@0.1.0: - resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} @@ -1606,21 +1515,9 @@ packages: globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - har-schema@2.0.0: - resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} - engines: {node: '>=4'} - - har-validator@5.1.5: - resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} - engines: {node: '>=6'} - deprecated: this library is no longer supported - has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -1660,8 +1557,8 @@ packages: hast-util-phrasing@3.0.1: resolution: {integrity: sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==} - hast-util-raw@9.0.2: - resolution: {integrity: sha512-PldBy71wO9Uq1kyaMch9AHIghtQvIwxBUkv823pKmkTM3oV1JxtsTNYdevMxvUHqcnOAuO65JKU2+0NOxc2ksA==} + hast-util-raw@9.0.3: + resolution: {integrity: sha512-ICWvVOF2fq4+7CMmtCPD5CM4QKjPbHpPotE6+8tDooV0ZuyJVUzHsrNX+O5NaRbieTf0F7FfeBOMAwi6Td0+yQ==} hast-util-to-html@9.0.1: resolution: {integrity: sha512-hZOofyZANbyWo+9RP75xIDV/gq+OUKx+T46IlwERnKmfpwp81XBFbT9mi26ws+SJchA4RVUQwIBJpqEOBhMzEQ==} @@ -1679,9 +1576,6 @@ packages: resolution: {integrity: sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==} engines: {node: '>=12.0.0'} - html-encoding-sniffer@1.0.2: - resolution: {integrity: sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==} - html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} @@ -1705,10 +1599,6 @@ packages: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} - http-signature@1.2.0: - resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} - engines: {node: '>=0.8', npm: '>=1.3.7'} - https-proxy-agent@7.0.4: resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} engines: {node: '>= 14'} @@ -1722,10 +1612,6 @@ packages: engines: {node: '>=18'} hasBin: true - iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -1769,10 +1655,6 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - is-fullwidth-code-point@2.0.0: - resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} - engines: {node: '>=4'} - is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} @@ -1815,9 +1697,6 @@ packages: resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} engines: {node: '>=8'} - is-typedarray@1.0.0: - resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - is-unicode-supported@1.3.0: resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} engines: {node: '>=12'} @@ -1829,9 +1708,6 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - isstream@0.1.2: - resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} - istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -1869,12 +1745,6 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true - jsbn@0.1.1: - resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} - - jsdom@11.12.0: - resolution: {integrity: sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==} - jsdom@24.0.0: resolution: {integrity: sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==} engines: {node: '>=18'} @@ -1896,23 +1766,13 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - json-schema@0.4.0: - resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} - json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - json-stringify-safe@5.0.1: - resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - jsonparse@1.3.1: resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} engines: {'0': node >= 0.2.0} - jsprim@1.4.2: - resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} - engines: {node: '>=0.6.0'} - katex@0.16.10: resolution: {integrity: sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==} hasBin: true @@ -1920,18 +1780,6 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - - left-pad@1.3.0: - resolution: {integrity: sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==} - deprecated: use String.prototype.padStart() - - levn@0.3.0: - resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} - engines: {node: '>= 0.8.0'} - levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1975,9 +1823,6 @@ packages: lodash.snakecase@4.1.1: resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} - lodash.sortby@4.7.0: - resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} - lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} @@ -1987,13 +1832,13 @@ packages: lodash.upperfirst@4.3.1: resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - log-symbols@6.0.0: resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} engines: {node: '>=18'} + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + loupe@2.3.7: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} @@ -2032,22 +1877,27 @@ packages: mathjax-full@3.2.2: resolution: {integrity: sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w==} - mathjax-node@2.1.1: - resolution: {integrity: sha512-i29tvqD8yHPB2WhrGV5rvliYnKwTT8a/TO8SCnuYtatpSHxLGy3aF7lDTVLD6B1bfuVMTFB6McZu2TBxk0XGeg==} - engines: {node: '>=6.0.0'} - - mathjax@2.7.9: - resolution: {integrity: sha512-NOGEDTIM9+MrsqnjPEjVGNx4q0GQxqm61yQwSK+/5S59i26wId5IC5gNu9/bu8+CCVl5p9G2IHcAl/wJa+5+BQ==} - mathjax@3.2.2: resolution: {integrity: sha512-Bt+SSVU8eBG27zChVewOicYs7Xsdt40qm4+UpHyX7k0/O9NliPc+x77k1/FEsPsjKPZGJvtRZM1vO+geW0OhGw==} mdast-util-from-markdown@2.0.0: resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} + mdast-util-math@3.0.0: + resolution: {integrity: sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==} + + mdast-util-mdx-expression@2.0.0: + resolution: {integrity: sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + mdast-util-to-hast@13.1.0: resolution: {integrity: sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==} + mdast-util-to-markdown@2.1.0: + resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} + mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} @@ -2077,12 +1927,27 @@ packages: micromark-core-commonmark@2.0.1: resolution: {integrity: sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==} + micromark-extension-math@3.0.0: + resolution: {integrity: sha512-iJ2Q28vBoEovLN5o3GO12CpqorQRYDPT+p4zW50tGwTfJB+iv/VnB6Ini+gqa24K97DwptMBBIvVX6Bjk49oyQ==} + + micromark-extension-mdx-expression@3.0.0: + resolution: {integrity: sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==} + + micromark-extension-mdx-jsx@3.0.0: + resolution: {integrity: sha512-uvhhss8OGuzR4/N17L1JwvmJIpPhAd8oByMawEKx6NVdBCbesjH4t+vjEp3ZXft9DwvlKSD07fCeI44/N0Vf2w==} + + micromark-extension-mdx-md@2.0.0: + resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} + micromark-factory-destination@2.0.0: resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} micromark-factory-label@2.0.0: resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} + micromark-factory-mdx-expression@2.0.1: + resolution: {integrity: sha512-F0ccWIUHRLRrYp5TC9ZYXmZo+p2AM13ggbsW4T0b5CRKP8KHVRB8t4pwtBgTxtjRmwrK0Irwm7vs2JOZabHZfg==} + micromark-factory-space@2.0.0: resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} @@ -2113,6 +1978,9 @@ packages: micromark-util-encode@2.0.0: resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + micromark-util-events-to-acorn@2.0.2: + resolution: {integrity: sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==} + micromark-util-html-tag-name@2.0.0: resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} @@ -2167,17 +2035,13 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@7.1.0: - resolution: {integrity: sha512-oGZRv2OT1lO2UF1zUcwdTb3wqUwI0kBGTgt/T7OdSj6M6N5m3o5uPf0AIW6lVxGGoiWUR7e2AwTE+xiwK8WQig==} + minipass@7.1.1: + resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==} engines: {node: '>=16 || 14 >=14.17'} mj-context-menu@0.6.1: resolution: {integrity: sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA==} - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - mlly@1.7.0: resolution: {integrity: sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==} @@ -2185,14 +2049,6 @@ packages: resolution: {integrity: sha512-2dF2R6YMSZbpip1V1WHKGLNjr/k48uQClqMVb5H3MOvwc9qhYis3/IWbj02qIg/Y8MDXKFF4c5v0rxx2o6xTZw==} engines: {node: '>=12.0.0'} - mri@1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} - - mrmime@2.0.0: - resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} - engines: {node: '>=10'} - ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -2227,11 +2083,8 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - nwsapi@2.2.9: - resolution: {integrity: sha512-2f3F0SEEer8bBu0dsNCFF50N0cTThV1nWFYcEYFZttdW0lDAoybv9cQoK7X7/68Z89S7FoRrVjP1LPX4XRf9vg==} - - oauth-sign@0.9.0: - resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} + nwsapi@2.2.10: + resolution: {integrity: sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==} once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -2244,10 +2097,6 @@ packages: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} - optionator@0.8.3: - resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} - engines: {node: '>= 0.8.0'} - optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -2284,9 +2133,6 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} - parse5@4.0.0: - resolution: {integrity: sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==} - parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} @@ -2313,9 +2159,9 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@1.10.2: - resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} - engines: {node: '>=16 || 14 >=14.17'} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} @@ -2327,14 +2173,11 @@ packages: pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - performance-now@2.1.0: - resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} - periscopic@3.1.0: resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} - picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -2344,16 +2187,16 @@ packages: resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} engines: {node: '>=14.16'} - pkg-types@1.1.0: - resolution: {integrity: sha512-/RpmvKdxKf8uILTtoOhAgf30wYbP2Qw+L9p3Rvshx1JZVX+XQNZQFjlbmGHEGIm4CkVPlSn+NXmIM8+9oWQaSA==} + pkg-types@1.1.1: + resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==} - playwright-core@1.43.1: - resolution: {integrity: sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==} + playwright-core@1.44.0: + resolution: {integrity: sha512-ZTbkNpFfYcGWohvTTl+xewITm7EOuqIqex0c7dNZ+aXsbrLj0qI8XlGKfPpipjm0Wny/4Lt4CJsWJk1stVS5qQ==} engines: {node: '>=16'} hasBin: true - playwright@1.43.1: - resolution: {integrity: sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==} + playwright@1.44.0: + resolution: {integrity: sha512-F9b3GUCLQ3Nffrfb6dunPOkE5Mh68tR7zN32L4jCk4FjQamgesGay7/dAAe1WaMEGV04DkdJfcJzjoCKygUaRQ==} engines: {node: '>=16'} hasBin: true @@ -2361,17 +2204,10 @@ packages: resolution: {integrity: sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==} engines: {node: '>=12'} - pn@1.1.0: - resolution: {integrity: sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==} - postcss@8.4.38: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} - prelude-ls@1.1.2: - resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} - engines: {node: '>= 0.8.0'} - prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -2407,10 +2243,6 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - qs@6.5.3: - resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} - engines: {node: '>=0.6'} - querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} @@ -2432,6 +2264,9 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + rehype-format@5.0.0: resolution: {integrity: sha512-kM4II8krCHmUhxrlvzFSptvaWh280Fr7UGNJU5DCMuvmAwGCNmGfi9CvFAQK6JDjsNoRMWQStglK3zKJH685Wg==} @@ -2453,24 +2288,6 @@ packages: remark-rehype@11.1.0: resolution: {integrity: sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==} - request-promise-core@1.1.4: - resolution: {integrity: sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==} - engines: {node: '>=0.10.0'} - peerDependencies: - request: ^2.34 - - request-promise-native@1.0.9: - resolution: {integrity: sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==} - engines: {node: '>=0.12.0'} - deprecated: request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142 - peerDependencies: - request: ^2.34 - - request@2.88.2: - resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} - engines: {node: '>= 6'} - deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 - require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -2504,17 +2321,9 @@ packages: rfdc@1.3.1: resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} - rimraf@2.7.1: - resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} - hasBin: true - - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - - rimraf@5.0.5: - resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==} - engines: {node: '>=14'} + rimraf@5.0.7: + resolution: {integrity: sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==} + engines: {node: '>=14.18'} hasBin: true rollup@4.17.2: @@ -2528,22 +2337,9 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - sade@1.8.1: - resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} - engines: {node: '>=6'} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - sander@0.5.1: - resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} - - sax@1.3.0: - resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} - saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} @@ -2553,9 +2349,6 @@ packages: engines: {node: '>=10'} hasBin: true - set-cookie-parser@2.6.0: - resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -2574,18 +2367,10 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - sirv@2.0.4: - resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} - engines: {node: '>= 10'} - slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - sorcery@0.11.0: - resolution: {integrity: sha512-J69LQ22xrQB1cIFJhPfgtLuI6BpWRiWu1Y3vSsIwK/eAScqJxd/+CJlUuHQRdX2C9NGFamq+KqNywGgaThwfHw==} - hasBin: true - source-map-js@1.2.0: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} @@ -2594,10 +2379,6 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - source-map@0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} - space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} @@ -2609,11 +2390,6 @@ packages: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} - sshpk@1.18.0: - resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} - engines: {node: '>=0.10.0'} - hasBin: true - stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -2624,10 +2400,6 @@ packages: resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} engines: {node: '>=18'} - stealthy-require@1.1.1: - resolution: {integrity: sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==} - engines: {node: '>=0.10.0'} - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -2670,18 +2442,12 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - svelte-hmr@0.16.0: - resolution: {integrity: sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==} - engines: {node: ^12.20 || ^14.13.1 || >= 16} - peerDependencies: - svelte: ^3.19.0 || ^4.0.0 - - svelte@4.2.15: - resolution: {integrity: sha512-j9KJSccHgLeRERPlhMKrCXpk2TqL2m5Z+k+OBTQhZOhIdCCd3WfqV+ylPWeipEwq17P/ekiSFWwrVQv93i3bsg==} + svelte@4.2.17: + resolution: {integrity: sha512-N7m1YnoXtRf5wya5Gyx3TWuTddI4nAyayyIWFojiWV5IayDYNV5i2mRp/7qNGol4DtxEYxljmrbgp1HM6hUbmQ==} engines: {node: '>=16'} - svgo@3.2.0: - resolution: {integrity: sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==} + svgo@3.3.2: + resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==} engines: {node: '>=14.0.0'} hasBin: true @@ -2702,9 +2468,6 @@ packages: through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - tiny-glob@0.2.9: - resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} - tinybench@2.8.0: resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==} @@ -2724,21 +2487,10 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - totalist@3.0.1: - resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} - engines: {node: '>=6'} - - tough-cookie@2.5.0: - resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} - engines: {node: '>=0.8'} - tough-cookie@4.1.4: resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} engines: {node: '>=6'} - tr46@1.0.1: - resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} - tr46@5.0.0: resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==} engines: {node: '>=18'} @@ -2772,8 +2524,8 @@ packages: tsafe@1.6.6: resolution: {integrity: sha512-gzkapsdbMNwBnTIjgO758GujLCj031IgHK/PKr2mrmkCSJMhSOR5FeOuSxKLMUoYc0vAA4RGEYYbjt/v6afD3g==} - tsc-alias@1.8.8: - resolution: {integrity: sha512-OYUOd2wl0H858NvABWr/BoSKNERw3N9GTi3rHPK8Iv4O1UyUXIrTTOAZNHsjlVpXFOhpJBVARI1s+rzwLivN3Q==} + tsc-alias@1.8.10: + resolution: {integrity: sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==} hasBin: true tsconfck@3.0.3: @@ -2786,16 +2538,6 @@ packages: typescript: optional: true - tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} - - tweetnacl@0.14.5: - resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} - - type-check@0.3.2: - resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} - engines: {node: '>= 0.8.0'} - type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -2808,11 +2550,10 @@ packages: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} - typescript-eslint@7.8.0: - resolution: {integrity: sha512-sheFG+/D8N/L7gC3WT0Q8sB97Nm573Yfr+vZFzl/4nBdYcmviBPtwGSX9TJ7wpVg28ocerKVOt+k2eGmHzcgVA==} - engines: {node: ^18.18.0 || >=20.0.0} + typescript-eslint@8.0.0-alpha.13: + resolution: {integrity: sha512-DMFKGlZTYPGrjejz1G8Cp0LuvxlelQqy1BY/T95yNVK13aVYTnDrAZ5ytW9a79OzserqBDoJnXs1AFaUqJoNEg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: @@ -2842,9 +2583,15 @@ packages: unist-util-is@6.0.0: resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + unist-util-position-from-estree@2.0.0: + resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} + unist-util-position@5.0.0: resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + unist-util-stringify-position@4.0.0: resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} @@ -2864,11 +2611,6 @@ packages: url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} - uuid@3.4.0: - resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} - deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. - hasBin: true - uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true @@ -2876,10 +2618,6 @@ packages: v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - verror@1.10.0: - resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} - engines: {'0': node >=0.6.0} - vfile-location@5.0.2: resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} @@ -2930,14 +2668,6 @@ packages: terser: optional: true - vitefu@0.2.5: - resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} - peerDependencies: - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 - peerDependenciesMeta: - vite: - optional: true - vitest@1.6.0: resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -2969,10 +2699,6 @@ packages: vscode-textmate@9.0.0: resolution: {integrity: sha512-Cl65diFGxz7gpwbav10HqiY/eVYTO1sjQpmRmV991Bj7wAoOAjGQ97PpQcXorDE2Uc4hnGWLY17xme+5t6MlSg==} - w3c-hr-time@1.0.2: - resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} - deprecated: Use your platform's native performance.now() and performance.timeOrigin. - w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} @@ -2984,23 +2710,14 @@ packages: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} - webidl-conversions@4.0.2: - resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} - webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} - whatwg-encoding@1.0.5: - resolution: {integrity: sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==} - whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} - whatwg-mimetype@2.3.0: - resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==} - whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} @@ -3009,12 +2726,6 @@ packages: resolution: {integrity: sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==} engines: {node: '>=18'} - whatwg-url@6.5.0: - resolution: {integrity: sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==} - - whatwg-url@7.1.0: - resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} - which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -3043,17 +2754,6 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@5.2.3: - resolution: {integrity: sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - ws@8.17.0: resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} engines: {node: '>=10.0.0'} @@ -3066,9 +2766,6 @@ packages: utf-8-validate: optional: true - xml-name-validator@3.0.0: - resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==} - xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} @@ -3080,6 +2777,9 @@ packages: resolution: {integrity: sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw==} engines: {node: '>=0.1'} + xregexp@5.1.1: + resolution: {integrity: sha512-fKXeVorD+CzWvFs7VBuKTYIW63YD1e1osxwQ8caZ6o1jg6pDAbABDG54LCIq0j5cy7PjRvGIq6sef9DYPXpncg==} + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -3122,7 +2822,7 @@ snapshots: '@babel/code-frame@7.24.2': dependencies: '@babel/highlight': 7.24.5 - picocolors: 1.0.0 + picocolors: 1.0.1 '@babel/helper-string-parser@7.24.1': {} @@ -3133,12 +2833,17 @@ snapshots: '@babel/helper-validator-identifier': 7.24.5 chalk: 2.4.2 js-tokens: 4.0.0 - picocolors: 1.0.0 + picocolors: 1.0.1 '@babel/parser@7.24.5': dependencies: '@babel/types': 7.24.5 + '@babel/runtime-corejs3@7.24.5': + dependencies: + core-js-pure: 3.37.1 + regenerator-runtime: 0.14.1 + '@babel/types@7.24.5': dependencies: '@babel/helper-string-parser': 7.24.1 @@ -3147,11 +2852,11 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} - '@commitlint/cli@19.3.0(@types/node@20.12.8)(typescript@5.4.5)': + '@commitlint/cli@19.3.0(@types/node@20.12.12)(typescript@5.4.5)': dependencies: '@commitlint/format': 19.3.0 '@commitlint/lint': 19.2.2 - '@commitlint/load': 19.2.0(@types/node@20.12.8)(typescript@5.4.5) + '@commitlint/load': 19.2.0(@types/node@20.12.12)(typescript@5.4.5) '@commitlint/read': 19.2.1 '@commitlint/types': 19.0.3 execa: 8.0.1 @@ -3198,7 +2903,7 @@ snapshots: '@commitlint/rules': 19.0.3 '@commitlint/types': 19.0.3 - '@commitlint/load@19.2.0(@types/node@20.12.8)(typescript@5.4.5)': + '@commitlint/load@19.2.0(@types/node@20.12.12)(typescript@5.4.5)': dependencies: '@commitlint/config-validator': 19.0.3 '@commitlint/execute-rule': 19.0.0 @@ -3206,7 +2911,7 @@ snapshots: '@commitlint/types': 19.0.3 chalk: 5.3.0 cosmiconfig: 9.0.0(typescript@5.4.5) - cosmiconfig-typescript-loader: 5.0.0(@types/node@20.12.8)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5) + cosmiconfig-typescript-loader: 5.0.0(@types/node@20.12.12)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -3331,19 +3036,19 @@ snapshots: '@esbuild/win32-x64@0.20.2': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@9.3.0)': dependencies: - eslint: 8.57.0 + eslint: 9.3.0 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.10.0': {} - '@eslint/eslintrc@2.1.4': + '@eslint/eslintrc@3.1.0': dependencies: ajv: 6.12.6 debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 + espree: 10.0.1 + globals: 14.0.0 ignore: 5.3.1 import-fresh: 3.3.0 js-yaml: 4.1.0 @@ -3352,9 +3057,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@8.57.0': {} + '@eslint/js@9.3.0': {} - '@humanwhocodes/config-array@0.11.14': + '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 debug: 4.3.4 @@ -3366,6 +3071,8 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} + '@humanwhocodes/retry@0.3.0': {} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -3427,11 +3134,9 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@playwright/test@1.43.1': + '@playwright/test@1.44.0': dependencies: - playwright: 1.43.1 - - '@polka/url@1.0.0-next.25': {} + playwright: 1.44.0 '@rollup/rollup-android-arm-eabi@4.17.2': optional: true @@ -3483,47 +3188,6 @@ snapshots: '@sinclair/typebox@0.27.8': {} - '@sveltejs/kit@2.5.7(@sveltejs/vite-plugin-svelte@3.1.0(svelte@4.2.15)(vite@5.2.11(@types/node@20.12.8)))(svelte@4.2.15)(vite@5.2.11(@types/node@20.12.8))': - dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.0(svelte@4.2.15)(vite@5.2.11(@types/node@20.12.8)) - '@types/cookie': 0.6.0 - cookie: 0.6.0 - devalue: 5.0.0 - esm-env: 1.0.0 - import-meta-resolve: 4.1.0 - kleur: 4.1.5 - magic-string: 0.30.10 - mrmime: 2.0.0 - sade: 1.8.1 - set-cookie-parser: 2.6.0 - sirv: 2.0.4 - svelte: 4.2.15 - tiny-glob: 0.2.9 - vite: 5.2.11(@types/node@20.12.8) - - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.0(svelte@4.2.15)(vite@5.2.11(@types/node@20.12.8)))(svelte@4.2.15)(vite@5.2.11(@types/node@20.12.8))': - dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.0(svelte@4.2.15)(vite@5.2.11(@types/node@20.12.8)) - debug: 4.3.4 - svelte: 4.2.15 - vite: 5.2.11(@types/node@20.12.8) - transitivePeerDependencies: - - supports-color - - '@sveltejs/vite-plugin-svelte@3.1.0(svelte@4.2.15)(vite@5.2.11(@types/node@20.12.8))': - dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.0(svelte@4.2.15)(vite@5.2.11(@types/node@20.12.8)))(svelte@4.2.15)(vite@5.2.11(@types/node@20.12.8)) - debug: 4.3.4 - deepmerge: 4.3.1 - kleur: 4.1.5 - magic-string: 0.30.10 - svelte: 4.2.15 - svelte-hmr: 0.16.0(svelte@4.2.15) - vite: 5.2.11(@types/node@20.12.8) - vitefu: 0.2.5(vite@5.2.11(@types/node@20.12.8)) - transitivePeerDependencies: - - supports-color - '@trysound/sax@0.2.0': {} '@tsconfig/node10@1.0.11': {} @@ -3534,21 +3198,27 @@ snapshots: '@tsconfig/node16@1.0.4': {} + '@types/acorn@4.0.6': + dependencies: + '@types/estree': 1.0.5 + '@types/clean-css@4.2.11': dependencies: - '@types/node': 20.12.8 + '@types/node': 20.12.12 source-map: 0.6.1 '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 20.12.8 - - '@types/cookie@0.6.0': {} + '@types/node': 20.12.12 '@types/debug@4.1.12': dependencies: '@types/ms': 0.7.34 + '@types/estree-jsx@1.0.5': + dependencies: + '@types/estree': 1.0.5 + '@types/estree@1.0.5': {} '@types/hast@3.0.4': @@ -3557,12 +3227,6 @@ snapshots: '@types/html-escaper@3.0.2': {} - '@types/jsdom@21.1.6': - dependencies: - '@types/node': 20.12.8 - '@types/tough-cookie': 4.0.5 - parse5: 7.1.2 - '@types/json-schema@7.0.15': {} '@types/katex@0.16.7': {} @@ -3574,13 +3238,9 @@ snapshots: '@types/linkify-it': 5.0.0 '@types/mdurl': 2.0.0 - '@types/mathjax-node@2.1.0': - dependencies: - '@types/mathjax': 0.0.40 - '@types/mathjax@0.0.40': {} - '@types/mdast@4.0.3': + '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.2 @@ -3588,34 +3248,32 @@ snapshots: '@types/mock-fs@4.13.4': dependencies: - '@types/node': 20.12.8 + '@types/node': 20.12.12 '@types/ms@0.7.34': {} - '@types/node@20.12.8': + '@types/node@20.12.12': dependencies: undici-types: 5.26.5 - '@types/prismjs@1.26.3': {} + '@types/prismjs@1.26.4': {} '@types/semver@7.5.8': {} - '@types/tough-cookie@4.0.5': {} - '@types/unist@3.0.2': {} '@types/uuid@9.0.8': {} - '@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@8.0.0-alpha.13(@typescript-eslint/parser@8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5))(eslint@9.3.0)(typescript@5.4.5)': dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/type-utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.8.0 + '@typescript-eslint/parser': 8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5) + '@typescript-eslint/scope-manager': 8.0.0-alpha.13 + '@typescript-eslint/type-utils': 8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5) + '@typescript-eslint/utils': 8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 8.0.0-alpha.13 debug: 4.3.4 - eslint: 8.57.0 + eslint: 9.3.0 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 @@ -3626,42 +3284,64 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/parser@8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5)': dependencies: - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.8.0 + '@typescript-eslint/scope-manager': 8.0.0-alpha.13 + '@typescript-eslint/types': 8.0.0-alpha.13 + '@typescript-eslint/typescript-estree': 8.0.0-alpha.13(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 8.0.0-alpha.13 debug: 4.3.4 - eslint: 8.57.0 + eslint: 9.3.0 optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@7.8.0': + '@typescript-eslint/scope-manager@7.9.0': dependencies: - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/visitor-keys': 7.8.0 + '@typescript-eslint/types': 7.9.0 + '@typescript-eslint/visitor-keys': 7.9.0 - '@typescript-eslint/type-utils@7.8.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/scope-manager@8.0.0-alpha.13': dependencies: - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/types': 8.0.0-alpha.13 + '@typescript-eslint/visitor-keys': 8.0.0-alpha.13 + + '@typescript-eslint/type-utils@8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5)': + dependencies: + '@typescript-eslint/typescript-estree': 8.0.0-alpha.13(typescript@5.4.5) + '@typescript-eslint/utils': 8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5) debug: 4.3.4 - eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.4.5) optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: + - eslint - supports-color - '@typescript-eslint/types@7.8.0': {} + '@typescript-eslint/types@7.9.0': {} + + '@typescript-eslint/types@8.0.0-alpha.13': {} + + '@typescript-eslint/typescript-estree@7.9.0(typescript@5.4.5)': + dependencies: + '@typescript-eslint/types': 7.9.0 + '@typescript-eslint/visitor-keys': 7.9.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.4 + semver: 7.6.2 + ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color - '@typescript-eslint/typescript-estree@7.8.0(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@8.0.0-alpha.13(typescript@5.4.5)': dependencies: - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/visitor-keys': 7.8.0 + '@typescript-eslint/types': 8.0.0-alpha.13 + '@typescript-eslint/visitor-keys': 8.0.0-alpha.13 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -3673,28 +3353,44 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.8.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/utils@7.9.0(eslint@9.3.0)(typescript@5.4.5)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.3.0) + '@typescript-eslint/scope-manager': 7.9.0 + '@typescript-eslint/types': 7.9.0 + '@typescript-eslint/typescript-estree': 7.9.0(typescript@5.4.5) + eslint: 9.3.0 + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/utils@8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.3.0) '@types/json-schema': 7.0.15 '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - eslint: 8.57.0 + '@typescript-eslint/scope-manager': 8.0.0-alpha.13 + '@typescript-eslint/types': 8.0.0-alpha.13 + '@typescript-eslint/typescript-estree': 8.0.0-alpha.13(typescript@5.4.5) + eslint: 9.3.0 semver: 7.6.2 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@7.8.0': + '@typescript-eslint/visitor-keys@7.9.0': dependencies: - '@typescript-eslint/types': 7.8.0 + '@typescript-eslint/types': 7.9.0 + eslint-visitor-keys: 3.4.3 + + '@typescript-eslint/visitor-keys@8.0.0-alpha.13': + dependencies: + '@typescript-eslint/types': 8.0.0-alpha.13 eslint-visitor-keys: 3.4.3 '@ungap/structured-clone@1.2.0': {} - '@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@20.12.8)(jsdom@24.0.0))': + '@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@20.12.12)(jsdom@24.0.0))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 0.2.3 @@ -3705,11 +3401,11 @@ snapshots: istanbul-reports: 3.1.7 magic-string: 0.30.10 magicast: 0.3.4 - picocolors: 1.0.0 + picocolors: 1.0.1 std-env: 3.7.0 strip-literal: 2.1.0 test-exclude: 6.0.0 - vitest: 1.6.0(@types/node@20.12.8)(jsdom@24.0.0) + vitest: 1.6.0(@types/node@20.12.12)(jsdom@24.0.0) transitivePeerDependencies: - supports-color @@ -3754,25 +3450,12 @@ snapshots: jsonparse: 1.3.1 through: 2.3.8 - abab@2.0.6: {} - - acorn-globals@4.3.4: - dependencies: - acorn: 6.4.2 - acorn-walk: 6.2.0 - acorn-jsx@5.3.2(acorn@8.11.3): dependencies: acorn: 8.11.3 - acorn-walk@6.2.0: {} - acorn-walk@8.3.2: {} - acorn@5.7.4: {} - - acorn@6.4.2: {} - acorn@8.11.3: {} agent-base@7.1.1: @@ -3825,27 +3508,14 @@ snapshots: dependencies: dequal: 2.0.3 - array-equal@1.0.2: {} - array-ify@1.0.0: {} array-union@2.1.0: {} - asn1@0.2.6: - dependencies: - safer-buffer: 2.1.2 - - assert-plus@1.0.0: {} - assertion-error@1.1.0: {} - async-limiter@1.0.1: {} - - asynckit@0.4.0: {} - - aws-sign2@0.7.0: {} - - aws4@1.12.0: {} + asynckit@0.4.0: + optional: true axobject-query@4.0.0: dependencies: @@ -3855,10 +3525,6 @@ snapshots: balanced-match@1.0.2: {} - bcrypt-pbkdf@1.0.2: - dependencies: - tweetnacl: 0.14.5 - binary-extensions@2.3.0: {} boolbase@1.0.0: {} @@ -3876,16 +3542,10 @@ snapshots: dependencies: fill-range: 7.0.1 - browser-process-hrtime@1.0.0: {} - - buffer-crc32@0.2.13: {} - cac@6.7.14: {} callsites@3.1.0: {} - caseless@0.12.0: {} - ccount@2.0.1: {} chai@4.4.1: @@ -3972,6 +3632,7 @@ snapshots: combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 + optional: true comma-separated-tokens@2.0.3: {} @@ -3983,9 +3644,9 @@ snapshots: commander@9.5.0: {} - commitlint@19.3.0(@types/node@20.12.8)(typescript@5.4.5): + commitlint@19.3.0(@types/node@20.12.12)(typescript@5.4.5): dependencies: - '@commitlint/cli': 19.3.0(@types/node@20.12.8)(typescript@5.4.5) + '@commitlint/cli': 19.3.0(@types/node@20.12.12)(typescript@5.4.5) '@commitlint/types': 19.0.3 transitivePeerDependencies: - '@types/node' @@ -4017,13 +3678,11 @@ snapshots: meow: 12.1.1 split2: 4.2.0 - cookie@0.6.0: {} + core-js-pure@3.37.1: {} - core-util-is@1.0.2: {} - - cosmiconfig-typescript-loader@5.0.0(@types/node@20.12.8)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5): + cosmiconfig-typescript-loader@5.0.0(@types/node@20.12.12)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5): dependencies: - '@types/node': 20.12.8 + '@types/node': 20.12.12 cosmiconfig: 9.0.0(typescript@5.4.5) jiti: 1.21.0 typescript: 5.4.5 @@ -4069,12 +3728,6 @@ snapshots: dependencies: css-tree: 2.2.1 - cssom@0.3.8: {} - - cssstyle@1.4.0: - dependencies: - cssom: 0.3.8 - cssstyle@4.0.1: dependencies: rrweb-cssom: 0.6.0 @@ -4082,18 +3735,8 @@ snapshots: dargs@8.1.0: {} - dashdash@1.14.1: - dependencies: - assert-plus: 1.0.0 - data-uri-to-buffer@4.0.1: {} - data-urls@1.1.0: - dependencies: - abab: 2.0.6 - whatwg-mimetype: 2.3.0 - whatwg-url: 7.1.0 - data-urls@5.0.0: dependencies: whatwg-mimetype: 4.0.0 @@ -4119,14 +3762,11 @@ snapshots: deepmerge-ts@5.1.0: {} - deepmerge@4.3.1: {} - - delayed-stream@1.0.0: {} + delayed-stream@1.0.0: + optional: true dequal@2.0.3: {} - devalue@5.0.0: {} - devlop@1.1.0: dependencies: dequal: 2.0.3 @@ -4139,10 +3779,6 @@ snapshots: dependencies: path-type: 4.0.0 - doctrine@3.0.0: - dependencies: - esutils: 2.0.3 - dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 @@ -4151,10 +3787,6 @@ snapshots: domelementtype@2.3.0: {} - domexception@1.0.1: - dependencies: - webidl-conversions: 4.0.2 - domhandler@5.0.3: dependencies: domelementtype: 2.3.0 @@ -4171,11 +3803,6 @@ snapshots: eastasianwidth@0.2.0: {} - ecc-jsbn@0.1.2: - dependencies: - jsbn: 0.1.1 - safer-buffer: 2.1.2 - emoji-regex@10.3.0: {} emoji-regex@8.0.0: {} @@ -4190,8 +3817,6 @@ snapshots: dependencies: is-arrayish: 0.2.1 - es6-promise@3.3.1: {} - esbuild@0.20.2: optionalDependencies: '@esbuild/aix-ppc64': 0.20.2 @@ -4226,22 +3851,13 @@ snapshots: escape-string-regexp@5.0.0: {} - escodegen@1.14.3: + eslint-config-prettier@9.1.0(eslint@9.3.0): dependencies: - esprima: 4.0.1 - estraverse: 4.3.0 - esutils: 2.0.3 - optionator: 0.8.3 - optionalDependencies: - source-map: 0.6.1 + eslint: 9.3.0 - eslint-config-prettier@9.1.0(eslint@8.57.0): + eslint-plugin-playwright@1.6.1(eslint@9.3.0): dependencies: - eslint: 8.57.0 - - eslint-plugin-playwright@1.6.0(eslint@8.57.0): - dependencies: - eslint: 8.57.0 + eslint: 9.3.0 globals: 13.24.0 eslint-plugin-tsdoc@0.2.17: @@ -4249,56 +3865,54 @@ snapshots: '@microsoft/tsdoc': 0.14.2 '@microsoft/tsdoc-config': 0.16.2 - eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)(vitest@1.6.0(@types/node@20.12.8)(jsdom@24.0.0)): + eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@8.0.0-alpha.13(@typescript-eslint/parser@8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5))(eslint@9.3.0)(typescript@5.4.5))(eslint@9.3.0)(typescript@5.4.5)(vitest@1.6.0(@types/node@20.12.12)(jsdom@24.0.0)): dependencies: - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - eslint: 8.57.0 + '@typescript-eslint/utils': 7.9.0(eslint@9.3.0)(typescript@5.4.5) + eslint: 9.3.0 optionalDependencies: - '@typescript-eslint/eslint-plugin': 7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) - vitest: 1.6.0(@types/node@20.12.8)(jsdom@24.0.0) + '@typescript-eslint/eslint-plugin': 8.0.0-alpha.13(@typescript-eslint/parser@8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5))(eslint@9.3.0)(typescript@5.4.5) + vitest: 1.6.0(@types/node@20.12.12)(jsdom@24.0.0) transitivePeerDependencies: - supports-color - typescript - eslint-scope@7.2.2: + eslint-scope@8.0.1: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 eslint-visitor-keys@3.4.3: {} - eslint@8.57.0: + eslint-visitor-keys@4.0.0: {} + + eslint@9.3.0: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.3.0) '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 + '@eslint/eslintrc': 3.1.0 + '@eslint/js': 9.3.0 + '@humanwhocodes/config-array': 0.13.0 '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.3.0 '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 debug: 4.3.4 - doctrine: 3.0.0 escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 + eslint-scope: 8.0.1 + eslint-visitor-keys: 4.0.0 + espree: 10.0.1 esquery: 1.5.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 + file-entry-cache: 8.0.0 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 ignore: 5.3.1 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 - js-yaml: 4.1.0 json-stable-stringify-without-jsonify: 1.0.1 levn: 0.4.1 lodash.merge: 4.6.2 @@ -4310,17 +3924,13 @@ snapshots: transitivePeerDependencies: - supports-color - esm-env@1.0.0: {} - esm@3.2.25: {} - espree@9.6.1: + espree@10.0.1: dependencies: acorn: 8.11.3 acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 - - esprima@4.0.1: {} + eslint-visitor-keys: 4.0.0 esquery@1.5.0: dependencies: @@ -4330,10 +3940,15 @@ snapshots: dependencies: estraverse: 5.3.0 - estraverse@4.3.0: {} - estraverse@5.3.0: {} + estree-util-is-identifier-name@3.0.0: {} + + estree-util-visit@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/unist': 3.0.2 + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.5 @@ -4354,8 +3969,6 @@ snapshots: extend@3.0.2: {} - extsprintf@1.3.0: {} - fast-deep-equal@3.1.3: {} fast-glob@3.3.2: @@ -4379,9 +3992,9 @@ snapshots: node-domexception: 1.0.0 web-streams-polyfill: 3.3.3 - file-entry-cache@6.0.1: + file-entry-cache@8.0.0: dependencies: - flat-cache: 3.2.0 + flat-cache: 4.0.1 fill-range@7.0.1: dependencies: @@ -4408,11 +4021,10 @@ snapshots: path-exists: 5.0.0 unicorn-magic: 0.1.0 - flat-cache@3.2.0: + flat-cache@4.0.1: dependencies: flatted: 3.3.1 keyv: 4.5.4 - rimraf: 3.0.2 flatted@3.3.1: {} @@ -4421,14 +4033,6 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - forever-agent@0.6.1: {} - - form-data@2.3.3: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - form-data@4.0.0: dependencies: asynckit: 0.4.0 @@ -4458,10 +4062,6 @@ snapshots: get-stream@8.0.1: {} - getpass@0.1.7: - dependencies: - assert-plus: 1.0.0 - git-raw-commits@4.0.0: dependencies: dargs: 8.1.0 @@ -4476,13 +4076,13 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@10.3.12: + glob@10.3.15: dependencies: foreground-child: 3.1.1 jackspeak: 2.3.6 minimatch: 9.0.4 - minipass: 7.1.0 - path-scurry: 1.10.2 + minipass: 7.1.1 + path-scurry: 1.11.1 glob@7.2.3: dependencies: @@ -4501,7 +4101,7 @@ snapshots: dependencies: type-fest: 0.20.2 - globalyzer@0.1.0: {} + globals@14.0.0: {} globby@11.1.0: dependencies: @@ -4514,17 +4114,8 @@ snapshots: globrex@0.1.2: {} - graceful-fs@4.2.11: {} - graphemer@1.4.0: {} - har-schema@2.0.0: {} - - har-validator@5.1.5: - dependencies: - ajv: 6.12.6 - har-schema: 2.0.0 - has-flag@3.0.0: {} has-flag@4.0.0: {} @@ -4589,7 +4180,7 @@ snapshots: hast-util-is-body-ok-link: 3.0.0 hast-util-is-element: 3.0.0 - hast-util-raw@9.0.2: + hast-util-raw@9.0.3: dependencies: '@types/hast': 3.0.4 '@types/unist': 3.0.2 @@ -4611,7 +4202,7 @@ snapshots: '@types/unist': 3.0.2 ccount: 2.0.1 comma-separated-tokens: 2.0.3 - hast-util-raw: 9.0.2 + hast-util-raw: 9.0.3 hast-util-whitespace: 3.0.0 html-void-elements: 3.0.0 mdast-util-to-hast: 13.1.0 @@ -4644,10 +4235,6 @@ snapshots: highlight.js@11.9.0: {} - html-encoding-sniffer@1.0.2: - dependencies: - whatwg-encoding: 1.0.5 - html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 @@ -4671,12 +4258,6 @@ snapshots: - supports-color optional: true - http-signature@1.2.0: - dependencies: - assert-plus: 1.0.0 - jsprim: 1.4.2 - sshpk: 1.18.0 - https-proxy-agent@7.0.4: dependencies: agent-base: 7.1.1 @@ -4689,10 +4270,6 @@ snapshots: husky@9.0.11: {} - iconv-lite@0.4.24: - dependencies: - safer-buffer: 2.1.2 - iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -4730,8 +4307,6 @@ snapshots: is-extglob@2.1.1: {} - is-fullwidth-code-point@2.0.0: {} - is-fullwidth-code-point@3.0.0: {} is-glob@4.0.3: @@ -4761,16 +4336,12 @@ snapshots: dependencies: text-extensions: 2.4.0 - is-typedarray@1.0.0: {} - is-unicode-supported@1.3.0: {} is-unicode-supported@2.0.0: {} isexe@2.0.0: {} - isstream@0.1.2: {} - istanbul-lib-coverage@3.2.2: {} istanbul-lib-report@3.0.1: @@ -4810,40 +4381,6 @@ snapshots: dependencies: argparse: 2.0.1 - jsbn@0.1.1: {} - - jsdom@11.12.0: - dependencies: - abab: 2.0.6 - acorn: 5.7.4 - acorn-globals: 4.3.4 - array-equal: 1.0.2 - cssom: 0.3.8 - cssstyle: 1.4.0 - data-urls: 1.1.0 - domexception: 1.0.1 - escodegen: 1.14.3 - html-encoding-sniffer: 1.0.2 - left-pad: 1.3.0 - nwsapi: 2.2.9 - parse5: 4.0.0 - pn: 1.1.0 - request: 2.88.2 - request-promise-native: 1.0.9(request@2.88.2) - sax: 1.3.0 - symbol-tree: 3.2.4 - tough-cookie: 2.5.0 - w3c-hr-time: 1.0.2 - webidl-conversions: 4.0.2 - whatwg-encoding: 1.0.5 - whatwg-mimetype: 2.3.0 - whatwg-url: 6.5.0 - ws: 5.2.3 - xml-name-validator: 3.0.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - jsdom@24.0.0: dependencies: cssstyle: 4.0.1 @@ -4854,7 +4391,7 @@ snapshots: http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.4 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.9 + nwsapi: 2.2.10 parse5: 7.1.2 rrweb-cssom: 0.6.0 saxes: 6.0.0 @@ -4881,21 +4418,10 @@ snapshots: json-schema-traverse@1.0.0: {} - json-schema@0.4.0: {} - json-stable-stringify-without-jsonify@1.0.1: {} - json-stringify-safe@5.0.1: {} - jsonparse@1.3.1: {} - jsprim@1.4.2: - dependencies: - assert-plus: 1.0.0 - extsprintf: 1.3.0 - json-schema: 0.4.0 - verror: 1.10.0 - katex@0.16.10: dependencies: commander: 8.3.0 @@ -4904,15 +4430,6 @@ snapshots: dependencies: json-buffer: 3.0.1 - kleur@4.1.5: {} - - left-pad@1.3.0: {} - - levn@0.3.0: - dependencies: - prelude-ls: 1.1.2 - type-check: 0.3.2 - levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -4927,7 +4444,7 @@ snapshots: local-pkg@0.5.0: dependencies: mlly: 1.7.0 - pkg-types: 1.1.0 + pkg-types: 1.1.1 locate-character@3.0.0: {} @@ -4951,21 +4468,19 @@ snapshots: lodash.snakecase@4.1.1: {} - lodash.sortby@4.7.0: {} - lodash.startcase@4.4.0: {} lodash.uniq@4.5.0: {} lodash.upperfirst@4.3.1: {} - lodash@4.17.21: {} - log-symbols@6.0.0: dependencies: chalk: 5.3.0 is-unicode-supported: 1.3.0 + longest-streak@3.1.0: {} + loupe@2.3.7: dependencies: get-func-name: 2.0.2 @@ -5010,22 +4525,11 @@ snapshots: mj-context-menu: 0.6.1 speech-rule-engine: 4.0.7 - mathjax-node@2.1.1: - dependencies: - is-fullwidth-code-point: 2.0.0 - jsdom: 11.12.0 - mathjax: 2.7.9 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - mathjax@2.7.9: {} - mathjax@3.2.2: {} mdast-util-from-markdown@2.0.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 '@types/unist': 3.0.2 decode-named-character-reference: 1.0.2 devlop: 1.1.0 @@ -5040,10 +4544,38 @@ snapshots: transitivePeerDependencies: - supports-color + mdast-util-math@3.0.0: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + longest-streak: 3.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + unist-util-remove-position: 5.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-expression@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + + mdast-util-phrasing@4.1.0: + dependencies: + '@types/mdast': 4.0.4 + unist-util-is: 6.0.0 + mdast-util-to-hast@13.1.0: dependencies: '@types/hast': 3.0.4 - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 '@ungap/structured-clone': 1.2.0 devlop: 1.1.0 micromark-util-sanitize-uri: 2.0.0 @@ -5052,9 +4584,20 @@ snapshots: unist-util-visit: 5.0.0 vfile: 6.0.1 + mdast-util-to-markdown@2.1.0: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.2 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-decode-string: 2.0.0 + unist-util-visit: 5.0.0 + zwitch: 2.0.4 + mdast-util-to-string@4.0.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 mdn-data@2.0.28: {} @@ -5089,6 +4632,44 @@ snapshots: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 + micromark-extension-math@3.0.0: + dependencies: + '@types/katex': 0.16.7 + devlop: 1.1.0 + katex: 0.16.10 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-extension-mdx-expression@3.0.0: + dependencies: + '@types/estree': 1.0.5 + devlop: 1.1.0 + micromark-factory-mdx-expression: 2.0.1 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-extension-mdx-jsx@3.0.0: + dependencies: + '@types/acorn': 4.0.6 + '@types/estree': 1.0.5 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + micromark-factory-mdx-expression: 2.0.1 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + vfile-message: 4.0.2 + + micromark-extension-mdx-md@2.0.0: + dependencies: + micromark-util-types: 2.0.0 + micromark-factory-destination@2.0.0: dependencies: micromark-util-character: 2.1.0 @@ -5102,6 +4683,17 @@ snapshots: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 + micromark-factory-mdx-expression@2.0.1: + dependencies: + '@types/estree': 1.0.5 + devlop: 1.1.0 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.2 + micromark-factory-space@2.0.0: dependencies: micromark-util-character: 2.1.0 @@ -5154,6 +4746,17 @@ snapshots: micromark-util-encode@2.0.0: {} + micromark-util-events-to-acorn@2.0.2: + dependencies: + '@types/acorn': 4.0.6 + '@types/estree': 1.0.5 + '@types/unist': 3.0.2 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + vfile-message: 4.0.2 + micromark-util-html-tag-name@2.0.0: {} micromark-util-normalize-identifier@2.0.0: @@ -5208,11 +4811,13 @@ snapshots: braces: 3.0.2 picomatch: 2.3.1 - mime-db@1.52.0: {} + mime-db@1.52.0: + optional: true mime-types@2.1.35: dependencies: mime-db: 1.52.0 + optional: true mimic-fn@2.1.0: {} @@ -5228,27 +4833,19 @@ snapshots: minimist@1.2.8: {} - minipass@7.1.0: {} + minipass@7.1.1: {} mj-context-menu@0.6.1: {} - mkdirp@0.5.6: - dependencies: - minimist: 1.2.8 - mlly@1.7.0: dependencies: acorn: 8.11.3 pathe: 1.1.2 - pkg-types: 1.1.0 + pkg-types: 1.1.1 ufo: 1.5.3 mock-fs@5.2.0: {} - mri@1.2.0: {} - - mrmime@2.0.0: {} - ms@2.1.2: {} mylas@2.1.13: {} @@ -5275,9 +4872,8 @@ snapshots: dependencies: boolbase: 1.0.0 - nwsapi@2.2.9: {} - - oauth-sign@0.9.0: {} + nwsapi@2.2.10: + optional: true once@1.4.0: dependencies: @@ -5291,15 +4887,6 @@ snapshots: dependencies: mimic-fn: 4.0.0 - optionator@0.8.3: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.3.0 - prelude-ls: 1.1.2 - type-check: 0.3.2 - word-wrap: 1.2.5 - optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -5352,8 +4939,6 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - parse5@4.0.0: {} - parse5@7.1.2: dependencies: entities: 4.5.0 @@ -5370,10 +4955,10 @@ snapshots: path-parse@1.0.7: {} - path-scurry@1.10.2: + path-scurry@1.11.1: dependencies: lru-cache: 10.2.2 - minipass: 7.1.0 + minipass: 7.1.1 path-type@4.0.0: {} @@ -5381,15 +4966,13 @@ snapshots: pathval@1.1.1: {} - performance-now@2.1.0: {} - periscopic@3.1.0: dependencies: '@types/estree': 1.0.5 estree-walker: 3.0.3 is-reference: 3.0.2 - picocolors@1.0.0: {} + picocolors@1.0.1: {} picomatch@2.3.1: {} @@ -5397,17 +4980,17 @@ snapshots: dependencies: find-up: 6.3.0 - pkg-types@1.1.0: + pkg-types@1.1.1: dependencies: confbox: 0.1.7 mlly: 1.7.0 pathe: 1.1.2 - playwright-core@1.43.1: {} + playwright-core@1.44.0: {} - playwright@1.43.1: + playwright@1.44.0: dependencies: - playwright-core: 1.43.1 + playwright-core: 1.44.0 optionalDependencies: fsevents: 2.3.2 @@ -5415,16 +4998,12 @@ snapshots: dependencies: queue-lit: 1.5.2 - pn@1.1.0: {} - postcss@8.4.38: dependencies: nanoid: 3.3.7 - picocolors: 1.0.0 + picocolors: 1.0.1 source-map-js: 1.2.0 - prelude-ls@1.1.2: {} - prelude-ls@1.2.1: {} prettier@3.2.5: {} @@ -5441,14 +5020,13 @@ snapshots: property-information@6.5.0: {} - psl@1.9.0: {} + psl@1.9.0: + optional: true punycode.js@2.3.1: {} punycode@2.3.1: {} - qs@6.5.3: {} - querystringify@2.2.0: optional: true @@ -5464,6 +5042,8 @@ snapshots: dependencies: picomatch: 2.3.1 + regenerator-runtime@0.14.1: {} + rehype-format@5.0.0: dependencies: '@types/hast': 3.0.4 @@ -5504,7 +5084,7 @@ snapshots: remark-parse@11.0.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 mdast-util-from-markdown: 2.0.0 micromark-util-types: 2.0.0 unified: 11.0.4 @@ -5514,46 +5094,11 @@ snapshots: remark-rehype@11.1.0: dependencies: '@types/hast': 3.0.4 - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 mdast-util-to-hast: 13.1.0 unified: 11.0.4 vfile: 6.0.1 - request-promise-core@1.1.4(request@2.88.2): - dependencies: - lodash: 4.17.21 - request: 2.88.2 - - request-promise-native@1.0.9(request@2.88.2): - dependencies: - request: 2.88.2 - request-promise-core: 1.1.4(request@2.88.2) - stealthy-require: 1.1.1 - tough-cookie: 2.5.0 - - request@2.88.2: - dependencies: - aws-sign2: 0.7.0 - aws4: 1.12.0 - caseless: 0.12.0 - combined-stream: 1.0.8 - extend: 3.0.2 - forever-agent: 0.6.1 - form-data: 2.3.3 - har-validator: 5.1.5 - http-signature: 1.2.0 - is-typedarray: 1.0.0 - isstream: 0.1.2 - json-stringify-safe: 5.0.1 - mime-types: 2.1.35 - oauth-sign: 0.9.0 - performance-now: 2.1.0 - qs: 6.5.3 - safe-buffer: 5.2.1 - tough-cookie: 2.5.0 - tunnel-agent: 0.6.0 - uuid: 3.4.0 - require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -5579,17 +5124,9 @@ snapshots: rfdc@1.3.1: {} - rimraf@2.7.1: - dependencies: - glob: 7.2.3 - - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - - rimraf@5.0.5: + rimraf@5.0.7: dependencies: - glob: 10.3.12 + glob: 10.3.15 rollup@4.17.2: dependencies: @@ -5620,22 +5157,8 @@ snapshots: dependencies: queue-microtask: 1.2.3 - sade@1.8.1: - dependencies: - mri: 1.2.0 - - safe-buffer@5.2.1: {} - - safer-buffer@2.1.2: {} - - sander@0.5.1: - dependencies: - es6-promise: 3.3.1 - graceful-fs: 4.2.11 - mkdirp: 0.5.6 - rimraf: 2.7.1 - - sax@1.3.0: {} + safer-buffer@2.1.2: + optional: true saxes@6.0.0: dependencies: @@ -5644,8 +5167,6 @@ snapshots: semver@7.6.2: {} - set-cookie-parser@2.6.0: {} - shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -5658,27 +5179,12 @@ snapshots: signal-exit@4.1.0: {} - sirv@2.0.4: - dependencies: - '@polka/url': 1.0.0-next.25 - mrmime: 2.0.0 - totalist: 3.0.1 - slash@3.0.0: {} - sorcery@0.11.0: - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - buffer-crc32: 0.2.13 - minimist: 1.2.8 - sander: 0.5.1 - source-map-js@1.2.0: {} source-map@0.6.1: {} - source-map@0.7.4: {} - space-separated-tokens@2.0.2: {} speech-rule-engine@4.0.7: @@ -5689,26 +5195,12 @@ snapshots: split2@4.2.0: {} - sshpk@1.18.0: - dependencies: - asn1: 0.2.6 - assert-plus: 1.0.0 - bcrypt-pbkdf: 1.0.2 - dashdash: 1.14.1 - ecc-jsbn: 0.1.2 - getpass: 0.1.7 - jsbn: 0.1.1 - safer-buffer: 2.1.2 - tweetnacl: 0.14.5 - stackback@0.0.2: {} std-env@3.7.0: {} stdin-discarder@0.2.2: {} - stealthy-require@1.1.1: {} - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -5756,11 +5248,7 @@ snapshots: dependencies: has-flag: 4.0.0 - svelte-hmr@0.16.0(svelte@4.2.15): - dependencies: - svelte: 4.2.15 - - svelte@4.2.15: + svelte@4.2.17: dependencies: '@ampproject/remapping': 2.3.0 '@jridgewell/sourcemap-codec': 1.4.15 @@ -5777,7 +5265,7 @@ snapshots: magic-string: 0.30.10 periscopic: 3.1.0 - svgo@3.2.0: + svgo@3.3.2: dependencies: '@trysound/sax': 0.2.0 commander: 7.2.0 @@ -5785,9 +5273,10 @@ snapshots: css-tree: 2.3.1 css-what: 6.1.0 csso: 5.0.5 - picocolors: 1.0.0 + picocolors: 1.0.1 - symbol-tree@3.2.4: {} + symbol-tree@3.2.4: + optional: true test-exclude@6.0.0: dependencies: @@ -5801,11 +5290,6 @@ snapshots: through@2.3.8: {} - tiny-glob@0.2.9: - dependencies: - globalyzer: 0.1.0 - globrex: 0.1.2 - tinybench@2.8.0: {} tinypool@0.8.4: {} @@ -5818,13 +5302,6 @@ snapshots: dependencies: is-number: 7.0.0 - totalist@3.0.1: {} - - tough-cookie@2.5.0: - dependencies: - psl: 1.9.0 - punycode: 2.3.1 - tough-cookie@4.1.4: dependencies: psl: 1.9.0 @@ -5833,10 +5310,6 @@ snapshots: url-parse: 1.5.10 optional: true - tr46@1.0.1: - dependencies: - punycode: 2.3.1 - tr46@5.0.0: dependencies: punycode: 2.3.1 @@ -5850,14 +5323,14 @@ snapshots: dependencies: typescript: 5.4.5 - ts-node@10.9.2(@types/node@20.12.8)(typescript@5.4.5): + ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.12.8 + '@types/node': 20.12.12 acorn: 8.11.3 acorn-walk: 8.3.2 arg: 4.1.3 @@ -5870,7 +5343,7 @@ snapshots: tsafe@1.6.6: {} - tsc-alias@1.8.8: + tsc-alias@1.8.10: dependencies: chokidar: 3.6.0 commander: 9.5.0 @@ -5883,16 +5356,6 @@ snapshots: optionalDependencies: typescript: 5.4.5 - tunnel-agent@0.6.0: - dependencies: - safe-buffer: 5.2.1 - - tweetnacl@0.14.5: {} - - type-check@0.3.2: - dependencies: - prelude-ls: 1.1.2 - type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -5901,15 +5364,15 @@ snapshots: type-fest@0.20.2: {} - typescript-eslint@7.8.0(eslint@8.57.0)(typescript@5.4.5): + typescript-eslint@8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5): dependencies: - '@typescript-eslint/eslint-plugin': 7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - eslint: 8.57.0 + '@typescript-eslint/eslint-plugin': 8.0.0-alpha.13(@typescript-eslint/parser@8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5))(eslint@9.3.0)(typescript@5.4.5) + '@typescript-eslint/parser': 8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5) + '@typescript-eslint/utils': 8.0.0-alpha.13(eslint@9.3.0)(typescript@5.4.5) optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: + - eslint - supports-color typescript@5.4.5: {} @@ -5936,10 +5399,19 @@ snapshots: dependencies: '@types/unist': 3.0.2 + unist-util-position-from-estree@2.0.0: + dependencies: + '@types/unist': 3.0.2 + unist-util-position@5.0.0: dependencies: '@types/unist': 3.0.2 + unist-util-remove-position@5.0.0: + dependencies: + '@types/unist': 3.0.2 + unist-util-visit: 5.0.0 + unist-util-stringify-position@4.0.0: dependencies: '@types/unist': 3.0.2 @@ -5968,18 +5440,10 @@ snapshots: requires-port: 1.0.0 optional: true - uuid@3.4.0: {} - uuid@9.0.1: {} v8-compile-cache-lib@3.0.1: {} - verror@1.10.0: - dependencies: - assert-plus: 1.0.0 - core-util-is: 1.0.2 - extsprintf: 1.3.0 - vfile-location@5.0.2: dependencies: '@types/unist': 3.0.2 @@ -5996,13 +5460,13 @@ snapshots: unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 - vite-node@1.6.0(@types/node@20.12.8): + vite-node@1.6.0(@types/node@20.12.12): dependencies: cac: 6.7.14 debug: 4.3.4 pathe: 1.1.2 - picocolors: 1.0.0 - vite: 5.2.11(@types/node@20.12.8) + picocolors: 1.0.1 + vite: 5.2.11(@types/node@20.12.12) transitivePeerDependencies: - '@types/node' - less @@ -6013,31 +5477,27 @@ snapshots: - supports-color - terser - vite-tsconfig-paths@4.3.2(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.8)): + vite-tsconfig-paths@4.3.2(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.12)): dependencies: debug: 4.3.4 globrex: 0.1.2 tsconfck: 3.0.3(typescript@5.4.5) optionalDependencies: - vite: 5.2.11(@types/node@20.12.8) + vite: 5.2.11(@types/node@20.12.12) transitivePeerDependencies: - supports-color - typescript - vite@5.2.11(@types/node@20.12.8): + vite@5.2.11(@types/node@20.12.12): dependencies: esbuild: 0.20.2 postcss: 8.4.38 rollup: 4.17.2 optionalDependencies: - '@types/node': 20.12.8 + '@types/node': 20.12.12 fsevents: 2.3.3 - vitefu@0.2.5(vite@5.2.11(@types/node@20.12.8)): - optionalDependencies: - vite: 5.2.11(@types/node@20.12.8) - - vitest@1.6.0(@types/node@20.12.8)(jsdom@24.0.0): + vitest@1.6.0(@types/node@20.12.12)(jsdom@24.0.0): dependencies: '@vitest/expect': 1.6.0 '@vitest/runner': 1.6.0 @@ -6051,16 +5511,16 @@ snapshots: local-pkg: 0.5.0 magic-string: 0.30.10 pathe: 1.1.2 - picocolors: 1.0.0 + picocolors: 1.0.1 std-env: 3.7.0 strip-literal: 2.1.0 tinybench: 2.8.0 tinypool: 0.8.4 - vite: 5.2.11(@types/node@20.12.8) - vite-node: 1.6.0(@types/node@20.12.8) + vite: 5.2.11(@types/node@20.12.12) + vite-node: 1.6.0(@types/node@20.12.12) why-is-node-running: 2.2.2 optionalDependencies: - '@types/node': 20.12.8 + '@types/node': 20.12.12 jsdom: 24.0.0 transitivePeerDependencies: - less @@ -6075,10 +5535,6 @@ snapshots: vscode-textmate@9.0.0: {} - w3c-hr-time@1.0.2: - dependencies: - browser-process-hrtime: 1.0.0 - w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 @@ -6088,22 +5544,14 @@ snapshots: web-streams-polyfill@3.3.3: {} - webidl-conversions@4.0.2: {} - webidl-conversions@7.0.0: optional: true - whatwg-encoding@1.0.5: - dependencies: - iconv-lite: 0.4.24 - whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 optional: true - whatwg-mimetype@2.3.0: {} - whatwg-mimetype@4.0.0: optional: true @@ -6113,18 +5561,6 @@ snapshots: webidl-conversions: 7.0.0 optional: true - whatwg-url@6.5.0: - dependencies: - lodash.sortby: 4.7.0 - tr46: 1.0.1 - webidl-conversions: 4.0.2 - - whatwg-url@7.1.0: - dependencies: - lodash.sortby: 4.7.0 - tr46: 1.0.1 - webidl-conversions: 4.0.2 - which@2.0.2: dependencies: isexe: 2.0.0 @@ -6152,15 +5588,9 @@ snapshots: wrappy@1.0.2: {} - ws@5.2.3: - dependencies: - async-limiter: 1.0.1 - ws@8.17.0: optional: true - xml-name-validator@3.0.0: {} - xml-name-validator@5.0.0: optional: true @@ -6169,6 +5599,10 @@ snapshots: xmldom-sre@0.1.31: {} + xregexp@5.1.1: + dependencies: + '@babel/runtime-corejs3': 7.24.5 + y18n@5.0.8: {} yaml@2.4.2: {} diff --git a/screenshot.png b/screenshot.png deleted file mode 100644 index 3cd44e9a69fc06f3ef57cbea6adb527a6baadab2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40063 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 PvE^lz&Ssr9y8ZtEdAtl` diff --git a/src/README.md b/src/README.md index 2e4b37f..bc76237 100644 --- a/src/README.md +++ b/src/README.md @@ -1,13 +1,11 @@ - # Source directory -- `config/`: Default configurations -- `handlers/`: Handlers to which Sveltex delegates the rendering of the - different kinds of content it encounters -- `type-guards/`: Type guards and similar verification functions -- `types/`: Type definitions -- `utils/`: Utility functions -- `index.ts`: Entry point of the package -- `Sveltex.ts`: Definition of the `Sveltex` class, which implements Svelte's - `PreprocessorGroup` interface. - +- `config/`: Default configurations +- `handlers/`: Handlers to which Sveltex delegates the rendering of the + different kinds of content it encounters +- `type-guards/`: Type guards and similar verification functions +- `types/`: Type definitions +- `utils/`: Utility functions +- `index.ts`: Entry point of the package +- `Sveltex.ts`: Definition of the `Sveltex` class, which implements Svelte's + `PreprocessorGroup` interface. diff --git a/src/Sveltex.ts b/src/Sveltex.ts index b4df9d8..4045e06 100644 --- a/src/Sveltex.ts +++ b/src/Sveltex.ts @@ -1,4 +1,9 @@ // Types +import type { + MarkupPreprocessor, + Preprocessor, + PreprocessorGroup, +} from '$deps.js'; import type { Processed } from '$types/Sveltex.js'; import type { BackendChoices, @@ -8,13 +13,12 @@ import type { import type { AdvancedTexBackend } from '$types/handlers/AdvancedTex.js'; import type { CodeBackend, CodeConfiguration } from '$types/handlers/Code.js'; import type { MarkdownBackend } from '$types/handlers/Markdown.js'; -import type { TexBackend, TexConfiguration } from '$types/handlers/Tex.js'; -import type { Location } from '$types/utils/Ast.js'; import type { - MarkupPreprocessor, - Preprocessor, - PreprocessorGroup, -} from 'svelte/compiler'; + TexBackend, + TexConfiguration, + TexProcessOptions, +} from '$types/handlers/Tex.js'; +import type { ProcessedSnippet, Snippet } from '$types/utils/Escape.js'; // Internal dependencies import { getDefaultSveltexConfig } from '$config/defaults.js'; @@ -24,15 +28,19 @@ import { MarkdownHandler } from '$handlers/MarkdownHandler.js'; import { TexHandler } from '$handlers/TexHandler.js'; import { VerbatimHandler } from '$handlers/VerbatimHandler.js'; import { TexComponent } from '$utils/TexComponent.js'; -import { parse, pushRangeIf, walk } from '$utils/ast.js'; import { log, prettifyError } from '$utils/debug.js'; -import { escapeMustacheTags, escapeVerb, unescape } from '$utils/escape.js'; -import { missingDeps, packageManager } from '$utils/globals.js'; -import { mergeConfigs } from '$utils/merge.js'; import { diagnoseBackendChoices } from '$utils/diagnosers/backendChoices.js'; +import { detectPackageManager, missingDeps } from '$utils/env.js'; +import { + colonUuid, + escape, + unescapeColons, + unescapeSnippets, +} from '$utils/escape.js'; +import { mergeConfigs } from '$utils/merge.js'; // External dependencies -import { MagicString, sorcery } from '$deps.js'; +import { MagicString, is, typeAssert } from '$deps.js'; /** * Returns a promise that resolves to a new instance of `Sveltex`. @@ -154,8 +162,12 @@ export class Sveltex< // append CoffeeScript code, which would (presumably) throw an error. const lang = attributes['lang']?.toString().toLowerCase() ?? 'js'; - script.push(...this.texHandler.scriptLines); - script.push(...this.codeHandler.scriptLines); + if (this.texPresent[filename]) { + script.push(...this.texHandler.scriptLines); + } + if (this.codePresent[filename]) { + script.push(...this.codeHandler.scriptLines); + } if (script.length === 0) return; @@ -194,6 +206,9 @@ export class Sveltex< } as Processed; }; + private codePresent: Record = {}; + private texPresent: Record = {}; + /** * @param content - The whole Svelte file content. * @param filename - The filename of the Svelte file. (Isn't this actually a @@ -219,7 +234,7 @@ export class Sveltex< // configured for SvelTeX, return early. if ( !filename || - !this.configuration.general.extensions.some((ext) => + !this._configuration.general.extensions.some((ext) => filename.endsWith(ext), ) ) { @@ -234,227 +249,135 @@ export class Sveltex< try { // Step 1: Escape potentially tricky code (fenced code blocks, // inline code, and content inside "verbatim" environments). - const { - escapedContent: escapedVerb, - savedMatches: savedMatchesVerb, - map: mapFromEscapingVerb, - } = escapeVerb(this, content, filename); - - // Step 2: Process the saved matches. - const processSavedMatches = Array.from( - savedMatchesVerb.entries(), - ).map(async ([uuid, content]) => { - let processedContent = ''; - if (content.startsWith('`') || content.startsWith('~')) { - processedContent = await codeHandler.process(content); - } else if (content.startsWith('<')) { - processedContent = await verbatimHandler.process(content, { - filename, - }); - } else { - processedContent = await texHandler.process(content); - } - savedMatchesVerb.set(uuid, processedContent); - }); - await Promise.all(processSavedMatches); - - // Step 3: Generate an AST of the (once) escaped content of the file - // using Svelte's parser. - - /** - * AST (abstract syntax tree) of the (once) escaped markup, - * generated using Svelte's parser. - */ - const { ast: astEscapedVerb, scriptPresent: scriptPresentV4 } = - parse(escapedVerb, filename); - - // Step 4: Walk the AST and keep track of the ranges of the mustache - // tag nodes. - - /** - * Ranges (starting and ending positions in the (once) escaped - * source code) of the mustache tags (i.e., nodes of type - * `'MustacheTag'`). These are strings of the form `{...}`, which - * are used to embed JavaScript expressions in the markup, and, as - * far as the markup preprocessor is concerned, should be treated as - * plain text (since that is what the contents of the expression - * will ultimately return). - */ - const mtRanges: Location[] = []; - - walk( - astEscapedVerb, - pushRangeIf('MustacheTag', mtRanges, escapedVerb), - ); - - // Step 5: Escape the mustache tag nodes by replacing them with - // UUIDv4 strings. - - const { - escapedContent: escapedVerbAndMT, - savedMatches: savedMatchesMT, - map: mapFromEscapingMT, - } = escapeMustacheTags( - escapedVerb, - mtRanges, - filename + '_escapedVerb', + const { escapedDocument, escapedSnippets } = escape( + content, + [ + ...this.verbatimHandler.verbEnvs.keys(), + ...this.advancedTexHandler.tccNames, + ...this.advancedTexHandler.tccAliases, + ], + this.configuration.general.tex, ); - // Step 6: Merge the savedMatches maps (for convenience later on). + let headId: string | undefined = undefined; + let headSnippet: ProcessedSnippet | undefined = undefined; + let scriptPresent: boolean = false; + const prependToProcessed: string[] = []; - const savedMatches = new Map([ - ...savedMatchesVerb, - ...savedMatchesMT, - ]); + let codePresent = false; + let texPresent = false; - // Step 7: Generate an AST of the (twice) escaped content of the - // file using Svelte's parser. + // Step 2: Process the saved matches. + const processedSnippets: [string, ProcessedSnippet][] = []; + const processEscapedSnippets = escapedSnippets.map( + async ([uuid, snippet]) => { + let processedSnippet: ProcessedSnippet; + let processed = ''; + const { unescapeOptions } = snippet; + if (snippet.type === 'code') { + typeAssert(is>(snippet)); + if (!codePresent) codePresent = true; + processedSnippet = await codeHandler.process( + snippet.processable.innerContent, + snippet.processable.optionsForProcessor, + ); + } else if (snippet.type === 'verbatim') { + typeAssert(is>(snippet)); + processedSnippet = await verbatimHandler.process( + snippet.processable.innerContent, + { + filename, + ...snippet.processable.optionsForProcessor, + }, + ); + } else if (snippet.type === 'tex') { + typeAssert(is>(snippet)); + if (!texPresent) texPresent = true; + processedSnippet = await texHandler.process( + snippet.processable.innerContent, + snippet.processable + .optionsForProcessor as TexProcessOptions, + ); + } else { + typeAssert( + is>(snippet), + ); + processed = snippet.original.outerContent; + if (snippet.type === 'svelte') { + if ( + !headId && + processed.startsWith(`` tag in - // the file. - - /** - * Ranges (starting and ending positions in the escaped source code) - * of the text nodes (i.e., nodes of type `'Text'`). - */ - const textRanges: Location[] = []; - - /** - * Whether a `\n'); + prependToProcessed.push(''); } + /* eslint-enable @typescript-eslint/no-unnecessary-condition */ - /** - * Fully preprocessed content. - */ - const code = s.toString(); + const html = (await markdownHandler.process(escapedDocument)) + .processed; - /** - * Source map for the unescaping and markdown preprocessing. - */ - const mapFromUnescapingAndMarkdownProcessing = s.generateMap({ - source: filename + '_escapedVerbAndMT', - hires: 'boundary', - includeContent: true, - }); + let code = unescapeSnippets(html, processedSnippets); + code = unescapeColons(code); + if (prependToProcessed.length > 0) { + code = prependToProcessed.join('\n') + '\n' + code; + } - const chain = await sorcery.load(filename + '_final', { - content: { - [filename + '_final']: code, - [filename + '_escapedVerb']: escapedVerb, - [filename + '_escapedVerbAndMT']: escapedVerbAndMT, - [filename]: content, - }, - sourcemaps: { - [filename + '_final']: - mapFromUnescapingAndMarkdownProcessing, - [filename + '_escapedVerbAndMT']: mapFromEscapingMT, - [filename + '_escapedVerb']: mapFromEscapingVerb, - }, - }); - const map = chain?.apply() ?? { - version: 3, - file: filename, - mappings: '', - names: [], - sources: [], - sourcesContent: [], - }; - - return { code, map }; + return { code }; } catch (err) { log('error', prettifyError(err)); return; @@ -721,7 +644,7 @@ export class Sveltex< if (errors.length > 0) { const install = '\n\nPlease install the necessary dependencies by running:\n\n' + - `${packageManager} add -D ${missingDeps.join(' ')}`; + `${detectPackageManager()} add -D ${missingDeps.join(' ')}`; throw Error(`Failed to create Sveltex preprocessor.` + install, { cause: diff --git a/src/config/defaults.ts b/src/config/defaults.ts index 53a557e..d5d7994 100644 --- a/src/config/defaults.ts +++ b/src/config/defaults.ts @@ -26,10 +26,10 @@ import { isPresentAndDefined, isString, } from '$type-guards/utils.js'; -import { interpretAttributes } from '$utils/misc.js'; // External dependencies import { findCacheDirectory, homedir, join, relative, resolve } from '$deps.js'; +import { interpretAttributes } from '$utils/parseComponent.js'; /** * Get the default configuration for a TeX backend. @@ -60,7 +60,14 @@ export function getDefaultTexConfiguration( timeout: 1000, }, outputFormat: 'svg', - mathjax: {}, + mathjax: { + tex: { + inlineMath: [ + ['$', '$'], + ['\\(', '\\)'], + ], + }, + }, // mathjax: { chtml: { fontURL: // 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/output/chtml/fonts/woff-v2', // }} @@ -351,11 +358,16 @@ export function getDefaultCodeConfiguration( * subsequent calls to this function. */ export function getDefaultSveltexConfig< - M extends MarkdownBackend, - C extends CodeBackend, - T extends TexBackend, - A extends AdvancedTexBackend, ->(m: M, c: C, t: T, a: A): FullSveltexConfiguration { + M extends MarkdownBackend = 'none', + C extends CodeBackend = 'none', + T extends TexBackend = 'none', + A extends AdvancedTexBackend = 'none', +>( + m: M = 'none' as M, + c: C = 'none' as C, + t: T = 'none' as T, + a: A = 'none' as A, +): FullSveltexConfiguration { return { general: { wrap: { @@ -364,10 +376,12 @@ export function getDefaultSveltexConfig< }, extensions: ['.sveltex'] as `.${string}`[], tex: { - delimiters: { - inline: ['$', '$'] as [string, string], - display: ['$$', '$$'] as [string, string], + enabled: t !== 'none', + delims: { + inline: { escapedParentheses: true, singleDollar: true }, + display: { escapedSquareBrackets: true }, }, + $$: { isDisplayMath: 'always' }, }, }, tex: getDefaultTexConfiguration(t), diff --git a/src/deps.ts b/src/deps.ts index b90faa8..5f2ecb5 100644 --- a/src/deps.ts +++ b/src/deps.ts @@ -15,19 +15,95 @@ export { Glob } from 'glob'; export { escape as escapeHtml } from 'html-escaper'; export { htmlTagNames } from 'html-tag-names'; export { default as MagicString, type SourceMap } from 'magic-string'; + +/** + * MDAST types for better type-safety. + */ +export type { + Code as MdastCodeNode, + InlineCode as MdastInlineCodeNode, + Root as MdastRoot, +} from 'mdast'; + +/** + * MDAST utility that turns markdown into a syntax tree. + * + * - `fromMarkdown`: Turn markdown into a syntax tree. + * + * Types: + * + * - `Extension`: An Extension object can change how markdown tokens from + * micromark are turned into MDAST. + * - `Options`: Options for `fromMarkdown`. + */ +export { + fromMarkdown as mdastFromMarkdown, + type Extension as MdastExtension, + type Options as MdastFromMarkdownOptions, +} from 'mdast-util-from-markdown'; + +/** + * MDAST extensions to parse and serialize math (e.g. $x^2$). + * + * - `mathFromMarkdown`: Create an extension for `mdast-util-from-markdown` that + * will help parse math. + * + * Types: + * + * - `InlineMath`: An inline math node within an MDAST. + * - `Math`: A display math node within an MDAST. + */ +export { + mathFromMarkdown as mdastMathFromMarkdown, + type InlineMath as MdastInlineMathNode, + type Math as MdastMathNode, +} from 'mdast-util-math'; + +/** + * + */ +export { + mdxExpressionFromMarkdown as mdastMdxExpressionFromMarkdown, + type MdxFlowExpression as MdastMdxFlowExpressionNode, + type MdxTextExpression as MdastMdxTextExpressionNode, +} from 'mdast-util-mdx-expression'; +export { + math as micromarkMath, + type Options as MicromarkMathOptions, +} from 'micromark-extension-math'; +export { + mdxExpression as micromarkMdxExpression, + type Options as MicromarkMdxExpressionOptions, +} from 'micromark-extension-mdx-expression'; +export { + mdxJsx as micromarkMdxJsx, + type Options as MicromarkMdxJsxOptions, +} from 'micromark-extension-mdx-jsx'; +export { + mdxMd as micromarkMdxMd, + type Extension as MicromarkExtension, +} from 'micromark-extension-mdx-md'; +export type { + Value as MdastFromMarkdownValue, + Options, +} from 'micromark-util-types'; export { AbortError, default as nodeFetch } from 'node-fetch'; export { default as ora, type Ora } from 'ora'; export { default as pc } from 'picocolors'; -export { type Colors } from 'picocolors/types.js'; +export type { Colors } from 'picocolors/types.js'; export { default as prettyBytes } from 'pretty-bytes'; export { get as getKey, get as getProperty, set as setProperty } from 'radash'; export { default as rfdc } from 'rfdc'; // "Really Fast Deep Clone" export { rimraf } from 'rimraf'; -export { major as semverMajor } from 'semver'; -export { default as sorcery } from 'sorcery'; -export { VERSION, parse as svelteParse } from 'svelte/compiler'; -export { type HTMLAttributes } from 'svelte/elements'; +export type { + MarkupPreprocessor, + Preprocessor, + PreprocessorGroup, +} from 'svelte/compiler'; +export type { HTMLAttributes } from 'svelte/elements'; export { optimize as svgoOptimize, type Config as SvgoOptions } from 'svgo'; -export { assert, is, type Equals, type Extends } from 'tsafe'; +export { is, assert as typeAssert, type Equals, type Extends } from 'tsafe'; +export type { Node as UnistNode } from 'unist'; export { v4 as uuid } from 'uuid'; +export { default as XRegExp } from 'xregexp'; export { default as YAML } from 'yaml'; diff --git a/src/handlers/CodeHandler.ts b/src/handlers/CodeHandler.ts index ca14e81..33ef77b 100644 --- a/src/handlers/CodeHandler.ts +++ b/src/handlers/CodeHandler.ts @@ -7,6 +7,7 @@ import type { CodeProcessOptions, CodeProcessor, FullCodeConfiguration, + FullCodeProcessOptions, ThemableCodeBackend, } from '$types/handlers/Code.js'; @@ -15,7 +16,7 @@ import { getDefaultCodeConfiguration } from '$config/defaults.js'; import { Handler } from '$handlers/Handler.js'; import { isThemableCodeBackend } from '$type-guards/code.js'; import { isArray } from '$type-guards/utils.js'; -import { cdnLink, fancyFetch, fancyWrite, getVersion } from '$utils/cdn.js'; +import { cdnLink, fancyFetch, fancyWrite } from '$utils/cdn.js'; import { log } from '$utils/debug.js'; import { diagnoseCodeConfiguration } from '$utils/diagnosers/codeConfiguration.js'; import { @@ -24,23 +25,27 @@ import { uniqueEscapeSequences, } from '$utils/escape.js'; import { fs } from '$utils/fs.js'; -import { missingDeps } from '$utils/globals.js'; +import { getVersion, missingDeps } from '$utils/env.js'; import { mergeConfigs } from '$utils/merge.js'; -import { prefixWithSlash, re } from '$utils/misc.js'; +import { prefixWithSlash } from '$utils/misc.js'; // External dependencies -import { assert, escapeHtml, is, join, pc } from '$deps.js'; +import { typeAssert, escapeHtml, is, join, pc } from '$deps.js'; +import { ProcessedSnippet, UnescapeOptions } from '$types/utils/Escape.js'; export class CodeHandler extends Handler< B, CodeBackend, CodeProcessor, - CodeProcessOptions, + FullCodeProcessOptions, CodeConfiguration, FullCodeConfiguration, CodeHandler > { - override get process() { + override get process(): ( + code: string, + options?: CodeProcessOptions | undefined, + ) => Promise { return async ( code: string, options?: CodeProcessOptions | undefined, @@ -50,36 +55,33 @@ export class CodeHandler extends Handler< diagnoseCodeConfiguration(this.backend, this.configuration) .errors === 0; } - if (!this.configIsValid) return code; - await this.handleCss(); - let innerCode: string = code; - let opts: CodeProcessOptions | undefined = { _wrap: true }; - - // If the options are provided, interpret `code` as `innerCode` and - // don't wrap the output with anything. Similarly, if - // optionsFromDelims === undefined, it means that the code snippet - // didn't have delimiters, so we should treat `code` as `innerCode` - // and not wrap the output with anything. - if (options !== undefined) { - opts = mergeConfigs(opts, options); - } else { - const res = this.consumeDelims(code); - if (res.optionsFromDelims !== undefined) { - innerCode = res.innerCode; - opts = mergeConfigs(opts, res.optionsFromDelims); - } - } + let opts: FullCodeProcessOptions = { + _wrap: true, + inline: false, + }; - const processedCode = await super.process(innerCode, opts); + if (options) opts = mergeConfigs(opts, options); + + let processed = code; + if (opts.inline) processed = processed.replace(/\r\n?|\n/gu, ' '); + const unescapeOptions: UnescapeOptions = { + removeParagraphTag: !opts.inline, + }; + + if (!this.configIsValid) return { processed, unescapeOptions }; + + await this.handleCss(); + + processed = (await super.process(processed, opts)).processed; // If the `_wrap` option is set to `false`, don't wrap the output. // (This is sometimes used, for example, by the VerbatimHandler.) - if (opts._wrap === false) return processedCode; + if (!opts._wrap) return { processed, unescapeOptions }; const configuration = this.configuration; - assert( + typeAssert( is>(configuration), ); @@ -88,12 +90,17 @@ export class CodeHandler extends Handler< wrapClassPrefix: configuration.wrapClassPrefix, }); - // Add a newline before and after the code block, since - // consumeDelims gobbles up the first newline after the opening - // delimiter and the last newline before the closing delimiter - const n = opts.inline === true ? '' : '\n'; + // Ensure that fenced code blocks end with newline + const n = + !opts.inline && + // !processed.match(/(\r\n?|\n)\s*$/u) && + processed !== '' + ? '\n' + : ''; + + processed = wrapArray[0] + processed + n + wrapArray[1]; - return wrapArray[0] + n + processedCode + n + wrapArray[1]; + return { processed, unescapeOptions }; }; } @@ -137,7 +144,7 @@ export class CodeHandler extends Handler< // Unfortunately, TypeScript doesn't realize that, at this point, B // extends ThemableCodeBackend - assert(is>(this)); + typeAssert(is>(this)); // Convenience alias + type assertion const theme = this.configuration.theme; @@ -192,120 +199,6 @@ export class CodeHandler extends Handler< this._scriptLines = [`import '${prefixWithSlash(path)}';`]; } - private static codeBlockDelimsRegex = re` - ^ # start of string - \s* # leading whitespace - ( \`\`\`+ | ~~~+ ) # $1: ≥3 backticks or tildes - [\ \t]* # inline whitespace (spaces or tabs) - ([\w-]*) # $2: language tag - [\ \t]* # inline whitespace (spaces or tabs) - (.*) # $3: info string - \r?\n # newline (supporting both CRLF and LF line endings) - ${'u'} # support unicode`; - - private static codeInlineDelimsRegex = re` - ^ # start of string - \s* # leading whitespace - ( \`+ | ~+ ) # $1: ≥1 backticks or tildes - ${'u'} # support unicode`; - - consumeDelims = (codeInDelims: string) => { - let innerCode = codeInDelims; - let optionsFromDelims: CodeProcessOptions | undefined = undefined; - const codeBlockMatchArray = innerCode.match( - CodeHandler.codeBlockDelimsRegex, - ); - if (codeBlockMatchArray) { - /* v8 ignore next 9 (unreachable code) */ - if (!codeBlockMatchArray[1]) { - log( - 'error', - 'Error parsing code snippet' + - "(opening delimiters couldn't be matched): " + - innerCode, - ); - return { innerCode, optionsFromDelims }; - } - - // If the code block was opened with n≥3 backticks resp. tildes, - // it must be closed with k≥n backticks resp. tildes. - const closingDelimRegExp = new RegExp( - `(\\r?\\n)[ \\t]*${codeBlockMatchArray[1]}+\\s*$`, - 'u', - ); - - if (!closingDelimRegExp.test(innerCode)) { - log( - 'error', - `Error parsing code block (closing delimiters not found); expected the following to end with ≥${String(codeBlockMatchArray[1].length)} ${codeBlockMatchArray[1].includes('`') ? 'backticks' : 'tildes'}:\n${innerCode}`, - ); - return { innerCode, optionsFromDelims }; - } - - // Extract the language and info string from the opening delimiter - let lang = codeBlockMatchArray[2]; - const info = codeBlockMatchArray[3]; - if (lang === '') lang = 'plaintext'; - - // Remove the opening and closing delimiters - innerCode = innerCode - .replace(CodeHandler.codeBlockDelimsRegex, '') - .replace(closingDelimRegExp, ''); - optionsFromDelims = { inline: false, lang, info }; - return { innerCode, optionsFromDelims }; - } - - // Let's remove the opening and closing delimiters - const codeInlineMatchArray = innerCode.match( - CodeHandler.codeInlineDelimsRegex, - ); - if (codeInlineMatchArray) { - /* v8 ignore next 9 (unreachable code) */ - if (!codeInlineMatchArray[1]) { - log( - 'error', - 'Error parsing code snippet' + - "(opening delimiters couldn't be matched): " + - innerCode, - ); - return { innerCode, optionsFromDelims }; - } - - // If the code block was opened with n≥1 backticks resp. tildes, - // it must be closed with n backticks resp. tildes. - const closingDelimRegExp = new RegExp( - `${codeInlineMatchArray[1]}+\\s*$`, - 'u', - ); - - if (!closingDelimRegExp.test(innerCode)) { - log( - 'error', - `Error parsing inline code snippet (closing delimiters not found); expected the following to end with ≥${String(codeInlineMatchArray[1].length)} ${codeInlineMatchArray[1].includes('`') ? 'backticks' : 'tildes'}:\n${innerCode}`, - ); - return { innerCode, optionsFromDelims }; - } - - // Currently we can't set the language or info string for inline - // code snippets, so we'll just set the language to 'plaintext' and - // the info string to an empty string. - optionsFromDelims = { inline: true, lang: 'plaintext', info: '' }; - - // Remove the opening and closing delimiters - innerCode = innerCode - .replace(CodeHandler.codeInlineDelimsRegex, '') - .replace(closingDelimRegExp, ''); - } else { - log( - 'error', - `Error parsing code snippet (no delimiters could be found/matched): ${innerCode}`, - ); - return { innerCode, optionsFromDelims }; - } - - return { innerCode, optionsFromDelims }; - }; - /** * Creates a code handler of the specified type. * @@ -369,18 +262,15 @@ export class CodeHandler extends Handler< try { type Backend = 'highlight.js'; const processor = (await import('highlight.js')).default; - return new CodeHandler({ + const handler = new CodeHandler({ backend: 'highlight.js', processor, configuration: getDefaultCodeConfiguration('highlight.js'), - process: (code, { lang } = {}, codeHandler) => { + process: (code, { lang }, codeHandler) => { return escapeBraces( codeHandler.processor.highlight(code, { - language: - lang === undefined || lang.length === 0 - ? 'plaintext' - : lang, + language: lang ?? 'plaintext', }).value, ); }, @@ -388,6 +278,16 @@ export class CodeHandler extends Handler< codeHandler.processor.configure(config); }, }); + // Apparently, the highlight.js processor isn't + // serializable. This will upset Vite, so we need to. + // remove it from the object returned by `toJSON` + (handler as unknown as { toJSON: () => object }).toJSON = + () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { processor, ...rest } = handler; + return rest; + }; + return handler; } catch (error) { missingDeps.push('highlight.js'); throw error; @@ -405,7 +305,7 @@ export class CodeHandler extends Handler< const codeHandler = new CodeHandler({ backend: 'prismjs', processor, - process: (code, { lang } = {}, codeHandler) => { + process: (code, { lang }, codeHandler) => { const langOrDefault = lang ?? 'plaintext'; const grammar = codeHandler.processor.prism.languages[ @@ -458,9 +358,9 @@ export class CodeHandler extends Handler< return new CodeHandler({ backend: 'starry-night', processor, - process: (code, { lang } = {}, codeHandler) => { + process: (code, { lang }, codeHandler) => { if ( - lang === undefined || + !lang || [ 'plaintext', 'plain', @@ -539,8 +439,8 @@ export class CodeHandler extends Handler< grammar.dependencies .length > 0 ) { - deps = deps.concat( - grammar.dependencies, + deps.push( + ...grammar.dependencies, ); } return grammar; diff --git a/src/handlers/Handler.ts b/src/handlers/Handler.ts index 00d212b..bb98317 100644 --- a/src/handlers/Handler.ts +++ b/src/handlers/Handler.ts @@ -10,6 +10,7 @@ import { mergeConfigs } from '$utils/merge.js'; // External dependencies import { getProperty, rfdc, setProperty } from '$deps.js'; +import { isString } from '$type-guards/utils.js'; export const deepClone = rfdc(); @@ -107,7 +108,7 @@ export class Handler< * @internal * @readonly */ - private readonly _process: ProcessFn; + protected readonly _process: ProcessFn; /** * Process content. @@ -117,12 +118,14 @@ export class Handler< * @returns The processed content, or promise resolving to it. */ get process(): SimplerProcessFn { - return (content: string, options: ProcessOptions) => { - return this._process( + return async (content: string, options: ProcessOptions) => { + const res = await this._process( content, options, this as unknown as ActualHandler, ); + if (isString(res)) return { processed: res }; + return res; }; } diff --git a/src/handlers/MarkdownHandler.ts b/src/handlers/MarkdownHandler.ts index 686966b..6f35914 100644 --- a/src/handlers/MarkdownHandler.ts +++ b/src/handlers/MarkdownHandler.ts @@ -10,7 +10,7 @@ import type { } from '$types/handlers/Markdown.js'; // Internal dependencies -import { missingDeps } from '$utils/globals.js'; +import { missingDeps } from '$utils/env.js'; import { Handler } from '$handlers/Handler.js'; import { re } from '$utils/misc.js'; @@ -289,7 +289,9 @@ export class MarkdownHandler extends Handler< .use(markdownHandler.configuration.remarkPlugins) .use(remarkRehype, { allowDangerousHtml: true }) .use(markdownHandler.configuration.rehypePlugins) - .use(rehypeStringify, { allowDangerousHtml: true }); + .use(rehypeStringify, { + allowDangerousHtml: true, + }); }; const process: MarkdownProcessFn = async ( markdown: string, @@ -350,7 +352,7 @@ export class MarkdownHandler extends Handler< \n\s*\n # multiple newlines | ^\s*\#{1,6} \s # headings | ( ^.* \S .*\n )+ # setext heading - ^\s*(-+|=+) \s* $ # setext heading underline + ^\s*(-+|=+) \s* $ # setext heading underline | ^( [*+-] | \d+\. ) \s # lists | ^\s* ( \`{3,} | ~{3,} ) # fenced code blocks | ^\s* # thematic breaks diff --git a/src/handlers/TexHandler.ts b/src/handlers/TexHandler.ts index 107a141..768fb61 100644 --- a/src/handlers/TexHandler.ts +++ b/src/handlers/TexHandler.ts @@ -15,16 +15,16 @@ import { katexFonts } from '$data/tex.js'; import { Handler, deepClone } from '$handlers/Handler.js'; import { isArray, isOneOf } from '$type-guards/utils.js'; import { CssApproach, CssApproachLocal } from '$types/handlers/misc.js'; -import { cdnLink, fancyFetch, fancyWrite, getVersion } from '$utils/cdn.js'; +import { cdnLink, fancyFetch, fancyWrite } from '$utils/cdn.js'; import { runWithSpinner } from '$utils/debug.js'; import { escapeBraces } from '$utils/escape.js'; import { fs } from '$utils/fs.js'; -import { missingDeps } from '$utils/globals.js'; +import { getVersion, missingDeps } from '$utils/env.js'; import { mergeConfigs } from '$utils/merge.js'; -import { copyTransformation, prefixWithSlash, re } from '$utils/misc.js'; +import { copyTransformation, prefixWithSlash } from '$utils/misc.js'; // External dependencies -import { CleanCSS, Output, assert, is, join, prettyBytes } from '$deps.js'; +import { CleanCSS, Output, typeAssert, is, join, prettyBytes } from '$deps.js'; import { escapeCssColorVars, unescapeCssColorVars } from '$utils/css.js'; export class TexHandler< @@ -48,7 +48,7 @@ export class TexHandler< // rfdc doesn't handle RegExps well, so we have to copy them manually if (isOneOf(this.backend, ['mathjax', 'katex'])) { - assert(is>(this)); + typeAssert(is>(this)); clone.transformations = { pre: [ ...this._configuration.transformations.pre.map( @@ -84,47 +84,44 @@ export class TexHandler< ]; override get process() { - return async ( - tex: string, - options?: TexProcessOptions['options'], - ) => { + return async (tex: string, options?: TexProcessOptions) => { await this.handleCss(); - const displayMath = tex.match( - re`^ (?: \$\$ (.*) \$\$ | \\\[ (.*) \\\] ) $ ${'su'}`, - ); - const inlineMath = tex.match( - re`^ (?: \$ (.*) \$ | \\\( (.*) \\\) ) $ ${'su'}`, - ); - if (displayMath) { - return super.process( - // We ignore the line below because the regex guarantees - // that one of the groups is not null, but TypeScript - // doesn't realize this, and I don't want to use a non-null - // assertion. - /* v8 ignore next */ - displayMath[1] ?? displayMath[2] ?? '', - { - options, - inline: false, - } as TexProcessOptions, - ); - } - if (inlineMath) { - return super.process( - // We ignore the line below because the regex guarantees - // that one of the groups is not null, but TypeScript - // doesn't realize this, and I don't want to use a non-null - // assertion. - /* v8 ignore next */ - inlineMath[1] ?? inlineMath[2] ?? '', - { - options, - inline: true, - } as TexProcessOptions, - ); - } - return super.process(tex, { options } as TexProcessOptions); + // const displayMath = tex.match( + // re`^ (?: \$\$ (.*) \$\$ | \\\[ (.*) \\\] ) $ ${'su'}`, + // ); + // const inlineMath = tex.match( + // re`^ (?: \$ (.*) \$ | \\\( (.*) \\\) ) $ ${'su'}`, + // ); + // if (displayMath) { + // return super.process( + // // We ignore the line below because the regex guarantees + // // that one of the groups is not null, but TypeScript + // // doesn't realize this, and I don't want to use a non-null + // // assertion. + // /* v8 ignore next */ + // displayMath[1] ?? displayMath[2] ?? '', + // { + // options, + // inline: false, + // } as TexProcessOptions, + // ); + // } + // if (inlineMath) { + // return super.process( + // // We ignore the line below because the regex guarantees + // // that one of the groups is not null, but TypeScript + // // doesn't realize this, and I don't want to use a non-null + // // assertion. + // /* v8 ignore next */ + // inlineMath[1] ?? inlineMath[2] ?? '', + // { + // options, + // inline: true, + // } as TexProcessOptions, + // ); + // } + return super.process(tex, options ?? ({} as TexProcessOptions)); }; } @@ -494,7 +491,7 @@ export class TexHandler< { startMessage: `Minifying MathJax stylesheet (${fmt})`, successMessage: (t) => - `Minified MathJax stylesheet (${fmt}) (${prettyBytes(opt.stats.originalSize)} → ${prettyBytes(opt.stats.minifiedSize)}, ${String(opt.stats.efficiency * 100)}% reduction) in ${t}`, + `Minified MathJax stylesheet (${fmt}) (${prettyBytes(opt.stats.originalSize)} → ${prettyBytes(opt.stats.minifiedSize)}, ${(opt.stats.efficiency * 100).toFixed(0)}% reduction) in ${t}`, failMessage: (t) => `Error minifying MathJax stylesheet (${fmt}) after ${t}`, }, diff --git a/src/handlers/VerbatimHandler.ts b/src/handlers/VerbatimHandler.ts index 5f0ffea..ab5d7a6 100644 --- a/src/handlers/VerbatimHandler.ts +++ b/src/handlers/VerbatimHandler.ts @@ -12,6 +12,7 @@ import type { VerbatimConfiguration, VerbatimProcessOptions, } from '$types/handlers/Verbatim.js'; +import type { UnescapeOptions } from '$types/utils/Escape.js'; // Internal dependencies import { getDefaultVerbatimEnvironmentConfiguration } from '$config/defaults.js'; @@ -19,12 +20,10 @@ import { AdvancedTexHandler } from '$handlers/AdvancedTexHandler.js'; import { CodeHandler } from '$handlers/CodeHandler.js'; import { Handler } from '$handlers/Handler.js'; import { isSimpleEscapeInstruction } from '$type-guards/verbatim.js'; -import { log, prettifyError } from '$utils/debug.js'; +import { log } from '$utils/debug.js'; import { diagnoseVerbatimEnvironmentConfiguration } from '$utils/diagnosers/verbatimEnvironmentConfiguration.js'; import { escapeBraces } from '$utils/escape.js'; import { mergeConfigs } from '$utils/merge.js'; -import { interpretAttributes } from '$utils/misc.js'; -import { parseComponent } from '$utils/parseComponent.js'; // External dependencies import { escapeHtml, nodeAssert, rfdc } from '$deps.js'; @@ -78,172 +77,158 @@ export class VerbatimHandler< * */ const process = async ( - content: string, + innerContent: string, options: VerbatimProcessOptions, verbatimHandler: VerbatimHandler, ) => { - try { - const { - tag, - attributes, - content: innerContent, - selfClosing, - } = parseComponent(content); - - if (selfClosing && innerContent !== undefined) { - log( - 'error', - `Self-closing HTML tag "${tag}" should not have content.`, - ); - return content; - } + const { tag, attributes, selfClosing, outerContent } = options; - if (!selfClosing && innerContent === undefined) { - log( - 'error', - `HTML tag "${tag}" should have content, but none was found.`, - ); - return content; - } + let processed: string = innerContent; + let unescapeOptions: UnescapeOptions | undefined = { + removeParagraphTag: !options.attributes['inline'], + }; - const isVerbEnv = verbatimHandler.verbEnvs.has(tag); - const isAdvancedTexComponent = - verbatimHandler.advancedTexHandler.tccMap.has(tag); + if (selfClosing && innerContent) { + log( + 'error', + `Self-closing HTML tag "${tag}" should not have content.`, + ); + return { processed: outerContent, unescapeOptions }; + } - if (!isVerbEnv && !isAdvancedTexComponent) { - log('error', `Unknown verbatim environment "${tag}".`); - return content; - } + if (!selfClosing && !innerContent) { + log( + 'error', + `HTML tag "${tag}" should have content, but none was found.`, + ); + return { processed: outerContent, unescapeOptions }; + } - if (isVerbEnv && isAdvancedTexComponent) { - log( - 'error', - `HTML tag "${tag}" is ambiguous, as it refers to both a verbatim environment and an advanced TeX component.`, - ); - return content; - } + const isVerbEnv = verbatimHandler.verbEnvs.has(tag); + const isAdvancedTexComponent = + verbatimHandler.advancedTexHandler.tccMap.has(tag); - if (isVerbEnv) { - const config = verbatimHandler.verbEnvs.get(tag); - nodeAssert(config !== undefined); + if (!isVerbEnv && !isAdvancedTexComponent) { + log('error', `Unknown verbatim environment "${tag}".`); + return { processed: outerContent, unescapeOptions }; + } - const defaultAttributes: Record< - string, - string | boolean | number | null | undefined - > = config.defaultAttributes; + if (isVerbEnv && isAdvancedTexComponent) { + log( + 'error', + `HTML tag "${tag}" is ambiguous, as it refers to both a verbatim environment and an advanced TeX component.`, + ); + return { processed: outerContent, unescapeOptions }; + } - const mergedAttributes = { - ...defaultAttributes, - ...attributes, - }; + if (isVerbEnv) { + const config = verbatimHandler.verbEnvs.get(tag); + nodeAssert(config !== undefined); - const fullConfig = mergeConfigs( - getDefaultVerbatimEnvironmentConfiguration(), - config, - ); + const mergedAttributes = { + ...config.defaultAttributes, + ...attributes, + }; - // isVerbEnv === true + const fullConfig = mergeConfigs( + getDefaultVerbatimEnvironmentConfiguration(), + config, + ); - const processInner = fullConfig.processInner; + // isVerbEnv === true - const component = fullConfig.component ?? tag; + const processInner = fullConfig.processInner; - let closingBracket = '>'; - if (selfClosing && fullConfig.respectSelfClosing) { - if (fullConfig.selfCloseOutputWith === 'auto') { - closingBracket = `${content.match(/\s+\/>\s*$/) ? ' ' : ''}/>`; - } else { - closingBracket = fullConfig.selfCloseOutputWith; - } + const component = fullConfig.component ?? tag; + + let closingBracket = '>'; + if (selfClosing && fullConfig.respectSelfClosing) { + if (fullConfig.selfCloseOutputWith === 'auto') { + closingBracket = `${outerContent.match(/\s+\/>\s*$/) ? ' ' : ''}/>`; + } else { + closingBracket = fullConfig.selfCloseOutputWith; } + } - const filteredMergedAttributes = Object.entries( - mergedAttributes, - ).filter( - ([key]) => - (fullConfig.attributeForwardingAllowlist === - 'all' || - fullConfig.attributeForwardingAllowlist.includes( - key, - )) && - !fullConfig.attributeForwardingBlocklist.includes( + const filteredMergedAttributes = Object.entries( + mergedAttributes, + ).filter( + ([key]) => + (fullConfig.attributeForwardingAllowlist === 'all' || + fullConfig.attributeForwardingAllowlist.includes( key, - ), - ); - - const returnComponentOpen = - `<${component}` + - (filteredMergedAttributes.length === 0 ? '' : ' ') + - filteredMergedAttributes - .map( - (attr) => - `${attr[0]}${attr[1] === undefined ? '' : `="${String(attr[1])}"`}`, - ) - .join(' ') + - closingBracket; - - if (selfClosing || innerContent === undefined) { - return returnComponentOpen; - } + )) && + !fullConfig.attributeForwardingBlocklist.includes(key), + ); - let processedInner: string = innerContent; - const returnComponentClose = ``; + const returnComponentOpen = + `<${component}` + + (filteredMergedAttributes.length === 0 ? '' : ' ') + + filteredMergedAttributes + .map( + (attr) => + `${attr[0]}${attr[1] === undefined ? '' : `="${String(attr[1])}"`}`, + ) + .join(' ') + + closingBracket; + + unescapeOptions = { + removeParagraphTag: !mergedAttributes['inline'], + }; + + if (selfClosing) { + return { + processed: returnComponentOpen, + unescapeOptions, + }; + } - if (isSimpleEscapeInstruction(fullConfig.processInner)) { - let escaped = innerContent; - if (fullConfig.processInner.escapeHtml) { - escaped = escapeHtml(escaped); - } - // NB: It's important to escape braces _after_ escaping HTML, since - // escaping braces will introduce ampersands which escapeHtml would - // escape - if (fullConfig.processInner.escapeBraces) { - escaped = escapeBraces(escaped); - } - processedInner = escaped; - } else if (typeof processInner === 'string') { - if (processInner === 'code') { - processedInner = - await verbatimHandler.codeHandler.process( - innerContent, - { - ...interpretAttributes( - mergedAttributes, - ), - _wrap: config.wrap, - }, - ); - } - if (processInner === 'noop') { - processedInner = innerContent; - } - } else if (typeof processInner === 'function') { - processedInner = processInner( - innerContent, - mergedAttributes, - ); - } + const returnComponentClose = ``; - return [ - returnComponentOpen, - processedInner, - returnComponentClose, - ].join(''); - } else { - return verbatimHandler.advancedTexHandler.process( - innerContent ?? '', - { - attributes, - tag, - filename: options.filename, - selfClosing, - }, - ); + if (isSimpleEscapeInstruction(fullConfig.processInner)) { + if (fullConfig.processInner.escapeHtml) { + processed = escapeHtml(processed); + } + // NB: It's important to escape braces _after_ escaping HTML, since + // escaping braces will introduce ampersands which escapeHtml would + // escape + if (fullConfig.processInner.escapeBraces) { + processed = escapeBraces(processed); + } + } else if (typeof processInner === 'string') { + if (processInner === 'code') { + const processedSnippet = + await verbatimHandler.codeHandler.process( + innerContent, + { ...mergedAttributes, _wrap: config.wrap }, + ); + processed = processedSnippet.processed; + unescapeOptions = processedSnippet.unescapeOptions; + } + if (processInner === 'noop') processed = innerContent; + } else if (typeof processInner === 'function') { + processed = processInner(innerContent, mergedAttributes); } - } catch (err) { - log('error', prettifyError(err)); - return content; + processed = [ + returnComponentOpen, + processed, + returnComponentClose, + ].join(''); + } else { + // Advanced TeX Content + const res = await verbatimHandler.advancedTexHandler.process( + innerContent, + { + attributes, + tag, + filename: options.filename, + selfClosing, + }, + ); + processed = res.processed; + unescapeOptions = res.unescapeOptions ?? unescapeOptions; } + return { processed, unescapeOptions }; }; const configure = ( _configuration: VerbatimConfiguration, diff --git a/src/type-guards/ast.ts b/src/type-guards/ast.ts index d0778b7..e15398c 100644 --- a/src/type-guards/ast.ts +++ b/src/type-guards/ast.ts @@ -8,26 +8,11 @@ // Types import type { - BaseNode, - BaseNode_ESTree, - BaseNode_v4, - BaseNode_v5, - Fragment_v5, LineColumn, StartEnd_LineColumn, StartEnd_Offset, } from '$types/utils/Ast.js'; -/** - * Type guard for `BaseNode`. - * - * @param node - The node to check. - * @returns True if the node is of type `BaseNode`, and false otherwise. - */ -export function isBaseNode(node: unknown): node is BaseNode { - return typeof node === 'object' && node !== null && 'type' in node; -} - /** * Checks that the given object has `start` and `end` properties, no matter * their types. @@ -43,22 +28,6 @@ export function hasStartEndUnknown( ); } -/** - * Checks that the given node has `start` and `end` properties, that both of them are - * numbers, and that 0 ≤ `start` ≤ `end`. - */ -export function hasStartEnd( - node: unknown, -): node is { start: number; end: number } { - return ( - hasStartEndUnknown(node) && - typeof node.start === 'number' && - typeof node.end === 'number' && - node.start >= 0 && - node.end >= node.start - ); -} - /** * Type guard for {@link StartEnd_Offset | `StartEnd_Offset`}. */ @@ -117,70 +86,3 @@ export function hasStartEnd_LineColumn( node.end.column >= node.start.column) ); } - -/** - * ESTree-compliant nodes may have a `range` property, which is an array of two - * numbers. This type guard checks for the presence of that property. - */ -export function hasRange(node: unknown): node is { range: [number, number] } { - return ( - typeof node === 'object' && - node !== null && - 'range' in node && - node.range instanceof Array && - node.range.length === 2 && - typeof node.range[0] === 'number' && - typeof node.range[1] === 'number' && - node.range[0] <= node.range[1] - ); -} - -/** - * Type guard for `BaseNode`. - * - * @param node - The node to check. - * @returns True if the node is of type `BaseNode`, and false otherwise. - */ -export function isBaseNode_v5(node: unknown): node is BaseNode_v5 { - return isBaseNode(node) && hasStartEnd(node); -} - -/** - * Type guard for `BaseNode_v4`. - * - * @param node - The node to check. - * @returns True if the node is of type `BaseNode_v4`, and false otherwise. - */ -export function isBaseNode_v4(node: unknown): node is BaseNode_v4 { - return isBaseNode(node) && hasStartEnd(node); -} - -/** - * Type guard for {@link Fragment_v5 | `Fragment_v5`}. - * - * @param node - The node to check. - * @returns True if the node is of type `Fragment_v5`, and false otherwise. - */ -export function isFragment_v5(node: unknown): node is Fragment_v5 { - return ( - isBaseNode_v5(node) && - node.type === 'Fragment' && - 'nodes' in node && - (node['nodes'] === null || - node['nodes'] === undefined || - (typeof node['nodes'] === 'object' && - Array.isArray(node['nodes']) && - node['nodes'].every(isBaseNode_v5))) - ); -} - -/** - * - */ -export function isBaseNode_ESTree(node: unknown): node is BaseNode_ESTree { - return ( - isBaseNode(node) && - (hasRange(node) || - ('loc' in node && hasStartEnd_LineColumn(node['loc']))) - ); -} diff --git a/src/type-guards/code.ts b/src/type-guards/code.ts index 940669a..fa7fc6d 100644 --- a/src/type-guards/code.ts +++ b/src/type-guards/code.ts @@ -12,7 +12,7 @@ import { import { highlightJsThemeNames, starryNightThemeNames } from '$data/code.js'; // External dependencies -import { assert } from '$deps.js'; +import { typeAssert } from '$deps.js'; export function isThemableCodeBackend( input: unknown, @@ -39,10 +39,12 @@ export function isHighlightJsThemeName( return isString(input) && isOneOf(input, highlightJsThemeNames); } -assert>(); -assert>(); -assert>(); -assert>(); +typeAssert>(); +typeAssert< + Equals +>(); +typeAssert>(); +typeAssert>(); export const codeBackends = [ 'escapeOnly', diff --git a/src/types/SveltexConfiguration.ts b/src/types/SveltexConfiguration.ts index c2bdd91..9f10be2 100644 --- a/src/types/SveltexConfiguration.ts +++ b/src/types/SveltexConfiguration.ts @@ -34,6 +34,7 @@ import type { FullVerbatimConfiguration, VerbatimConfiguration, } from '$types/handlers/Verbatim.js'; +import { TexEscapeSettings } from '$types/utils/Escape.js'; import type { RequiredNonNullable } from '$types/utils/utility-types.js'; /** @@ -341,24 +342,7 @@ export interface SveltexConfiguration< /** * General options surrounding SvelTeX's LaTeX support. */ - tex?: - | undefined - | { - delimiters?: { - /** - * Delimiter to use to render inline TeX blocks (e.g., `$x^2$`). - * @defaultValue `['$', '$']`. - */ - inline?: [string, string] | undefined; - - /** - * Delimiter to use to render display TeX blocks (e.g., - * `$$x^2$$`). - * @defaultValue `['$$', '$$']`. - */ - display?: [string, string] | undefined; - }; - }; + tex?: undefined | Omit; }; } @@ -373,7 +357,7 @@ export interface FullSveltexConfiguration< > { general: NonNullable< RequiredNonNullable['general']> - >; + > & { tex: { enabled: boolean } }; markdown: FullMarkdownConfiguration; code: FullCodeConfiguration; tex: FullTexConfiguration; diff --git a/src/types/handlers/AdvancedTex.ts b/src/types/handlers/AdvancedTex.ts index 16dccd7..c980f20 100644 --- a/src/types/handlers/AdvancedTex.ts +++ b/src/types/handlers/AdvancedTex.ts @@ -5,6 +5,10 @@ import type { SupportedTexEngine } from '$types/SveltexConfiguration.js'; import type { ConfigureFn, ProcessFn } from '$types/handlers/Handler.js'; import type { CliInstruction } from '$types/utils/CliInstruction.js'; import type { DvisvgmOptions } from '$types/utils/DvisvgmOptions.js'; +import type { + EscapeOptions, + InterpretedAttributes, +} from '$types/utils/Escape.js'; import type { RequiredNonNullable, RequiredNonNullableExcept, @@ -352,9 +356,10 @@ export type AdvancedTexProcessor = object; export interface AdvancedTexProcessOptions { tag: string; - attributes: Record; + attributes: InterpretedAttributes; filename: string; selfClosing: boolean; + escapeOptions?: EscapeOptions | undefined; } /** diff --git a/src/types/handlers/Code.ts b/src/types/handlers/Code.ts index 2aac0dd..01d6639 100644 --- a/src/types/handlers/Code.ts +++ b/src/types/handlers/Code.ts @@ -88,7 +88,7 @@ export interface GeneralCodeConfiguration { wrap?: | undefined | (( - options: CodeProcessOptions & { wrapClassPrefix: string }, + options: FullCodeProcessOptions & { wrapClassPrefix: string }, ) => [string, string]); } @@ -251,6 +251,14 @@ export interface CodeProcessOptions { _wrap?: boolean | undefined; } +/** + * + */ +export type FullCodeProcessOptions = RequiredNonNullable< + Omit +> & + Pick; + /** * Type of the function that configures a code processor of the specified * type. diff --git a/src/types/handlers/Handler.ts b/src/types/handlers/Handler.ts index 8b74336..ab00be7 100644 --- a/src/types/handlers/Handler.ts +++ b/src/types/handlers/Handler.ts @@ -1,3 +1,5 @@ +import { ProcessedSnippet } from '$types/utils/Escape.js'; + /** * Generic type for the a handler's `process` function, as returned by the * handler's getter for the function. @@ -8,7 +10,7 @@ export type SimplerProcessFn = ( content: string, options: ProcessOptions, -) => string | Promise; +) => ProcessedSnippet | Promise; /** * Generic type for the a handler's `process` function, as stored internally and @@ -22,7 +24,7 @@ export type ProcessFn = ( content: string, options: ProcessOptions, handler: H, -) => string | Promise; +) => string | ProcessedSnippet | Promise; /** * Generic type for a handler's `configure` function. diff --git a/src/types/handlers/Tex.ts b/src/types/handlers/Tex.ts index 1d18028..f14a7c5 100644 --- a/src/types/handlers/Tex.ts +++ b/src/types/handlers/Tex.ts @@ -1,5 +1,5 @@ // Types -import { Equals, assert } from '$deps.js'; +import { Equals, typeAssert } from '$deps.js'; import type { TexHandler } from '$handlers/TexHandler.js'; import type { CssApproach, @@ -212,24 +212,24 @@ export type TexProcessOptions = B extends 'mathjax' // Compile-time unit tests -assert< +typeAssert< Equals< keyof TexConfiguration<'mathjax'>, keyof FullTexConfiguration<'mathjax'> > >(); -assert< +typeAssert< Equals, keyof FullTexConfiguration<'katex'>> >(); -assert< +typeAssert< Equals< keyof TexConfiguration<'custom'>, keyof FullTexConfiguration<'custom'> > >(); -assert< +typeAssert< Equals, keyof FullTexConfiguration<'none'>> >(); diff --git a/src/types/handlers/Verbatim.ts b/src/types/handlers/Verbatim.ts index b83d151..3f915c6 100644 --- a/src/types/handlers/Verbatim.ts +++ b/src/types/handlers/Verbatim.ts @@ -5,6 +5,10 @@ import type { export interface VerbatimProcessOptions { filename: string; + selfClosing: boolean; + attributes: Record; + tag: string; + outerContent: string; } export type FullVerbatimConfiguration = diff --git a/src/types/utils/Ast.ts b/src/types/utils/Ast.ts index 43651e5..5d576c4 100644 --- a/src/types/utils/Ast.ts +++ b/src/types/utils/Ast.ts @@ -18,7 +18,7 @@ export interface BaseNode extends Record { * `'0123'` and a `Location` object `{ start: 0, end: 2 }`, the `Location` would * refer to the substring `'01'`. */ -export interface Location { +export interface Offsets { /** * The index of the first character of the substring to which this * `Location` object refers. diff --git a/src/types/utils/Escape.ts b/src/types/utils/Escape.ts new file mode 100644 index 0000000..44878c5 --- /dev/null +++ b/src/types/utils/Escape.ts @@ -0,0 +1,255 @@ +import { Extends, typeAssert } from '$deps.js'; +import { TexBackend } from '$mod.js'; +import { FullCodeProcessOptions } from '$types/handlers/Code.js'; +import { TexProcessOptions } from '$types/handlers/Tex.js'; +import { VerbatimProcessOptions } from '$types/handlers/Verbatim.js'; +import { Offsets } from '$types/utils/Ast.js'; + +/** + * Vernacular: + * - "snippet": A small segment (or fragment, part, excerpt... or, indeed, + * snippet) of a document that should be escaped and processed by a handler + * other than the markdown processor. + * - "escaped snippet": A snippet that has been replaced with a UUID. + * - "processed snippet": An escaped snippet that has been processed by a + * handler. + */ + +export type InterpretedAttributes = Record< + string, + string | number | boolean | null | undefined +>; + +export interface ParsedComponent { + innerContent: string; + selfClosing: boolean; + attributes: InterpretedAttributes; + tag: string; +} + +export interface ProcessableSnippet { + /** + * The "inner" content of the snippet, i.e., the content that should be + * passed, as-is, as the first argument of the appropriate handler's + * `process` function. At the very least, this means that `innerContent` + * should lack the outermost delimiters of the snippet. + */ + innerContent: string; + + /** + * Object that contains options that should be passed as the second argument + * of the `process` function of the handler that should process the snippet. + * For example, for a fenced code block, this could be the language tag and + * the meta/info string, alongside `inline: false` to indicate that the + * `innerContent` should be processed as a code block, not a code span. + */ + optionsForProcessor: T extends 'code' + ? FullCodeProcessOptions + : T extends 'tex' + ? TexProcessOptions + : T extends 'verbatim' + ? Omit + : undefined; +} + +export type PaddingInstruction = + | boolean + | string + | number + | [string | boolean | number, string | boolean | number]; + +export interface EscapeOptions { + /** + * Whether (or how) to pad the UUID generated for the snippet when inserting + * it into the document. + */ + pad?: PaddingInstruction | undefined; + /** + * Whether to include hyphens in the UUID generated for the snippet. + * + * @defaultValue `true` + */ + hyphens?: boolean | undefined; +} + +export interface UnescapeOptions { + /** + * Sveltex escapes "snippets" by replacing them with UUIDs before running + * the markdown processor. This can often result in the UUIDs being wrapped + * in paragraph tags. Setting this option to `true` will remove such tags, + * if present. + */ + removeParagraphTag?: boolean | undefined; +} + +/** + * Description of a "snippet" in the original document. + */ +export interface OriginalSnippet { + /** + * The location of the snippet in the original document. + * - `start` is the index of the first character of the snippet. + * - `end` is the index of the character immediately following the + * snippet. + */ + loc: Offsets; + + /** + * The original content of the snippet, including the delimiters etc. + * Essentially just the slice of the original document at + * {@link loc | `loc`}. + */ + outerContent: T extends 'svelte' | 'mustacheTag' | 'verbatim' + ? string + : string | undefined; +} + +export type SnippetType = + | 'tex' + | 'code' + | 'svelte' + | 'mustacheTag' + | 'verbatim'; +// | 'advancedTex'; + +export interface ProcessedSnippet { + processed: string; + unescapeOptions?: UnescapeOptions | undefined; +} + +export interface EscapableSnippet + extends Snippet { + escapeOptions?: EscapeOptions | undefined; + unescapeOptions?: UnescapeOptions | undefined; +} + +export interface EscapedSnippet + extends Snippet { + unescapeOptions?: UnescapeOptions | undefined; +} + +type ProcessableSnippetType = 'code' | 'tex' | 'verbatim'; + +/** + * A small segment (or fragment, part, excerpt... or, indeed, snippet) of a + * document that should be escaped and processed by a handler other than the + * markdown processor. + */ +export interface Snippet { + /** + * Snippet type. This is used to determine which handler, if any, should + * process the snippet. Possible values are: + * - `'tex'`: A snippet of LaTeX code. + * - `'code'`: A code span or a fenced code block. This is forwarded to the + * `CodeHandler`. + * - `'verbatim'`: A verbatim environment. This is forwarded to the + * `VerbatimHandler`, which checks for some errors and then may forward + * the snippet to: + * - `AdvancedTexHandler`, if the verbatim environment was set up as a TeX + * component. + * - `CodeHandler`, if the verbatim environment was set up with + * `processInner` set to `code`. + * - Otherwise: the `VerbatimHandler` will take care of the processing + * itself (this is the case for `processInner` values `noop`, + * `escapeOnly`). + * - `'mustacheTag'`: A mustache tag, like `{...}`. + * - `'svelte'`: Svelte syntax (other than mustache tags), like + * `{@html ...}`, `{#if ...}`, ``, `b')) + * // [ + * // { + * // escapeOptions: { pad: 2 }, + * // original: { + * // loc: { start: 1, end: 21 }, + * // outerContent: '', + * // }, + * // processable: undefined, + * // type: 'svelte', + * // unescapeOptions: { removeParagraphTag: true }, + * // }, + * // ] + * ``` + */ +export function getSvelteES(document: string): EscapableSnippet<'svelte'>[] { + const escapableSnippets: EscapableSnippet<'svelte'>[] = []; + [ + normalComponentsRegExp(['script', 'style', `svelte${colonUuid}head`]), + normalAndSelfClosingComponentsRegExp([ + `svelte${colonUuid}window`, + `svelte${colonUuid}document`, + `svelte${colonUuid}body`, + `svelte${colonUuid}options`, + ]), + ].forEach((regExp) => { + // console.log('document: ', document); + // console.log('regExp: ', regExp.source); + for (const match of document.matchAll(regExp)) { + // console.log('match: ', match[0]); + const { index, 0: outerContent } = match; + const loc = { + start: index, + end: index + outerContent.length, + }; + escapableSnippets.push({ + type: 'svelte', + original: { loc, outerContent }, + processable: undefined, + escapeOptions: { pad: 2 }, + unescapeOptions: { removeParagraphTag: true }, + }); + } + }); + return escapableSnippets; +} + +export const colonUuid = uuid().replace(/-/g, ''); + +export function getColonES(document: string): EscapableSnippet<'svelte'>[] { + const escapableSnippets: EscapableSnippet<'svelte'>[] = []; + const addColon = (loc: Offsets) => { + escapableSnippets.push({ + type: 'svelte', + original: { loc, outerContent: ':' }, + processable: undefined, + escapeOptions: { pad: false, hyphens: false }, + unescapeOptions: { removeParagraphTag: false }, + }); + }; + [ + normalComponentsRegExp(['svelte:head']), + normalAndSelfClosingComponentsRegExp([ + 'svelte:self', + 'svelte:component', + 'svelte:element', + 'svelte:fragment', + // + 'svelte:window', + 'svelte:document', + 'svelte:body', + 'svelte:options', + ]), + ].forEach((regExp) => { + for (const match of document.matchAll(regExp)) { + const { index, 0: outerContent } = match; + // console.log(match); + const firstColonIdx = outerContent.indexOf(':'); + const locFirst = { + start: index + firstColonIdx, + end: index + firstColonIdx + 1, + }; + // console.log(locFirst); + addColon(locFirst); + const lastColonIdx = outerContent.lastIndexOf(':'); + if (lastColonIdx !== firstColonIdx) { + const locLast = { + start: index + lastColonIdx, + end: index + lastColonIdx + 1, + }; + addColon(locLast); + } + } + }); + return escapableSnippets; +} + +// /|'"/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/]+)*\s*)(?:\/>|>([\S\s]*?)<\/style>)/g + +/* eslint-disable tsdoc/syntax */ +/** + * @param document - The document in which to find escapable snippets. + * @param documentLines - The lines of the document, i.e., `document.split('\n')`. + * @returns An array of escapable snippets of: + * - `'code'`: Code spans (`` `...` ``) and fenced code blocks + * (```` ```...\n...\n``` ````) + * - `'math'`: Inline math (`$...$`) and display math (`$$...$$`) + * - `'svelte'`: Special tags (`{@const ...}`, `{@debug ...}`) + * - `'svelte'`: Delimiters of logic blocks (`{#if ...}`, `{#else ...}`, + * `{/if}`, etc.) + * - `'mustacheTag'` Mustache tags (`{...}`), i.e., almost anything in braces + * that hasn't already been escaped by this method or otherwise. + */ +/* eslint-enable tsdoc/syntax */ +export function getMdastES({ + ast, + document, + lines, + texSettings, +}: { + ast: MdastRoot; + document: string; + lines: string[]; + texSettings: TexEscapeSettings; +}): EscapableSnippet<'code' | 'mustacheTag' | 'tex' | 'svelte'>[] { + const escapableSnippets: EscapableSnippet< + 'code' | 'mustacheTag' | 'tex' | 'svelte' + >[] = []; + walkMdast(ast, (node) => { + // If the node is not one of the interesting types, we don't need to + // analyze it any further; instead, we just keep walking this branch + // of the tree. + if ( + !isOneOf(node.type, [ + 'math', + 'inlineMath', + 'code', + 'inlineCode', + 'mdxTextExpression', + 'mdxFlowExpression', + ]) + ) { + return true; + } + const loc = getLocationUnist(node, lines); + // Inline math and display math + if (isOneOf(node.type, ['inlineMath', 'math'])) { + if (!texSettings.enabled) return true; + typeAssert(is(node)); + nodeAssert(node.position, 'Node has positional information.'); + const isDisplayMath = texSettings.$$?.isDisplayMath ?? 'always'; + let inline: boolean = node.type === 'inlineMath'; + // Micromark parses a lot of stuff that some might expect to be + // display math as inline math, so we need to check if it really is + // inline math given the user's preferences. On the other hand, if + // Micromark parses something as display math, we can be sure that + // it really is display math. + const { start, end } = node.position; + + // `true` iff the first line of the outer content matches /^\s*\$/ + const startsWithNewline = !!lines[start.line - 1] + ?.trimStart() + .startsWith('$'); + + // `true` iff the last line of the outer content matches /\$\s*$/ + const endsWithNewline = !!lines[end.line - 1] + ?.trimEnd() + .endsWith('$'); + + if (inline) { + // Get math content _with_ the surrounding delimiters + const outerContent = document.slice(loc.start, loc.end); + // Check if the delimiters are ≥2 dollar signs + if (outerContent.match(/^\s*\$\$.*\$\$\s*$/su)) { + if (isDisplayMath === 'always') { + inline = false; + } else if (isDisplayMath === 'newline') { + inline = !(startsWithNewline && endsWithNewline); + } + } + } + + // If we're dealing with inline math, we don't pad the escape + // string. However, if we're dealing with display math, we want to + // make sure that the processed math won't be caught within a + // paragraph tag with other content, so we pad the escape string + // with newlines. + const pad = inline ? 0 : 2; + + // To follow CommonMark conventions, if the inner content starts + // resp. ends with ≥1 spaces or newlines, we trim the first resp. + // last such whitespace character. + const innerContent = node.value.replace( + /^(?: |\r\n?|\n)(.*)(?: |\r\n?|\n)$/su, + '$1', + ); + + escapableSnippets.push({ + type: 'tex', + original: { loc, outerContent: undefined }, + escapeOptions: { pad }, + processable: { + innerContent, + optionsForProcessor: { inline }, + }, + unescapeOptions: { removeParagraphTag: !inline }, + }); + } + // Code spans and fenced code blocks + else if (isOneOf(node.type, ['inlineCode', 'code'])) { + typeAssert(is(node)); + nodeAssert(node.position, 'Node has positional information.'); + const inline = node.type === 'inlineCode'; + const { start, end } = node.position; + escapableSnippets.push({ + type: 'code', + original: { loc, outerContent: undefined }, + processable: { + innerContent: node.value, + optionsForProcessor: inline + ? { _wrap: true, inline } + : { + _wrap: true, + lang: node.lang ?? undefined, + inline, + info: node.meta ?? undefined, + }, + }, + escapeOptions: { + pad: inline + ? false + : [ + lines[start.line - 1 - 1]?.trim().length !== 0, + lines[end.line - 1 + 1]?.trim().length !== 0, + ], + }, + unescapeOptions: { removeParagraphTag: !inline }, + }); + } else if ( + isOneOf(node.type, ['mdxTextExpression', 'mdxFlowExpression']) + ) { + typeAssert( + is( + node, + ), + ); + const outerContent = document.slice(loc.start, loc.end); + // const innerContent = node.value; + // If the expression starts with `#`, `:`, or `/`, it's a Svelte + // logic block. In this case, we want to remove any

...

tags + // with which the markdown processor may wrap the escaped string. + // If the expression starts with `@html`, it's a raw HTML block. In + // this case, it should be treated as plain text, just like mustache + // tags. + if ( + node.value.match(/^\s*[#@:/]/) && + !node.value.startsWith('@html') + ) { + let pad: boolean | [string, string] = true; + if (node.position) { + // We don't want a logic block to be caught within a + // paragraph tag with other content, so we pad the escape + // string with newlines if necessary. + pad = [ + // `node.position.start.line - 1` = 0-based line number + !lines[node.position.start.line - 1 - 1]?.trim() + ? '\n\n' + : '\n', + // `node.position.end.line - 1` = 0-based line number + !lines[node.position.end.line - 1 + 1]?.trim() + ? '\n\n' + : '\n', + ]; + // pad = false; + } + escapableSnippets.push({ + original: { loc, outerContent }, + processable: undefined, + escapeOptions: { pad }, + type: 'svelte', + unescapeOptions: { removeParagraphTag: true }, + }); + } else { + escapableSnippets.push({ + type: 'mustacheTag', + original: { loc, outerContent }, + processable: undefined, + escapeOptions: { pad: false }, + unescapeOptions: { removeParagraphTag: false }, + }); + } + } + return false; + }); + return escapableSnippets; +} + +/** + * Pad a string left and right. + * + * @param str - The string to pad. + * @param padInstr - The padding instruction. If `true` (the default), a newline + * is added on both sides. If `false`, no padding is added. If a number, then + * that number of newlines (`\n`) is added to both sides. If a string, that + * string is added on both sides. If a 2-tuple, the previous procedure is + * applied independently to the left and right side of the string with the first + * and second element of the tuple, respectively. + * @returns The padded string. + * + * @example + * ```ts + * padString('foo'); // '\nfoo\n' + * padString('foo', true); // '\nfoo\n' + * padString('foo', false); // 'foo' + * padString('foo', 'bar'); // 'barfoobar' + * padString('foo', [true, false]); // '\nfoo' + * padString('foo', [true, 'bar']); // '\nfoobar' + * padString('foo', [0, 2]); // 'foo\n\n' + * padString('foo', ['bar\n', 1]); // 'bar\nfoo\n' + * padString('foo', ['bar', 'baz']); // 'barfoobaz' + * ``` + */ +export function padString( + str: string, + padInstr: PaddingInstruction | undefined = true, +): string { + if (!padInstr) return str; + const pad: [string | boolean | number, string | boolean | number] = + !isArray(padInstr) ? [padInstr, padInstr] : [...padInstr]; + return ( + (isString(pad[0]) ? pad[0] : '\n'.repeat(+pad[0])) + + str + + (isString(pad[1]) ? pad[1] : '\n'.repeat(+pad[1])) + ); +} -// export const svelteEscapeStrings: Record = { -// '&': '&', -// '<': '<', -// '>': '>', -// '"': '"', -// "'": ''', -// '{': '{', -// '}': '}', -// }; +/** + * Escape snippets in a document. + * + * @param document - The document in which to escape the snippets. + * @param snippets - The (escapable) snippets to escape. + * + */ +export function escapeSnippets( + document: string, + snippets: EscapableSnippet[], +): { + escapedDocument: string; + escapedSnippets: [string, EscapedSnippet][]; +} { + const s = new MagicString(document); + const ranges = outermostRanges([...snippets], 'original.loc'); + const escapedSnippets: [string, Snippet][] = ranges.map((range) => { + const id = uuid(); + const paddedId = padString(id, range.escapeOptions?.pad ?? false); + nodeAssert(paddedId, 'paddedId must be truthy'); + s.overwrite(range.original.loc.start, range.original.loc.end, paddedId); + return [id, range]; + }); + const escapedDocument = s.toString(); + return { escapedDocument, escapedSnippets }; +} -// export function svelteEscapeString(char: string) { -// return svelteEscapeStrings[char] ?? char; -// } +/** + * Escape colons (in tag/component names) in a document. + * + * @param document - The document in which to escape the colons. + * @returns The document with the colons escaped. + */ +export function escapeColons(document: string): string { + const snippets = getColonES(document); + const s = new MagicString(document); + snippets.forEach((snippet) => { + s.overwrite( + snippet.original.loc.start, + snippet.original.loc.end, + colonUuid, + ); + }); + return s.toString(); +} + +/** + * Unescape colons (in tag/component names) in a document. + * + * @param document - The document in which to unescape the colons. + * @returns The document with the colons unescaped. + */ +export function unescapeColons(document: string): string { + return document.replaceAll(colonUuid, ':'); +} + +export function escape( + document: string, + verbatimTags: string[] = [], + texSettings: TexEscapeSettings = { enabled: true }, +) { + // Escape colons inside special Svelte elements (e.g. ) so + // that they don't confuse the markdown processor. We don't want to escape + // the entire special Svelte element because we want the markdown processor + // to be able to transform any markdown that it may find within it. + const escapedDocument = escapeColons(document); + + // Escape other things using MDAST + const ast = parseToMdast( + escapedDocument, + [ + ...verbatimTags, + 'script', + 'style', + // `svelte${colonUuid}head`, + `svelte${colonUuid}window`, + `svelte${colonUuid}document`, + `svelte${colonUuid}body`, + `svelte${colonUuid}options`, + ], + texSettings, + ); + const lines = escapedDocument.split(/\r\n?|\n/); + return escapeSnippets(escapedDocument, [ + ...getMdastES({ + ast, + document: escapedDocument, + lines, + texSettings, + }), + // Escape Svelte syntax + ...getSvelteES(escapedDocument), + // Escape math in \[...\] and \(...\) + ...getMathInSpecialDelimsES(escapedDocument, texSettings), + ...getVerbatimES(document, verbatimTags), + ]); +} + +/** + * "Unescapes" content. + * + * @param document - Escaped content. + * @param processedSnippets - An array of 2-tuples, with the first element being + * the UUIDv4 and the second element being the processed snippet corresponding + * to that UUIDv4. + * @returns The original content, with the escaped matches restored. + */ +export function unescapeSnippets( + document: string, + processedSnippets: [string, ProcessedSnippet][], +): string { + let unescaped = document; + const keys: string[] = processedSnippets.map((v) => v[0]); + const processedSnippetsRecord = Object.fromEntries(processedSnippets); + if (keys.length === 0) return document; + unescaped = XRegExp.replace( + document, + new RegExp( + `(?:(

\\s*)(${keys.join('|')})(\\s*

))|(${keys.join('|')})`, + 'g', + ), + (...match) => { + typeAssert(is<(string | undefined)[]>(match)); + const key = match[2] ?? match[4]; + nodeAssert(key, "RegExp must've matched an UUIDv4 key."); + const processedSnippet = processedSnippetsRecord[key]; + if (!processedSnippet) return key; + if ( + !processedSnippet.unescapeOptions?.removeParagraphTag && + match[2] + ) { + nodeAssert( + match[1] && match[3], + 'Matched

...

, so

and

tags must be present.', + ); + return match[1] + processedSnippet.processed + match[3]; + } + return processedSnippet.processed; + }, + ); + return unescaped; +} + +/** + * Parse a document into an MDAST. + * + * @param document - The document to parse. + * @param texSettings - The settings for escaping TeX math. + * @returns The MDAST of the document. + * + * @remarks This function uses the following modules and plugins to parse the + * document: + * - `mdast-util-from-markdown`: Its `fromMarkdown` method is the backbone of + * our `parseToMdast` method. + * - + */ +export function parseToMdast( + document: string, + verbatimTags: string[] | undefined = undefined, + texSettings: TexEscapeSettings = getDefaultSveltexConfig().general.tex, +): MdastRoot { + return mdastFromMarkdown(document, { + extensions: [ + micromarkMdxMd(), + micromarkMdxJsx(), + // micromarkSkip(verbatimTags), + micromarkMath({ + singleDollarTextMath: + texSettings.enabled && + (texSettings.delims?.inline?.singleDollar ?? true), + }), + micromarkMdxExpression(), + micromarkSkip(verbatimTags), + ], + mdastExtensions: [ + mdastMathFromMarkdown(), + mdastMdxExpressionFromMarkdown(), + ], + }); +} diff --git a/src/utils/fs.ts b/src/utils/fs.ts index 2c57ecc..c9f78cd 100644 --- a/src/utils/fs.ts +++ b/src/utils/fs.ts @@ -44,3 +44,17 @@ async function writeFileEnsureDir(file: string, content: string) { if (dir !== '.') await ensureDir(dir); await fs.writeFile(file, content, 'utf8'); } + +/** + * Checks if a file or directory exists at the specified path. + * + * @param path - The path to check. + * @returns `true` if the path exists, `false` otherwise. + */ +export function pathExists(path: string) { + try { + return fs.existsSync(path); + } catch { + return false; + } +} diff --git a/src/utils/globals.ts b/src/utils/globals.ts deleted file mode 100644 index f1c931c..0000000 --- a/src/utils/globals.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Internal dependencies -import { detectPackageManager, log, prettifyError } from '$utils/debug.js'; - -// External dependencies -import { VERSION, semverMajor } from '$deps.js'; - -function getMajorVersion(version: string): number { - try { - return (semverMajor as (v: string) => number)(version); - } catch (error) { - log( - 'error', - `Could not determine Svelte compiler version. Got: "${version}".\n\n${prettifyError(error)}\n\n`, - ); - return -1; - } -} - -/** - * The major version of the Svelte compiler (e.g., `4` or `5`). - * - * @see {@link VERSION | `VERSION`}, from `svelte/compiler`. - */ -export const SVELTE_MAJOR_VERSION: number = getMajorVersion(VERSION); - -/** - * Array to keep track of missing dependencies - */ -export const missingDeps: string[] = []; - -/** - * Package manager used in the project, detected by the `detect-package-manager` - * package. - */ -export const packageManager: 'pnpm' | 'bun' | 'npm' | 'yarn' = - detectPackageManager(); diff --git a/src/utils/html.ts b/src/utils/html.ts deleted file mode 100644 index d13ef90..0000000 --- a/src/utils/html.ts +++ /dev/null @@ -1,21 +0,0 @@ -// External dependencies -import { htmlTagNames } from '$deps.js'; - -/** - * Check if a string is a valid name for a component. For this to be the case, - * it has to not be an HTML tag name, and it has to be an alphanumeric string - * that starts with a letter. - * - * @param name - The name to check. - * @returns `true` if the name is valid, `false` otherwise. - * - * @example - * ```ts - * isValidComponentName('div'); // false - * isValidComponentName('div2'); // true - * isValidComponentName('MyComponent'); // true - * ``` - */ -export function isValidComponentName(name: string): boolean { - return /^[a-zA-Z][a-zA-Z0-9]*$/.test(name) && !htmlTagNames.includes(name); -} diff --git a/src/utils/micromark/skip-flow.ts b/src/utils/micromark/skip-flow.ts new file mode 100644 index 0000000..297fe65 --- /dev/null +++ b/src/utils/micromark/skip-flow.ts @@ -0,0 +1,400 @@ +/* eslint-disable @typescript-eslint/no-this-alias */ +// Types +import type { + Code, + Construct, + Effects, + State, + TokenizeContext, +} from 'micromark-util-types'; + +import { + markdownLineEnding, + markdownLineEndingOrSpace, +} from 'micromark-util-character'; +import { codes } from 'micromark-util-symbol'; +import { skipTags } from '$utils/micromark/syntax.js'; +import { htmlRawNames } from 'micromark-util-html-tag-name'; + +declare module 'micromark-util-types' { + interface TokenTypeMap { + skipFlow: 'skipFlow'; + skipFlowData: 'skipFlowData'; + } +} + +const nonLazyContinuationStart: Construct = { + tokenize: tokenizeNonLazyContinuationStart, + partial: true, +}; + +// // Could also still provide second param `context: TokenizeContext`, see +// // `Resolver` type. +// export function resolveToSkipFlow(events: Event[]): Event[] { +// let index = events.length; +// while (index--) { +// if ( +// events[index]?.[0] === 'enter' && +// events[index]?.[1].type === 'skipFlow' +// ) { +// break; +// } +// } +// if (index > 1 && events[index - 2]?.[1].type === 'linePrefix') { +// // Add the prefix start to the HTML token. +// // eslint-disable-next-line @typescript-eslint/no-non-null-assertion +// events[index]![1].start = events[index - 2]![1].start; +// // Add the prefix start to the HTML line token. +// // eslint-disable-next-line @typescript-eslint/no-non-null-assertion +// events[index + 1]![1].start = events[index - 2]![1].start; +// // Remove the line prefix. +// events.splice(index - 2, 2); +// } +// return events; +// } + +export function tokenizeSkipFlow( + this: TokenizeContext, + effects: Effects, + ok: State, + nok: State, +): State { + const self = this; + let closingTag: boolean; + let buffer: string; + let openingTagString: string = ''; + + return start; + + /** + * Start of HTML (flow). + * + * ```markdown + * > | + * ^ + * ``` + */ + function start(code: Code): State | undefined { + // To do: parse indent like `markdown-rs`. + return before(code); + } + + /** + * At `<`, after optional whitespace. + * + * ```markdown + * > | + * ^ + * ``` + */ + function before(code: Code): State | undefined { + effects.enter('skipFlow'); + effects.enter('skipFlowData'); + effects.consume(code); + return open; + } + + /** + * After `<`, at tag name or other stuff. + * + * ```markdown + * > | + * ^ + * > | + * ^ + * > | + * ^ + * ``` + */ + function open(this: TokenizeContext, code: Code): State | undefined { + // ASCII alphabetical + if (code !== null && asciiAlphabetic(code)) { + effects.consume(code); + buffer = String.fromCharCode(code); + return tagName; + } + return nok(code); + } + + /** + * In tag name. + * + * ```markdown + * > | + * ^^ + * > | + * ^^ + * ``` + */ + function tagName(this: TokenizeContext, code: Code): State | undefined { + if ( + code === null || + code === codes.slash || + code === codes.greaterThan || + markdownLineEndingOrSpace(code) + ) { + const slash = code === codes.slash; + const bufferLowerCase = buffer.toLowerCase(); + // `script`, `style`, `textarea`, and `pre` should be treated as + // case-insensitive. + if (htmlRawNames.includes(bufferLowerCase)) { + openingTagString = bufferLowerCase; + } else { + openingTagString = buffer; + } + if (!slash && !closingTag && skipTags.includes(openingTagString)) { + return self.interrupt ? ok(code) : continuation(code); + } + return nok(code); + } + + // ASCII alphanumerical and `-`, `.`, `:`, and `_`. + if (asciiAlphanumeric(code) || tagPunctuation(code)) { + effects.consume(code); + buffer += String.fromCharCode(code); + return tagName; + } + return nok(code); + } + + /** + * In continuation of any HTML kind. + * + * ```markdown + * > | + * ^ + * ``` + */ + function continuation(code: Code): State | undefined { + if (code === codes.lessThan) { + effects.consume(code); + return continuationRawTagOpen; + } + if (code === null || markdownLineEnding(code)) { + effects.exit('skipFlowData'); + return continuationStart(code); + } + effects.consume(code); + return continuation; + } + + /** + * In continuation, at eol. + * + * ```markdown + * > | + * ^ + * | asd + * ``` + */ + function continuationStart(code: Code): State | undefined { + return effects.check( + nonLazyContinuationStart, + continuationStartNonLazy, + continuationAfter, + )(code); + } + + /** + * In continuation, at eol, before non-lazy content. + * + * ```markdown + * > | + * ^ + * | asd + * ``` + */ + function continuationStartNonLazy(code: Code): State | undefined { + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return continuationBefore; + } + + /** + * In continuation, before non-lazy content. + * + * ```markdown + * | + * > | asd + * ^ + * ``` + */ + function continuationBefore(code: Code): State | undefined { + if (code === null || markdownLineEnding(code)) { + return continuationStart(code); + } + effects.enter('skipFlowData'); + return continuation(code); + } + + /** + * In raw continuation, after `<`, at `/`. + * + * ```markdown + * > | + * ^ + * ``` + */ + function continuationRawTagOpen(code: Code): State | undefined { + if (code === codes.slash) { + effects.consume(code); + buffer = ''; + return continuationRawEndTagFirstChar; + } + return continuation(code); + } + + /** + * In raw continuation, after ` | + * ^^^^^^ + * ``` + */ + function continuationRawEndTagFirstChar(code: Code): State | undefined { + if (code !== null && asciiAlphabetic(code)) { + effects.consume(code); + buffer += String.fromCharCode(code); + return continuationRawEndTag; + } + return continuation(code); + } + + /** + * In raw continuation, after ` | + * ^^^^^^ + * ``` + */ + function continuationRawEndTag(code: Code): State | undefined { + if (code === codes.greaterThan) { + const bufferLowerCase = buffer.toLowerCase(); + let closingTagString: string; + // `script`, `style`, `textarea`, and `pre` should be treated as + // case-insensitive. + if (htmlRawNames.includes(bufferLowerCase)) { + closingTagString = bufferLowerCase; + } else { + closingTagString = buffer; + } + if (closingTagString === openingTagString) { + effects.consume(code); + return continuationClose; + } + return continuation(code); + } + + // ASCII alphanumerical and `-`, `.`, `:`, and `_`. + if ( + code !== null && + (asciiAlphanumeric(code) || tagPunctuation(code)) + ) { + effects.consume(code); + buffer += String.fromCharCode(code); + return continuationRawEndTag; + } + return continuation(code); + } + + /** + * In closed continuation: everything we get until the eol/eof is part of it. + * + * ```markdown + * > | + * ^ + * ``` + */ + function continuationClose(code: Code): State | undefined { + // if (code === null || markdownLineEnding(code)) { + effects.exit('skipFlowData'); + return continuationAfter(code); + // } + // effects.consume(code); + // return continuationClose; + } + + /** + * Done. + * + * ```markdown + * > | + * ^ + * ``` + */ + function continuationAfter(code: Code): State | undefined { + effects.exit('skipFlow'); + // // Feel free to interrupt. + // tokenizer.interrupt = false + // // No longer concrete. + // tokenizer.concrete = false + return ok(code); + } +} + +function tokenizeNonLazyContinuationStart( + this: TokenizeContext, + effects: Effects, + ok: State, + nok: State, +): State { + const self = this; + return start; + + /** + * At eol, before continuation. + * + * ```markdown + * > | * ```js + * ^ + * | b + * ``` + */ + function start(code: Code): State | undefined { + if (markdownLineEnding(code)) { + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return after; + } + return nok(code); + } + + /** + * A continuation. + * + * ```markdown + * | * ```js + * > | b + * ^ + * ``` + */ + function after(this: TokenizeContext, code: Code): State | undefined { + return self.parser.lazy[self.now().line] ? nok(code) : ok(code); + } +} + +function tagPunctuation(code: NonNullable): boolean { + return ( + code === codes.dash || + code === codes.dot || + code === codes.colon || + code === codes.underscore + ); +} + +function asciiAlphabetic(code: NonNullable): boolean { + return ( + (codes.uppercaseA <= code && code <= codes.uppercaseZ) || + (codes.lowercaseA <= code && code <= codes.lowercaseZ) + ); +} + +function asciiAlphanumeric(code: NonNullable): boolean { + return ( + asciiAlphabetic(code) || (codes.digit0 <= code && code <= codes.digit9) + ); +} diff --git a/src/utils/micromark/syntax.ts b/src/utils/micromark/syntax.ts new file mode 100644 index 0000000..00abda0 --- /dev/null +++ b/src/utils/micromark/syntax.ts @@ -0,0 +1,28 @@ +import type { Construct } from 'micromark-util-types'; +import { codes } from 'micromark-util-symbol'; +import { tokenizeSkipFlow } from './skip-flow.js'; +// import { tokenizeSkipText } from '$utils/micromark/skip-text.js'; + +const skipFlow: Construct = { + name: 'skipFlow', + tokenize: tokenizeSkipFlow, + // resolveTo: resolveToSkipFlow, + concrete: true, +}; + +export let skipTags: string[]; + +// const skipText: Construct = { +// name: 'skipText', +// tokenize: tokenizeSkipText, +// }; + +export function micromarkSkip( + tags: string[] | undefined = ['script', 'style'], +) { + skipTags = tags; + return { + flow: { [codes.lessThan]: skipFlow }, + text: { [codes.lessThan]: skipFlow }, + }; +} diff --git a/src/utils/misc.ts b/src/utils/misc.ts index 755918c..bcce067 100644 --- a/src/utils/misc.ts +++ b/src/utils/misc.ts @@ -1,120 +1,31 @@ // Types import type { BinaryToTextEncoding } from '$deps.js'; +import type { Transformation } from '$types/handlers/Tex.js'; // Internal dependencies -import { isBoolean, isNumber, isString } from '$type-guards/utils.js'; +import { isString } from '$type-guards/utils.js'; import { log } from '$utils/debug.js'; // External dependencies -import { createHash } from '$deps.js'; -import { Transformation } from '$types/handlers/Tex.js'; +import { createHash, htmlTagNames } from '$deps.js'; /** - * "Interprets" a string as a boolean, number, null, or undefined, if - * applicable. Otherwise, returns the string as is. + * Check if a string is a valid name for a component. For this to be the case, + * it has to not be an HTML tag name, and it has to be an alphanumeric string + * that starts with a letter. * - * @param str - The string to interpret. - * @returns The interpreted value. + * @param name - The name to check. + * @returns `true` if the name is valid, `false` otherwise. * * @example - * // All of the below are true - * interpretString('true') === true; - * interpretString('false') === false; - * interpretString('null') === null; - * interpretString('undefined') === undefined; - * interpretString('NaN') === NaN; - * interpretString('Infinity') === Infinity; - * interpretString('-Infinity') === -Infinity; - * interpretString('5') === 5; - * interpretString('5.5') === 5.5; - * interpretString('something') === 'something'; - */ -export function interpretString( - str: string | undefined, -): string | number | boolean | null | undefined { - if (str === undefined) return undefined; - const trimmedStr = str.trim(); - switch (trimmedStr) { - case 'true': - return true; - case 'false': - return false; - case 'null': - return null; - case 'undefined': - return undefined; - case 'NaN': - return NaN; - case 'Infinity': - return Infinity; - } - if (trimmedStr.endsWith('Infinity')) { - if (trimmedStr.match(/^[+]\s*Infinity$/)) { - return +Infinity; - } - if (trimmedStr.match(/^[-]\s*Infinity$/)) { - return -Infinity; - } - } - if (trimmedStr.replace(/\s*/g, '').match(/^[+-]?(\d+|\d*.\d+)$/)) { - const num = Number(trimmedStr); - if (!isNaN(num)) { - return num; - } - } - return str; -} - -/** - * Calls {@link interpretString | `interpretString`} on each value in the given - * object. - * - * @param attrs - The object whose values to interpret. - * @returns A new object with the interpreted values. - * - * @example - * ```ts - * interpretAttributes({ - * a: 'true', - * b: '5', - * c: 'something', - * }); - * ``` - * - * ...would return... - * * ```ts - * { - * a: true, - * b: 5, - * c: 'something', - * } + * isValidComponentName('div'); // false + * isValidComponentName('div2'); // true + * isValidComponentName('MyComponent'); // true * ``` */ -export function interpretAttributes( - attrs: Record, - strict: boolean = true, -): Record { - const rv: Record = {}; - for (const [key, value] of Object.entries(attrs)) { - if (value !== undefined && !isString(value)) { - const supportedValueType: boolean = - isBoolean(value) || - isNumber(value) || - (value as unknown) === null; - log( - strict ? 'error' : 'warn', - `Expected string for attribute \`${key}\`, but got \`${String(value)}\`. ${strict || !supportedValueType ? 'Ignoring attribute.' : 'Passing value as-is.'} (Hint: Numbers, booleans, null and undefined, if wrapped in double quotes, will be transformed back into their original types by Sveltex.)`, - ); - if (!strict && supportedValueType) - rv[key] = value as boolean | number | null; - } else if (value === undefined) { - rv[key] === value; - } else { - rv[key] = interpretString(value); - } - } - return rv; +export function isValidComponentName(name: string): boolean { + return /^[a-zA-Z][a-zA-Z0-9]*$/.test(name) && !htmlTagNames.includes(name); } /** @@ -204,60 +115,6 @@ export function re(strings: TemplateStringsArray, ...flags: string[]) { ); } -/** - * Splits content into segments based on ` - * B - * - * D - * ` - * ``` - * - * Then the output of `splitContent(content)` would be: - * - * ```ts - * [ - * "", - * 'B', - * '', - * 'D' - * ] - * ``` - */ -export function splitContent(content: string): string[] { - const regex = re` - (?: - \n', ''); + html = html.replace(/

(.*?)<\/p>/gsu, '$1'); + code = code?.replace(/

(.*?)<\/p>/gsu, '$1'); + if ( + (s.markdownBackend === 'markdown-it' && + [127, 137, 139].includes(example)) || + (s.markdownBackend === 'marked' && + [126, 130].includes(example)) + ) { + expect(code?.replace(/\s/g, '')).toContain( + html.replace(/\s/g, ''), + ); + } else if ( + s.markdownBackend === 'marked' && + [12].includes(example) + ) { + // + } else { + expect(code).toContain(html.trim()); + } + expect(log).not.toHaveBeenCalled(); + }); + }, + ); + + describe.concurrent.each(processors)( + 'CommonMark: code spans ($markdownBackend)', + (s) => { + fixture(); + it.concurrent.each([ + { + markdown: '`foo`\n', + html: '

foo

\n', + example: 328, + }, + { + markdown: '`` foo ` bar ``\n', + html: '

foo ` bar

\n', + example: 329, + }, + { + markdown: '` `` `\n', + html: '

``

\n', + example: 330, + }, + { + markdown: '` `` `\n', + html: '

``

\n', + example: 331, + }, + { + markdown: '` a`\n', + html: '

a

\n', + example: 332, + }, + { + markdown: '`\tb\t`\n', + html: '

\tb\t

\n', + example: 333, + }, + { + markdown: '` `\n` `\n', + html: '

\n

\n', + example: 334, + }, + { + markdown: '``\nfoo\nbar \nbaz\n``\n', + html: '

foo bar baz

\n', + example: 335, + }, + { + markdown: '``\nfoo \n``\n', + html: '

foo

\n', + example: 336, + }, + { + markdown: '`foo bar \nbaz`\n', + html: '

foo bar baz

\n', + example: 337, + }, + { + markdown: '`foo\\`bar`\n', + html: '

foo\\bar`

\n', + example: 338, + }, + { + markdown: '``foo`bar``\n', + html: '

foo`bar

\n', + example: 339, + }, + { + markdown: '` foo `` bar `\n', + html: '

foo `` bar

\n', + example: 340, + }, + { + markdown: '*foo`*`\n', + html: '

*foo*

\n', + example: 341, + }, + { + markdown: '[not a `link](/foo`)\n', + html: '

[not a link](/foo)

\n', + example: 342, + }, + { + markdown: '``\n', + html: '

<a href="">`

\n', + example: 343, + }, + // { + // markdown: '
`\n', + // html: '

`

\n', + // example: 344, + // }, + { + markdown: '``\n', + html: '

<https://foo.bar.baz>`

\n', + example: 345, + }, + // { + // markdown: '`\n', + // html: '

https://foo.bar.`baz`

\n', + // example: 346, + // }, + { + markdown: '```foo``\n', + html: '

```foo``

\n', + example: 347, + }, + { + markdown: '`foo\n', + html: '

`foo

\n', + example: 348, + }, + { + markdown: '`foo``bar``\n', + html: '

`foobar

\n', + example: 349, + }, + ])('Example $example', async ({ markdown, html, example }) => { + let code = ( + await s.markup({ + content: markdown, + filename: `${String(example)}.sveltex`, + }) + )?.code; + code = code?.replaceAll(' class="language-plaintext"', ''); + code = code?.replace('\n', ''); + html = html.replace(/

(.*?)<\/p>/gsu, '$1'); + code = code?.replace(/

(.*?)<\/p>/gsu, '$1'); + if ( + s.markdownBackend === 'unified' && + [343, 345].includes(example) + ) { + // It seems unified does not escapes some special characters in + // the same way as other markdown processors. + if (example === 343) { + expect(code).toContain( + '<a href="">`', + ); + } else if (example === 345) { + expect(code).toContain( + '<https://foo.bar.baz>`', + ); + } + } else expect(code).toContain(html.trim()); + expect(log).not.toHaveBeenCalled(); + }); + }, + ); +}); diff --git a/tests/Sveltex/sveltex.error.test.ts b/tests/Sveltex/sveltex.error.test.ts index deec726..8f10176 100644 --- a/tests/Sveltex/sveltex.error.test.ts +++ b/tests/Sveltex/sveltex.error.test.ts @@ -1,27 +1,30 @@ -import { missingDeps } from '$utils/globals.js'; +import { missingDeps } from '$utils/env.js'; import { sveltex } from '$Sveltex.js'; import { consoles } from '$utils/debug.js'; -import { afterAll, describe, expect, it, suite, vi } from 'vitest'; +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; import { spy } from '$tests/fixtures.js'; -suite('sveltex error handling', async () => { - await spy(['writeFile', 'log', 'mkdir'], true); +describe('sveltex error handling', () => { + beforeAll(async () => { + await spy(['writeFile', 'log', 'mkdir'], true); + }); afterAll(() => { vi.restoreAllMocks(); }); it('catches errors', async () => { - vi.mock('svelte/compiler', async (importOriginal) => { - const actual = await importOriginal(); - if (typeof actual !== 'object') { - throw new Error('test error'); - } - return { - ...actual, - parse: () => { - throw new Error('test error'); - }, - }; - }); + vi.mock( + 'mdast-util-from-markdown', + async ( + orig: () => Promise, + ) => { + return { + ...(await orig()), + fromMarkdown: () => { + throw new Error('test error'); + }, + }; + }, + ); const consoleErrorMock = vi .spyOn(consoles, 'error') .mockImplementation(() => undefined); diff --git a/tests/Sveltex/sveltex.real.test.ts b/tests/Sveltex/sveltex.real.test.ts index 6ca8602..6341051 100644 --- a/tests/Sveltex/sveltex.real.test.ts +++ b/tests/Sveltex/sveltex.real.test.ts @@ -9,17 +9,18 @@ import type { TexBackend } from '$types/handlers/Tex.js'; import { Sveltex, sveltex } from '$Sveltex.js'; import { spy } from '$tests/fixtures.js'; import { isArray, isString } from '$type-guards/utils.js'; -import { splitContent } from '$utils/misc.js'; +import { re } from '$utils/misc.js'; -import { assert, is, uuid } from '$deps.js'; +import { typeAssert, is, uuid } from '$deps.js'; import { + type MockInstance, afterAll, afterEach, + beforeAll, beforeEach, describe, expect, it, - suite, vi, } from 'vitest'; @@ -108,6 +109,18 @@ const preprocessors = [ ), ] as Sveltex[]; +function splitContent(content: string): string[] { + return content.match(splitContentRegExp) ?? []; +} + +const splitContentRegExp = re` + (?: + \n

\n\n
code', + '\n
\n\n
\ncode', ); expect( Object.keys(sp.advancedTexHandler.texComponents).length, @@ -103,6 +106,7 @@ suite('Sveltex', async () => { expect((scriptOut as Processed).code).toEqual( "\nimport Sveltex__tex__something from '/src/sveltex/tex/something.svelte';\nimport '/src/sveltex/mathjax@3.2.2.svg.min.css';\nimport '/src/sveltex/highlight.js@11.9.0.default.min.css';\n", ); + expect(log).toHaveBeenCalledTimes(1); sp.advancedTexHandler.texComponents = {}; }); @@ -134,18 +138,19 @@ suite('Sveltex', async () => { '7a541239-3058-460b-b3c6-5076a2f3f73b.sveltex', }) )?.code, - ).not.toContain('Sveltex__'); + ).toBeUndefined(); sp.advancedTexHandler.texComponents = {}; }); it('works', async () => { const markupOut = await sp.markup({ content: - 'x`code`$x$', + 'x\n`code`\n$x$', filename: '9ae17b43-d19c-4ca3-9772-36e506ffb4a5.sveltex', }); + expect((markupOut as Processed).code).toContain( - '\n
\n\n
some text here
\n
code', + '\n
\n\n
some text here
\n
\ncode\n', ); expect( Object.keys(sp.advancedTexHandler.texComponents).length, @@ -159,11 +164,11 @@ suite('Sveltex', async () => { const scriptOut = await sp.script({ content: '', attributes: {}, - markup: 'x`code`$x$', + markup: 'x`code`$x$', filename: '9ae17b43-d19c-4ca3-9772-36e506ffb4a5.sveltex', }); expect((scriptOut as Processed).code).toEqual( - "\nimport Sveltex__tex__ref_as_valueless_attribute from '/src/sveltex/tex/ref-as-valueless-attribute.svelte';\nimport '/src/sveltex/mathjax@3.2.2.svg.min.css';\nimport '/src/sveltex/highlight.js@11.9.0.default.min.css';\n", + "\nimport Sveltex__tex__ref_without_quotation_marks from '/src/sveltex/tex/ref-without-quotation-marks.svelte';\nimport '/src/sveltex/mathjax@3.2.2.svg.min.css';\nimport '/src/sveltex/highlight.js@11.9.0.default.min.css';\n", ); sp.advancedTexHandler.texComponents = {}; @@ -172,11 +177,11 @@ suite('Sveltex', async () => { it('works (coffeescript)', async () => { const markupOut = await sp.markup({ content: - 'x`code`$x$', + 'x\n`code`\n$x$', filename: '420274ac-0f4d-49b9-842e-f9937ae45ca6.sveltex', }); expect((markupOut as Processed).code).toContain( - '\n
\n\n
some text here
\n
', + '\n
\n\n
some text here
\n
', ); expect( Object.keys(sp.advancedTexHandler.texComponents).length, @@ -190,11 +195,11 @@ suite('Sveltex', async () => { const scriptOut = await sp.script({ content: '', attributes: { lang: 'coffeescript' }, - markup: 'x', + markup: 'x', filename: '420274ac-0f4d-49b9-842e-f9937ae45ca6.sveltex', }); expect((scriptOut as Processed).code).toEqual( - "\n```\nimport Sveltex__tex__ref_as_valueless_attribute from '/src/sveltex/tex/ref-as-valueless-attribute.svelte';\nimport '/src/sveltex/mathjax@3.2.2.svg.min.css';\nimport '/src/sveltex/highlight.js@11.9.0.default.min.css';\n```\n", + "\n```\nimport Sveltex__tex__ref_without_quotation_marks from '/src/sveltex/tex/ref-without-quotation-marks.svelte';\nimport '/src/sveltex/mathjax@3.2.2.svg.min.css';\nimport '/src/sveltex/highlight.js@11.9.0.default.min.css';\n```\n", ); sp.advancedTexHandler.texComponents = {}; diff --git a/tests/Sveltex/sveltex.test.ts b/tests/Sveltex/sveltex.test.ts index 1dd2b4b..d5e1483 100644 --- a/tests/Sveltex/sveltex.test.ts +++ b/tests/Sveltex/sveltex.test.ts @@ -7,19 +7,19 @@ import type { MarkdownBackend } from '$types/handlers/Markdown.js'; import type { TexBackend } from '$types/handlers/Tex.js'; import { sveltex, type Sveltex } from '$Sveltex.js'; -import { Processed } from '$types/Sveltex.js'; import { AdvancedTexHandler } from '$handlers/AdvancedTexHandler.js'; import { CodeHandler } from '$handlers/CodeHandler.js'; import { MarkdownHandler } from '$handlers/MarkdownHandler.js'; import { TexHandler } from '$handlers/TexHandler.js'; -import { spy } from '$tests/fixtures.js'; +import { removeEmptyLines, spy } from '$tests/fixtures.js'; import { range } from '$tests/utils.js'; -import { SourceMapConsumer } from 'source-map'; -import { afterAll, describe, expect, it, suite, vi } from 'vitest'; +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; -suite.concurrent('Sveltex', async () => { - await spy(['writeFile', 'log', 'existsSync', 'mkdir'], true); +describe.concurrent('Sveltex', () => { + beforeAll(async () => { + await spy(['writeFile', 'log', 'existsSync', 'mkdir'], true); + }); afterAll(() => { vi.restoreAllMocks(); }); @@ -82,22 +82,24 @@ suite.concurrent('Sveltex', async () => { process: () => 'custom output advanced tex', }, ); - expect(await preprocessor.markdownHandler.process('')).toEqual( - 'custom output markdown', - ); - expect(await preprocessor.codeHandler.process('')).toEqual( - '
\ncustom output code\n
', - ); - expect(await preprocessor.texHandler.process('')).toEqual( - 'custom output tex', - ); expect( - await preprocessor.advancedTexHandler.process('', { - attributes: { ref: 'ref' }, - selfClosing: false, - tag: 'name', - filename: 'test.sveltex', - }), + (await preprocessor.markdownHandler.process('')).processed, + ).toEqual('custom output markdown'); + expect( + (await preprocessor.codeHandler.process('')).processed, + ).toEqual('
custom output code\n
'); + expect( + (await preprocessor.texHandler.process('')).processed, + ).toEqual('custom output tex'); + expect( + ( + await preprocessor.advancedTexHandler.process('', { + attributes: { ref: 'ref' }, + selfClosing: false, + tag: 'name', + filename: 'test.sveltex', + }) + ).processed, ).toEqual('custom output advanced tex'); }); it('should throw error if corresponding backend is not custom', async () => { @@ -204,194 +206,196 @@ preprocessor.configure({ }, }); -suite.each([ - [ - [ - 'hello', - '', - 'test1', - 'test2', - 'test3', - 'test4', - 'test5', - 'test6', - 'test7', - 'test8', - 'test9', - '', - 'there', // 1 - '`1`', // 2 - '{#if condition}', // 3 - '*a* {mustache}', // 4 - '{:else}', // 5 - '**b**', // 6 - '{/if}', // 7 - '*italic*', // 8 - '`code`', // 9 - 'or **bold**', // 10 - ], - [ - null, - null, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 15, - 15, - 17, - 17, - 19, - 19, - 19, - 19, - ], - ], -])('source maps', async (inputLines, lineMap) => { - const input = inputLines.join('\n'); - const result = (await preprocessor.markup({ - content: input, - filename: 'test.sveltex', - })) as Processed | undefined; - if (result === undefined) { - return; - } - const output = result.code; - const outputLines = output.split('\n'); - const map = result.map; - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, - // @typescript-eslint/no-explicit-any, - // @typescript-eslint/no-non-null-assertion - if (map === undefined) { - return; - } - const smc = await new SourceMapConsumer(map); - describe('output', () => { - it('should be as expected', () => { - expect(output).toEqual( - [ - '', // 2 - 'hello', // 3 - '', // 4 - 'test1', - 'test2', - 'test3', - 'test4', - 'test5', - 'test6', - 'test7', - 'test8', - 'test9', - '', // 10 - 'there', // 11 - '1', // 12 - '{#if condition}', // 13 - 'a {mustache}', // 14 - '{:else}', // 15 - 'b', // 16 - '{/if}', // 17 - 'italic', // 18 - 'code', // 19 - 'or bold', // 20 - ].join('\n'), - ); - }); - }); +// suite.skip.each([ +// [ +// [ +// 'hello', +// '', +// 'test1', +// 'test2', +// 'test3', +// 'test4', +// 'test5', +// 'test6', +// 'test7', +// 'test8', +// 'test9', +// '', +// 'there', // 1 +// '`1`', // 2 +// '{#if condition}', // 3 +// '*a* {mustache}', // 4 +// '{:else}', // 5 +// '**b**', // 6 +// '{/if}', // 7 +// '*italic*', // 8 +// '`code`', // 9 +// 'or **bold**', // 10 +// ], +// [ +// null, +// null, +// 1, +// 1, +// 1, +// 1, +// 1, +// 1, +// 1, +// 1, +// 1, +// 1, +// 1, +// 1, +// 1, +// 1, +// 15, +// 15, +// 17, +// 17, +// 19, +// 19, +// 19, +// 19, +// ], +// ], +// ])('source maps', async (inputLines, lineMap) => { +// const input = inputLines.join('\n'); +// const result = (await preprocessor.markup({ +// content: input, +// filename: 'test.sveltex', +// })) as Processed | undefined; +// if (result === undefined) { +// return; +// } +// const output = result.code; +// const outputLines = output.split('\n'); +// const map = result.map; +// // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, +// // @typescript-eslint/no-explicit-any, +// // @typescript-eslint/no-non-null-assertion +// if (map === undefined) { +// return; +// } +// const smc = await new SourceMapConsumer(map); +// describe('output', () => { +// it('should be as expected', () => { +// expect(output).toEqual( +// [ +// '', // 2 +// 'hello', // 3 +// '', // 4 +// 'test1', +// 'test2', +// 'test3', +// 'test4', +// 'test5', +// 'test6', +// 'test7', +// 'test8', +// 'test9', +// '', // 10 +// 'there', // 11 +// '1', // 12 +// '{#if condition}', // 13 +// 'a {mustache}', // 14 +// '{:else}', // 15 +// 'b', // 16 +// '{/if}', // 17 +// 'italic', // 18 +// 'code', // 19 +// 'or bold', // 20 +// ].join('\n'), +// ); +// }); +// }); - describe.each(range(1, outputLines.length))( - 'preimage of line %o of result', - (outputLine) => { - const outputLineIndex0 = outputLine - 1; - const origPos = smc.originalPositionFor({ - line: outputLine, - column: 0, - }); - it(`output line ${String(outputLine)} comes from input line ${String(lineMap[outputLineIndex0])}`, async () => { - const input = inputLines.join('\n'); - await preprocessor.markup({ - content: input, - filename: 'test.sveltex', - }); - // const outputLines = output.split('\n'); - // const map = result?.map; - expect(origPos.line).toEqual(lineMap[outputLineIndex0]); - }); - }, - ); +// describe.each(range(1, outputLines.length))( +// 'preimage of line %o of result', +// (outputLine) => { +// const outputLineIndex0 = outputLine - 1; +// const origPos = smc.originalPositionFor({ +// line: outputLine, +// column: 0, +// }); +// it(`output line ${String(outputLine)} comes from input line ${String(lineMap[outputLineIndex0])}`, async () => { +// const input = inputLines.join('\n'); +// await preprocessor.markup({ +// content: input, +// filename: 'test.sveltex', +// }); +// // const outputLines = output.split('\n'); +// // const map = result?.map; +// expect(origPos.line).toEqual(lineMap[outputLineIndex0]); +// }); +// }, +// ); - describe('should provide empty source map if sorcery fails', () => { - it('should provide empty source map', async () => { - const sorceryLoadMock = vi - .spyOn(await import('sorcery'), 'load') - .mockResolvedValueOnce(null); - const result = (await preprocessor.markup({ - content: input, - filename: 'test.sveltex', - })) as Processed; - expect(result.map).toEqual({ - file: 'test.sveltex', - mappings: '', - names: [], - sources: [], - sourcesContent: [], - version: 3, - }); - sorceryLoadMock.mockRestore(); - }); - }); -}); +// describe('should provide empty source map if sorcery fails', () => { +// it('should provide empty source map', async () => { +// const sorceryLoadMock = vi +// .spyOn(await import('sorcery'), 'load') +// .mockResolvedValueOnce(null); +// const result = (await preprocessor.markup({ +// content: input, +// filename: 'test.sveltex', +// })) as Processed; +// expect(result.map).toEqual({ +// file: 'test.sveltex', +// mappings: '', +// names: [], +// sources: [], +// sourcesContent: [], +// version: 3, +// }); +// sorceryLoadMock.mockRestore(); +// }); +// }); +// }); -suite('edge cases', async () => { - const s = await sveltex({ - markdownBackend: 'marked', - codeBackend: 'starry-night', - texBackend: 'none', - advancedTexBackend: 'none', - }); - await s.configure({ - advancedTex: { - components: { - TeX: {}, +describe('edge cases', () => { + let s: Sveltex<'marked', 'starry-night'>; + beforeAll(async () => { + s = await sveltex({ + markdownBackend: 'marked', + codeBackend: 'starry-night', + }); + await s.configure({ + advancedTex: { + components: { + TeX: {}, + }, }, - }, - verbatim: { - verbatimEnvironments: { - Verbatim: {}, + verbatim: { + verbatimEnvironments: { + Verbatim: {}, + Verb: {}, + }, }, - }, - code: { - languages: 'common', - }, + code: { + languages: 'common', + }, + }); }); async function markup(content: string, filename: string = 'test.sveltex') { return (await s.markup({ content, filename }))?.code; } describe('escaping edge cases', () => { - it('Verbatim inside Code', async () => { + it('Verb inside Verbatim', async () => { expect( await markup( [ - '```html', '', + '', 'test', + '', '', - '```', ].join('\n'), ), ).toEqual( - '\n\n\n\n
\n<Verbatim>\ntest\n</Verbatim>\n
', + '\n\n<Verb>\ntest\n</Verb>\n', ); }); @@ -404,11 +408,17 @@ suite('edge cases', async () => { ), ).toContain('\n```\ntest\n```\n'); }); + + it('dollar signs in mustache tags', async () => { + expect(await markup(["text {'$$'} text"].join('\n'))).toContain( + "text {'$$'} text", + ); + }); }); }); -suite.concurrent('sveltex()', async () => { - describe.concurrent('basics', () => { +describe('sveltex()', () => { + describe('basics', () => { it('is defined', () => { expect(preprocessor).toBeDefined(); expect(preprocessor.markup).toBeDefined(); @@ -436,23 +446,23 @@ suite.concurrent('sveltex()', async () => { }); }); - describe.sequential('respects svelte syntax', () => { + describe('respects svelte syntax', () => { const tests = [ { label: 'script tag', - input: 'test', + input: '\n

test

', }, { label: 'style tag', input: '', expected: - '\n', + '\n\n\n', }, { label: 'svelte:head tag', input: '_test_', expected: - '\n<em>test</em>', + '\n_test_', }, { label: 'svelte:options tag', @@ -478,43 +488,64 @@ suite.concurrent('sveltex()', async () => { expected: '\n', }, + { + label: 'svelte:element tag', + input: 'foo', + expected: + '\nfoo', + }, { label: 'if block', input: '{#if condition}\nA\n{/if}', - expected: '\n{#if condition}\nA\n{/if}', + expected: + '\n{#if condition}\n

A

\n{/if}', }, { label: 'else block', input: '{#if condition}\nA\n{:else}\nB\n{/if}', expected: - '\n{#if condition}\nA\n{:else}\nB\n{/if}', + '\n{#if condition}\n

A

\n{:else}\n

B

\n{/if}', }, { label: 'else if block', input: '{#if condition}\n>A\n{:else if otherCondition}\n*B*\n{:else}\nC\n{/if}', expected: - '\n{#if condition}
\n

A

\n
\n{:else if otherCondition}\nB\n{:else}\nC\n{/if}', + '\n{#if condition}\n
\n

A

\n
\n{:else if otherCondition}\n

B

\n{:else}\n

C

\n{/if}\n', }, { label: 'each block', input: '{#each items as item}\n*A* {item} B\n{/each}', expected: - '\n{#each items as item}\nA {item} B\n{/each}', + '\n{#each items as item}\n

A {item} B

\n{/each}\n', }, { label: 'await block', input: '{#await promise}\n*loading...*\n{:then value}\n{value}\n{:catch error}\n

{error.message}

\n{/await}', expected: - '\n{#await promise}\nloading...\n{:then value}\n{value}\n{:catch error}\n

{error.message}

\n{/await}', + '\n{#await promise}\n

loading...

\n{:then value}\n

{value}

\n{:catch error}\n

{error.message}

\n{/await}', }, { label: 'html block', input: '\n{@html "

hello, world!

"}', + expected: + '\n

{@html "

hello, world!

"}

', }, ]; - it.each(tests)('$test.label', async (test) => { - expect(await preprocess(test.input)).toEqual( - test.expected ?? test.input, + it.each(tests)('$label', async (test) => { + expect(removeEmptyLines(await preprocess(test.input))).toContain( + removeEmptyLines(test.expected ?? test.input), + ); + }); + }); + + describe("code blocks don't need more than one newline character around them", () => { + it('should work', async () => { + expect( + await preprocess( + '\n\ntext\n```typescript\n() => {let a}\n```\ntext\n\n', + ), + ).toEqual( + '\n

text

\n
() => {let a}\n
\n

text

\n', ); }); }); @@ -564,7 +595,7 @@ suite.concurrent('sveltex()', async () => { '\nalt', }, ]; - it.each(tests)('$test.label', async (test) => { + it.each(tests)('$label', async (test) => { expect(await preprocess(test.input)).toEqual(test.expected); }); }); @@ -616,15 +647,14 @@ suite.concurrent('sveltex()', async () => { label: 'code block', input: '```\nsomething\n```', expected: - '\n
\nsomething\n
', + '\n\n
something\n
\n', }, ]; - it.each(tests)('$test.label', async (test) => { + it.each(tests)('$label', async (test) => { expect(await preprocess(test.input)).toEqual(test.expected); }); }); - // eslint-disable-next-line vitest/valid-describe-callback describe('works with code blocks', () => { it('starry night should work with this', async () => { const preprocessor = await sveltex({ @@ -635,11 +665,13 @@ suite.concurrent('sveltex()', async () => { }); await preprocessor.configure({ code: { languages: 'common' } }); expect( - await preprocessor.codeHandler.process( - '```typescript\n() => {let a}\n```', - ), + ( + await preprocessor.codeHandler.process('() => {let a}', { + lang: 'typescript', + }) + ).processed, ).toEqual( - '
\n() => {let a}\n
', + '
() => {let a}\n
', ); }); @@ -648,15 +680,15 @@ suite.concurrent('sveltex()', async () => { label: 'code block (plain)', input: '```\n() => {let a}\n```', expected: - '\n\n\n\n
\n() => {let a}\n
', + '\n\n\n\n\n
() => {let a}\n
\n', }, { label: 'code block (ts)', input: '```typescript\n() => {let a}\n```', expected: - '\n\n\n\n
\n() => {let a}\n
', + '\n\n\n\n\n
() => {let a}\n
\n', }, - ])('$test.label', async (test) => { + ])('$label', async (test) => { const preprocessor = await sveltex({ markdownBackend: 'marked', codeBackend: 'starry-night', @@ -705,35 +737,36 @@ suite.concurrent('sveltex()', async () => { '\n{alt}', }, ]; - it.each(tests)('$test.label', async (test) => { + it.each(tests)('$label', async (test) => { expect(await preprocess(test.input)).toEqual(test.expected); }); }); - const preprocessorVerbatim = await sveltex({ - markdownBackend: 'none', - codeBackend: 'none', - texBackend: 'none', - advancedTexBackend: 'none', - }); - await preprocessorVerbatim.configure({ - verbatim: { - verbatimEnvironments: { - Verbatim: { - processInner: { escapeBraces: true, escapeHtml: true }, - }, - }, - }, - }); - const preprocessVerbatim = preprocessFn(preprocessorVerbatim); - describe('verbatim environments', () => { + let preprocessVerbatim: ( + input: string, + filename?: string, + ) => Promise; + beforeAll(async () => { + const preprocessorVerbatim = await sveltex(); + await preprocessorVerbatim.configure({ + verbatim: { + verbatimEnvironments: { + Verbatim: { + processInner: { + escapeBraces: true, + escapeHtml: true, + }, + }, + }, + }, + }); + preprocessVerbatim = preprocessFn(preprocessorVerbatim); + }); it('should work with custom verbatim environments', async () => { expect( await preprocessVerbatim('{test}'), - ).toEqual( - '\n{test}', - ); + ).toContain('{test}'); }); it('should work with TeX verbatim environments', async () => { @@ -756,27 +789,32 @@ suite.concurrent('sveltex()', async () => { }, }); const preprocess = preprocessFn(preprocessor); - expect(await preprocess('$x$')).toEqual('\nx'); + expect(await preprocess('$x$')).toEqual('\n$x$'); }); }); - const preprocessorMisc = await sveltex({ - markdownBackend: 'none', - codeBackend: 'escapeOnly', - texBackend: 'none', - advancedTexBackend: 'none', - }); - await preprocessorMisc.configure({ - general: { - extensions: undefined, - }, - }); - const preprocessMisc = preprocessFn(preprocessorMisc); - describe('misc', () => { - it('should work', async () => { - expect(await preprocessMisc('`{}`')).toEqual( - '\n{}', + let preprocessMisc: ( + input: string, + filename?: string, + ) => Promise; + beforeAll(async () => { + const preprocessorMisc = await sveltex({ + markdownBackend: 'none', + codeBackend: 'escapeOnly', + texBackend: 'none', + advancedTexBackend: 'none', + }); + await preprocessorMisc.configure({ + general: { + extensions: undefined, + }, + }); + preprocessMisc = preprocessFn(preprocessorMisc); + }); + it('`{}`', async () => { + expect(await preprocessMisc('`{}`')).toContain( + '{}', ); }); }); diff --git a/tests/config/defaults.test.ts b/tests/config/defaults.test.ts index 4541725..b916817 100644 --- a/tests/config/defaults.test.ts +++ b/tests/config/defaults.test.ts @@ -3,10 +3,11 @@ import { it, expect, vi, - suite, afterAll, beforeEach, afterEach, + beforeAll, + MockInstance, } from 'vitest'; import { getDefaultCodeConfiguration, @@ -29,12 +30,16 @@ function fixture() { }); } -suite.concurrent('config/defaults', async () => { +describe.concurrent('config/defaults', () => { + let log: MockInstance; + beforeAll(async () => { + const mocks = await spy(['log']); + log = mocks.log; + }); afterAll(() => { vi.restoreAllMocks(); }); fixture(); - const { log } = await spy(['log']); describe('getDefaultTexComponentConfig', () => { fixture(); @@ -142,6 +147,7 @@ suite.concurrent('config/defaults', async () => { inline: true, lang: 'javascript', wrapClassPrefix: 'language-', + _wrap: true, }; const [openingTag, closingTag] = getDefaultCodeConfiguration('escapeOnly').wrap(opts); @@ -154,6 +160,7 @@ suite.concurrent('config/defaults', async () => { inline: false, lang: 'typescript', wrapClassPrefix: 'language-', + _wrap: true, }; const [openingTag, closingTag] = getDefaultCodeConfiguration('escapeOnly').wrap(opts); @@ -165,6 +172,7 @@ suite.concurrent('config/defaults', async () => { const opts = { inline: false, wrapClassPrefix: 'language-', + _wrap: true, }; const [openingTag, closingTag] = getDefaultCodeConfiguration('escapeOnly').wrap(opts); diff --git a/tests/fixtures.ts b/tests/fixtures.ts index 549e727..08fcb3f 100644 --- a/tests/fixtures.ts +++ b/tests/fixtures.ts @@ -1,6 +1,6 @@ import { isArray, isString } from '$type-guards/utils.js'; import { mockFs } from '$dev_deps.js'; -import { type MockInstance, vi, beforeEach, afterAll } from 'vitest'; +import { type MockInstance, vi, beforeEach, afterAll, expect } from 'vitest'; type Mockable = (typeof mockableFunctions)[number]; @@ -120,6 +120,17 @@ export function fixture1( }); } +export function removeEmptyLines(input: string = '') { + return input + .split('\n') + .filter((line) => line.trim().length > 0) + .join('\n'); +} + +export function equalUpToNewlines(a: string = '', b: string = '') { + expect(removeEmptyLines(a)).toEqual(removeEmptyLines(b)); +} + // export async function mockNodeFs() { // vi.mock( // 'node:fs', @@ -160,14 +171,6 @@ export function fixture1( // }; // } -export async function createLogSpy(): Promise { - return vi.spyOn(await import('$utils/debug.js'), 'log'); -} - -export async function createSpawnCliInstructionSpy(): Promise { - return vi.spyOn(await import('$utils/cli.js'), 'spawnCliInstruction'); -} - // export async function spy(target: { // module: 'node:fs'; // readFileSync?: 'spy' | 'mock' | undefined; diff --git a/tests/handlers/AdvancedTexHandler/AdvancedTexHandler.test.ts b/tests/handlers/AdvancedTexHandler/AdvancedTexHandler.test.ts index 50d8c9e..8efeca0 100644 --- a/tests/handlers/AdvancedTexHandler/AdvancedTexHandler.test.ts +++ b/tests/handlers/AdvancedTexHandler/AdvancedTexHandler.test.ts @@ -1,10 +1,9 @@ import { AdvancedTexHandler } from '$handlers/AdvancedTexHandler.js'; -// import { sveltex } from '$Sveltex.js'; import { spy } from '$tests/fixtures.js'; -import { pathExists } from '$utils/debug.js'; import { rimraf, resolve } from '$deps.js'; import { + type MockInstance, afterAll, afterEach, beforeAll, @@ -12,11 +11,11 @@ import { describe, expect, it, - suite, vi, } from 'vitest'; import { sha256 } from '$utils/misc.js'; import { AdvancedTexConfiguration } from '$mod.js'; +import { pathExists } from '$utils/fs.js'; // async function handlers() { // const ath = await AdvancedTexHandler.create('local'); @@ -101,7 +100,7 @@ function fixture(config?: AdvancedTexConfiguration<'local'>) { }); } -suite("AdvancedTexHandler<'local'>", async () => { +describe("AdvancedTexHandler<'local'>", () => { vi.restoreAllMocks(); beforeAll(async () => { vi.spyOn(await import('$deps.js'), 'ora').mockImplementation((() => ({ @@ -112,16 +111,27 @@ suite("AdvancedTexHandler<'local'>", async () => { fail: vi.fn(), }), })) as unknown as typeof import('ora').default); + const mocks = await spy( + ['writeFile', 'log', 'spawnCliInstruction'], + false, + ); + writeFile = mocks.writeFile; + log = mocks.log; + spawnCliInstruction = mocks.spawnCliInstruction; + log.mockImplementation(() => undefined); }); afterAll(() => { vi.restoreAllMocks(); }); fixture(); - const { writeFile, log, spawnCliInstruction } = await spy( - ['writeFile', 'log', 'spawnCliInstruction'], - false, - ); - log.mockImplementation(() => undefined); + let writeFile: MockInstance; + let log: MockInstance; + let spawnCliInstruction: MockInstance; + // const { writeFile, log, spawnCliInstruction } = await spy( + // ['writeFile', 'log', 'spawnCliInstruction'], + // false, + // ); + // writeFile.mockImplementation( // async (path: string, data: string, opts: ObjectEncodingOptions) => { // if (path.endsWith('cache.json')) { @@ -178,16 +188,15 @@ suite("AdvancedTexHandler<'local'>", async () => { ); }); - it.each([ - { components: undefined }, - { components: {} }, - { components: { newComponent1: {} } }, - { - components: { newComponent2: {}, newComponent3: {} }, - }, - ])( - 'appends new tex components to current array of tex components', - async ({ components }) => { + describe('adds new tex components to current record of tex components', () => { + it.each([ + { components: undefined }, + { components: {} }, + { components: { newComponent1: {} } }, + { + components: { newComponent2: {}, newComponent3: {} }, + }, + ])('adding $components', async ({ components }) => { const origComponents = { ...ath.configuration.components, }; @@ -197,8 +206,8 @@ suite("AdvancedTexHandler<'local'>", async () => { ...origComponents, ...components, }); - }, - ); + }); + }); }); describe.each([{}])('advancedTexHandler.noteTcInFile', (config) => { @@ -254,12 +263,14 @@ suite("AdvancedTexHandler<'local'>", async () => { fixture(config); it('should work with self-closing components', async () => { expect( - await ath.process('x', { - tag: 'ExampleAlias', - attributes: { ref: 'ref' }, - selfClosing: true, - filename: 'test-73cd8d85.sveltex', - }), + ( + await ath.process('x', { + tag: 'ExampleAlias', + attributes: { ref: 'ref' }, + selfClosing: true, + filename: 'test-73cd8d85.sveltex', + }) + ).processed, ).toEqual( '
\n\n
', ); @@ -269,12 +280,14 @@ suite("AdvancedTexHandler<'local'>", async () => { it('supports aliases', async () => { expect( - await ath.process('x', { - tag: 'ExampleAlias', - attributes: { ref: 'ref' }, - selfClosing: false, - filename: 'test-d9f77b2e.sveltex', - }), + ( + await ath.process('x', { + tag: 'ExampleAlias', + attributes: { ref: 'ref' }, + selfClosing: false, + filename: 'test-d9f77b2e.sveltex', + }) + ).processed, ).toEqual( '
\n\n
', ); @@ -358,16 +371,18 @@ suite("AdvancedTexHandler<'local'>", async () => { it('css variables', async () => { expect( - await ath.process( - '\\textcolor{var(--some-css-variable)}{$x$}', - { - attributes: { ref: 'ath-something-test-348902' }, - selfClosing: false, - tag: 'tex', - filename: - 'css variables (ath-something-test-348902).sveltex', - }, - ), + ( + await ath.process( + '\\textcolor{var(--some-css-variable)}{$x$}', + { + attributes: { ref: 'ath-something-test-348902' }, + selfClosing: false, + tag: 'tex', + filename: + 'css variables (ath-something-test-348902).sveltex', + }, + ) + ).processed, ).toEqual( '
\n\n
', ); @@ -471,12 +486,14 @@ describe.each([ ])("AdvancedTexHandler<'custom'>", (handler) => { it('should work', async () => { expect( - await handler.process('input', { - tag: '', - attributes: { ref: '' }, - selfClosing: false, - filename: 'test.sveltex', - }), + ( + await handler.process('input', { + tag: '', + attributes: { ref: '' }, + selfClosing: false, + filename: 'test.sveltex', + }) + ).processed, ).toEqual('output'); }); }); @@ -494,12 +511,14 @@ describe('AdvancedTexHandler.create', () => { it('edge cases', async () => { const handler = await AdvancedTexHandler.create('local'); expect( - await handler.process('', { - attributes: { ref: 'ref' }, - selfClosing: false, - tag: '', - filename: 'test.sveltex', - }), + ( + await handler.process('', { + attributes: { ref: 'ref' }, + selfClosing: false, + tag: '', + filename: 'test.sveltex', + }) + ).processed, ).toEqual(''); }); @@ -516,12 +535,14 @@ describe('AdvancedTexHandler.create', () => { expect(handler).not.toBeNull(); expect(handler).toBeInstanceOf(AdvancedTexHandler); expect( - handler.process('ath-something-test-908423', { - tag: '', - attributes: { ref: '' }, - selfClosing: false, - filename: 'test.sveltex', - }), + ( + await handler.process('ath-something-test-908423', { + tag: '', + attributes: { ref: '' }, + selfClosing: false, + filename: 'test.sveltex', + }) + ).processed, ).toEqual('ath-something-test-908423'); }); @@ -555,12 +576,14 @@ describe('AdvancedTexHandler.create', () => { expect(handler.processor).toEqual({}); expect(handler.process).toBeTypeOf('function'); expect( - await handler.process('input', { - attributes: { ref: '' }, - selfClosing: false, - tag: '', - filename: 'test.sveltex', - }), + ( + await handler.process('input', { + attributes: { ref: '' }, + selfClosing: false, + tag: '', + filename: 'test.sveltex', + }) + ).processed, ).toEqual('custom process'); // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression expect(await handler.configure({})).toBeUndefined(); diff --git a/tests/handlers/CodeHandler/CodeHandler.escapeOnly.test.ts b/tests/handlers/CodeHandler/CodeHandler.escapeOnly.test.ts index ea0d39f..a641032 100644 --- a/tests/handlers/CodeHandler/CodeHandler.escapeOnly.test.ts +++ b/tests/handlers/CodeHandler/CodeHandler.escapeOnly.test.ts @@ -1,12 +1,15 @@ -import { suite, describe, it, expect, vi } from 'vitest'; +import { describe, it, expect, vi, beforeAll } from 'vitest'; import { CodeHandler } from '$handlers/CodeHandler.js'; import { consoles } from '$utils/debug.js'; vi.spyOn(consoles, 'error').mockImplementation(() => undefined); -suite("CodeHandler<'escapeOnly'>", async () => { - const handler = await CodeHandler.create('escapeOnly'); +describe("CodeHandler<'escapeOnly'>", () => { + let handler: CodeHandler<'escapeOnly'>; + beforeAll(async () => { + handler = await CodeHandler.create('escapeOnly'); + }); describe("CodeHandler.create('escapeOnly')", () => { it('returns instance of CodeHandler', () => { @@ -24,11 +27,13 @@ suite("CodeHandler<'escapeOnly'>", async () => { }); it('escapes `{`, `}`, `<`, and `>` in plain code correctly', async () => { - const output = await handler.process('a {c}', { - lang: 'plaintext', - }); + const output = ( + await handler.process('a {c}', { + lang: 'plaintext', + }) + ).processed; const expected = - '
\na <b> {c}\n
'; + '
a <b> {c}\n
'; expect(output).toEqual(expected); }); }); diff --git a/tests/handlers/CodeHandler/CodeHandler.highlight-js.test.ts b/tests/handlers/CodeHandler/CodeHandler.highlight-js.test.ts index a9ba22e..1ec89d8 100644 --- a/tests/handlers/CodeHandler/CodeHandler.highlight-js.test.ts +++ b/tests/handlers/CodeHandler/CodeHandler.highlight-js.test.ts @@ -1,20 +1,21 @@ /* eslint-disable vitest/no-commented-out-tests */ import { - suite, + afterAll, + afterEach, + beforeAll, + beforeEach, describe, - it, expect, + it, vi, - afterAll, - beforeEach, - afterEach, + type MockInstance, } from 'vitest'; -import { CodeHandler } from '$handlers/CodeHandler.js'; import { getDefaultCodeConfiguration } from '$config/defaults.js'; -import { consoles } from '$utils/debug.js'; -import { isFunction } from '$type-guards/utils.js'; +import { CodeHandler } from '$handlers/CodeHandler.js'; import { spy } from '$tests/fixtures.js'; +import { isFunction } from '$type-guards/utils.js'; +import { consoles } from '$utils/debug.js'; import { v4 as uuid } from 'uuid'; function fixture() { @@ -26,20 +27,30 @@ function fixture() { }); } -suite("CodeHandler<'highlight.js'>", async () => { +describe("CodeHandler<'highlight.js'>", () => { fixture(); const consoleErrorMock = vi .spyOn(consoles, 'error') .mockImplementation(() => undefined); vi.spyOn(consoles, 'warn').mockImplementation(() => undefined); - const { writeFileEnsureDir, existsSync, log } = await spy( - ['writeFileEnsureDir', 'writeFile', 'existsSync', 'log'], - true, - ); + beforeAll(async () => { + const mocks = await spy( + ['writeFileEnsureDir', 'writeFile', 'existsSync', 'log'], + true, + ); + writeFileEnsureDir = mocks.writeFileEnsureDir; + existsSync = mocks.existsSync; + log = mocks.log; + handler = await CodeHandler.create('highlight.js'); + }); + let handler: CodeHandler<'highlight.js'>; + let writeFileEnsureDir: MockInstance; + let existsSync: MockInstance; + let log: MockInstance; + afterAll(() => { vi.restoreAllMocks(); }); - const handler = await CodeHandler.create('highlight.js'); describe("CodeHandler.create('highlight.js')", () => { fixture(); it('returns instance of CodeHandler', () => { @@ -54,7 +65,7 @@ suite("CodeHandler<'highlight.js'>", async () => { it('fetches and generates CSS if run for the first time', async () => { const handler = await CodeHandler.create('highlight.js'); await handler.configure({ theme: { type: 'self-hosted' } }); - await handler.process('', {}); + (await handler.process('', {})).processed; expect(writeFileEnsureDir).toHaveBeenCalledTimes(1); expect(writeFileEnsureDir).toHaveBeenNthCalledWith( 1, @@ -64,7 +75,7 @@ suite("CodeHandler<'highlight.js'>", async () => { expect.stringContaining('pre code'), ); await handler.configure({ theme: { type: 'self-hosted' } }); - await handler.process('', {}); + (await handler.process('', {})).processed; expect(writeFileEnsureDir).toHaveBeenCalledTimes(1); }); @@ -75,7 +86,7 @@ suite("CodeHandler<'highlight.js'>", async () => { }); const handler = await CodeHandler.create('highlight.js'); await handler.configure({ theme: { type: 'self-hosted' } }); - await handler.process('', {}); + (await handler.process('', {})).processed; expect(consoleErrorMock).toHaveBeenCalledTimes(1); expect(consoleErrorMock).toHaveBeenNthCalledWith( 1, @@ -86,7 +97,7 @@ suite("CodeHandler<'highlight.js'>", async () => { it("shouldn't write CSS if configuration.theme.type is none", async () => { const handler = await CodeHandler.create('highlight.js'); await handler.configure({ theme: { type: 'none' } }); - await handler.process('', {}); + (await handler.process('', {})).processed; expect(consoleErrorMock).toHaveBeenCalledTimes(0); expect(writeFileEnsureDir).not.toHaveBeenCalled(); expect(existsSync).not.toHaveBeenCalled(); @@ -97,7 +108,7 @@ suite("CodeHandler<'highlight.js'>", async () => { await handler.configure({ theme: 123 as unknown as { type: 'none' }, }); - await handler.process('', {}); + (await handler.process('', {})).processed; expect(log).toHaveBeenCalledTimes(1); expect(writeFileEnsureDir).not.toHaveBeenCalled(); expect(existsSync).not.toHaveBeenCalled(); @@ -105,11 +116,11 @@ suite("CodeHandler<'highlight.js'>", async () => { it("should work even if version can't be fetched", async () => { const getVersionMock = vi - .spyOn(await import('$utils/cdn.js'), 'getVersion') + .spyOn(await import('$utils/env.js'), 'getVersion') .mockResolvedValueOnce(undefined); const handler = await CodeHandler.create('highlight.js'); await handler.configure({ theme: { type: 'self-hosted' } }); - await handler.process('', {}); + (await handler.process('', {})).processed; expect(writeFileEnsureDir).toHaveBeenCalledTimes(1); expect(writeFileEnsureDir).toHaveBeenNthCalledWith( 1, @@ -127,7 +138,7 @@ suite("CodeHandler<'highlight.js'>", async () => { .mockResolvedValueOnce(undefined); const handler = await CodeHandler.create('highlight.js'); await handler.configure({ theme: { type: 'self-hosted' } }); - await handler.process('', {}); + (await handler.process('', {})).processed; expect(writeFileEnsureDir).toHaveBeenCalledTimes(0); fetchCssMock.mockRestore(); }); @@ -139,7 +150,7 @@ suite("CodeHandler<'highlight.js'>", async () => { existsSync.mockReturnValueOnce(true); const handler = await CodeHandler.create('highlight.js'); await handler.configure({ theme: { type: 'self-hosted' } }); - await handler.process('', {}); + (await handler.process('', {})).processed; expect(writeFileEnsureDir).toHaveBeenCalledTimes(0); fetchCssMock.mockRestore(); }); @@ -155,69 +166,33 @@ suite("CodeHandler<'highlight.js'>", async () => { }); it('processes simple JS code correctly', async () => { - const output = await handler.process('let a', { lang: 'js' }); + const output = (await handler.process('let a', { lang: 'js' })) + .processed; const expected = - '
\nlet a\n
'; + '
let a\n
'; expect(output).toEqual(expected); }); - it('parses info from delimiters if present', async () => { - const codeList = [ - 'something', - 'let a', - '/**\n * @remarks comment\n */\nconst a = new Map();', - ]; - - for (const code of codeList) { - await (async () => { - expect( - await handler.process('```\n' + code + '\n```'), - ).toEqual( - expect.stringMatching( - /^
\n[\w\W]*\n<\/code><\/pre>$/,
-                            ),
-                        );
-                        expect(await handler.process('`' + code + '`')).toEqual(
-                            expect.stringMatching(
-                                /^[\w\W]*<\/code>$/,
-                            ),
-                        );
-                        expect(
-                            await handler.process('```js\n' + code + '\n```'),
-                        ).toEqual(
-                            expect.stringMatching(
-                                /^
\n[\w\W]*\n<\/code><\/pre>$/,
-                            ),
-                        );
-                        expect(
-                            await handler.process(
-                                '```javascript\n' + code + '\n```',
-                            ),
-                        ).toEqual(
-                            expect.stringMatching(
-                                /^
\n[\w\W]*\n<\/code><\/pre>$/,
-                            ),
-                        );
-                    })();
-                }
-            });
-
             it('escapes `{`, `}`, `<`, and `>` in plain code correctly', async () => {
-                const output = await handler.process('a  {c}', {
-                    lang: 'plaintext',
-                });
+                const output = (
+                    await handler.process('a  {c}', {
+                        lang: 'plaintext',
+                    })
+                ).processed;
                 const expected =
-                    '
\na <b> {c}\n
'; + '
a <b> {c}\n
'; expect(output).toEqual(expected); }); it('escapes `{`, `}`, `<`, and `>` in JS code correctly', async () => { - const output = await handler.process( - 'const a = new Map();', - { lang: 'js' }, - ); + const output = ( + await handler.process( + 'const a = new Map();', + { lang: 'js' }, + ) + ).processed; const expected = - '
\nconst a = new Map<string, {prop: number}>();\n
'; + '
const a = new Map<string, {prop: number}>();\n
'; expect(output).toEqual(expected); }); }); @@ -231,22 +206,26 @@ suite("CodeHandler<'highlight.js'>", async () => { it('configures code correctly', async () => { await handler.configure({ classPrefix: 'test_' }); - expect(await handler.process('let a', { lang: 'js' })).toEqual( - '
\nlet a\n
', + expect( + (await handler.process('let a', { lang: 'js' })).processed, + ).toEqual( + '
let a\n
', ); await handler.configure({ classPrefix: 'hljs-' }); - expect(await handler.process('let a', { lang: 'js' })).toEqual( - '
\nlet a\n
', + expect( + (await handler.process('let a', { lang: 'js' })).processed, + ).toEqual( + '
let a\n
', ); }); // it('can add new languages', () => { // handler.configure({ languages: [] }); - // expect(await handler.process('let a', { lang: 'js' })).toEqual( + // expect((await handler.process('let a', { lang: 'js' })).processed).toEqual( // 'let a', // ); // handler.configure({ languages: ['js'] }); - // expect(await handler.process('let a', { lang: 'js' })).toEqual( + // expect((await handler.process('let a', { lang: 'js' })).processed).toEqual( // 'let a', // ); // }); @@ -273,21 +252,23 @@ suite("CodeHandler<'highlight.js'>", async () => { ).toEqual( Object.entries(defaultCC).filter(([, v]) => !isFunction(v)), ); - expect( - handler.configuration.wrap({ wrapClassPrefix: 'test-' }), - ).toEqual( - defaultCC.wrap({ - wrapClassPrefix: 'test-', - }), + const defaultOptions = { + lang: 'plaintext', + _wrap: true, + inline: false, + wrapClassPrefix: 'test-', + }; + expect(handler.configuration.wrap(defaultOptions)).toEqual( + defaultCC.wrap(defaultOptions), ); expect( handler.configuration.wrap({ - wrapClassPrefix: 'test-', + ...defaultOptions, inline: true, }), ).toEqual( defaultCC.wrap({ - wrapClassPrefix: 'test-', + ...defaultOptions, inline: true, }), ); diff --git a/tests/handlers/CodeHandler/CodeHandler.none.test.ts b/tests/handlers/CodeHandler/CodeHandler.none.test.ts index e6089ba..0e9994c 100644 --- a/tests/handlers/CodeHandler/CodeHandler.none.test.ts +++ b/tests/handlers/CodeHandler/CodeHandler.none.test.ts @@ -1,21 +1,14 @@ -import { - suite, - describe, - it, - expect, - afterAll, - beforeEach, - vi, - type MockInstance, -} from 'vitest'; +import { describe, it, expect, beforeAll } from 'vitest'; import { CodeHandler } from '$handlers/CodeHandler.js'; -import { consoles } from '$utils/debug.js'; import { mockFs } from '$dev_deps.js'; mockFs({}); -suite("CodeHandler<'none'>", async () => { - const handler = await CodeHandler.create('none'); +describe("CodeHandler<'none'>", () => { + let handler: CodeHandler<'none'>; + beforeAll(async () => { + handler = await CodeHandler.create('none'); + }); describe("CodeHandler.create('none')", () => { it('returns instance of CodeHandler', () => { @@ -33,10 +26,12 @@ suite("CodeHandler<'none'>", async () => { }); it("doesn't escape anything", async () => { - const output = await handler.process('a {c}', { - lang: 'plaintext', - }); - const expected = '\na {c}\n'; + const output = ( + await handler.process('a {c}', { + lang: 'plaintext', + }) + ).processed; + const expected = 'a {c}\n'; expect(output).toEqual(expected); }); }); @@ -61,8 +56,15 @@ suite("CodeHandler<'none'>", async () => { describe('configuration getter', () => { it('has correct defaults', async () => { + const defaultOptions = { + lang: 'plaintext', + _wrap: true, + inline: false, + wrapClassPrefix: 'test-', + }; expect( handler.configuration.wrap({ + ...defaultOptions, wrapClassPrefix: 'test-', lang: 'js', }), @@ -73,114 +75,13 @@ suite("CodeHandler<'none'>", async () => { }); expect( handler.configuration.wrap({ + ...defaultOptions, wrapClassPrefix: 'test-', lang: 'js', }), ).toEqual(['', '']); }); }); - - describe('consumeDelims()', () => { - let consoleErrorMock: MockInstance; - - beforeEach(() => { - consoleErrorMock = vi - .spyOn(consoles, 'error') - .mockImplementation(() => undefined); - }); - afterAll(() => { - consoleErrorMock.mockReset(); - }); - it('should work if no options are set with the delims', () => { - const { innerCode, optionsFromDelims } = - handler.consumeDelims('```\nabc\n```'); - expect(innerCode).toEqual('abc'); - expect(optionsFromDelims).toEqual({ - info: '', - inline: false, - lang: 'plaintext', - }); - }); - - it('should work if language is set with the delims', () => { - const { innerCode, optionsFromDelims } = handler.consumeDelims( - '```language\nabc\n```', - ); - expect(innerCode).toEqual('abc'); - expect(optionsFromDelims).toEqual({ - info: '', - inline: false, - lang: 'language', - }); - }); - - it('should work if language and options are set with the delims', () => { - const { innerCode, optionsFromDelims } = handler.consumeDelims( - '```some text here\nabc\n```', - ); - expect(innerCode).toEqual('abc'); - expect(optionsFromDelims).toEqual({ - info: 'text here', - inline: false, - lang: 'some', - }); - }); - - it.each([ - { input: '```\n\nabc\n\n```', expected: '\nabc\n' }, - { input: '`\n\nabc\n\n`', expected: '\n\nabc\n\n' }, - ])('should respect whitespace', (test) => { - expect(handler.consumeDelims(test.input).innerCode).toEqual( - test.expected, - ); - }); - - it.each([ - { - input: '```some text here\nabc\n~~~', - expectedError: - 'Error parsing code block (closing delimiters not found); expected the following to end with ≥3 backticks:\n```some text here\nabc\n~~~', - opts: undefined, - }, - { - input: '~~~~language\nabc', - expectedError: - 'Error parsing code block (closing delimiters not found); expected the following to end with ≥4 tildes:\n~~~~language\nabc', - opts: undefined, - }, - { - input: '`some text here\nabc', - expectedError: - 'Error parsing inline code snippet (closing delimiters not found); expected the following to end with ≥1 backticks:\n`some text here\nabc', - opts: undefined, // { inline: true, lang: 'plaintext', info: '' }, - }, - { - input: '~~some text here\nabc', - expectedError: - 'Error parsing inline code snippet (closing delimiters not found); expected the following to end with ≥2 tildes:\n~~some text here\nabc', - opts: undefined, // { inline: true, lang: 'plaintext', info: '' }, - }, - { - input: 'text', - expectedError: - 'Error parsing code snippet (no delimiters could be found/matched): text', - opts: undefined, // { inline: true, lang: 'plaintext', info: '' }, - }, - ])( - 'should log error if delims are mismatched', - ({ input, expectedError, opts }) => { - const { innerCode, optionsFromDelims } = - handler.consumeDelims(input); - expect(innerCode).toEqual(input); - expect(optionsFromDelims).toEqual(opts); - expect(consoleErrorMock).toHaveBeenCalledTimes(1); - expect(consoleErrorMock).toHaveBeenNthCalledWith( - 1, - expect.stringContaining(expectedError), - ); - }, - ); - }); }); describe('backend', () => { diff --git a/tests/handlers/CodeHandler/CodeHandler.prismjs.test.ts b/tests/handlers/CodeHandler/CodeHandler.prismjs.test.ts index fb40a42..d05f62c 100644 --- a/tests/handlers/CodeHandler/CodeHandler.prismjs.test.ts +++ b/tests/handlers/CodeHandler/CodeHandler.prismjs.test.ts @@ -1,5 +1,5 @@ /* eslint-disable vitest/no-commented-out-tests */ -import { suite, describe, it, expect, vi } from 'vitest'; +import { describe, it, expect, vi, beforeAll } from 'vitest'; import { CodeHandler } from '$handlers/CodeHandler.js'; import { getDefaultCodeConfiguration } from '$config/defaults.js'; @@ -8,8 +8,11 @@ import { consoles } from '$utils/debug.js'; vi.spyOn(consoles, 'error').mockImplementation(() => undefined); vi.spyOn(consoles, 'warn').mockImplementation(() => undefined); -suite("CodeHandler<'prismjs'>", async () => { - const handler = await CodeHandler.create('prismjs'); +describe("CodeHandler<'prismjs'>", () => { + let handler: CodeHandler<'prismjs'>; + beforeAll(async () => { + handler = await CodeHandler.create('prismjs'); + }); describe("CodeHandler.create('prismjs')", () => { it('returns instance of CodeHandler', () => { @@ -27,78 +30,51 @@ suite("CodeHandler<'prismjs'>", async () => { }); it('processes simple JS code correctly', async () => { - const output = await handler.process('let a', { lang: 'js' }); + const output = (await handler.process('let a', { lang: 'js' })) + .processed; const expected = - '
\nlet a\n
'; + '
let a\n
'; expect(output).toEqual(expected); }); - it.each(['unknown-language', undefined])( - 'processes code of unknown language correctly', - async (lang) => { - expect( + it('processes code of unknown language correctly', async () => { + expect( + ( await handler.process('let a = b', { - lang, - }), - ).toEqual( - `
\nlet a = b\n
`, - ); - }, - ); - - it.each([ - 'something', - 'let a', - '/**\n * @remarks comment\n */\nconst a = new Map();', - ])('parses info from delimiters if present', async (code) => { - await (async () => { - expect( - await handler.process('```\n' + code + '\n```'), - ).toEqual( - expect.stringMatching( - /^
\n[\w\W]*\n<\/code><\/pre>$/,
-                        ),
-                    );
-                    expect(await handler.process('`' + code + '`')).toEqual(
-                        expect.stringMatching(
-                            /^[\w\W]*<\/code>$/,
-                        ),
-                    );
-                    expect(
-                        await handler.process('```js\n' + code + '\n```'),
-                    ).toEqual(
-                        expect.stringMatching(
-                            /^
\n[\w\W]*\n<\/code><\/pre>$/,
-                        ),
-                    );
-                    expect(
-                        await handler.process(
-                            '```javascript\n' + code + '\n```',
-                        ),
-                    ).toEqual(
-                        expect.stringMatching(
-                            /^
\n[\w\W]*\n<\/code><\/pre>$/,
-                        ),
-                    );
-                })();
+                            lang: 'unknown-language',
+                        })
+                    ).processed,
+                ).toEqual(
+                    `
let a = b\n
`, + ); + }); + + it('defaults to no language', async () => { + const output = (await handler.process('let a')).processed; + const expected = '
let a\n
'; + expect(output).toEqual(expected); }); it('escapes `{`, `}`, `<`, and `>` in plain code correctly', async () => { - const output = await handler.process('a {c}', { - lang: 'plaintext', - }); + const output = ( + await handler.process('a {c}', { + lang: 'plaintext', + }) + ).processed; const expected = - '
\na <b> {c}\n
'; + '
a <b> {c}\n
'; expect(output).toEqual(expected); }); it('escapes `{`, `}`, `<`, and `>` in JS code correctly', async () => { - const output = await handler.process( - 'const a = new Map();', - { lang: 'js' }, - ); + const output = ( + await handler.process( + 'const a = new Map();', + { lang: 'js' }, + ) + ).processed; const expected = - '
\nconst a = new Map<string, {prop: number}>();\n
'; + '
const a = new Map<string, {prop: number}>();\n
'; expect(output).toEqual(expected); }); }); @@ -115,19 +91,19 @@ suite("CodeHandler<'prismjs'>", async () => { // it('configures code correctly', () => { // expect( - // await handler.process('\\documentclass{article}\n$math$', { + // (await handler.process('\\documentclass{article}\n$math$', { // lang: 'latex', - // }), + // })).processed, // ).toEqual('\\example'); // }); // it('can add new languages', () => { // handler.configure({ languages: [] }); - // expect(await handler.process('let a', { lang: 'js' })).toEqual( + // expect((await handler.process('let a', { lang: 'js' })).processed).toEqual( // 'let a', // ); // handler.configure({ languages: ['js'] }); - // expect(await handler.process('let a', { lang: 'js' })).toEqual( + // expect((await handler.process('let a', { lang: 'js' })).processed).toEqual( // 'let a', // ); // }); diff --git a/tests/handlers/CodeHandler/CodeHandler.starry-night.test.ts b/tests/handlers/CodeHandler/CodeHandler.starry-night.test.ts index 7f819fb..40b3696 100644 --- a/tests/handlers/CodeHandler/CodeHandler.starry-night.test.ts +++ b/tests/handlers/CodeHandler/CodeHandler.starry-night.test.ts @@ -1,6 +1,4 @@ -/* eslint-disable vitest/no-commented-out-tests */ import { - suite, describe, it, expect, @@ -8,6 +6,8 @@ import { beforeEach, afterEach, afterAll, + beforeAll, + type MockInstance, } from 'vitest'; import { CodeHandler } from '$handlers/CodeHandler.js'; @@ -25,19 +25,22 @@ function fixture() { }); } -suite.concurrent("CodeHandler<'starry-night'>", async () => { +describe.concurrent("CodeHandler<'starry-night'>", () => { fixture(); - const { writeFileEnsureDir } = await spy( - ['writeFileEnsureDir', 'existsSync'], - true, - ); + + let handler: CodeHandler<'starry-night'>; + let writeFileEnsureDir: MockInstance; + + beforeAll(async () => { + handler = await CodeHandler.create('starry-night'); + await handler.configure({ languages: 'common' }); + const mocks = await spy(['writeFileEnsureDir', 'existsSync'], true); + writeFileEnsureDir = mocks.writeFileEnsureDir; + }); afterAll(() => { vi.restoreAllMocks(); }); - const handler = await CodeHandler.create('starry-night'); - await handler.configure({ languages: 'common' }); - describe.concurrent("CodeHandler.create('starry-night')", () => { fixture(); it('returns instance of CodeHandler', () => { @@ -52,14 +55,14 @@ suite.concurrent("CodeHandler<'starry-night'>", async () => { it('fetches and generates CSS if run for the first time', async () => { const handler = await CodeHandler.create('starry-night'); await handler.configure({ theme: { type: 'self-hosted' } }); - await handler.process(''); + (await handler.process('')).processed; expect(writeFileEnsureDir).toHaveBeenCalledTimes(1); expect(writeFileEnsureDir).toHaveBeenNthCalledWith( 1, expect.stringMatching(/src\/sveltex\/starry-night@.*\.css/), expect.stringContaining(':root'), ); - await handler.process(''); + (await handler.process('')).processed; expect(writeFileEnsureDir).toHaveBeenCalledTimes(1); }); }); @@ -74,77 +77,50 @@ suite.concurrent("CodeHandler<'starry-night'>", async () => { }); it('processes simple JS code correctly', async () => { - const output = await handler.process('let a', { lang: 'js' }); + const output = (await handler.process('let a', { lang: 'js' })) + .processed; const expected = - '
\nlet a\n
'; + '
let a\n
'; expect(output).toEqual(expected); }); - it('processes plaintext correctly', async () => { - const output = await handler.process('let a', { - lang: undefined, - }); - const expected = '
\nlet a\n
'; + it('defaults to no language', async () => { + const output = (await handler.process('let a')).processed; + const expected = '
let a\n
'; expect(output).toEqual(expected); }); - it('parses info from delimiters if present', async () => { - const codeList = [ - 'something', - 'let a', - '/**\n * @remarks comment\n */\nconst a = new Map();', - ]; - - for (const code of codeList) { - await (async () => { - expect( - await handler.process('```\n' + code + '\n```'), - ).toEqual( - expect.stringMatching( - /^
\n[\w\W]*\n<\/code><\/pre>$/,
-                            ),
-                        );
-                        expect(await handler.process('`' + code + '`')).toEqual(
-                            expect.stringMatching(
-                                /^[\w\W]*<\/code>$/,
-                            ),
-                        );
-                        expect(
-                            await handler.process('```js\n' + code + '\n```'),
-                        ).toEqual(
-                            expect.stringMatching(
-                                /^
\n[\w\W]*\n<\/code><\/pre>$/,
-                            ),
-                        );
-                        expect(
-                            await handler.process(
-                                '```javascript\n' + code + '\n```',
-                            ),
-                        ).toEqual(
-                            expect.stringMatching(
-                                /^
\n[\w\W]*\n<\/code><\/pre>$/,
-                            ),
-                        );
-                    })();
-                }
+            it('processes plaintext correctly', async () => {
+                const output = (
+                    await handler.process('let a', {
+                        lang: 'plaintext',
+                    })
+                ).processed;
+                const expected =
+                    '
let a\n
'; + expect(output).toEqual(expected); }); it('escapes `{`, `}`, `<`, and `>` in plain code correctly', async () => { - const output = await handler.process('a {c}', { - lang: 'plaintext', - }); + const output = ( + await handler.process('a {c}', { + lang: 'plaintext', + }) + ).processed; const expected = - '
\na <b> {c}\n
'; + '
a <b> {c}\n
'; expect(output).toEqual(expected); }); it('escapes `{`, `}`, `<`, and `>` in JS code correctly', async () => { - const output = await handler.process( - 'const a = new Map();', - { lang: 'js' }, - ); + const output = ( + await handler.process( + 'const a = new Map();', + { lang: 'js' }, + ) + ).processed; const expected = - '
\nconst a = new Map<string, {prop: number}>();\n
'; + '
const a = new Map<string, {prop: number}>();\n
'; expect(output).toEqual(expected); }); }); @@ -170,36 +146,41 @@ suite.concurrent("CodeHandler<'starry-night'>", async () => { it('configures code correctly', async () => { expect( - await handler.process('\\example', { lang: 'tex' }), + (await handler.process('\\example', { lang: 'tex' })) + .processed, ).toEqual( - '
\n\\example\n
', + '
\\example\n
', ); await handler.configure({ languages: ['text.tex.latex'], }); expect( - await handler.process('\\example', { lang: 'tex' }), + (await handler.process('\\example', { lang: 'tex' })) + .processed, ).toEqual( - '
\n\\example\n
', + '
\\example\n
', ); expect( - await handler.process('a ::= b', { lang: 'ebnf' }), + (await handler.process('a ::= b', { lang: 'ebnf' })) + .processed, ).toEqual( - '
\na ::= b\n
', + '
a ::= b\n
', ); await handler.configure({ languages: 'all' }); expect( - await handler.process('a ::= b', { lang: 'ebnf' }), + (await handler.process('a ::= b', { lang: 'ebnf' })) + .processed, ).toEqual( - '
\na ::= b\n
', + '
a ::= b\n
', ); // can't unload languages though... await handler.configure({ languages: [] }); expect( - await handler.process('a ::= b', { lang: 'ebnf' }), + (await handler.process('a ::= b', { lang: 'ebnf' })) + .processed, ).toEqual( - '
\na ::= b\n
', + '
a ::= b\n
', ); expect(consoleWarnMock).toHaveBeenCalledTimes(2); @@ -216,9 +197,10 @@ suite.concurrent("CodeHandler<'starry-night'>", async () => { it('can add new languages', async () => { const handler = await CodeHandler.create('starry-night'); expect( - await handler.process('a ::= b', { lang: 'ebnf' }), + (await handler.process('a ::= b', { lang: 'ebnf' })) + .processed, ).toEqual( - '
\na ::= b\n
', + '
a ::= b\n
', ); expect(consoleWarnMock).toHaveBeenCalledTimes(1); expect(consoleWarnMock).toHaveBeenNthCalledWith( @@ -227,20 +209,23 @@ suite.concurrent("CodeHandler<'starry-night'>", async () => { ); await handler.configure({ languages: ['source.ebnf'] }); expect( - await handler.process('a ::= b', { lang: 'ebnf' }), + (await handler.process('a ::= b', { lang: 'ebnf' })) + .processed, ).toEqual( - '
\na ::= b\n
', + '
a ::= b\n
', ); }); it('can add new custom languages', async () => { const handler = await CodeHandler.create('starry-night'); expect( - await handler.process('something a', { - lang: 'custom-language', - }), + ( + await handler.process('something a', { + lang: 'custom-language', + }) + ).processed, ).toEqual( - '
\nsomething a\n
', + '
something a\n
', ); expect(consoleWarnMock).toHaveBeenCalledTimes(1); expect(consoleWarnMock).toHaveBeenNthCalledWith( @@ -265,11 +250,13 @@ suite.concurrent("CodeHandler<'starry-night'>", async () => { ], }); expect( - await handler.process('something a', { - lang: 'custom-language', - }), + ( + await handler.process('something a', { + lang: 'custom-language', + }) + ).processed, ).toEqual( - '
\nsomething a\n
', + '
something a\n
', ); }); }); @@ -295,20 +282,32 @@ suite.concurrent("CodeHandler<'starry-night'>", async () => { ).toEqual( Object.entries(defaultCC).filter(([, v]) => !isFunction(v)), ); + const defaultOptions = { + lang: 'plaintext', + _wrap: true, + inline: false, + wrapClassPrefix: 'test-', + }; expect( - handler.configuration.wrap({ wrapClassPrefix: 'test-' }), + handler.configuration.wrap({ + ...defaultOptions, + wrapClassPrefix: 'test-', + }), ).toEqual( defaultCC.wrap({ + ...defaultOptions, wrapClassPrefix: 'test-', }), ); expect( handler.configuration.wrap({ + ...defaultOptions, wrapClassPrefix: 'test-', inline: true, }), ).toEqual( defaultCC.wrap({ + ...defaultOptions, wrapClassPrefix: 'test-', inline: true, }), diff --git a/tests/handlers/CodeHandler/CodeHandler.test.ts b/tests/handlers/CodeHandler/CodeHandler.test.ts index e133d2f..836d6d7 100644 --- a/tests/handlers/CodeHandler/CodeHandler.test.ts +++ b/tests/handlers/CodeHandler/CodeHandler.test.ts @@ -1,14 +1,17 @@ -import { suite, describe, it, expect, vi } from 'vitest'; +import { describe, it, expect, vi, beforeAll } from 'vitest'; import { CodeHandler } from '$handlers/CodeHandler.js'; -import { missingDeps } from '$utils/globals.js'; +import { missingDeps } from '$utils/env.js'; import { getDefaultCodeConfiguration } from '$config/defaults.js'; import { consoles } from '$utils/debug.js'; vi.spyOn(consoles, 'error').mockImplementation(() => undefined); -suite("CodeHandler<'custom'>", async () => { - const handler = await CodeHandler.create('custom', { - process: (input: string) => input, +describe("CodeHandler<'custom'>", () => { + let handler: CodeHandler<'custom'>; + beforeAll(async () => { + handler = await CodeHandler.create('custom', { + process: (input: string) => input, + }); }); describe("CodeHandler.create('custom', ...)", () => { it('returns instance of CodeHandler', () => { @@ -38,10 +41,10 @@ suite("CodeHandler<'custom'>", async () => { describe('codeHandler', () => { describe('process()', () => { - it('should work', async () => { - expect(await handler.process('x', {})).toEqual( - '
\nx\n
', - ); + it('defaults to no language', async () => { + const output = (await handler.process('let a')).processed; + const expected = '
let a\n
'; + expect(output).toEqual(expected); }); }); @@ -62,7 +65,7 @@ suite("CodeHandler<'custom'>", async () => { }); }); -suite('CodeHandler error handling', () => { +describe('CodeHandler error handling', () => { describe("CodeHandler.create('highlight.js') with highlight.js mocked to throw error", () => { vi.mock('highlight.js', () => { throw new Error('highlight.js not found'); diff --git a/tests/handlers/MarkdownHandler/MarkdownHandler.custom.errors.test.ts b/tests/handlers/MarkdownHandler/MarkdownHandler.custom.errors.test.ts index 137966f..598ab00 100644 --- a/tests/handlers/MarkdownHandler/MarkdownHandler.custom.errors.test.ts +++ b/tests/handlers/MarkdownHandler/MarkdownHandler.custom.errors.test.ts @@ -1,10 +1,10 @@ -import { suite, describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'vitest'; import { MarkdownHandler } from '$handlers/MarkdownHandler.js'; import { Marked, type MarkedOptions, type MarkedExtension } from 'marked'; -suite("MarkdownHandler<'custom'>", () => { +describe("MarkdownHandler<'custom'>", () => { const customProcessor = new Marked(); interface Configuration { options?: MarkedOptions; diff --git a/tests/handlers/MarkdownHandler/MarkdownHandler.custom.test.ts b/tests/handlers/MarkdownHandler/MarkdownHandler.custom.test.ts index ddc5f63..fc6b0e9 100644 --- a/tests/handlers/MarkdownHandler/MarkdownHandler.custom.test.ts +++ b/tests/handlers/MarkdownHandler/MarkdownHandler.custom.test.ts @@ -1,45 +1,50 @@ -import { suite, describe, it, expect } from 'vitest'; +import { describe, it, expect, beforeAll } from 'vitest'; import { MarkdownHandler } from '$handlers/MarkdownHandler.js'; import { Marked, type MarkedOptions, type MarkedExtension } from 'marked'; -suite("MarkdownHandler<'custom'>", async () => { - const customProcessor = new Marked(); - interface Configuration { - options?: MarkedOptions; - extensions?: MarkedExtension[]; - } - const customConfigure = ( - opts: unknown, - markdownHandler: MarkdownHandler<'custom'>, - ) => { - if ((opts as Configuration).options) { - (markdownHandler.processor as Marked).setOptions( - (opts as Configuration).options ?? {}, - ); +describe("MarkdownHandler<'custom'>", () => { + let handler: MarkdownHandler<'custom'>; + beforeAll(async () => { + const customProcessor = new Marked(); + interface Configuration { + options?: MarkedOptions; + extensions?: MarkedExtension[]; } - if ((opts as Configuration).extensions) { - (markdownHandler.processor as Marked).use( - ...((opts as Configuration).extensions ?? []), - ); - } - }; - const customProcess = async ( - markdown: string, - { inline }: { inline?: boolean | undefined } | undefined = { - inline: !MarkdownHandler.shouldParseAsInline(markdown), - }, - markdownHandler: MarkdownHandler<'custom'>, - ) => { - return inline - ? await (markdownHandler.processor as Marked).parseInline(markdown) - : await (markdownHandler.processor as Marked).parse(markdown); - }; - const handler = await MarkdownHandler.create('custom', { - processor: customProcessor, - process: customProcess, - configure: customConfigure, + const customConfigure = ( + opts: unknown, + markdownHandler: MarkdownHandler<'custom'>, + ) => { + if ((opts as Configuration).options) { + (markdownHandler.processor as Marked).setOptions( + (opts as Configuration).options ?? {}, + ); + } + if ((opts as Configuration).extensions) { + (markdownHandler.processor as Marked).use( + ...((opts as Configuration).extensions ?? []), + ); + } + }; + const customProcess = async ( + markdown: string, + { inline }: { inline?: boolean | undefined } | undefined = { + inline: !MarkdownHandler.shouldParseAsInline(markdown), + }, + markdownHandler: MarkdownHandler<'custom'>, + ) => { + return inline + ? await (markdownHandler.processor as Marked).parseInline( + markdown, + ) + : await (markdownHandler.processor as Marked).parse(markdown); + }; + handler = await MarkdownHandler.create('custom', { + processor: customProcessor, + process: customProcess, + configure: customConfigure, + }); }); describe("MarkdownHandler.create('custom')", () => { @@ -58,25 +63,28 @@ suite("MarkdownHandler<'custom'>", async () => { }); it('processes markdown correctly', async () => { - const output = await handler.process('**strong** *em*'); + const output = (await handler.process('**strong** *em*')) + .processed; const expected = 'strong em'; expect(output).toEqual(expected); }); it("automatically distinguishes between inline and 'block' markdown", async () => { - expect(await handler.process('a\nb')).toEqual('a\nb'); - expect(await handler.process('a\n\nb')).toEqual( + expect((await handler.process('a\nb')).processed).toEqual( + 'a\nb', + ); + expect((await handler.process('a\n\nb')).processed).toEqual( '

a

\n

b

\n', ); }); it('has working `inline` parameter', async () => { - expect(await handler.process('a', { inline: true })).toEqual( - 'a', - ); - expect(await handler.process('a', { inline: false })).toEqual( - '

a

\n', - ); + expect( + (await handler.process('a', { inline: true })).processed, + ).toEqual('a'); + expect( + (await handler.process('a', { inline: false })).processed, + ).toEqual('

a

\n'); }); }); @@ -90,11 +98,15 @@ suite("MarkdownHandler<'custom'>", async () => { await handler.configure({ options: { gfm: true, breaks: true }, }); - expect(await handler.process('a\nb')).toEqual('a
b'); + expect((await handler.process('a\nb')).processed).toEqual( + 'a
b', + ); await handler.configure({ options: { gfm: false, breaks: false }, }); - expect(await handler.process('a\nb')).toEqual('a\nb'); + expect((await handler.process('a\nb')).processed).toEqual( + 'a\nb', + ); expect(handler.configuration).toEqual({ options: { gfm: false, breaks: false }, }); diff --git a/tests/handlers/MarkdownHandler/MarkdownHandler.markdown-it.test.ts b/tests/handlers/MarkdownHandler/MarkdownHandler.markdown-it.test.ts index f2f235f..942a101 100644 --- a/tests/handlers/MarkdownHandler/MarkdownHandler.markdown-it.test.ts +++ b/tests/handlers/MarkdownHandler/MarkdownHandler.markdown-it.test.ts @@ -1,11 +1,14 @@ -import { suite, describe, it, expect } from 'vitest'; +import { describe, it, expect, beforeAll } from 'vitest'; import multimdTablePlugin from 'markdown-it-multimd-table'; import { MarkdownHandler } from '$handlers/MarkdownHandler.js'; import MarkdownIt from 'markdown-it'; -suite("MarkdownHandler<'markdown-it'>", async () => { - const handler = await MarkdownHandler.create('markdown-it'); +describe("MarkdownHandler<'markdown-it'>", () => { + let handler: MarkdownHandler<'markdown-it'>; + beforeAll(async () => { + handler = await MarkdownHandler.create('markdown-it'); + }); describe("MarkdownHandler.create('markdown-it')", () => { it('returns instance of MarkdownHandler', () => { @@ -23,25 +26,28 @@ suite("MarkdownHandler<'markdown-it'>", async () => { }); it('processes markdown correctly', async () => { - const output = await handler.process('**strong** *em*'); + const output = (await handler.process('**strong** *em*')) + .processed; const expected = 'strong em'; expect(output).toEqual(expected); }); it("automatically distinguishes between inline and 'block' markdown", async () => { - expect(await handler.process('a\nb')).toEqual('a\nb'); - expect(await handler.process('a\n\nb')).toEqual( + expect((await handler.process('a\nb')).processed).toEqual( + 'a\nb', + ); + expect((await handler.process('a\n\nb')).processed).toEqual( '

a

\n

b

\n', ); }); it('has working `inline` parameter', async () => { - expect(await handler.process('a', { inline: true })).toEqual( - 'a', - ); - expect(await handler.process('a', { inline: false })).toEqual( - '

a

\n', - ); + expect( + (await handler.process('a', { inline: true })).processed, + ).toEqual('a'); + expect( + (await handler.process('a', { inline: false })).processed, + ).toEqual('

a

\n'); }); }); @@ -57,13 +63,17 @@ suite("MarkdownHandler<'markdown-it'>", async () => { }); expect(handler.processor.options.breaks).toBeTruthy(); expect(handler.processor.options.xhtmlOut).toBeTruthy(); - expect(handler.process('a\nb')).toEqual('a
\nb'); + expect((await handler.process('a\nb')).processed).toEqual( + 'a
\nb', + ); await handler.configure({ options: { breaks: true, xhtmlOut: false }, }); expect(handler.processor.options.breaks).toBeTruthy(); expect(handler.processor.options.xhtmlOut).toBeFalsy(); - expect(handler.process('a\nb')).toEqual('a
\nb'); + expect((await handler.process('a\nb')).processed).toEqual( + 'a
\nb', + ); expect(handler.configuration).toEqual({ options: { breaks: true, @@ -137,7 +147,9 @@ suite("MarkdownHandler<'markdown-it'>", async () => { '\n' + '\n' + '\n'; - expect(await handler.process(exampleTable)).toEqual(expected); + expect((await handler.process(exampleTable)).processed).toEqual( + expected, + ); }); }); diff --git a/tests/handlers/MarkdownHandler/MarkdownHandler.marked.test.ts b/tests/handlers/MarkdownHandler/MarkdownHandler.marked.test.ts index dd8843a..9c5baad 100644 --- a/tests/handlers/MarkdownHandler/MarkdownHandler.marked.test.ts +++ b/tests/handlers/MarkdownHandler/MarkdownHandler.marked.test.ts @@ -1,10 +1,13 @@ -import { suite, describe, it, expect } from 'vitest'; +import { describe, it, expect, beforeAll } from 'vitest'; import { MarkdownHandler } from '$handlers/MarkdownHandler.js'; import { Marked } from 'marked'; -suite("MarkdownHandler<'marked'>", async () => { - const handler = await MarkdownHandler.create('marked'); +describe("MarkdownHandler<'marked'>", () => { + let handler: MarkdownHandler<'marked'>; + beforeAll(async () => { + handler = await MarkdownHandler.create('marked'); + }); describe("MarkdownHandler.create('marked')", () => { it('returns instance of MarkdownHandler', () => { @@ -22,25 +25,28 @@ suite("MarkdownHandler<'marked'>", async () => { }); it('processes markdown correctly', async () => { - const output = await handler.process('**strong** *em*'); + const output = (await handler.process('**strong** *em*')) + .processed; const expected = 'strong em'; expect(output).toEqual(expected); }); it("automatically distinguishes between inline and 'block' markdown", async () => { - expect(await handler.process('a\nb')).toEqual('a\nb'); - expect(await handler.process('a\n\nb')).toEqual( + expect((await handler.process('a\nb')).processed).toEqual( + 'a\nb', + ); + expect((await handler.process('a\n\nb')).processed).toEqual( '

a

\n

b

\n', ); }); it('has working `inline` parameter', async () => { - expect(await handler.process('a', { inline: true })).toEqual( - 'a', - ); - expect(await handler.process('a', { inline: false })).toEqual( - '

a

\n', - ); + expect( + (await handler.process('a', { inline: true })).processed, + ).toEqual('a'); + expect( + (await handler.process('a', { inline: false })).processed, + ).toEqual('

a

\n'); }); }); @@ -54,13 +60,19 @@ suite("MarkdownHandler<'marked'>", async () => { await handler.configure({ options: { gfm: true, breaks: true }, }); - expect(await handler.process('a\nb')).toEqual('a
b'); + expect((await handler.process('a\nb')).processed).toEqual( + 'a
b', + ); await handler.configure({ extensions: [] }); - expect(await handler.process('a\nb')).toEqual('a
b'); + expect((await handler.process('a\nb')).processed).toEqual( + 'a
b', + ); await handler.configure({ options: { gfm: false, breaks: false }, }); - expect(await handler.process('a\nb')).toEqual('a\nb'); + expect((await handler.process('a\nb')).processed).toEqual( + 'a\nb', + ); expect(handler.configuration).toEqual({ extensions: [], options: { gfm: false, breaks: false }, diff --git a/tests/handlers/MarkdownHandler/MarkdownHandler.micromark.test.ts b/tests/handlers/MarkdownHandler/MarkdownHandler.micromark.test.ts index f211e88..5a4a285 100644 --- a/tests/handlers/MarkdownHandler/MarkdownHandler.micromark.test.ts +++ b/tests/handlers/MarkdownHandler/MarkdownHandler.micromark.test.ts @@ -1,9 +1,12 @@ -import { suite, describe, it, expect } from 'vitest'; +import { describe, it, expect, beforeAll } from 'vitest'; import { MarkdownHandler } from '$handlers/MarkdownHandler.js'; -suite("MarkdownHandler<'micromark'>", async () => { - const handler = await MarkdownHandler.create('micromark'); +describe("MarkdownHandler<'micromark'>", () => { + let handler: MarkdownHandler<'micromark'>; + beforeAll(async () => { + handler = await MarkdownHandler.create('micromark'); + }); describe("MarkdownHandler.create('micromark')", () => { it('returns instance of MarkdownHandler', () => { @@ -21,7 +24,8 @@ suite("MarkdownHandler<'micromark'>", async () => { }); it('processes markdown correctly', async () => { - const output = await handler.process('**strong** *em*'); + const output = (await handler.process('**strong** *em*')) + .processed; const expected = '

strong em

'; expect(output).toEqual(expected); }); @@ -37,14 +41,16 @@ suite("MarkdownHandler<'micromark'>", async () => { await handler.configure({ allowDangerousProtocol: true }); expect(handler.configuration.allowDangerousProtocol).toBe(true); expect( - await handler.process('[example](unsafe://example.com)'), + (await handler.process('[example](unsafe://example.com)')) + .processed, ).toEqual('

example

'); await handler.configure({ allowDangerousProtocol: false }); expect(handler.configuration.allowDangerousProtocol).toBe( false, ); expect( - await handler.process('[example](unsafe://example.com)'), + (await handler.process('[example](unsafe://example.com)')) + .processed, ).toEqual('

example

'); }); }); diff --git a/tests/handlers/MarkdownHandler/MarkdownHandler.none.test.ts b/tests/handlers/MarkdownHandler/MarkdownHandler.none.test.ts index c90a870..faa50d8 100644 --- a/tests/handlers/MarkdownHandler/MarkdownHandler.none.test.ts +++ b/tests/handlers/MarkdownHandler/MarkdownHandler.none.test.ts @@ -1,8 +1,11 @@ -import { suite, describe, it, expect } from 'vitest'; +import { describe, it, expect, beforeAll } from 'vitest'; import { MarkdownHandler } from '$handlers/MarkdownHandler.js'; -suite("MarkdownHandler<'none'>", async () => { - const handler = await MarkdownHandler.create('none'); +describe("MarkdownHandler<'none'>", () => { + let handler: MarkdownHandler<'none'>; + beforeAll(async () => { + handler = await MarkdownHandler.create('none'); + }); describe("MarkdownHandler.create('none')", () => { it('returns instance of MarkdownHandler', () => { @@ -20,7 +23,8 @@ suite("MarkdownHandler<'none'>", async () => { }); it('leaves markdown as-is', async () => { - const output = await handler.process('**strong** *em*'); + const output = (await handler.process('**strong** *em*')) + .processed; const expected = '**strong** *em*'; expect(output).toEqual(expected); }); diff --git a/tests/handlers/MarkdownHandler/MarkdownHandler.test.ts b/tests/handlers/MarkdownHandler/MarkdownHandler.test.ts index 1f8964f..10e9622 100644 --- a/tests/handlers/MarkdownHandler/MarkdownHandler.test.ts +++ b/tests/handlers/MarkdownHandler/MarkdownHandler.test.ts @@ -1,8 +1,8 @@ -import { suite, describe, it, expect, vi } from 'vitest'; +import { describe, it, expect, vi } from 'vitest'; import { MarkdownHandler } from '$handlers/MarkdownHandler.js'; -import { missingDeps } from '$utils/globals.js'; +import { missingDeps } from '$utils/env.js'; -suite('MarkdownHandler', () => { +describe('MarkdownHandler', () => { describe('MarkdownHandler.shouldParseAsInline()', () => { it('should return true for inline markdown', () => { expect(MarkdownHandler.shouldParseAsInline('**strong** *em*')).toBe( @@ -63,7 +63,7 @@ suite('MarkdownHandler', () => { }); }); -suite('MarkdownHandler error handling', () => { +describe('MarkdownHandler error handling', () => { describe("MarkdownHandler.create('marked') with marked mocked to throw error", () => { vi.mock('marked', () => { throw new Error('marked not found'); diff --git a/tests/handlers/MarkdownHandler/MarkdownHandler.unified.test.ts b/tests/handlers/MarkdownHandler/MarkdownHandler.unified.test.ts index 13ebaaa..051f3c3 100644 --- a/tests/handlers/MarkdownHandler/MarkdownHandler.unified.test.ts +++ b/tests/handlers/MarkdownHandler/MarkdownHandler.unified.test.ts @@ -1,9 +1,12 @@ -import { suite, describe, it, expect } from 'vitest'; +import { describe, it, expect, beforeAll } from 'vitest'; import { MarkdownHandler } from '$handlers/MarkdownHandler.js'; -suite("MarkdownHandler<'unified'>", async () => { - const handler = await MarkdownHandler.create('unified'); +describe("MarkdownHandler<'unified'>", () => { + let handler: MarkdownHandler<'unified'>; + beforeAll(async () => { + handler = await MarkdownHandler.create('unified'); + }); describe("MarkdownHandler.create('unified')", () => { it('returns instance of MarkdownHandler', () => { @@ -21,7 +24,8 @@ suite("MarkdownHandler<'unified'>", async () => { }); it('processes markdown correctly', async () => { - const output = await handler.process('**strong** *em*'); + const output = (await handler.process('**strong** *em*')) + .processed; const expected = '

strong em

'; expect(output).toEqual(expected); }); @@ -39,13 +43,13 @@ suite("MarkdownHandler<'unified'>", async () => { remarkPlugins: undefined, rehypePlugins: undefined, }); - expect(await handler.process('**strong** *em*')).toEqual( - '

strong em

', - ); + expect( + (await handler.process('**strong** *em*')).processed, + ).toEqual('

strong em

'); await handler.configure({}); - expect(await handler.process('**strong** *em*')).toEqual( - '

strong em

', - ); + expect( + (await handler.process('**strong** *em*')).processed, + ).toEqual('

strong em

'); }); }); diff --git a/tests/handlers/TexHandler/TexHandler.katex.errors.2.test.ts b/tests/handlers/TexHandler/TexHandler.katex.errors.2.test.ts index c8ac726..c862eb6 100644 --- a/tests/handlers/TexHandler/TexHandler.katex.errors.2.test.ts +++ b/tests/handlers/TexHandler/TexHandler.katex.errors.2.test.ts @@ -1,6 +1,4 @@ -/* eslint-disable vitest/no-commented-out-tests */ import { - suite, describe, it, expect, @@ -8,6 +6,7 @@ import { vi, beforeEach, beforeAll, + type MockInstance, } from 'vitest'; import { TexHandler } from '$handlers/TexHandler.js'; import { spy } from '$tests/fixtures.js'; @@ -15,14 +14,13 @@ import fetch, { type Response } from 'node-fetch'; import { v4 as uuid } from 'uuid'; import { range } from '$tests/utils.js'; -suite("TexHandler<'katex'>", async () => { - beforeEach(() => { +describe("TexHandler<'katex'>", () => { + let log: MockInstance; + beforeEach(async () => { vi.clearAllMocks(); + log = (await spy(['fancyWrite', 'log', 'mkdir', 'existsSync'], true)) + .log; }); - const { log } = await spy( - ['fancyWrite', 'log', 'mkdir', 'existsSync'], - true, - ); beforeAll(async () => { vi.spyOn(await import('$deps.js'), 'ora').mockImplementation((() => ({ start: vi.fn().mockReturnValue({ diff --git a/tests/handlers/TexHandler/TexHandler.katex.errors.test.ts b/tests/handlers/TexHandler/TexHandler.katex.errors.test.ts index 5a12000..58cc8d4 100644 --- a/tests/handlers/TexHandler/TexHandler.katex.errors.test.ts +++ b/tests/handlers/TexHandler/TexHandler.katex.errors.test.ts @@ -1,6 +1,4 @@ -/* eslint-disable vitest/no-commented-out-tests */ import { - suite, describe, it, expect, @@ -8,6 +6,7 @@ import { vi, beforeEach, beforeAll, + MockInstance, } from 'vitest'; import { TexHandler } from '$handlers/TexHandler.js'; import { spy } from '$tests/fixtures.js'; @@ -15,14 +14,11 @@ import fetch, { type Response } from 'node-fetch'; import { v4 as uuid } from 'uuid'; import { range } from '$tests/utils.js'; -suite("TexHandler<'katex'>", async () => { +describe("TexHandler<'katex'>", () => { beforeEach(() => { vi.clearAllMocks(); }); - const { log } = await spy( - ['writeFile', 'log', 'mkdir', 'existsSync'], - true, - ); + let log: MockInstance; beforeAll(async () => { vi.spyOn(await import('$deps.js'), 'ora').mockImplementation((() => ({ start: vi.fn().mockReturnValue({ @@ -32,6 +28,11 @@ suite("TexHandler<'katex'>", async () => { fail: vi.fn(), }), })) as unknown as typeof import('ora').default); + const mocks = await spy( + ['writeFile', 'log', 'mkdir', 'existsSync'], + true, + ); + log = mocks.log; }); afterAll(() => { vi.restoreAllMocks(); diff --git a/tests/handlers/TexHandler/TexHandler.katex.test.ts b/tests/handlers/TexHandler/TexHandler.katex.test.ts index 272bc74..c65cc82 100644 --- a/tests/handlers/TexHandler/TexHandler.katex.test.ts +++ b/tests/handlers/TexHandler/TexHandler.katex.test.ts @@ -1,6 +1,4 @@ -/* eslint-disable vitest/no-commented-out-tests */ import { - suite, describe, it, expect, @@ -8,6 +6,7 @@ import { vi, beforeEach, beforeAll, + MockInstance, } from 'vitest'; import { TexHandler } from '$handlers/TexHandler.js'; import { spy } from '$tests/fixtures.js'; @@ -19,13 +18,13 @@ function fixture() { }); } -suite("TexHandler<'katex'>", async () => { +describe("TexHandler<'katex'>", () => { + let handler: TexHandler<'katex'>; + let log: MockInstance; + let writeFileEnsureDir: MockInstance; + let fancyWrite: MockInstance; + let existsSync: MockInstance; fixture(); - const { writeFileEnsureDir, fancyWrite, log, existsSync } = await spy( - ['writeFileEnsureDir', 'fancyWrite', 'log', 'existsSync', 'mkdir'], - true, - ); - const handler = await TexHandler.create('katex'); beforeAll(async () => { vi.spyOn(await import('$deps.js'), 'ora').mockImplementation((() => ({ start: vi.fn().mockReturnValue({ @@ -35,6 +34,15 @@ suite("TexHandler<'katex'>", async () => { fail: vi.fn(), }), })) as unknown as typeof import('ora').default); + const mocks = await spy( + ['writeFileEnsureDir', 'fancyWrite', 'log', 'existsSync', 'mkdir'], + true, + ); + writeFileEnsureDir = mocks.writeFileEnsureDir; + fancyWrite = mocks.fancyWrite; + log = mocks.log; + existsSync = mocks.existsSync; + handler = await TexHandler.create('katex'); }); afterAll(() => { vi.restoreAllMocks(); @@ -103,14 +111,16 @@ suite("TexHandler<'katex'>", async () => { describe('process()', () => { fixture(); it('should work for basic inline math', async () => { - expect(await handler.process('$x$')).toEqual( + expect((await handler.process('x')).processed).toEqual( 'xx', ); expect(log).not.toHaveBeenCalled(); }); it('should work for basic display math', async () => { - expect(await handler.process('$$x$$')).toEqual( + expect( + (await handler.process('x', { inline: false })).processed, + ).toEqual( 'xx', ); expect(log).not.toHaveBeenCalled(); @@ -118,7 +128,11 @@ suite("TexHandler<'katex'>", async () => { it('should support CSS color variables', async () => { expect( - await handler.process('$$\\color{var(--red)}x$$'), + ( + await handler.process('\\color{var(--red)}x', { + inline: false, + }) + ).processed, ).toEqual( 'x\\color{var(--red)}x', ); @@ -136,7 +150,10 @@ suite("TexHandler<'katex'>", async () => { post: [[/ xmlns:xlink=".*?"/g, '']], }, }); - expect(await handler.process('$a * b$')).toEqual( + expect( + (await handler.process('a * b', { inline: true })) + .processed, + ).toEqual( 'ccc \\cdot c', ); await handler.configure({ @@ -162,7 +179,9 @@ suite("TexHandler<'katex'>", async () => { it('configures code correctly', async () => { await handler.configure({ katex: { output: 'mathml' } }); - expect(await handler.process('$x$')).toEqual( + expect( + (await handler.process('x', { inline: true })).processed, + ).toEqual( 'xx', ); await handler.configure({ katex: { output: 'html' } }); diff --git a/tests/handlers/TexHandler/TexHandler.mathjax.errors.test.ts b/tests/handlers/TexHandler/TexHandler.mathjax.errors.test.ts index 7fc9ce4..78f31fb 100644 --- a/tests/handlers/TexHandler/TexHandler.mathjax.errors.test.ts +++ b/tests/handlers/TexHandler/TexHandler.mathjax.errors.test.ts @@ -1,5 +1,4 @@ import { - suite, describe, it, expect, @@ -18,8 +17,7 @@ function fixture() { }); } -suite("TexHandler<'mathjax'>", async () => { - await spy(['writeFile', 'log', 'existsSync', 'mkdir'], true); +describe("TexHandler<'mathjax'>", () => { beforeAll(async () => { vi.spyOn(await import('$deps.js'), 'ora').mockImplementation((() => ({ start: vi.fn().mockReturnValue({ @@ -29,6 +27,7 @@ suite("TexHandler<'mathjax'>", async () => { fail: vi.fn(), }), })) as unknown as typeof import('ora').default); + await spy(['writeFile', 'log', 'existsSync', 'mkdir'], true); }); afterAll(() => { vi.restoreAllMocks(); diff --git a/tests/handlers/TexHandler/TexHandler.mathjax.test.ts b/tests/handlers/TexHandler/TexHandler.mathjax.test.ts index 50dde4e..df1c237 100644 --- a/tests/handlers/TexHandler/TexHandler.mathjax.test.ts +++ b/tests/handlers/TexHandler/TexHandler.mathjax.test.ts @@ -1,5 +1,4 @@ import { - suite, describe, it, expect, @@ -7,6 +6,7 @@ import { vi, beforeEach, beforeAll, + MockInstance, } from 'vitest'; import { TexHandler } from '$handlers/TexHandler.js'; import { MathDocument } from 'mathjax-full/js/core/MathDocument.js'; @@ -20,8 +20,12 @@ function fixture() { }); } -suite("TexHandler<'mathjax'>", async () => { +describe("TexHandler<'mathjax'>", () => { fixture(); + let writeFile: MockInstance; + let fancyWrite: MockInstance; + let log: MockInstance; + let existsSync: MockInstance; beforeAll(async () => { vi.spyOn(await import('$deps.js'), 'ora').mockImplementation((() => ({ start: vi.fn().mockReturnValue({ @@ -31,11 +35,15 @@ suite("TexHandler<'mathjax'>", async () => { fail: vi.fn(), }), })) as unknown as typeof import('ora').default); + const mocks = await spy( + ['writeFile', 'fancyWrite', 'mkdir', 'log', 'existsSync'], + true, + ); + writeFile = mocks.writeFile; + fancyWrite = mocks.fancyWrite; + log = mocks.log; + existsSync = mocks.existsSync; }); - const { writeFile, fancyWrite, log, existsSync } = await spy( - ['writeFile', 'fancyWrite', 'mkdir', 'log', 'existsSync'], - true, - ); afterAll(() => { vi.restoreAllMocks(); @@ -108,14 +116,14 @@ suite("TexHandler<'mathjax'>", async () => { fixture(); it('should work, and output SVG by default', async () => { const handler = await TexHandler.create('mathjax'); - expect(await handler.process('x')).toEqual(xSvg); + expect((await handler.process('x')).processed).toEqual(xSvg); expect(log).not.toHaveBeenCalled(); }); it('should be able to output CHTML', async () => { const handler = await TexHandler.create('mathjax'); await handler.configure({ outputFormat: 'chtml' }); - expect(await handler.process('x')).toEqual(xChtml); + expect((await handler.process('x')).processed).toEqual(xChtml); await handler.configure({ outputFormat: 'svg' }); expect(log).not.toHaveBeenCalled(); }); @@ -137,7 +145,11 @@ suite("TexHandler<'mathjax'>", async () => { it('should support CSS color variables', async () => { const handler = await TexHandler.create('mathjax'); expect( - await handler.process('$$\\color{var(--red)}x$$'), + ( + await handler.process('\\color{var(--red)}x', { + inline: false, + }) + ).processed, ).toEqual( '', ); @@ -161,7 +173,10 @@ suite("TexHandler<'mathjax'>", async () => { ], }, }); - expect(await handler.process('$a * b$')).toEqual( + expect( + (await handler.process('a * b', { inline: true })) + .processed, + ).toEqual( '', ); expect(log).not.toHaveBeenCalled(); @@ -188,7 +203,7 @@ suite("TexHandler<'mathjax'>", async () => { it('configures code correctly', async () => { const handler = await TexHandler.create('mathjax'); await handler.configure({ outputFormat: 'svg' }); - expect(await handler.process('x')).toEqual(xSvg); + expect((await handler.process('x')).processed).toEqual(xSvg); expect(log).not.toHaveBeenCalled(); }); diff --git a/tests/handlers/TexHandler/TexHandler.test.ts b/tests/handlers/TexHandler/TexHandler.test.ts index a939112..cfef849 100644 --- a/tests/handlers/TexHandler/TexHandler.test.ts +++ b/tests/handlers/TexHandler/TexHandler.test.ts @@ -1,9 +1,13 @@ -import { suite, describe, it, expect, vi, beforeAll } from 'vitest'; +import { describe, it, expect, vi, beforeAll } from 'vitest'; import { TexHandler } from '$handlers/TexHandler.js'; -import { missingDeps } from '$utils/globals.js'; +import { missingDeps } from '$utils/env.js'; + +describe("TexHandler<'none'>", () => { + let handler: TexHandler<'none'>; + beforeAll(async () => { + handler = await TexHandler.create('none'); + }); -suite("TexHandler<'none'>", async () => { - const handler = await TexHandler.create('none'); beforeAll(async () => { vi.spyOn(await import('$deps.js'), 'ora').mockImplementation((() => ({ start: vi.fn().mockReturnValue({ @@ -25,7 +29,7 @@ suite("TexHandler<'none'>", async () => { describe('texHandler', () => { describe('process()', () => { it('should work, and output the input as-is', async () => { - expect(await handler.process('x')).toEqual('x'); + expect((await handler.process('x')).processed).toEqual('x'); }); }); @@ -44,9 +48,12 @@ suite("TexHandler<'none'>", async () => { }); }); -suite("TexHandler<'custom'>", async () => { - const handler = await TexHandler.create('custom', { - process: (input: string) => input, +describe("TexHandler<'custom'>", () => { + let handler: TexHandler<'custom'>; + beforeAll(async () => { + handler = await TexHandler.create('custom', { + process: (input: string) => input, + }); }); describe("TexHandler.create('custom', ...)", () => { it('returns instance of TexHandler', () => { @@ -75,14 +82,7 @@ suite("TexHandler<'custom'>", async () => { describe('texHandler', () => { describe('process()', () => { it('should work, and output the input as-is', async () => { - expect(await handler.process('x')).toEqual('x'); - }); - - it('should work strip math delims', async () => { - expect(await handler.process('$x$')).toEqual('x'); - expect(await handler.process('\\(x\\)')).toEqual('x'); - expect(await handler.process('$$x$$')).toEqual('x'); - expect(await handler.process('\\[x\\]')).toEqual('x'); + expect((await handler.process('x')).processed).toEqual('x'); }); }); @@ -103,7 +103,7 @@ suite("TexHandler<'custom'>", async () => { }); }); -suite('TexHandler error handling', () => { +describe('TexHandler error handling', () => { describe("TexHandler.create('mathjax') with mathjax mocked to throw error", () => { vi.mock('mathjax-full/js/handlers/html.js', () => { throw new Error('MathJax not found'); diff --git a/tests/handlers/VerbatimHandler/VerbatimHandler.test.ts b/tests/handlers/VerbatimHandler/VerbatimHandler.test.ts index 76f9e98..5827997 100644 --- a/tests/handlers/VerbatimHandler/VerbatimHandler.test.ts +++ b/tests/handlers/VerbatimHandler/VerbatimHandler.test.ts @@ -1,11 +1,12 @@ import { afterAll, afterEach, + beforeAll, beforeEach, describe, expect, it, - suite, + type MockInstance, vi, } from 'vitest'; @@ -68,11 +69,16 @@ function fixture() { }); } -suite('VerbatimHandler', async () => { +describe('VerbatimHandler', () => { + let log: MockInstance; + beforeAll(async () => { + const mocks = await spy(['log']); + log = mocks.log; + }); afterAll(() => { vi.restoreAllMocks(); }); - const { log } = await spy(['log']); + fixture(); describe('constructor(sveltex: Sveltex)', () => { @@ -134,32 +140,44 @@ suite('VerbatimHandler', async () => { describe('process(content: string)', () => { fixture(); it('should process JS code correctly', async () => { - const result = await sveltexPreprocessor.verbatimHandler.process( - '\nconst a = new Map();\n', - { filename: 'test.sveltex' }, - ); + const result = ( + await sveltexPreprocessor.verbatimHandler.process( + '\nconst a = new Map();\n', + { + filename: 'test.sveltex', + selfClosing: false, + tag: 'Code', + attributes: { lang: 'js' }, + outerContent: + '\nconst a = new Map();\n', + }, + ) + ).processed; expect(result).toEqual( '\nconst a = new Map<string, { prop: number[] }>();\n', ); }); it('should escape plain text correctly', async () => { - const result = await sveltexPreprocessor.verbatimHandler.process( - '\nconst a = new Map();\n', - { filename: 'test.sveltex' }, - ); + const result = ( + await sveltexPreprocessor.verbatimHandler.process( + '\nconst a = new Map();\n', + { + filename: 'test.sveltex', + selfClosing: false, + tag: 'Code', + attributes: {}, + outerContent: + '\nconst a = new Map();\n', + }, + ) + ).processed; expect(result).toEqual( '\nconst a = new Map<string, { prop: number[] }>();\n', ); }); it('should correctly handle self-closing components', async () => { - expect( - await sveltexPreprocessor.verbatimHandler.process( - '', - { filename: 'test.sveltex' }, - ), - ).toEqual(''); await sveltexPreprocessor.configure({ verbatim: { verbatimEnvironments: { @@ -170,10 +188,15 @@ suite('VerbatimHandler', async () => { }, }); expect( - await sveltexPreprocessor.verbatimHandler.process( - '', - { filename: 'test.sveltex' }, - ), + ( + await sveltexPreprocessor.verbatimHandler.process('', { + filename: 'test.sveltex', + selfClosing: true, + tag: 'Code', + attributes: { id: 'something' }, + outerContent: '', + }) + ).processed, ).toEqual(''); await sveltexPreprocessor.configure({ verbatim: { @@ -185,10 +208,18 @@ suite('VerbatimHandler', async () => { }, }); expect( - await sveltexPreprocessor.verbatimHandler.process( - '', - { filename: 'test.sveltex' }, - ), + ( + await sveltexPreprocessor.verbatimHandler.process( + '', + { + filename: 'test.sveltex', + selfClosing: true, + tag: 'Code', + attributes: { id: 'something' }, + outerContent: '', + }, + ) + ).processed, ).toEqual(''); await sveltexPreprocessor.configure({ verbatim: { @@ -200,17 +231,27 @@ suite('VerbatimHandler', async () => { }, }); expect( - await sveltexPreprocessor.verbatimHandler.process( - '', - { filename: 'test.sveltex' }, - ), - ).toEqual(''); - expect( - await sveltexPreprocessor.verbatimHandler.process( - '', - { filename: 'test.sveltex' }, - ), + ( + await sveltexPreprocessor.verbatimHandler.process('', { + filename: 'test.sveltex', + selfClosing: true, + tag: 'Code', + attributes: { id: 'something' }, + outerContent: '', + }) + ).processed, ).toEqual(''); + expect( + ( + await sveltexPreprocessor.verbatimHandler.process('', { + filename: 'test.sveltex', + selfClosing: true, + tag: 'Code', + attributes: { id: 'something' }, + outerContent: '', + }) + ).processed, + ).toEqual(''); }); it('should correctly handle self-closing components (TeX)', async () => { @@ -223,9 +264,15 @@ suite('VerbatimHandler', async () => { }, }); expect( - await sp.verbatimHandler.process('', { - filename: 'test.sveltex', - }), + ( + await sp.verbatimHandler.process('', { + filename: 'test.sveltex', + selfClosing: true, + tag: 'tex', + attributes: { ref: 'something' }, + outerContent: '', + }) + ).processed, ).toEqual( '
\n\n
', ); @@ -244,46 +291,48 @@ suite('VerbatimHandler', async () => { }, }); expect( - await sp.verbatimHandler.process( - '', - { + ( + await sp.verbatimHandler.process('', { filename: 'test.sveltex', - }, - ), + selfClosing: true, + tag: 'Code', + attributes: { a: 1, b: 2, c: 3, d: 4 }, + outerContent: '', + }) + ).processed, ).toEqual(''); expect( - await sp.verbatimHandler.process('', { - filename: 'test.sveltex', - }), + ( + await sp.verbatimHandler.process('', { + filename: 'test.sveltex', + selfClosing: true, + tag: 'Code', + attributes: { + a: undefined, + b: undefined, + c: undefined, + d: undefined, + }, + outerContent: '', + }) + ).processed, ).toEqual(''); }); - it.each([ - 'x', - '', - 'x', - 'x', - '', - '', - '', - ])('should deal with weird content gracefully: %o', async (content) => { - const result = await sveltexPreprocessor.verbatimHandler.process( - content, - { - filename: 'test.sveltex', - }, - ); - expect(result).toEqual(content); - expect(log).toHaveBeenCalledTimes(1); - expect(log).toHaveBeenNthCalledWith(1, 'error', expect.any(String)); - }); - it('should deal with unknown verbatim tags gracefully', async () => { expect( - await sveltexPreprocessor.verbatimHandler.process( - 'something', - { filename: 'test.sveltex' }, - ), + ( + await sveltexPreprocessor.verbatimHandler.process( + 'something', + { + filename: 'test.sveltex', + selfClosing: false, + tag: 'unknown', + attributes: {}, + outerContent: 'something', + }, + ) + ).processed, ).toEqual('something'); expect(log).toHaveBeenCalledTimes(1); expect(log).toHaveBeenNthCalledWith( @@ -297,10 +346,18 @@ suite('VerbatimHandler', async () => { it('should deal with ambiguous verbatim tags gracefully', async () => { expect( - await sveltexPreprocessor.verbatimHandler.process( - 'something', - { filename: 'test.sveltex' }, - ), + ( + await sveltexPreprocessor.verbatimHandler.process( + 'something', + { + filename: 'test.sveltex', + selfClosing: false, + tag: 'Ambiguous', + attributes: {}, + outerContent: 'something', + }, + ) + ).processed, ).toEqual('something'); expect(log).toHaveBeenCalledTimes(1); expect(log).toHaveBeenNthCalledWith( @@ -313,20 +370,38 @@ suite('VerbatimHandler', async () => { }); it('should work with aliases', async () => { - const result = await sveltexPreprocessor.verbatimHandler.process( - '\nconst a = new Map();\n', - { filename: 'test.sveltex' }, - ); + const result = ( + await sveltexPreprocessor.verbatimHandler.process( + '\nconst a = new Map();\n', + { + filename: 'test.sveltex', + selfClosing: false, + tag: 'CodeBlock', + attributes: { lang: 'js' }, + outerContent: + '\nconst a = new Map();\n', + }, + ) + ).processed; expect(result).toEqual( '\nconst a = new Map<string, { prop: number[] }>();\n', ); }); it('should support transformation of component', async () => { - const result = await sveltexPreprocessor.verbatimHandler.process( - '\nconst a = new Map();\n', - { filename: 'test.sveltex' }, - ); + const result = ( + await sveltexPreprocessor.verbatimHandler.process( + '\nconst a = new Map();\n', + { + filename: 'test.sveltex', + selfClosing: false, + tag: 'JS', + attributes: {}, + outerContent: + '\nconst a = new Map();\n', + }, + ) + ).processed; expect(result).toEqual( '\nconst a = new Map<string, { prop: number[] }>();\n', ); @@ -334,49 +409,81 @@ suite('VerbatimHandler', async () => { it('should support simple escape instructions', async () => { expect( - await sveltexPreprocessor.verbatimHandler.process( - '\n<>&{', - { filename: 'test.sveltex' }, - ), - ).toEqual('\n<>&{'); - - expect( - await sveltexPreprocessor.verbatimHandler.process( - '\n<>&{', - { filename: 'test.sveltex' }, - ), + ( + await sveltexPreprocessor.verbatimHandler.process( + '\n<>&{', + { + filename: 'test.sveltex', + selfClosing: false, + tag: 'Verbatim', + attributes: {}, + outerContent: '\n<>&{', + }, + ) + ).processed, ).toEqual('\n<>&{'); }); it('should support custom processInner functions', async () => { expect( - await sveltexPreprocessor.verbatimHandler.process( - 'content', - { filename: 'test.sveltex' }, - ), + ( + await sveltexPreprocessor.verbatimHandler.process( + 'content', + { + filename: 'test.sveltex', + selfClosing: false, + tag: 'Custom', + attributes: { attr: 'test', attr2: 'test2' }, + outerContent: + 'content', + }, + ) + ).processed, ).toEqual( 'Custom: content{"attr":"test","attr2":"test2"}', ); expect( - await sveltexPreprocessor.verbatimHandler.process( - 'content', - { filename: 'test.sveltex' }, - ), - ).toEqual('Custom: content{}'); + ( + await sveltexPreprocessor.verbatimHandler.process( + 'content', + { + filename: 'test.sveltex', + selfClosing: false, + tag: 'Custom', + attributes: { attr: 'test', attr2: 'test2' }, + outerContent: + 'content', + }, + ) + ).processed, + ).toEqual( + 'Custom: content{"attr":"test","attr2":"test2"}', + ); }); it('misc', async () => { expect( - await sveltexPreprocessor.verbatimHandler.process('', { - filename: 'test.sveltex', - }), + ( + await sveltexPreprocessor.verbatimHandler.process('', { + filename: 'test.sveltex', + selfClosing: false, + tag: '', + attributes: {}, + outerContent: '', + }) + ).processed, ).toEqual(''); expect( - await sveltexPreprocessor.verbatimHandler.process( - 'abc', - { filename: 'test.sveltex' }, - ), + ( + await sveltexPreprocessor.verbatimHandler.process('abc', { + filename: 'test.sveltex', + selfClosing: false, + tag: 'noop', + attributes: {}, + outerContent: 'abc', + }) + ).processed, ).toEqual('abc'); }); }); diff --git a/tests/type-guards/ast.test.ts b/tests/type-guards/ast.test.ts index f1ed6c4..9ad1df5 100644 --- a/tests/type-guards/ast.test.ts +++ b/tests/type-guards/ast.test.ts @@ -1,7 +1,6 @@ import { hasStartEnd_LineColumn, hasStartEnd_Offset, - isFragment_v5, } from '$type-guards/ast.js'; import { describe, expect, it } from 'vitest'; @@ -164,70 +163,3 @@ describe('hasStartEnd_LineColumn', () => { expect(result).toBe(false); }); }); - -describe('isFragment_v5', () => { - it('should return true for a valid Fragment_v5 node', () => { - const node = { - type: 'Fragment', - nodes: [ - { type: 'Text', data: 'Hello', start: 1, end: 2 }, - { type: 'Element', name: 'div', start: 3, end: 4 }, - ], - start: 1, - end: 4, - }; - - const result = isFragment_v5(node); - - expect(result).toBe(true); - }); - - it('should return false for a node with incorrect type', () => { - const node = { - type: 'Element', - name: 'div', - start: 1, - end: 2, - }; - - const result = isFragment_v5(node); - - expect(result).toBe(false); - }); - - it('should return false for a node without "nodes" property', () => { - const node = { - type: 'Fragment', - }; - - const result = isFragment_v5(node); - - expect(result).toBe(false); - }); - - it('should return false for a node with "nodes" property that is not an array', () => { - const node = { - type: 'Fragment', - nodes: {}, - }; - - const result = isFragment_v5(node); - - expect(result).toBe(false); - }); - - it('should return false for a node with "nodes" property that contains non-BaseNode elements', () => { - const node = { - type: 'Fragment', - nodes: [ - { type: 'Text', data: 'Hello', start: 1, end: 2 }, - { type: 'Element', name: 'div', start: 3, end: 4 }, - 'InvalidNode', - ], - }; - - const result = isFragment_v5(node); - - expect(result).toBe(false); - }); -}); diff --git a/tests/utils.ts b/tests/utils.ts index db50cfd..53f6d36 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -46,7 +46,7 @@ export function expectWith( export function range(start: number, end: number, step: number = 1): number[] { const arr = []; - for (let i = start; i < end; i += step) { + for (let i = start; i <= end; i += step) { arr.push(i); } return arr; @@ -62,8 +62,37 @@ interface Variables { advancedTex?: boolean | AdvancedTexBackend[]; } -const cartesianProduct = (...a: unknown[][]) => - a.reduce((a, b) => a.flatMap((d) => b.map((e) => [d, e].flat()))); +export function cartesianProduct(x1: X1[]): [X1][]; +export function cartesianProduct(x1: X1[], x2: X2[]): [X1, X2][]; +export function cartesianProduct( + x1: X1[], + x2: X2[], + x3: X3[], +): [X1, X2, X3][]; +export function cartesianProduct( + x1: X1[], + x2: X2[], + x3: X3[], + x4: X4[], +): [X1, X2, X3, X4][]; +export function cartesianProduct( + x1: X1[], + x2: X2[], + x3: X3[], + x4: X4[], + x5: X5[], +): [X1, X2, X3, X4, X5][]; +export function cartesianProduct( + x1: X1[], + x2: X2[], + x3: X3[], + x4: X4[], + x5: X5[], + x6: X6[], +): [X1, X2, X3, X4, X5, X6][]; +export function cartesianProduct(...a: unknown[][]) { + return a.reduce((a, b) => a.flatMap((d) => b.map((e) => [d, e].flat()))); +} type BackendCombination = `${MarkdownBackend}-${CodeBackend}-${TexBackend}-${AdvancedTexBackend}`; diff --git a/tests/utils/TexComponent.test.ts b/tests/utils/TexComponent.test.ts index fd28db6..5227bea 100644 --- a/tests/utils/TexComponent.test.ts +++ b/tests/utils/TexComponent.test.ts @@ -1,12 +1,11 @@ +import { resolve, rimraf } from '$deps.js'; import { AdvancedTexHandler } from '$handlers/AdvancedTexHandler.js'; import { spy } from '$tests/fixtures.js'; import type { SupportedTexEngine } from '$types/SveltexConfiguration.js'; import { TexComponent } from '$utils/TexComponent.js'; import { unescapeCssColorVars } from '$utils/css.js'; -import { pathExists } from '$utils/debug.js'; +import { pathExists } from '$utils/fs.js'; import { sha256 } from '$utils/misc.js'; -import { resolve } from 'node:path'; -import { rimraf } from 'rimraf'; import { afterAll, afterEach, @@ -15,8 +14,8 @@ import { describe, expect, it, - suite, vi, + type MockInstance, } from 'vitest'; let ath: AdvancedTexHandler<'local'>; @@ -68,8 +67,12 @@ function fixture() { }); } -suite('TexComponent', async () => { +describe('TexComponent', () => { vi.restoreAllMocks(); + let log: MockInstance; + let writeFile: MockInstance; + let spawnCliInstruction: MockInstance; + let readFile: MockInstance; beforeAll(async () => { vi.spyOn(await import('$deps.js'), 'ora').mockImplementation((() => ({ start: vi.fn().mockReturnValue({ @@ -79,6 +82,15 @@ suite('TexComponent', async () => { fail: vi.fn(), }), })) as unknown as typeof import('ora').default); + const mocks = await spy( + ['writeFile', 'log', 'spawnCliInstruction', 'readFile'], + false, + ); + log = mocks.log; + writeFile = mocks.writeFile; + spawnCliInstruction = mocks.spawnCliInstruction; + readFile = mocks.readFile; + log.mockImplementation(() => undefined); }); afterAll(async () => { vi.restoreAllMocks(); @@ -86,12 +98,6 @@ suite('TexComponent', async () => { await rimraf(resolve(`tmp/tests`)); } }); - // fixture(); - const { writeFile, log, spawnCliInstruction, readFile } = await spy( - ['writeFile', 'log', 'spawnCliInstruction', 'readFile'], - false, - ); - log.mockImplementation(() => undefined); describe('create', () => { describe('error handling', () => { @@ -106,62 +112,10 @@ suite('TexComponent', async () => { filename: 'TexComponent_test_ts.sveltex', selfClosing: false, }), - ).toThrowError('TeX component must have a ref attribute.'); + ).toThrowError(/ref.*attribute/isu); }, ); }); - - describe('valueless attributes', () => { - fixture(); - it('if exactly 1 valueless attribute is provided, but a ref attribute is also provided, log a warning about the valueless attribute', () => { - const tc = ath.createTexComponent('content', { - tag: 'tex', - attributes: { - ref: 'something', - someValuelessAttribute: undefined, - }, - filename: 'TexComponent_test_ts.sveltex', - selfClosing: false, - }); - expect(tc.ref).toEqual('something'); - expect(log).toHaveBeenCalledTimes(1); - expect(log).toHaveBeenNthCalledWith( - 1, - 'warn', - 'TeX component tex with ref "something" has attributes with no value: someValuelessAttribute. These attributes will be ignored.', - ); - }); - - it('if exactly 1 valueless attribute is provided, and no ref attribute, the valueless attribute is used as ref', () => { - const tc = ath.createTexComponent('content', { - tag: 'tex', - attributes: { refFromValuelessAttribute: undefined }, - filename: 'TexComponent_test_ts.sveltex', - selfClosing: false, - }); - expect(tc.ref).toEqual('refFromValuelessAttribute'); - expect(log).not.toHaveBeenCalled(); - }); - - it('if ≥1 valueless attributes are provided, and no ref attribute, the first valueless attribute is used as ref', () => { - const tc = ath.createTexComponent('content', { - tag: 'tex', - attributes: { - refFromValuelessAttribute: undefined, - anotherValuelessAttribute: undefined, - }, - filename: 'TexComponent_test_ts.sveltex', - selfClosing: false, - }); - expect(tc.ref).toEqual('refFromValuelessAttribute'); - expect(log).toHaveBeenCalledTimes(1); - expect(log).toHaveBeenNthCalledWith( - 1, - 'warn', - 'TeX component tex with ref "refFromValuelessAttribute" has attributes with no value: refFromValuelessAttribute, anotherValuelessAttribute. Of these, the first, "refFromValuelessAttribute", is being used as the ref attribute, and the rest will be ignored.', - ); - }); - }); }); describe('configuration setter', () => { diff --git a/tests/utils/ast.test.ts b/tests/utils/ast.test.ts index c438a34..5311124 100644 --- a/tests/utils/ast.test.ts +++ b/tests/utils/ast.test.ts @@ -1,421 +1,119 @@ -import { describe, it, expect, vi, suite, beforeEach } from 'vitest'; -import { - getChildren, - getLocation, - lineColToLocation, - parse, - stringifyAst, - walk, -} from '$utils/ast.js'; - -suite('AST utilities', () => { - describe.each([3, 4, 5, 6, 7, 8])('getLocation', (version) => { - it('should return the correct location for a node with start and end properties', () => { - const node = { - type: 'test', - start: 1, - end: 10, - }; - - const location = getLocation(node, undefined, version); - - expect(location).toEqual({ - start: 1, - end: 10, - }); - }); - - it('should return the correct location for a node with range property', () => { - const node = { type: 'test', range: [5, 15] }; - - const location = getLocation(node, undefined, version); - - expect(location).toEqual({ - start: 5, - end: 15, - }); - }); - - it('should return the correct location for a node with loc property and source', () => { - const node = { - type: 'test', - loc: { - start: { line: 1, column: 5 }, - end: { line: 2, column: 10 }, - }, - }; - - const source = - 'const x = "something";\nconst y = "something else";'; - - const location = getLocation(node, source, version); - - expect(location).toEqual({ - start: 5, - end: 32, - }); - }); - - it('should throw an error for a node without start and end properties', () => { - const node = { - type: 'test', - }; - - expect(() => getLocation(node, undefined, version)).toThrowError( - 'Could not determine location of node: ' + JSON.stringify(node), - ); - }); - +import { describe, it, expect } from 'vitest'; +import { getLocationUnist, lineColToLocation } from '$utils/ast.js'; +import type { UnistNode } from '$deps.js'; +import { cartesianProduct, range } from '$tests/utils.js'; +import { LineColumn, Offsets } from '$types/utils/Ast.js'; + +describe('getLocationUnist', () => { + describe('core functionality', () => { it.each([ - { - start: { - offset: 5, - }, - end: { - offset: 32, - }, - }, - { - start: { - line: 1, - column: 5, - }, - end: { - line: 1, - column: 32, + [ + { + start: { offset: 0, column: 1, line: 1 }, + end: { offset: 10, column: 11, line: 1 }, }, - }, - { - loc: { - start: { - offset: 5, - }, - end: { - offset: 32, - }, + ['const x = "something";', 'const y = "something else";'], + ], + [ + { + start: { offset: 20, column: 21, line: 1 }, + end: { offset: 25, column: 3, line: 2 }, }, - }, - { - loc: { - start: { - line: 1, - column: 5, - }, - end: { - line: 1, - column: 32, - }, + ['const x = "something";', 'const y = "something else";'], + ], + [ + { + start: { offset: 2, column: 1, line: 2 }, + end: { offset: 6, column: 2, line: 4 }, }, - }, - ])('should work with some weird formats', (props) => { - const node = { - type: 'test', - ...props, - }; - - const source = - 'const x = "something";\nconst y = "something else";'; - - const location = getLocation(node, source, version); + ['a', '', 'b', 'c'], + ], + ] as [NonNullable, string[]][])( + '%o on %o', + (position, source) => { + const n1: UnistNode = { type: '', position }; + + const expected = { + start: position.start.offset, + end: position.end.offset, + }; - expect(location).toEqual({ - start: 5, - end: 32, - }); - }); + position.start.offset = undefined; + position.end.offset = undefined; - vi.unmock('$utils/globals.js'); - }); + const n2: UnistNode = { type: '', position }; - describe('lineColToLocation', () => { - it('should correctly convert line-column to offset location with string source', () => { - const source = 'line 1 - text\nline 2 - text\nline 3 - text'; - const start = { line: 2, column: 1 }; - const end = { line: 3, column: 5 }; - const location = lineColToLocation(start, end, source); - expect(location).toEqual({ start: 14, end: 31 }); - }); + const loc1 = getLocationUnist(n1, source); + const loc2 = getLocationUnist(n2, source); - it('should correctly convert line-column to offset location with source', () => { - const source = ['line 1 - text', 'line 2 - text', 'line 3 - text']; - const start = { line: 1, column: 6 }; - const end = { line: 2, column: 3 }; - const location = lineColToLocation(start, end, source); - expect(location).toEqual({ start: 6, end: 16 }); - }); + expect(loc1).toEqual(expected); + expect(loc2).toEqual(expected); + }, + ); }); - - describe('getChildren', () => { - it('should return child nodes for a given Svelte AST node', () => { - const node = { - type: 'Fragment', - children: [ - { type: 'Text', data: 'Hello' }, - { type: 'Element', name: 'div' }, - ], - start: 1, - end: 4, - }; - const children = getChildren(node, 4); - expect(children).toEqual(node.children); - expect(children).not.toBe(node.children); - }); - - it('should return (a copy of) the .nodes property if version is 5', () => { - const node = { - type: 'Fragment', - nodes: [ - { type: 'Text', data: 'Hello', start: 1, end: 2 }, - { type: 'Element', name: 'div', start: 3, end: 4 }, - ], - start: 1, - end: 4, - }; - const children = getChildren(node, 5); - expect(children).toEqual(node.nodes); - expect(children).not.toBe(node.nodes); - }); - - it.each([1, 5, 100])('AwaitBlock (v5)', (version) => { - const node = { - type: 'Fragment', - nodes: [ - { type: 'AwaitBlock', data: 'Hello', start: 1, end: 2 }, - { type: 'Element', name: 'div', start: 3, end: 4 }, - ], - start: 1, - end: 4, - }; - const children = getChildren(node, version); - expect(children).toEqual(node.nodes); - expect(children).not.toBe(node.nodes); - }); - - it.each([1, 4, 100])('AwaitBlock (v4)', (version) => { - const node = { - type: 'AwaitBlock', - children: [ - { type: 'Text', data: 'Hello', start: 1, end: 2 }, - { type: 'Element', name: 'div', start: 3, end: 4 }, - ], - start: 1, - end: 4, - pending: { type: 'Text', data: 'Pending', start: 1, end: 2 }, - then: { type: 'Text', data: 'Then', start: 1, end: 2 }, - catch: [ - { type: 'Text', data: 'Catch', start: 1, end: 2 }, - { type: 'Text', data: 'Catch2', start: 1, end: 2 }, - ], - }; - const children = getChildren(node, version); - expect(children).toEqual([ - ...node.children, - node.pending, - node.then, - ...node.catch, - ]); + describe('error handling', () => { + it('no position prop → throw error', () => { + const node = { type: 'test' }; + expect(() => getLocationUnist(node, [''])).toThrowError( + /Could not determine location of node:/, + ); }); }); +}); - describe('walk', () => { - it('should perform an action on each node in the AST', () => { - const node = { - type: 'Fragment', - children: [{ type: 'Text', data: 'Hello' }], - }; - const walkedNodes: { node: unknown; depth: number }[] = []; - const mockAction = vi.fn((node: unknown, depth: number) => - walkedNodes.push({ node, depth }), +describe('lineColToLocation', () => { + describe("'123456789\\n123...9\\n1...'", () => { + /** + * This source string has the neat property that within it one can + * convert line-column pairs to offsets with the following + * formula: + * + * ``` + * offset = (line - 1) * 10 + col - 1 + * ``` + */ + const source = range(1, 10).map(() => '123456789'); + + const tests: [string, LineColumn, LineColumn, Offsets][] = + cartesianProduct([1, 2, 5], [1, 4, 10], [1, 2, 3], [1, 4, 10]).map( + ([line, column, lineShift, endColumn]) => { + const start = (line - 1) * 10 + column - 1; + const end = (line + lineShift - 1) * 10 + endColumn - 1; + const label = `${String(line)}:${String(column)} to ${String(line + lineShift)}:${String(endColumn)} → ${String(start)} to ${String(end)}`; + return [ + label, + { line, column }, + { line: line + lineShift, column: endColumn }, + { start, end }, + ]; + }, ); - walk(node, mockAction); - expect(mockAction).toHaveBeenCalledTimes(2); // Once for Fragment, once for Text - expect(walkedNodes).toHaveLength(2); - expect(walkedNodes).toEqual([ - { - depth: 0, - node: { - children: [ - { - data: 'Hello', - type: 'Text', - }, - ], - type: 'Fragment', - }, - }, - { - depth: 1, - node: { - data: 'Hello', - type: 'Text', - }, - }, - ]); + describe.each([0, 1])(`%i-based cols`, (colOrigin) => { + it.each(tests)('%s', (_label, start, end, expected) => { + const location = lineColToLocation( + start, + end, + source, + !!colOrigin, + ); + expect(location.start).toEqual(expected.start + +!colOrigin); + expect(location.end).toEqual(expected.end + +!colOrigin); + }); }); }); - describe('stringifyAst', () => { - it('should return a string representation of the Svelte AST', () => { - const ast = { - type: 'Fragment', - children: [{ type: 'Text', data: 'Hello, world!' }], - }; - const result = stringifyAst(ast); - expect(result).toBe('Fragment\n Text (Hello, world!)'); - }); - - it('should abridge long data', () => { - const ast = { - type: 'Fragment', - children: [ - { type: 'Text', data: '123456789012345678901234567890' }, - ], - }; - const result = stringifyAst(ast); - expect(result).toBe('Fragment\n Text (12345678901234567890[...])'); - }); - - it('should accept non-string data (and print "[data]" to represent it)', () => { - const ast = { - type: 'Fragment', - children: [{ type: 'Text', data: {} }], - }; - const result = stringifyAst(ast); - expect(result).toBe('Fragment\n Text ([data])'); - }); - - it("should show a node's name, if there is one", () => { - const ast = { - type: 'Fragment', - name: 'test', - children: [{ type: 'Text', data: {} }], - }; - const result = stringifyAst(ast); - expect(result).toBe('Fragment (test)\n Text ([data])'); - }); - - it("should prioritize a node's name over the data it contains", () => { - expect( - stringifyAst({ - type: 'Fragment', - children: [{ type: 'Text', name: 'test', data: {} }], - }), - ).toBe('Fragment\n Text (test)'); + describe('empty string', () => { + it.each([0, 1])('%i-based cols', (colOrigin) => { + const source = ['']; expect( - stringifyAst({ - type: 'Fragment', - children: [{ type: 'Text', name: 'test', data: 'data' }], - }), - ).toBe('Fragment\n Text (test)'); - }); - }); - - describe('parse', () => { - beforeEach(() => { - vi.restoreAllMocks(); - }); - - it('should parse Svelte content into an AST (v4)', () => { - const content = - '
Hello, world!
\n{#if true}Hello, world!{/if}'; - const ast = parse(content).ast; - expect(ast).toEqual({ - children: [ - { - attributes: [], - children: [ - { - data: 'Hello, world!', - end: 18, - raw: 'Hello, world!', - start: 5, - type: 'Text', - }, - ], - end: 24, - name: 'div', - start: 0, - type: 'Element', - }, - { - data: '\n', - end: 25, - raw: '\n', - start: 24, - type: 'Text', - }, - { - children: [ - { - data: 'Hello, world!', - end: 48, - raw: 'Hello, world!', - start: 35, - type: 'Text', - }, - ], - end: 53, - expression: { - end: 34, - loc: { - end: { - column: 9, - line: 2, - }, - start: { - column: 5, - line: 2, - }, - }, - raw: 'true', - start: 30, - type: 'Literal', - value: true, - }, - start: 25, - type: 'IfBlock', - }, - ], - end: 53, - start: 0, - type: 'Fragment', - }); - }); - - it('should parse Svelte content into an AST (v6)', () => { - vi.mock('$utils/globals.js', async (importOriginal) => { - const actual = await importOriginal(); - if (typeof actual !== 'object') { - throw new Error('test error'); - } - return { - ...actual, - SVELTE_MAJOR_VERSION: 6, - }; - }); - const content = - '
Hello, world!
\n{#if true}Hello, world!{/if}'; - const ast = parse(content); - expect(ast).toBeDefined(); // We currently have Svelte 4 installed, so we can't generate the actual v5 AST (more precisely, even though we're mocking the version, the actual AST will be the same as from the v4 test) - vi.unmock('$utils/globals.js'); - }); - - it('should parse Svelte content into an AST (v100)', () => { - vi.mock( - 'svelte/compiler', - async (importOriginal: () => Promise) => { - return { - ...(await importOriginal()), - VERSION: '100.0.0', - }; - }, - ); - const content = - '
Hello, world!
\n{#if true}Hello, world!{/if}'; - const ast = parse(content); - expect(ast).toBeDefined(); - vi.unmock('svelte/compiler'); + lineColToLocation( + { line: 1, column: colOrigin }, + { line: 1, column: colOrigin }, + source, + !!colOrigin, + ), + ).toEqual({ start: 0, end: 0 }); }); }); }); diff --git a/tests/utils/cache.test.ts b/tests/utils/cache.test.ts index 2bc2cee..3b1510d 100644 --- a/tests/utils/cache.test.ts +++ b/tests/utils/cache.test.ts @@ -1,15 +1,29 @@ -import { suite, describe, it, expect, vi, afterAll } from 'vitest'; +import { + describe, + it, + expect, + vi, + afterAll, + type MockInstance, + beforeAll, +} from 'vitest'; import { spy } from '$tests/fixtures.js'; import { mockFs } from '$dev_deps.js'; import { SveltexCache } from '$utils/cache.js'; -suite('SveltexCache', async () => { +describe('SveltexCache', () => { + let writeFile: MockInstance; + let log: MockInstance; + beforeAll(async () => { + const mocks = await spy(['writeFile', 'log'], true); + writeFile = mocks.writeFile; + log = mocks.log; + }); afterAll(() => { vi.restoreAllMocks(); mockFs.restore(); }); - const { writeFile, log } = await spy(['writeFile', 'log'], true); describe('misc', () => { it('is serializable', async () => { diff --git a/tests/utils/cdn.error.test.ts b/tests/utils/cdn.error.test.ts index 766299e..41bddcc 100644 --- a/tests/utils/cdn.error.test.ts +++ b/tests/utils/cdn.error.test.ts @@ -1,7 +1,6 @@ import { fancyFetch, fetchWithTimeout } from '$utils/cdn.js'; import { spy } from '$tests/fixtures.js'; import { - suite, describe, it, expect, @@ -10,6 +9,7 @@ import { beforeEach, afterEach, beforeAll, + type MockInstance, } from 'vitest'; function fixture() { @@ -21,12 +21,16 @@ function fixture() { }); } -suite.sequential('utils/cdn', async () => { +describe.sequential('utils/cdn', () => { + let log: MockInstance; fixture(); - const { log } = await spy( - ['writeFileEnsureDir', 'log', 'existsSync'], - true, - ); + beforeAll(async () => { + const mocks = await spy( + ['writeFileEnsureDir', 'log', 'existsSync'], + true, + ); + log = mocks.log; + }); afterAll(() => { vi.restoreAllMocks(); vi.unmock('node-fetch'); diff --git a/tests/utils/cdn.test.ts b/tests/utils/cdn.test.ts index 19bc70c..9303a74 100644 --- a/tests/utils/cdn.test.ts +++ b/tests/utils/cdn.test.ts @@ -1,7 +1,6 @@ -import { fetchWithTimeout, getVersion, cdnLink } from '$utils/cdn.js'; +import { fetchWithTimeout, cdnLink } from '$utils/cdn.js'; import { spy } from '$tests/fixtures.js'; import { - suite, describe, it, expect, @@ -9,6 +8,8 @@ import { afterAll, beforeEach, afterEach, + type MockInstance, + beforeAll, } from 'vitest'; function fixture() { @@ -20,12 +21,16 @@ function fixture() { }); } -suite('utils/cdn', async () => { +describe('utils/cdn', () => { + let log: MockInstance; fixture(); - const { log } = await spy( - ['writeFileEnsureDir', 'log', 'existsSync'], - true, - ); + beforeAll(async () => { + const mocks = await spy( + ['writeFileEnsureDir', 'log', 'existsSync'], + true, + ); + log = mocks.log; + }); afterAll(() => { vi.restoreAllMocks(); }); @@ -97,14 +102,4 @@ suite('utils/cdn', async () => { }, ); }); - - describe('getVersion', () => { - fixture(); - it.each(['katex', 'highlight.js', 'mathjax-full'] as const)( - 'getVersion(%o) has format "x.y.z"', - async (dep) => { - expect(await getVersion(dep)).toMatch(/(\d+\.\d+\.\d+)/); - }, - ); - }); }); diff --git a/tests/utils/cli.test.ts b/tests/utils/cli.test.ts index 57751b3..7774025 100644 --- a/tests/utils/cli.test.ts +++ b/tests/utils/cli.test.ts @@ -1,4 +1,5 @@ import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; + import { spawnCliInstruction } from '$utils/cli.js'; describe('spawnCliInstruction', () => { diff --git a/tests/utils/debug.test.ts b/tests/utils/debug.test.ts index aa16fac..8c2c32c 100644 --- a/tests/utils/debug.test.ts +++ b/tests/utils/debug.test.ts @@ -1,23 +1,19 @@ import { mockFs } from '$dev_deps.js'; import { + type MockInstance, afterAll, beforeAll, beforeEach, describe, expect, it, - suite, vi, } from 'vitest'; import { consoles, - detectPackageManager, escapeWhitespace, - getPmFromLockfile, - getPmFromPackageJson, log, - pathExists, prettifyError, runWithSpinner, } from '$utils/debug.js'; @@ -26,7 +22,8 @@ import { spy } from 'tests/fixtures.js'; import { readFileSync } from 'node:fs'; import pc from 'picocolors'; -suite('debug', async () => { +describe('debug', () => { + let existsSync: MockInstance; beforeAll(async () => { vi.spyOn(await import('$deps.js'), 'ora').mockImplementation((() => ({ start: vi.fn().mockReturnValue({ @@ -36,23 +33,22 @@ suite('debug', async () => { fail: vi.fn(), }), })) as unknown as typeof import('ora').default); + const mocks = await spy(['existsSync'], false); + existsSync = mocks.existsSync; + existsSync.mockImplementation((path: string) => { + try { + readFileSync(path); + return true; + } catch { + return false; + } + }); }); afterAll(() => { vi.restoreAllMocks(); mockFs.restore(); }); - const { existsSync } = await spy(['existsSync'], false); - - existsSync.mockImplementation((path: string) => { - try { - readFileSync(path); - return true; - } catch { - return false; - } - }); - describe('log', () => { beforeEach(() => { vi.clearAllMocks(); @@ -187,126 +183,4 @@ suite('debug', async () => { expect(output).toEqual(expectedOutput); }); }); - - describe('pathExists', () => { - it.each([[{ 'exists.txt': '' }, 'exists.txt']])( - 'returns true when the path exists', - (files, path) => { - mockFs(files); - const res = pathExists(path); - expect(existsSync).toHaveBeenCalledTimes(1); - expect(existsSync).toHaveBeenNthCalledWith(1, path); - expect(existsSync).toHaveNthReturnedWith(1, true); - expect(res).toEqual(true); - }, - ); - - it('returns false when the path does not exist', () => { - mockFs({}); - expect(pathExists('does-not-exist')).toEqual(false); - }); - - it('catches errors and silently returns false', () => { - mockFs({}); - existsSync.mockImplementationOnce(() => { - throw new Error(); - }); - expect(pathExists('does-not-exist')).toEqual(false); - }); - }); - - describe('getPmFromPackageJson', () => { - it('identifies a valid package manager (pnpm)', () => { - mockFs({ - project: { - 'package.json': '{ "packageManager": "pnpm@6.14.2"}', - }, - }); - expect(getPmFromPackageJson('project')).toEqual('pnpm'); - }); - - it('identifies a valid package manager (bun)', () => { - mockFs({ - project: { - 'package.json': JSON.stringify({ - packageManager: 'bun@6.14.2', - }), - }, - }); - expect(getPmFromPackageJson('project')).toEqual('bun'); - }); - - it('identifies a valid package manager (yarn)', () => { - mockFs({ - 'package.json': JSON.stringify({ - packageManager: 'yarn@6.14.2', - }), - }); - expect(getPmFromPackageJson()).toEqual('yarn'); - }); - - it('returns undefined for an unrecognized package manager', () => { - mockFs({ - 'project/package.json': JSON.stringify({ - packageManager: 'unknown@1.0.0', - }), - }); - expect(getPmFromPackageJson('project')).toBeUndefined(); - }); - - it('returns undefined if package.json does not have packageManager set', () => { - mockFs({ - 'project/package.json': JSON.stringify({}), - }); - expect(getPmFromPackageJson('project')).toBeUndefined(); - }); - - it('returns undefined if package.json does not exist', () => { - mockFs({}); - expect(getPmFromPackageJson('project')).toBeUndefined(); - }); - }); - - describe('getPmFromLockfile', () => { - it.each([ - { file: 'pnpm-lock.yaml', pm: 'pnpm' }, - { file: 'bun.lockb', pm: 'bun' }, - { file: 'package-lock.json', pm: 'npm' }, - { file: 'yarn.lock', pm: 'yarn' }, - ])('detects $pm from the lockfile', ({ file, pm }) => { - mockFs({ [file]: '' }); - expect(getPmFromLockfile()).toEqual(pm); - }); - - it('returns undefined if no known lock file is found', () => { - mockFs({}); - expect(getPmFromLockfile()).toBeUndefined(); - }); - }); - - describe('detectPackageManager', () => { - it('defaults to npm if no package manager is detected', () => { - mockFs({}); - expect(detectPackageManager('project')).toEqual('npm'); - }); - - it('detects package manager from package.json', () => { - mockFs({ - 'project/package.json': JSON.stringify({ - packageManager: 'yarn@6.14.2', - }), - }); - expect(detectPackageManager('project')).toEqual('yarn'); - }); - - it.each([ - { file: 'pnpm-lock.yaml', pm: 'pnpm' }, - { file: 'bun.lockb', pm: 'bun' }, - { file: 'package-lock.json', pm: 'npm' }, - { file: 'yarn.lock', pm: 'yarn' }, - ])('detects package manager from lockfile', ({ file, pm }) => { - mockFs({ [file]: 'test' }); - expect(detectPackageManager()).toEqual(pm); - }); - }); }); diff --git a/tests/utils/diagnosers/backendChoices.test.ts b/tests/utils/diagnosers/backendChoices.test.ts index 4fd93f5..d2242a7 100644 --- a/tests/utils/diagnosers/backendChoices.test.ts +++ b/tests/utils/diagnosers/backendChoices.test.ts @@ -6,7 +6,17 @@ import type { TexBackend } from '$types/handlers/Tex.js'; import { spy } from '$tests/fixtures.js'; import { diagnoseBackendChoices } from '$utils/diagnosers/backendChoices.js'; -import { suite, it, expect, vi, afterAll, beforeEach, afterEach } from 'vitest'; +import { + it, + expect, + vi, + afterAll, + beforeEach, + afterEach, + type MockInstance, + beforeAll, + describe, +} from 'vitest'; function fixture() { beforeEach(() => { @@ -17,15 +27,19 @@ function fixture() { }); } -suite('utils/diagnosers/backendChoices', async () => { +describe('utils/diagnosers/backendChoices', () => { fixture(); afterAll(() => { vi.restoreAllMocks(); }); - const { log } = await spy( - ['writeFileEnsureDir', 'log', 'existsSync'], - true, - ); + let log: MockInstance; + beforeAll(async () => { + const mocks = await spy( + ['writeFileEnsureDir', 'log', 'existsSync'], + true, + ); + log = mocks.log; + }); it.each([ ['something', 1, 0], diff --git a/tests/utils/diagnosers/codeConfiguration.test.ts b/tests/utils/diagnosers/codeConfiguration.test.ts index 048c488..c006942 100644 --- a/tests/utils/diagnosers/codeConfiguration.test.ts +++ b/tests/utils/diagnosers/codeConfiguration.test.ts @@ -2,7 +2,6 @@ import { spy } from '$tests/fixtures.js'; import { codeBackends, isThemableCodeBackend } from '$type-guards/code.js'; import { diagnoseCodeConfiguration } from '$utils/diagnosers/codeConfiguration.js'; import { - suite, it, expect, vi, @@ -10,6 +9,7 @@ import { beforeEach, afterEach, describe, + beforeAll, } from 'vitest'; function fixture() { @@ -21,12 +21,14 @@ function fixture() { }); } -suite('utils/diagnosers/codeConfiguration', async () => { +describe('utils/diagnosers/codeConfiguration', () => { fixture(); + beforeAll(async () => { + await spy(['writeFileEnsureDir', 'log', 'existsSync'], true); + }); afterAll(() => { vi.restoreAllMocks(); }); - await spy(['writeFileEnsureDir', 'log', 'existsSync'], true); describe.each(codeBackends)('code backend: %o', (b) => { it.each([ diff --git a/tests/utils/diagnosers/diagnosers.test.ts b/tests/utils/diagnosers/diagnosers.test.ts index 88c2f7c..d09ea75 100644 --- a/tests/utils/diagnosers/diagnosers.test.ts +++ b/tests/utils/diagnosers/diagnosers.test.ts @@ -3,7 +3,6 @@ import { spy } from '$tests/fixtures.js'; import { isString } from '$type-guards/utils.js'; import { Diagnoser } from '$utils/diagnosers/Diagnoser.js'; import { - suite, describe, it, expect, @@ -11,6 +10,8 @@ import { afterAll, beforeEach, afterEach, + type MockInstance, + beforeAll, } from 'vitest'; function fixture() { @@ -22,15 +23,19 @@ function fixture() { }); } -suite('utils/diagnosers', async () => { +describe('utils/diagnosers', () => { + let log: MockInstance; fixture(); + beforeAll(async () => { + const mocks = await spy( + ['writeFileEnsureDir', 'log', 'existsSync'], + true, + ); + log = mocks.log; + }); afterAll(() => { vi.restoreAllMocks(); }); - const { log } = await spy( - ['writeFileEnsureDir', 'log', 'existsSync'], - true, - ); describe('Diagnoser', () => { fixture(); diff --git a/tests/utils/dvisvgm.test.ts b/tests/utils/dvisvgm.test.ts index a22f2e7..9fac686 100644 --- a/tests/utils/dvisvgm.test.ts +++ b/tests/utils/dvisvgm.test.ts @@ -1,10 +1,5 @@ -import { describe, it, expect, suite } from 'vitest'; +import { describe, expect, it } from 'vitest'; -import { - bboxToFlagValue, - bitmapFormatToFlagValue, - buildDvisvgmInstruction, -} from '$utils/dvisvgm.js'; import type { BBox, BitmapFormat, @@ -13,360 +8,364 @@ import type { TexDim, } from '$types/utils/DvisvgmOptions.js'; -suite.concurrent('utils/dvisvgm', () => { - describe.concurrent('bboxToFlagValue', () => { - it('should return the string representation of a TexDim', () => { - const bbox: TexDim = [10, 'pt']; - const result = bboxToFlagValue(bbox); - expect(result).toEqual('10pt'); - }); +import { + bboxToFlagValue, + bitmapFormatToFlagValue, + buildDvisvgmInstruction, +} from '$utils/dvisvgm.js'; - it('should return the string representation of a TexDim with unitless value', () => { - const bbox: TexDim = 20; - const result = bboxToFlagValue(bbox); - expect(result).toEqual('20'); - }); +describe.concurrent('bboxToFlagValue', () => { + it('should return the string representation of a TexDim', () => { + const bbox: TexDim = [10, 'pt']; + const result = bboxToFlagValue(bbox); + expect(result).toEqual('10pt'); + }); - it('should return the string representation of a BoundingBox', () => { - const bbox: BoundingBox = { - topLeft: { x: 0, y: 0 }, - bottomRight: { x: 100, y: 100 }, - }; - const result = bboxToFlagValue(bbox); - expect(result).toEqual('0,0,100,100'); - }); + it('should return the string representation of a TexDim with unitless value', () => { + const bbox: TexDim = 20; + const result = bboxToFlagValue(bbox); + expect(result).toEqual('20'); + }); - it('should return the string representation of a PaperSize (A4, landscape)', () => { - const bbox: PaperSize = { - paperSize: 'A4', - orientation: 'landscape', - }; - const result = bboxToFlagValue(bbox); - expect(result).toEqual('A4-landscape'); - }); + it('should return the string representation of a BoundingBox', () => { + const bbox: BoundingBox = { + topLeft: { x: 0, y: 0 }, + bottomRight: { x: 100, y: 100 }, + }; + const result = bboxToFlagValue(bbox); + expect(result).toEqual('0,0,100,100'); + }); - it('should return the string representation of a PaperSize (letter, portrait)', () => { - const bbox: PaperSize = { - paperSize: 'letter', - orientation: 'portrait', - }; - const result = bboxToFlagValue(bbox); - expect(result).toEqual('letter-portrait'); - }); + it('should return the string representation of a PaperSize (A4, landscape)', () => { + const bbox: PaperSize = { + paperSize: 'A4', + orientation: 'landscape', + }; + const result = bboxToFlagValue(bbox); + expect(result).toEqual('A4-landscape'); + }); - it('should return the string representation of a PaperSize (C5)', () => { - const bbox: PaperSize = { - paperSize: 'C5', - }; - const result = bboxToFlagValue(bbox); - expect(result).toEqual('C5'); - }); + it('should return the string representation of a PaperSize (letter, portrait)', () => { + const bbox: PaperSize = { + paperSize: 'letter', + orientation: 'portrait', + }; + const result = bboxToFlagValue(bbox); + expect(result).toEqual('letter-portrait'); + }); - it('should return the input value if it is not a recognized type', () => { - const bbox = 'custom-bbox' as BBox; - const result = bboxToFlagValue(bbox); - expect(result).toEqual('custom-bbox'); - }); + it('should return the string representation of a PaperSize (C5)', () => { + const bbox: PaperSize = { + paperSize: 'C5', + }; + const result = bboxToFlagValue(bbox); + expect(result).toEqual('C5'); }); - describe.concurrent('bitmapFormatToFlagValue', () => { - it('should return the bitmap format as string if it is already a string', () => { - const bitmapFormat = 'png'; - const result = bitmapFormatToFlagValue(bitmapFormat); - expect(result).toEqual(bitmapFormat); - }); + it('should return the input value if it is not a recognized type', () => { + const bbox = 'custom-bbox' as BBox; + const result = bboxToFlagValue(bbox); + expect(result).toEqual('custom-bbox'); + }); +}); - it('should return the bitmap format as string with percentage if it is an array', () => { - const bitmapFormat: BitmapFormat = ['jpeggray', 80]; - const result = bitmapFormatToFlagValue(bitmapFormat); - expect(result).toEqual('jpeggray:80'); - }); +describe.concurrent('bitmapFormatToFlagValue', () => { + it('should return the bitmap format as string if it is already a string', () => { + const bitmapFormat = 'png'; + const result = bitmapFormatToFlagValue(bitmapFormat); + expect(result).toEqual(bitmapFormat); + }); - it('should return the bitmap format as string with 0 percentage if it is less than 0', () => { - const bitmapFormat: BitmapFormat = ['jpeg', -10]; - const result = bitmapFormatToFlagValue(bitmapFormat); - expect(result).toEqual('jpeg:0'); - }); + it('should return the bitmap format as string with percentage if it is an array', () => { + const bitmapFormat: BitmapFormat = ['jpeggray', 80]; + const result = bitmapFormatToFlagValue(bitmapFormat); + expect(result).toEqual('jpeggray:80'); + }); - it('should return the bitmap format as string with 100 percentage if it is greater than 100', () => { - const bitmapFormat: BitmapFormat = ['jpeg', 120]; - const result = bitmapFormatToFlagValue(bitmapFormat); - expect(result).toEqual('jpeg:100'); - }); + it('should return the bitmap format as string with 0 percentage if it is less than 0', () => { + const bitmapFormat: BitmapFormat = ['jpeg', -10]; + const result = bitmapFormatToFlagValue(bitmapFormat); + expect(result).toEqual('jpeg:0'); }); - describe.concurrent('buildDvisvgmInstruction', () => { - it('should build the correct CLI instruction for DVI input', () => { - const instruction = buildDvisvgmInstruction({ - outputPath: '/path/to/output.svg', - texPath: '/path/to/input.tex', - inputType: 'dvi', - dvisvgmOptions: { - processing: { - cache: '/path/to/cache', - exactBbox: true, - keep: true, - mag: 1.2, - noMktexmf: true, - noSpecials: ['bgcolor', 'html'], - traceAll: 'retrace', - }, - svg: { - bbox: { - topLeft: { x: 0, y: 0 }, - bottomRight: { x: 100, y: 100 }, - }, - bitmapFormat: 'png', - clipJoin: true, - comments: true, - currentColor: '#000000', - fontFormat: 'woff2', - gradOverlap: true, - gradSegments: 10, - gradSimplify: 0.5, - linkmark: 'box', - noStyles: true, - optimize: [ - 'collapse-groups', - 'reassign-clippaths', - 'remove-clippaths', - ], - precision: 4, - relative: true, - zip: 5, - }, - console: { - color: true, - message: 'Hello, world!', - progress: 50, - }, - svgTransformations: { - rotate: 90, - scale: [2, 2], - transform: 'matrix(1, 0, 0, 1, 0, 0)', - translate: [10, 10], - zoom: 2, + it('should return the bitmap format as string with 100 percentage if it is greater than 100', () => { + const bitmapFormat: BitmapFormat = ['jpeg', 120]; + const result = bitmapFormatToFlagValue(bitmapFormat); + expect(result).toEqual('jpeg:100'); + }); +}); + +describe.concurrent('buildDvisvgmInstruction', () => { + it('should build the correct CLI instruction for DVI input', () => { + const instruction = buildDvisvgmInstruction({ + outputPath: '/path/to/output.svg', + texPath: '/path/to/input.tex', + inputType: 'dvi', + dvisvgmOptions: { + processing: { + cache: '/path/to/cache', + exactBbox: true, + keep: true, + mag: 1.2, + noMktexmf: true, + noSpecials: ['bgcolor', 'html'], + traceAll: 'retrace', + }, + svg: { + bbox: { + topLeft: { x: 0, y: 0 }, + bottomRight: { x: 100, y: 100 }, }, - customArgs: ['--custom-flag'], + bitmapFormat: 'png', + clipJoin: true, + comments: true, + currentColor: '#000000', + fontFormat: 'woff2', + gradOverlap: true, + gradSegments: 10, + gradSimplify: 0.5, + linkmark: 'box', + noStyles: true, + optimize: [ + 'collapse-groups', + 'reassign-clippaths', + 'remove-clippaths', + ], + precision: 4, + relative: true, + zip: 5, + }, + console: { + color: true, + message: 'Hello, world!', + progress: 50, }, - }); + svgTransformations: { + rotate: 90, + scale: [2, 2], + transform: 'matrix(1, 0, 0, 1, 0, 0)', + translate: [10, 10], + zoom: 2, + }, + customArgs: ['--custom-flag'], + }, + }); - expect(instruction).toEqual({ - command: 'dvisvgm', - args: [ - '--output=/path/to/output.svg', - '--cache=/path/to/cache', - '--exact-bbox', - '--keep', - '--mag=1.2', - '--no-mktexmf', - '--no-specials=bgcolor,html', - '--trace-all=true', - '--bbox=0,0,100,100', - '--bitmap-format=png', - '--clip-join', - '--comments', - '--currentcolor=#000000', - '--embed-bitmaps', - '--font-format=woff2', - '--grad-overlap', - '--grad-segments=10', - '--grad-simplify=0.5', - '--linkmark=box', - '--no-styles', - '--optimize=collapse-groups,reassign-clippaths,remove-clippaths', - '--precision=4', - '--relative', - '--zip=5', - '--color', - '--message=Hello, world!', - '--progress=50', - '--verbosity=3', - '--rotate=90', - '--scale=2,2', - '--transform=matrix(1, 0, 0, 1, 0, 0)', - '--translate=10,10', - '--zoom=2', - '--custom-flag', - '/path/to/input.tex', - ], - }); + expect(instruction).toEqual({ + command: 'dvisvgm', + args: [ + '--output=/path/to/output.svg', + '--cache=/path/to/cache', + '--exact-bbox', + '--keep', + '--mag=1.2', + '--no-mktexmf', + '--no-specials=bgcolor,html', + '--trace-all=true', + '--bbox=0,0,100,100', + '--bitmap-format=png', + '--clip-join', + '--comments', + '--currentcolor=#000000', + '--embed-bitmaps', + '--font-format=woff2', + '--grad-overlap', + '--grad-segments=10', + '--grad-simplify=0.5', + '--linkmark=box', + '--no-styles', + '--optimize=collapse-groups,reassign-clippaths,remove-clippaths', + '--precision=4', + '--relative', + '--zip=5', + '--color', + '--message=Hello, world!', + '--progress=50', + '--verbosity=3', + '--rotate=90', + '--scale=2,2', + '--transform=matrix(1, 0, 0, 1, 0, 0)', + '--translate=10,10', + '--zoom=2', + '--custom-flag', + '/path/to/input.tex', + ], }); + }); - it('should build the correct CLI instruction for PDF input', () => { - const instruction = buildDvisvgmInstruction({ - outputPath: '/path/to/output.svg', - texPath: '/path/to/input.tex', - inputType: 'pdf', - dvisvgmOptions: { - processing: { - cache: '/path/to/cache', - exactBbox: true, - keep: true, - mag: 1.2, - noMktexmf: true, - noSpecials: true, - traceAll: 'retrace', - }, - svg: { - bbox: 'A4', - bitmapFormat: 'png', - clipJoin: true, - comments: true, - currentColor: '#000000', - fontFormat: 'woff2', - gradOverlap: true, - gradSegments: 10, - gradSimplify: 0.5, - linkmark: 'box', - noStyles: true, - optimize: [ - 'collapse-groups', - 'reassign-clippaths', - 'remove-clippaths', - ], - precision: 4, - relative: true, - zip: 5, - }, - console: { - color: true, - message: 'Hello, world!', - progress: 50, - }, - svgTransformations: { - rotate: 90, - scale: [2, 2], - transform: 'matrix(1, 0, 0, 1, 0, 0)', - translate: [10, 10], - zoom: 2, - }, - customArgs: ['--custom-flag'], + it('should build the correct CLI instruction for PDF input', () => { + const instruction = buildDvisvgmInstruction({ + outputPath: '/path/to/output.svg', + texPath: '/path/to/input.tex', + inputType: 'pdf', + dvisvgmOptions: { + processing: { + cache: '/path/to/cache', + exactBbox: true, + keep: true, + mag: 1.2, + noMktexmf: true, + noSpecials: true, + traceAll: 'retrace', + }, + svg: { + bbox: 'A4', + bitmapFormat: 'png', + clipJoin: true, + comments: true, + currentColor: '#000000', + fontFormat: 'woff2', + gradOverlap: true, + gradSegments: 10, + gradSimplify: 0.5, + linkmark: 'box', + noStyles: true, + optimize: [ + 'collapse-groups', + 'reassign-clippaths', + 'remove-clippaths', + ], + precision: 4, + relative: true, + zip: 5, + }, + console: { + color: true, + message: 'Hello, world!', + progress: 50, }, - }); + svgTransformations: { + rotate: 90, + scale: [2, 2], + transform: 'matrix(1, 0, 0, 1, 0, 0)', + translate: [10, 10], + zoom: 2, + }, + customArgs: ['--custom-flag'], + }, + }); - expect(instruction).toEqual({ - command: 'dvisvgm', - args: [ - '--pdf', - '--output=/path/to/output.svg', - '--cache=/path/to/cache', - '--keep', - '--mag=1.2', - '--no-mktexmf', - '--no-specials', - '--trace-all=true', - '--bitmap-format=png', - '--clip-join', - '--comments', - '--currentcolor=#000000', - '--font-format=woff2', - '--grad-overlap', - '--grad-segments=10', - '--grad-simplify=0.5', - '--linkmark=box', - '--no-styles', - '--optimize=collapse-groups,reassign-clippaths,remove-clippaths', - '--precision=4', - '--relative', - '--zip=5', - '--color', - '--message=Hello, world!', - '--progress=50', - '--verbosity=3', - '--rotate=90', - '--scale=2,2', - '--transform=matrix(1, 0, 0, 1, 0, 0)', - '--translate=10,10', - '--zoom=2', - '--custom-flag', - '/path/to/input.tex', - ], - }); + expect(instruction).toEqual({ + command: 'dvisvgm', + args: [ + '--pdf', + '--output=/path/to/output.svg', + '--cache=/path/to/cache', + '--keep', + '--mag=1.2', + '--no-mktexmf', + '--no-specials', + '--trace-all=true', + '--bitmap-format=png', + '--clip-join', + '--comments', + '--currentcolor=#000000', + '--font-format=woff2', + '--grad-overlap', + '--grad-segments=10', + '--grad-simplify=0.5', + '--linkmark=box', + '--no-styles', + '--optimize=collapse-groups,reassign-clippaths,remove-clippaths', + '--precision=4', + '--relative', + '--zip=5', + '--color', + '--message=Hello, world!', + '--progress=50', + '--verbosity=3', + '--rotate=90', + '--scale=2,2', + '--transform=matrix(1, 0, 0, 1, 0, 0)', + '--translate=10,10', + '--zoom=2', + '--custom-flag', + '/path/to/input.tex', + ], }); + }); - it('should build the correct CLI instruction for DVI input 2', () => { - const instruction = buildDvisvgmInstruction({ - outputPath: '/path/to/output.svg', - texPath: '/path/to/input.tex', - inputType: 'dvi', - dvisvgmOptions: { - processing: { - noSpecials: 'html', - traceAll: true, - }, - svg: { - bbox: { - topLeft: { x: [0, 'cc'], y: 0 }, - bottomRight: { x: [100, 'cm'], y: [100, 'bp'] }, - }, - currentColor: true, - zip: true, - }, - customArgs: ['--custom-flag=1', '--custom-flag-two'], - svgTransformations: { - scale: 2, - translate: 3, + it('should build the correct CLI instruction for DVI input 2', () => { + const instruction = buildDvisvgmInstruction({ + outputPath: '/path/to/output.svg', + texPath: '/path/to/input.tex', + inputType: 'dvi', + dvisvgmOptions: { + processing: { + noSpecials: 'html', + traceAll: true, + }, + svg: { + bbox: { + topLeft: { x: [0, 'cc'], y: 0 }, + bottomRight: { x: [100, 'cm'], y: [100, 'bp'] }, }, + currentColor: true, + zip: true, + }, + customArgs: ['--custom-flag=1', '--custom-flag-two'], + svgTransformations: { + scale: 2, + translate: 3, }, - }); + }, + }); - expect(instruction).toEqual({ - command: 'dvisvgm', - args: [ - '--output=/path/to/output.svg', - '--exact-bbox', - '--no-specials=html', - '--trace-all', - '--bbox=0cc,0,100cm,100bp', - '--bitmap-format=png', - '--currentcolor', - '--embed-bitmaps', - '--font-format=woff2', - '--linkmark=none', - '--optimize=all', - '--precision=0', - '--relative', - '--zip', - '--color', - '--progress', - '--verbosity=3', - '--scale=2', - '--translate=3', - '--custom-flag=1', - '--custom-flag-two', - '/path/to/input.tex', - ], - }); + expect(instruction).toEqual({ + command: 'dvisvgm', + args: [ + '--output=/path/to/output.svg', + '--exact-bbox', + '--no-specials=html', + '--trace-all', + '--bbox=0cc,0,100cm,100bp', + '--bitmap-format=png', + '--currentcolor', + '--embed-bitmaps', + '--font-format=woff2', + '--linkmark=none', + '--optimize=all', + '--precision=0', + '--relative', + '--zip', + '--color', + '--progress', + '--verbosity=3', + '--scale=2', + '--translate=3', + '--custom-flag=1', + '--custom-flag-two', + '/path/to/input.tex', + ], }); + }); - it('should build the correct default CLI instruction', () => { - const instruction = buildDvisvgmInstruction({ - outputPath: "'/path/to/output.svg'", - texPath: '/path/to/input.tex', - inputType: 'dvi', - }); + it('should build the correct default CLI instruction', () => { + const instruction = buildDvisvgmInstruction({ + outputPath: "'/path/to/output.svg'", + texPath: '/path/to/input.tex', + inputType: 'dvi', + }); - expect(instruction).toEqual({ - command: 'dvisvgm', - args: [ - "--output='/path/to/output.svg'", - '--exact-bbox', - '--bbox=2pt', - '--bitmap-format=png', - '--currentcolor=#000', - '--embed-bitmaps', - '--font-format=woff2', - '--linkmark=none', - '--optimize=all', - '--precision=0', - '--relative', - '--color', - '--progress', - '--verbosity=3', - '/path/to/input.tex', - ], - }); + expect(instruction).toEqual({ + command: 'dvisvgm', + args: [ + "--output='/path/to/output.svg'", + '--exact-bbox', + '--bbox=2pt', + '--bitmap-format=png', + '--currentcolor=#000', + '--embed-bitmaps', + '--font-format=woff2', + '--linkmark=none', + '--optimize=all', + '--precision=0', + '--relative', + '--color', + '--progress', + '--verbosity=3', + '/path/to/input.tex', + ], }); }); }); diff --git a/tests/utils/env.test.ts b/tests/utils/env.test.ts new file mode 100644 index 0000000..c2fb9aa --- /dev/null +++ b/tests/utils/env.test.ts @@ -0,0 +1,160 @@ +import { + MockInstance, + afterEach, + beforeAll, + beforeEach, + describe, + expect, + it, + vi, +} from 'vitest'; + +import { + detectPackageManager, + getPmFromLockfile, + getPmFromPackageJson, + getVersion, +} from '$utils/env.js'; + +import { mockFs } from '$dev_deps.js'; +import { spy } from '$tests/fixtures.js'; +import { readFileSync } from '$deps.js'; + +function fixture() { + beforeEach(() => { + vi.clearAllMocks(); + }); + afterEach(() => { + vi.clearAllMocks(); + }); +} + +let existsSync: MockInstance; +beforeAll(async () => { + vi.spyOn(await import('$deps.js'), 'ora').mockImplementation((() => ({ + start: vi.fn().mockReturnValue({ + stop: vi.fn(), + text: vi.fn(), + succeed: vi.fn(), + fail: vi.fn(), + }), + })) as unknown as typeof import('ora').default); + const mocks = await spy(['existsSync'], false); + existsSync = mocks.existsSync; + existsSync.mockImplementation((path: string) => { + try { + readFileSync(path); + return true; + } catch { + return false; + } + }); +}); + +describe('getVersion', () => { + fixture(); + it.each(['katex', 'highlight.js', 'mathjax-full'] as const)( + 'getVersion(%o) has format "x.y.z"', + async (dep) => { + expect(await getVersion(dep)).toMatch(/(\d+\.\d+\.\d+)/); + }, + ); +}); + +describe('getPmFromPackageJson', () => { + fixture(); + it('identifies a valid package manager (pnpm)', () => { + mockFs({ + project: { + 'package.json': '{ "packageManager": "pnpm@6.14.2"}', + }, + }); + expect(getPmFromPackageJson('project')).toEqual('pnpm'); + }); + + it('identifies a valid package manager (bun)', () => { + mockFs({ + project: { + 'package.json': JSON.stringify({ + packageManager: 'bun@6.14.2', + }), + }, + }); + expect(getPmFromPackageJson('project')).toEqual('bun'); + }); + + it('identifies a valid package manager (yarn)', () => { + mockFs({ + 'package.json': JSON.stringify({ + packageManager: 'yarn@6.14.2', + }), + }); + expect(getPmFromPackageJson()).toEqual('yarn'); + }); + + it('returns undefined for an unrecognized package manager', () => { + mockFs({ + 'project/package.json': JSON.stringify({ + packageManager: 'unknown@1.0.0', + }), + }); + expect(getPmFromPackageJson('project')).toBeUndefined(); + }); + + it('returns undefined if package.json does not have packageManager set', () => { + mockFs({ + 'project/package.json': JSON.stringify({}), + }); + expect(getPmFromPackageJson('project')).toBeUndefined(); + }); + + it('returns undefined if package.json does not exist', () => { + mockFs({}); + expect(getPmFromPackageJson('project')).toBeUndefined(); + }); +}); + +describe('detectPackageManager', () => { + fixture(); + it('defaults to npm if no package manager is detected', () => { + mockFs({}); + expect(detectPackageManager('project')).toEqual('npm'); + }); + + it('detects package manager from package.json', () => { + mockFs({ + 'project/package.json': JSON.stringify({ + packageManager: 'yarn@6.14.2', + }), + }); + expect(detectPackageManager('project')).toEqual('yarn'); + }); + + it.each([ + { file: 'pnpm-lock.yaml', pm: 'pnpm' }, + { file: 'bun.lockb', pm: 'bun' }, + { file: 'package-lock.json', pm: 'npm' }, + { file: 'yarn.lock', pm: 'yarn' }, + ])('detects package manager from lockfile', ({ file, pm }) => { + mockFs({ [file]: 'test' }); + expect(detectPackageManager()).toEqual(pm); + }); +}); + +describe('getPmFromLockfile', () => { + fixture(); + it.each([ + { file: 'pnpm-lock.yaml', pm: 'pnpm' }, + { file: 'bun.lockb', pm: 'bun' }, + { file: 'package-lock.json', pm: 'npm' }, + { file: 'yarn.lock', pm: 'yarn' }, + ])('detects $pm from the lockfile', ({ file, pm }) => { + mockFs({ [file]: '' }); + expect(getPmFromLockfile()).toEqual(pm); + }); + + it('returns undefined if no known lock file is found', () => { + mockFs({}); + expect(getPmFromLockfile()).toBeUndefined(); + }); +}); diff --git a/tests/utils/escape.test.ts b/tests/utils/escape.test.ts index bedfae2..225e798 100644 --- a/tests/utils/escape.test.ts +++ b/tests/utils/escape.test.ts @@ -1,423 +1,561 @@ -/* eslint-disable vitest/no-commented-out-tests */ -import { type Sveltex, sveltex } from '$Sveltex.js'; -import { uuidV4Regexp } from '$tests/utils.js'; import { - escapeBraces, - escapeRegExps, - escapeVerb, - intersection, + afterAll, + afterEach, + beforeAll, + beforeEach, + describe, + expect, + it, + vi, +} from 'vitest'; +import { spy } from '$tests/fixtures.js'; +import { + colonUuid, + escape, + escapeSnippets, + escapeStringForRegExp, + getColonES, + getMathInSpecialDelimsES, + getMdastES, + getSvelteES, outermostRanges, - unescape, + padString, + parseToMdast, + unescapeSnippets, } from '$utils/escape.js'; -import { describe, expect, it, suite } from 'vitest'; - -suite.concurrent('processor/escape', async () => { - describe.concurrent('escape regexes', () => { - it('should match LaTeX display math', () => { - const input = 'A$$B$$C'; - const expected = ['$$B$$']; - const result = input.match(escapeRegExps.texDisplay); - expect(result).toEqual(expected); - }); - - it('should match inline LaTeX code', () => { - const input = 'Some text $x^2 + y^2 = \\frac{z^2}{2}$ more text'; - const expected = ['$x^2 + y^2 = \\frac{z^2}{2}$']; - const result = input.match(escapeRegExps.texInline); - expect(result).toEqual(expected); - }); - - it('should match fenced code blocks', () => { - const input = '```typescript\nconsole.log("Hello, world!");\n```'; - const expected = [ - '```typescript\nconsole.log("Hello, world!");\n```', - ]; - const result = input.match(escapeRegExps.codeBlock); - expect(result).toEqual(expected); - }); +import { cartesianProduct, range, uuidV4Regexp } from '$tests/utils.js'; +import { typeAssert, is } from '$deps.js'; +import { + EscapableSnippet, + EscapedSnippet, + ProcessedSnippet, + Snippet, + TexEscapeSettings, + UnescapeOptions, +} from '$types/utils/Escape.js'; +import { isArray, isString } from '$type-guards/utils.js'; - it('should match inline code (double backtick)', () => { - const input = - 'Some text ``console.log("Hello, world!");`` more text'; - const expected = ['``console.log("Hello, world!");``']; - const result = input.match(escapeRegExps.codeInlineDoubleBacktick); - expect(result).toEqual(expected); - }); +function fixture() { + beforeEach(() => { + vi.resetAllMocks(); + }); + afterEach(() => { + vi.resetAllMocks(); + }); +} - it('should match inline code (single backtick)', () => { - const input = 'Some text `console.log("Hello, world!");` more text'; - const expected = ['`console.log("Hello, world!");`']; - const result = input.match(escapeRegExps.codeInlineSingleBacktick); - expect(result).toEqual(expected); - }); +describe.concurrent.shuffle('escape()', () => { + fixture(); + beforeAll(async () => { + await spy(['log', 'fancyWrite', 'writeFile']); + }); + afterAll(() => { + vi.restoreAllMocks(); }); - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - const preprocessor1 = (await sveltex()) as Sveltex< - 'none', - 'none', - 'none', - 'none' | 'local' - >; - - const preprocessor2 = (await sveltex({ - advancedTexBackend: 'local', - })) as Sveltex<'none', 'none', 'none', 'none' | 'local'>; - - const preprocessor3 = (await sveltex({ - advancedTexBackend: 'local', - })) as Sveltex<'none', 'none', 'none', 'none' | 'local'>; - - await preprocessor3.configure({ - verbatim: { - verbatimEnvironments: { - Verbatim: { - processInner: { escapeBraces: true, escapeHtml: true }, - }, + describe.concurrent.each([ + [ + 'code (inline)', + [1, 2, 3, 4, 5].map((n) => [ + `a ${'`'.repeat(n)}b${'`'.repeat(n)} c`, + 'a □ c', + [ + { + type: 'code', + processable: { + innerContent: 'b', + optionsForProcessor: { inline: true }, + }, + }, + ], + ]), + ], + [ + 'code (block)', + ( + [[0], [0, '1', '2', 0], [1], [2, undefined, undefined, 1]] as [ + number, + string | undefined, + string | undefined, + number | undefined, + ][] + ).map(([n, lang, info, padding]) => [ + `a${'\n'.repeat(padding ?? 0)}\n\`\`\`${'`'.repeat(n)}${lang ?? ''}${info ? ` ${info}` : ''}\nb\n${'`'.repeat(n)}\`\`\`\n${'\n'.repeat(padding ?? 0)}c`, + `a${'\n'.repeat(padding ? padding - 1 : 0)}\n\n□\n\n${'\n'.repeat(padding ? padding - 1 : 0)}c`, + [ + { + type: 'code', + processable: { + innerContent: 'b', + optionsForProcessor: { inline: false, lang, info }, + }, + } as Partial>, + ], + ]), + ], + ...generateTexTests(), + [ + 'mustacheTag', + [1, 2, 3, 4, 5].map((n) => [ + `a ${'{'.repeat(n)}b${'}'.repeat(n)} c`, + 'a □ c', + [ + { + type: 'mustacheTag', + original: { + outerContent: `${'{'.repeat(n)}b${'}'.repeat(n)}`, + }, + }, + ], + ]), + ], + [ + 'svelte', + [ + 'script', + 'style', + 'svelte:head', + 'svelte:window', + 'svelte:document', + 'svelte:body', + 'svelte:options', + ].map((tag) => [ + `a <${tag}>b c`, + 'a \n\n□\n\n c', + [ + { + type: 'svelte', + original: { + outerContent: `<${tag.replace(':', colonUuid)}>b`, + }, + processable: undefined, + escapeOptions: { pad: 2 }, + unescapeOptions: { removeParagraphTag: true }, + }, + ], + ]), + ], + ] as [ + string, + [ + string, + string, + Partial[], + TexEscapeSettings | undefined, + ][], + ][])('%s', (_label, tests) => { + it.concurrent.each(tests)( + '%o → %o', + (raw, escaped, escapedSnippets, texEscapeSettings) => { + // expect(escape('a')).toEqual({ + // escapedDocument: 'a', + // escapedSnippets: [], + // }); + const res = escape(raw, undefined, texEscapeSettings); + expect(res.escapedDocument).toEqual( + expect.stringMatching( + new RegExp( + escapeStringForRegExp(escaped).replaceAll( + '□', + uuidV4Regexp.source, + ), + ), + ) as unknown, + ); + escapedSnippets.forEach((snip, i) => { + expect(res.escapedSnippets[i]?.[0]).toEqual( + expect.stringMatching(uuidV4Regexp), + ); + expect(res.escapedSnippets[i]?.[1]).toMatchObject(snip); + }); }, - }, - advancedTex: { components: { TeX: {} } }, + ); }); - const preprocessor4 = (await sveltex({ - advancedTexBackend: 'local', - })) as Sveltex<'none', 'none', 'none', 'none' | 'local'>; + describe('edge cases', () => { + fixture(); - await preprocessor4.configure({ - verbatim: { - verbatimEnvironments: { - Verbatim: { - processInner: { escapeBraces: true, escapeHtml: true }, - aliases: ['verbatim'], - }, + it.each([ + [ + '${...}$', + '□', + [ + { + type: 'tex', + processable: { + innerContent: '{...}', + optionsForProcessor: { inline: true }, + }, + escapeOpts: { pad: false }, + unescapeOpts: { removeParagraphTag: false }, + }, + ], + ], + [ + '${$}', + '□}', + [ + { + type: 'tex', + processable: { + innerContent: '{', + optionsForProcessor: { inline: true }, + }, + }, + ], + ], + [ + '{$}$', + '□$', + [ + { + type: 'mustacheTag', + original: { + outerContent: '{$}', + }, + }, + ], + ], + [ + '`{$}$`', + '□', + [ + { + type: 'code', + processable: { + innerContent: '{$}$', + }, + }, + ], + ], + [ + '', + '□', + [ + { + type: 'svelte', + original: { + loc: { + end: 43, + start: 0, + }, + outerContent: + '', + }, + }, + ], + ], + [ + '\n...\n', + '\n\n□\n\n\n...\n\n\n□\n\n', + [ + { + type: 'svelte', + original: { + outerContent: '', + }, + }, + { + type: 'svelte', + original: { + outerContent: '', + }, + }, + ], + ], + [ + 'a $$b$$ c', + 'a \n\n□\n\n c', + [ + { + type: 'tex', + processable: { + innerContent: 'b', + optionsForProcessor: { inline: false }, + }, + }, + ], + ], + ] as [string, string, PartialSnippet[]][])( + '%o → %o', + (str, escaped, snippets) => { + const res = escape(str); + expect(res.escapedDocument).toMatch( + new RegExp( + escapeStringForRegExp(escaped).replaceAll( + '□', + uuidV4Regexp.source, + ), + ), + ); + expect(res.escapedSnippets.length).toEqual(snippets.length); + res.escapedSnippets.forEach((snippet, i) => { + expect(snippet[0]).toEqual( + expect.stringMatching(uuidV4Regexp), + ); + const snip = snippets[i]; + typeAssert(is(snip)); + expect(snippet[1].type).toEqual(snip.type); + if (snip.original?.outerContent) { + expect(snippet[1].original.outerContent).toEqual( + snip.original.outerContent, + ); + } + if (snip.original?.loc) { + expect(snippet[1].original.loc).toEqual( + snip.original.loc, + ); + } + if (snip.processable?.innerContent) { + expect(snippet[1].processable?.innerContent).toEqual( + snip.processable.innerContent, + ); + } + if (snip.processable?.optionsForProcessor) { + expect( + snippet[1].processable?.optionsForProcessor, + ).toEqual(snip.processable.optionsForProcessor); + } + if (snip.unescapeOpts?.removeParagraphTag) { + expect( + snippet[1].unescapeOptions?.removeParagraphTag, + ).toEqual(snip.unescapeOpts.removeParagraphTag); + } + }); }, - }, - advancedTex: { components: { TeX: { aliases: ['tex'] } } }, + ); }); +}); - describe.concurrent.each([ - { preprocessor: preprocessor1, num: 1 }, - { preprocessor: preprocessor2, num: 2 }, - { preprocessor: preprocessor3, num: 3 }, - { preprocessor: preprocessor4, num: 4 }, - ])('escapeVerb()', ({ preprocessor, num }) => { - it('should noop empty content', () => { - const content = ''; - const expected = ''; - const result = escapeVerb(preprocessor, content).escapedContent; - expect(result).toEqual(expected); - }); - - it('should noop plain text', () => { - const content = 'Some text without markup'; - const expected = 'Some text without markup'; - const result = escapeVerb(preprocessor, content).escapedContent; - expect(result).toEqual(expected); - }); - - it('should escape display math 1', () => { - const content = 'a$$b$$c'; - // WARNING: uncommenting the line below will cause the test to fail for - // some reason beyond my understanding. - // expect(escapeRegExps.texDisplay.test(content)).toBe(true); - const result = escapeVerb(preprocessor, content).escapedContent; - // expect(result).toMatch(/^A [a-f0-9-]{36} B$/); - expect(result).toEqual( - `a${(result.match(uuidV4Regexp) ?? [''])[0]}c`, - ); - }); - - it('should escape display math 2', () => { - const content = '$$2 + 2 = 4.$$'; - // WARNING: uncommenting the line below will cause the test to fail for - // some reason beyond my understanding. - // expect(escapeRegExps.texDisplay.test(content)).toBe(true); - const result = escapeVerb(preprocessor, content).escapedContent; - // expect(result).toMatch(/^A [a-f0-9-]{36} B$/); - expect(result).toEqual((result.match(uuidV4Regexp) ?? [''])[0]); - }); - - it('should escape display math 3', () => { - const content = 'A $$\\LaTeX$$ B'; - // expect(escapeRegExps.texDisplay.test(content)).toBe(true); - const result = escapeVerb(preprocessor, content).escapedContent; - // expect(result).toMatch(/^A [a-f0-9-]{36} B$/); - expect(result).toEqual( - `A ${(result.match(uuidV4Regexp) ?? [''])[0]} B`, - ); - }); - - it('should escape inline math', () => { - const content = 'A $\\LaTeX$ B'; - const result = escapeVerb(preprocessor, content).escapedContent; - expect(result).toMatch(/^A [a-f0-9-]{36} B$/); - expect(result).toEqual( - `A ${(result.match(uuidV4Regexp) ?? [''])[0]} B`, - ); - }); - - it('should escape fenced code blocks', () => { - const content = - 'A\n```typescript\nconsole.log("Hello, world!");\n```\nB'; - const result = escapeVerb(preprocessor, content).escapedContent; - expect(result).toMatch(/^A\n[a-f0-9-]{36}\nB$/); - expect(result).toEqual( - `A\n${(result.match(uuidV4Regexp) ?? [''])[0]}\nB`, - ); - }); +interface PartialSnippet { + type: Snippet['type']; + original?: Partial; + processable?: Partial; + unescapeOpts?: Partial; +} - it('should escape inline code (double backtick)', () => { - const content = - 'Some text ``console.log("Hello, world!");`` more text'; - const result = escapeVerb(preprocessor, content).escapedContent; - expect(result).toMatch(/^Some text [a-f0-9-]{36} more text$/); - expect(result).toEqual( - `Some text ${(result.match(uuidV4Regexp) ?? [''])[0]} more text`, - ); - }); +describe.concurrent.shuffle('padString()', () => { + it('should add a newline on both sides by default', () => { + expect(padString('foo')).toEqual('\nfoo\n'); + }); - it('should escape inline code (single backtick)', () => { - const content = - 'Some text `console.log("Hello, world!");` more text'; - const { escapedContent, savedMatches } = escapeVerb( - preprocessor, - content, - ); - expect(escapedContent).toMatch( - /^Some text [a-f0-9-]{36} more text$/, - ); - expect(escapedContent).toEqual( - `Some text ${(escapedContent.match(uuidV4Regexp) ?? [''])[0]} more text`, - ); - expect( - [...savedMatches.values()].includes( - '`console.log("Hello, world!");`', - ), - ).toBe(true); - }); + it('should add a newline on both sides when padInstr is true', () => { + expect(padString('foo', true)).toEqual('\nfoo\n'); + }); - it('should escape verbatim components', () => { - if (num < 3) return; - const content = - 'Some text x^{2} 3 more text'; - const { escapedContent, savedMatches } = escapeVerb( - preprocessor, - content, - ); - expect(escapedContent).toMatch( - /^Some text [a-f0-9-]{36} more text$/, - ); - expect(escapedContent).toEqual( - `Some text ${(escapedContent.match(uuidV4Regexp) ?? [''])[0]} more text`, - ); - expect( - [...savedMatches.values()].includes( - 'x^{2} 3', - ), - ).toBe(true); - }); + it('should add a newline on both sides when padInstr is 1', () => { + expect(padString('foo', 1)).toEqual('\nfoo\n'); + }); - it('should escape verbatim components (aliases)', () => { - if (num < 4) return; - const content = - 'Some text x^{2} 3 more text'; - const { escapedContent, savedMatches } = escapeVerb( - preprocessor, - content, - ); - expect(escapedContent).toMatch( - /^Some text [a-f0-9-]{36} more text$/, - ); - expect(escapedContent).toEqual( - `Some text ${(escapedContent.match(uuidV4Regexp) ?? [''])[0]} more text`, - ); - expect( - [...savedMatches.values()].includes( - 'x^{2} 3', - ), - ).toBe(true); - }); + it('should add 2 newlines on each side when padInstr is 2', () => { + expect(padString('foo', 2)).toEqual('\n\nfoo\n\n'); + }); - it('should escape tex components', () => { - if (num < 3) return; - const content = 'Some text x^{2} < 3 more text'; - const { escapedContent, savedMatches } = escapeVerb( - preprocessor, - content, - ); - expect(escapedContent).toMatch( - /^Some text [a-f0-9-]{36} more text$/, - ); - expect(escapedContent).toEqual( - `Some text ${(escapedContent.match(uuidV4Regexp) ?? [''])[0]} more text`, - ); - expect( - [...savedMatches.values()].includes('x^{2} < 3'), - ).toBe(true); - }); + it('should not add any padding when padInstr is false', () => { + expect(padString('foo', false)).toEqual('foo'); + }); - it('should escape tex components (special characters)', () => { - if (num < 3) return; - const content = - 'Some text \n\\begin{a}}&<>/>>;\n more text'; - const { escapedContent, savedMatches } = escapeVerb( - preprocessor, - content, - ); - expect(escapedContent).toMatch( - /^Some text [a-f0-9-]{36} more text$/, - ); - expect(escapedContent).toEqual( - `Some text ${(escapedContent.match(uuidV4Regexp) ?? [''])[0]} more text`, - ); - expect( - [...savedMatches.values()].includes( - '\n\\begin{a}}&<>/>>;\n', - ), - ).toBe(true); - }); + it('should add the specified string on both sides', () => { + expect(padString('foo', 'bar')).toEqual('barfoobar'); + }); - it('should escape tex components (tikz)', () => { - if (num < 3) return; - const content = - '\n\ntest1 *italic* test2\n\n\n\\begin{tikzpicture}\n\\draw (0,0) circle (3);\n\\draw (0,-1) circle (1.8);\n\\draw[var(--red), thick] (0,0) rectangle (3, 3);\n\\end{tikzpicture}\n\n\ntest3 **bold** test4'; - const { escapedContent, savedMatches } = escapeVerb( - preprocessor, - content, - ); - expect(escapedContent).toEqual( - `\n\ntest1 *italic* test2\n\n${(escapedContent.match(uuidV4Regexp) ?? [''])[0]}\n\ntest3 **bold** test4`, - ); - expect( - [...savedMatches.values()].includes( - '\n\\begin{tikzpicture}\n\\draw (0,0) circle (3);\n\\draw (0,-1) circle (1.8);\n\\draw[var(--red), thick] (0,0) rectangle (3, 3);\n\\end{tikzpicture}\n', - ), - ).toBe(true); - }); + it('should add the specified string on the left side', () => { + expect(padString('foo', ['bar', false])).toEqual('barfoo'); + }); - it('should escape tex components (aliases)', () => { - if (num < 4) return; - const content = 'Some text x^{2} < 3 more text'; - const { escapedContent, savedMatches } = escapeVerb( - preprocessor, - content, - ); - expect(escapedContent).toMatch( - /^Some text [a-f0-9-]{36} more text$/, - ); - expect(escapedContent).toEqual( - `Some text ${(escapedContent.match(uuidV4Regexp) ?? [''])[0]} more text`, - ); - expect( - [...savedMatches.values()].includes('x^{2} < 3'), - ).toBe(true); - }); + it('should add the specified string on the right side', () => { + expect(padString('foo', [false, 'bar'])).toEqual('foobar'); }); - describe.concurrent('unescape()', () => { - it('should unescape content', () => { - expect(unescape('123', new Map([['123', 'something']]))).toEqual( - 'something', - ); - }); + it('should add the specified strings on both sides', () => { + expect(padString('foo', ['bar', 'baz'])).toEqual('barfoobaz'); + }); - it('should remove

tags by default content', () => { - expect( - unescape('

123

', new Map([['123', 'something']])), - ).toEqual('something'); - }); + it('should work with 2-tuples of strings _and_ numbers', () => { + expect(padString('foo', ['bar', 3])).toEqual('barfoo\n\n\n'); + expect(padString('foo', [3, 'bar'])).toEqual('\n\n\nfoobar'); + }); +}); - it('should accept optional removeParagraphTag argument', () => { - expect( - unescape( - '

123

\n

456

', - new Map([ - ['123', 'something'], - ['456', 'something else'], - ]), - (code) => code === 'something', +describe.concurrent.shuffle('escapeSnippets()', () => { + // vi.mock('□', () => { + // return { + // v4: vi.fn().mockReturnValue('□'), + // }; + // }); + // const □Mock = vi.spyOn(await import('□'), 'v4'); + // let c = 1; + // □Mock.mockReturnValue('□' + String(c++)); + // beforeEach(() => { + // vi.resetAllMocks(); + // c = 1; + // }); + // afterAll(() => { + // vi.restoreAllMocks(); + // }); + it.each([ + { + document: 'a b c', + type: 'svelte', + original: { loc: { start: 2, end: 3 } }, + escapeOptions: { pad: false }, + escapedDocument: 'a □ c', + escapedSnippets: [ + [ + '□', + { + type: 'svelte', + original: { loc: { start: 2, end: 3 } }, + }, + ], + ], + }, + { + document: 'a b c', + type: 'svelte', + original: { loc: { start: 2, end: 3 } }, + escapeOptions: { pad: true }, + escapedDocument: 'a \n□\n c', + escapedSnippets: [ + [ + '□', + { + type: 'svelte', + original: { loc: { start: 2, end: 3 } }, + }, + ], + ], + }, + { + document: 'a b c', + type: 'svelte', + original: { loc: { start: 2, end: 3 } }, + escapeOptions: { pad: ['\n\n', '\n\n'] }, + escapedDocument: 'a \n\n□\n\n c', + escapedSnippets: [ + [ + '□', + { + type: 'svelte', + original: { loc: { start: 2, end: 3 } }, + }, + ], + ], + }, + { + document: '\ntest', + type: 'svelte', + original: { loc: { start: 0, end: 20 } }, + escapeOptions: { pad: ['\n\n', '\n\n'] }, + escapedDocument: '\n\n□\n\n\ntest', + escapedSnippets: [ + [ + '□', + { + type: 'svelte', + original: { loc: { start: 0, end: 20 } }, + }, + ], + ], + }, + ] as (ProcessedSnippet & + EscapableSnippet & { + document: string; + escapedDocument: string; + escapedSnippets: [string, EscapedSnippet][]; + })[])('$type: $document → $escapedDocument', (test) => { + expect( + escapeSnippets(test.document, [ + { + type: test.type, + escapeOptions: test.escapeOptions, + original: test.original, + processable: test.processable, + }, + ]), + ).toMatchObject({ + escapedDocument: expect.stringMatching( + new RegExp( + escapeStringForRegExp(test.escapedDocument).replaceAll( + '□', + uuidV4Regexp.source, + ), ), - ).toEqual('something\n

something else

'); + ) as unknown, + escapedSnippets: test.escapedSnippets.map( + (snip) => + [expect.stringMatching(uuidV4Regexp), snip[1]] as [ + string, + EscapedSnippet, + ], + ), }); }); +}); - describe.concurrent('escapeCurlyBraces()', () => { - it('should escape curly braces in the content', () => { - const content = 'Some {text} with {curly} braces'; - const expected = - 'Some {text} with {curly} braces'; - const result = escapeBraces(content); - expect(result).toEqual(expected); - }); - - it('should escape multiple curly braces in the content', () => { - const content = '{{{multiple}}} {{{curly}}} {{{braces}}}'; - const expected = - '{{{multiple}}} {{{curly}}} {{{braces}}}'; - const result = escapeBraces(content); - expect(result).toEqual(expected); - }); - - it('should not escape other characters in the content', () => { - const content = 'Some {text} with other characters: !@#$%^&*()'; - const expected = - 'Some {text} with other characters: !@#$%^&*()'; - const result = escapeBraces(content); - expect(result).toEqual(expected); - }); - - it('should not escape already escaped curly braces in the content', () => { - const content = - 'Some {text} with {escaped} curly braces'; - const expected = - 'Some {text} with {escaped} curly braces'; - const result = escapeBraces(content); - expect(result).toEqual(expected); - }); - - it('should escape "() => {}" properly', () => { - const content = '
() => {}\n
'; - const expected = - '
() => {}\n
'; - const result = escapeBraces(content); - expect(result).toEqual(expected); - }); +describe.concurrent.shuffle('unescapeSnippets()', () => { + describe('removeParagraphTag: true', () => { + const ps: ProcessedSnippet = { + processed: 'b', + unescapeOptions: { removeParagraphTag: true }, + }; + it.each([ + ['a □ c', 'a b c', [['□', ps]]], + ['a

c', 'a b c', [['□', ps]]], + ['a

\n□

c', 'a b c', [['□', ps]]], + ['a

□\n

c', 'a b c', [['□', ps]]], + ['a

\n\t \n□\n\n\n

c', 'a b c', [['□', ps]]], + ['

\nc', 'b\nc', [['□', ps]]], + ] as [string, string, [string, ProcessedSnippet][]][])( + '%o → %o', + (document, unescaped, processedSnippets) => { + expect(unescapeSnippets(document, processedSnippets)).toEqual( + unescaped, + ); + }, + ); }); - describe.concurrent('intersection()', () => { - it('should return null if there is no intersection', () => { - const a = { start: 1, end: 5 }; - const b = { start: 6, end: 10 }; - const result = intersection(a, b); - expect(result).toBeNull(); - }); - - it('should return the intersection if it exists', () => { - const a = { start: 1, end: 10 }; - const b = { start: 5, end: 15 }; - const expected = { start: 5, end: 10 }; - const result = intersection(a, b); - expect(result).toEqual(expected); - }); - - it('should handle overlapping intervals', () => { - const a = { start: 1, end: 10 }; - const b = { start: 5, end: 8 }; - const expected = { start: 5, end: 8 }; - const result = intersection(a, b); - expect(result).toEqual(expected); - }); + describe('removeParagraphTag: false', () => { + const ps: ProcessedSnippet = { + processed: 'b', + unescapeOptions: { removeParagraphTag: false }, + }; + it.each([ + ['a □ c', 'a b c', [['□', ps]]], + ['a

c', 'a

b

c', [['□', ps]]], + ['a

\n□

c', 'a

\nb

c', [['□', ps]]], + ['a

□\n

c', 'a

b\n

c', [['□', ps]]], + [ + 'a

\n\t \n□\n\n\n

c', + 'a

\n\t \nb\n\n\n

c', + [['□', ps]], + ], + ['

\nc', '

b

\nc', [['□', ps]]], + ] as [string, string, [string, ProcessedSnippet][]][])( + '%o → %o', + (document, unescaped, processedSnippets) => { + expect(unescapeSnippets(document, processedSnippets)).toEqual( + unescaped, + ); + }, + ); + }); - it('should handle identical intervals', () => { - const a = { start: 1, end: 10 }; - const b = { start: 1, end: 10 }; - const expected = { start: 1, end: 10 }; - const result = intersection(a, b); - expect(result).toEqual(expected); + describe('behaves gracefully if processed snippet for UUID is undefined', () => { + it.each([['a □ c', 'a □ c', [['□', undefined]]]] as unknown as [ + string, + string, + [string, ProcessedSnippet][], + ][])('%o → %o', (document, unescaped, processedSnippets) => { + expect(unescapeSnippets(document, processedSnippets)).toEqual( + unescaped, + ); }); }); }); -describe('outermostRanges()', () => { + +describe.concurrent.shuffle('outermostRanges()', () => { it('should return the outermost ranges', () => { const ranges = [ { start: 0, end: 100 }, // outermost @@ -461,3 +599,903 @@ describe('outermostRanges()', () => { expect(result).toEqual(expected); }); }); + +describe.concurrent.shuffle('getSvelteES()', () => { + describe.each([ + [ + 'normal', + [ + ...[ + 'script', + 'style', + 'svelte:head', + 'svelte:window', + 'svelte:document', + 'svelte:body', + 'svelte:options', + ].map( + (tag) => + [ + `a<${tag}>...b`, + `<${tag}>...`, + [ + { + escapeOptions: { pad: 2 }, + original: { + loc: { + start: 1, + end: + 9 + + 2 * + tag.replace(':', colonUuid) + .length, + }, + outerContent: `<${tag.replace(':', colonUuid)}>...`, + }, + processable: undefined, + type: 'svelte', + unescapeOptions: { + removeParagraphTag: true, + }, + }, + ], + ] as [string, string, EscapableSnippet[]], + ), + ], + ], + [ + 'self-closing', + [ + ['a