diff --git a/.build/common.ts b/.build/common.ts index 274977fa2..86ccd15d1 100644 --- a/.build/common.ts +++ b/.build/common.ts @@ -1,3 +1,9 @@ +export interface PackageOptions { + name: string; + packageName: string; + file: string; +} + /** * Shared common options for both ESBuild and Vite */ @@ -22,9 +28,9 @@ export const packageOptions = { packageName: 'mermaid-zenuml', file: 'detector.ts', }, - 'mermaid-flowchart-elk': { - name: 'mermaid-flowchart-elk', - packageName: 'mermaid-flowchart-elk', - file: 'detector.ts', + 'mermaid-layout-elk': { + name: 'mermaid-layout-elk', + packageName: 'mermaid-layout-elk', + file: 'layouts.ts', }, -} as const; +} as const satisfies Record; diff --git a/.build/jisonTransformer.ts b/.build/jisonTransformer.ts index 314df8a33..b60350230 100644 --- a/.build/jisonTransformer.ts +++ b/.build/jisonTransformer.ts @@ -1,6 +1,7 @@ import jison from 'jison'; export const transformJison = (src: string): string => { + // @ts-ignore - Jison is not typed properly const parser = new jison.Generator(src, { moduleType: 'js', 'token-stack': true, diff --git a/.build/jsonSchema.ts b/.build/jsonSchema.ts index 6fd8ca3f5..48a9883de 100644 --- a/.build/jsonSchema.ts +++ b/.build/jsonSchema.ts @@ -19,12 +19,15 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [ 'xyChart', 'requirement', 'mindmap', + 'kanban', 'timeline', 'gitGraph', 'c4', 'sankey', 'block', 'packet', + 'architecture', + 'radar', ] as const; /** diff --git a/.build/types.ts b/.build/types.ts index 419240782..9dec05a68 100644 --- a/.build/types.ts +++ b/.build/types.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import { packageOptions } from './common.js'; import { execSync } from 'child_process'; @@ -5,11 +6,17 @@ const buildType = (packageName: string) => { console.log(`Building types for ${packageName}`); try { const out = execSync(`tsc -p ./packages/${packageName}/tsconfig.json --emitDeclarationOnly`); - out.length > 0 && console.log(out.toString()); + if (out.length > 0) { + console.log(out.toString()); + } } catch (e) { console.error(e); - e.stdout.length > 0 && console.error(e.stdout.toString()); - e.stderr.length > 0 && console.error(e.stderr.toString()); + if (e.stdout.length > 0) { + console.error(e.stdout.toString()); + } + if (e.stderr.length > 0) { + console.error(e.stderr.toString()); + } } }; diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 000000000..e5b6d8d6a --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 000000000..ffda055e8 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", + "changelog": ["@changesets/changelog-github", { "repo": "mermaid-js/mermaid" }], + "commit": false, + "fixed": [], + "linked": [], + "access": "public", + "baseBranch": "master", + "updateInternalDependencies": "patch", + "bumpVersionsWithWorkspaceProtocolOnly": true, + "ignore": ["@mermaid-js/docs", "@mermaid-js/webpack-test", "@mermaid-js/mermaid-example-diagram"] +} diff --git a/.changeset/eleven-wolves-deny.md b/.changeset/eleven-wolves-deny.md new file mode 100644 index 000000000..76bb69ec5 --- /dev/null +++ b/.changeset/eleven-wolves-deny.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +chore: Convert StateDB into TypeScript diff --git a/.changeset/gold-shoes-camp.md b/.changeset/gold-shoes-camp.md new file mode 100644 index 000000000..3018e7381 --- /dev/null +++ b/.changeset/gold-shoes-camp.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: Remove incorrect `style="undefined;"` attributes in some Mermaid diagrams diff --git a/.changeset/honest-trees-dress.md b/.changeset/honest-trees-dress.md new file mode 100644 index 000000000..054f1bedb --- /dev/null +++ b/.changeset/honest-trees-dress.md @@ -0,0 +1,7 @@ +--- +'@mermaid-js/mermaid-zenuml': patch +--- + +chore: bump minimum ZenUML version to 3.23.28 + +commit: 9d06d8f31e7f12af9e9e092214f907f2dc93ad75 diff --git a/.changeset/neat-moose-compare.md b/.changeset/neat-moose-compare.md new file mode 100644 index 000000000..98a064789 --- /dev/null +++ b/.changeset/neat-moose-compare.md @@ -0,0 +1,5 @@ +--- +'mermaid': minor +--- + +feat: Add support for styling Journey Diagram title (color, font-family, and font-size) diff --git a/.changeset/sad-mails-accept.md b/.changeset/sad-mails-accept.md new file mode 100644 index 000000000..11dd69d8d --- /dev/null +++ b/.changeset/sad-mails-accept.md @@ -0,0 +1,6 @@ +--- +'mermaid': patch +'@mermaid-js/parser': patch +--- + +Refactor grammar so that title don't break Architecture Diagrams diff --git a/.changeset/soft-readers-tan.md b/.changeset/soft-readers-tan.md new file mode 100644 index 000000000..ec3fa97af --- /dev/null +++ b/.changeset/soft-readers-tan.md @@ -0,0 +1,5 @@ +--- +'mermaid': minor +--- + +feat: Dynamically Render Data Labels Within Bar Charts diff --git a/.changeset/yellow-mirrors-change.md b/.changeset/yellow-mirrors-change.md new file mode 100644 index 000000000..09a766104 --- /dev/null +++ b/.changeset/yellow-mirrors-change.md @@ -0,0 +1,7 @@ +--- +'@mermaid-js/mermaid-zenuml': patch +--- + +fix(zenuml): limit `peerDependencies` to Mermaid v10 and v11 + +commit: 0ad44c12feead9d20c6a870a49327ada58d6e657 diff --git a/.cspell/code-terms.txt b/.cspell/code-terms.txt index fa063616a..285b66365 100644 --- a/.cspell/code-terms.txt +++ b/.cspell/code-terms.txt @@ -13,6 +13,7 @@ bqstring BQUOTE bramp BRKT +brotli callbackargs callbackname classdef @@ -25,8 +26,10 @@ concat controlx controly CSSCLASS +curv CYLINDEREND CYLINDERSTART +DAGA datakey DEND descr @@ -50,9 +53,9 @@ frontmatter funs gantt GENERICTYPE -getBoundarys grammr graphtype +halign iife interp introdcued @@ -64,6 +67,7 @@ Kaufmann keyify LABELPOS LABELTYPE +layoutstop lcov LEFTOF Lexa @@ -89,6 +93,7 @@ reqs rewritelinks rgba RIGHTOF +roughjs sankey sequencenumber shrc @@ -108,13 +113,17 @@ strikethrough stringifying struct STYLECLASS +STYLEDEF STYLEOPTS subcomponent subcomponents +subconfig SUBROUTINEEND SUBROUTINESTART Subschemas substr +SVGG +SVGSVG TAGEND TAGSTART techn @@ -125,11 +134,13 @@ titlevalue topbar TRAPEND TRAPSTART +treemap ts-nocheck tsdoc typeof typestr unshift +urlsafe verifymethod VERIFYMTHD WARN_DOCSDIR_DOESNT_MATCH diff --git a/.cspell/contributors.txt b/.cspell/contributors.txt index bd3ad9da2..b7f52f8d0 100644 --- a/.cspell/contributors.txt +++ b/.cspell/contributors.txt @@ -4,5 +4,6 @@ cpettitt Dong Cai Nikolay Rozhkov Peng Xiao +Per Brolin subhash-halder Vinod Sidharth diff --git a/.cspell/cspell.config.yaml b/.cspell/cspell.config.yaml index 33d690193..b16040c8c 100644 --- a/.cspell/cspell.config.yaml +++ b/.cspell/cspell.config.yaml @@ -28,6 +28,9 @@ dictionaryDefinitions: - name: suggestions words: - none + - disp + - subproc + - tria suggestWords: - seperator:separator - vertice:vertex diff --git a/.cspell/libraries.txt b/.cspell/libraries.txt index 9d2926186..185d284f7 100644 --- a/.cspell/libraries.txt +++ b/.cspell/libraries.txt @@ -20,14 +20,18 @@ dagre-d3 Deepdwn Docsify Docsy +Doctave DokuWiki dompurify elkjs +fcose fontawesome +Forgejo Foswiki Gitea graphlib Grav +icones iconify Inkdrop jiti @@ -54,13 +58,17 @@ presetAttributify pyplot redmine rehype +roughjs rscratch +shiki +Slidev sparkline sphinxcontrib ssim stylis Swimm tsbuildinfo +tseslint Tuleap Typora unocss diff --git a/.cspell/mermaid-terms.txt b/.cspell/mermaid-terms.txt index 3fa5eff26..cb6db41de 100644 --- a/.cspell/mermaid-terms.txt +++ b/.cspell/mermaid-terms.txt @@ -1,14 +1,18 @@ Adamiecki arrowend +Bendpoints bmatrix braintree catmull compositTitleSize +curv doublecircle elems gantt gitgraph gzipped +handDrawn +kanban knsv Knut marginx @@ -17,10 +21,12 @@ Markdownish mermaidjs mindmap mindmaps +mrtree multigraph nodesep NOTEGROUP Pinterest +procs rankdir ranksep rect diff --git a/.cspell/misc-terms.txt b/.cspell/misc-terms.txt index 467e48891..1820e3c86 100644 --- a/.cspell/misc-terms.txt +++ b/.cspell/misc-terms.txt @@ -1 +1,7 @@ +BRANDES +circo +handDrawn +KOEPF +neato newbranch +validify diff --git a/.esbuild/build.ts b/.esbuild/build.ts index 3eea8dfe2..4eb6ab002 100644 --- a/.esbuild/build.ts +++ b/.esbuild/build.ts @@ -2,13 +2,17 @@ import { build } from 'esbuild'; import { mkdir, writeFile } from 'node:fs/promises'; import { packageOptions } from '../.build/common.js'; import { generateLangium } from '../.build/generateLangium.js'; -import { MermaidBuildOptions, defaultOptions, getBuildConfig } from './util.js'; +import type { MermaidBuildOptions } from './util.js'; +import { defaultOptions, getBuildConfig } from './util.js'; const shouldVisualize = process.argv.includes('--visualize'); const buildPackage = async (entryName: keyof typeof packageOptions) => { - const commonOptions = { ...defaultOptions, entryName } as const; - const buildConfigs = [ + const commonOptions: MermaidBuildOptions = { + ...defaultOptions, + options: packageOptions[entryName], + } as const; + const buildConfigs: MermaidBuildOptions[] = [ // package.mjs { ...commonOptions }, // package.min.mjs @@ -37,16 +41,29 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => { } ); } + if (entryName === 'mermaid-zenuml') { + const iifeOptions: MermaidBuildOptions = { + ...commonOptions, + format: 'iife', + globalName: 'mermaid-zenuml', + }; + buildConfigs.push( + // mermaid-zenuml.js + { ...iifeOptions }, + // mermaid-zenuml.min.js + { ...iifeOptions, minify: true, metafile: shouldVisualize } + ); + } const results = await Promise.all(buildConfigs.map((option) => build(getBuildConfig(option)))); if (shouldVisualize) { for (const { metafile } of results) { - if (!metafile) { + if (!metafile?.outputs) { continue; } const fileName = Object.keys(metafile.outputs) - .filter((file) => !file.includes('chunks') && file.endsWith('js'))[0] + .find((file) => !file.includes('chunks') && file.endsWith('js'))! .replace('dist/', ''); // Upload metafile into https://esbuild.github.io/analyze/ await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile)); @@ -55,13 +72,14 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => { }; const handler = (e) => { + // eslint-disable-next-line no-console console.error(e); process.exit(1); }; const main = async () => { await generateLangium(); - await mkdir('stats').catch(() => {}); + await mkdir('stats', { recursive: true }); const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[]; // it should build `parser` before `mermaid` because it's a dependency for (const pkg of packageNames) { diff --git a/.esbuild/jisonPlugin.ts b/.esbuild/jisonPlugin.ts index de801ea9f..007516f08 100644 --- a/.esbuild/jisonPlugin.ts +++ b/.esbuild/jisonPlugin.ts @@ -1,6 +1,6 @@ import { readFile } from 'node:fs/promises'; import { transformJison } from '../.build/jisonTransformer.js'; -import { Plugin } from 'esbuild'; +import type { Plugin } from 'esbuild'; export const jisonPlugin: Plugin = { name: 'jison', diff --git a/.esbuild/server.ts b/.esbuild/server.ts index 9102c7de8..6e1bcb460 100644 --- a/.esbuild/server.ts +++ b/.esbuild/server.ts @@ -1,34 +1,52 @@ -import express from 'express'; -import type { NextFunction, Request, Response } from 'express'; -import cors from 'cors'; -import { getBuildConfig, defaultOptions } from './util.js'; -import { context } from 'esbuild'; +/* eslint-disable no-console */ import chokidar from 'chokidar'; -import { generateLangium } from '../.build/generateLangium.js'; +import cors from 'cors'; +import { context } from 'esbuild'; +import type { Request, Response } from 'express'; +import express from 'express'; import { packageOptions } from '../.build/common.js'; +import { generateLangium } from '../.build/generateLangium.js'; +import { defaultOptions, getBuildConfig } from './util.js'; const configs = Object.values(packageOptions).map(({ packageName }) => - getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: packageName }) + getBuildConfig({ + ...defaultOptions, + minify: false, + core: false, + options: packageOptions[packageName], + }) ); const mermaidIIFEConfig = getBuildConfig({ ...defaultOptions, minify: false, core: false, - entryName: 'mermaid', + options: packageOptions.mermaid, format: 'iife', }); configs.push(mermaidIIFEConfig); -const contexts = await Promise.all(configs.map((config) => context(config))); +const contexts = await Promise.all( + configs.map(async (config) => ({ config, context: await context(config) })) +); +let rebuildCounter = 1; const rebuildAll = async () => { - console.time('Rebuild time'); - await Promise.all(contexts.map((ctx) => ctx.rebuild())).catch((e) => console.error(e)); - console.timeEnd('Rebuild time'); + const buildNumber = rebuildCounter++; + const timeLabel = `Rebuild ${buildNumber} Time (total)`; + console.time(timeLabel); + await Promise.all( + contexts.map(async ({ config, context }) => { + const buildVariant = `Rebuild ${buildNumber} Time (${Object.keys(config.entryPoints!)[0]} ${config.format})`; + console.time(buildVariant); + await context.rebuild(); + console.timeEnd(buildVariant); + }) + ).catch((e) => console.error(e)); + console.timeEnd(timeLabel); }; let clients: { id: number; response: Response }[] = []; -function eventsHandler(request: Request, response: Response, next: NextFunction) { +function eventsHandler(request: Request, response: Response) { const headers = { 'Content-Type': 'text/event-stream', Connection: 'keep-alive', @@ -45,19 +63,20 @@ function eventsHandler(request: Request, response: Response, next: NextFunction) }); } -let timeoutId: NodeJS.Timeout | undefined = undefined; +let timeoutID: NodeJS.Timeout | undefined = undefined; /** * Debounce file change events to avoid rebuilding multiple times. */ function handleFileChange() { - if (timeoutId !== undefined) { - clearTimeout(timeoutId); + if (timeoutID !== undefined) { + clearTimeout(timeoutID); } - timeoutId = setTimeout(async () => { + // eslint-disable-next-line @typescript-eslint/no-misused-promises + timeoutID = setTimeout(async () => { await rebuildAll(); sendEventsToAll(); - timeoutId = undefined; + timeoutID = undefined; }, 100); } @@ -74,15 +93,16 @@ async function createServer() { ignoreInitial: true, ignored: [/node_modules/, /dist/, /docs/, /coverage/], }) + // eslint-disable-next-line @typescript-eslint/no-misused-promises .on('all', async (event, path) => { // Ignore other events. if (!['add', 'change'].includes(event)) { return; } - if (/\.langium$/.test(path)) { + console.log(`${path} changed. Rebuilding...`); + if (path.endsWith('.langium')) { await generateLangium(); } - console.log(`${path} changed. Rebuilding...`); handleFileChange(); }); @@ -99,4 +119,4 @@ async function createServer() { }); } -createServer(); +void createServer(); diff --git a/.esbuild/util.ts b/.esbuild/util.ts index 0048da94e..d2b7ca08c 100644 --- a/.esbuild/util.ts +++ b/.esbuild/util.ts @@ -3,21 +3,21 @@ import { fileURLToPath } from 'url'; import type { BuildOptions } from 'esbuild'; import { readFileSync } from 'fs'; import jsonSchemaPlugin from './jsonSchemaPlugin.js'; -import { packageOptions } from '../.build/common.js'; +import type { PackageOptions } from '../.build/common.js'; import { jisonPlugin } from './jisonPlugin.js'; const __dirname = fileURLToPath(new URL('.', import.meta.url)); -export interface MermaidBuildOptions { +export interface MermaidBuildOptions extends BuildOptions { minify: boolean; core: boolean; metafile: boolean; format: 'esm' | 'iife'; - entryName: keyof typeof packageOptions; + options: PackageOptions; includeLargeFeatures: boolean; } -export const defaultOptions: Omit = { +export const defaultOptions: Omit = { minify: false, metafile: false, core: false, @@ -60,17 +60,25 @@ const getFileName = ( }; export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { - const { core, entryName, metafile, format, includeLargeFeatures, minify } = options; + const { + core, + metafile, + format, + minify, + options: { name, file, packageName }, + globalName = 'mermaid', + includeLargeFeatures, + } = options; const external: string[] = ['require', 'fs', 'path']; - const { name, file, packageName } = packageOptions[entryName]; const outFileName = getFileName(name, options); - let output: BuildOptions = buildOptions({ + const output: BuildOptions = buildOptions({ absWorkingDir: resolve(__dirname, `../packages/${packageName}`), entryPoints: { [outFileName]: `src/${file}`, }, metafile, minify, + globalName, logLevel: 'info', chunkNames: `chunks/${outFileName}/[name]-[hash]`, define: { @@ -94,11 +102,12 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { if (format === 'iife') { output.format = 'iife'; output.splitting = false; - output.globalName = '__esbuild_esm_mermaid'; + const originalGlobalName = output.globalName ?? 'mermaid'; + output.globalName = `__esbuild_esm_mermaid_nm[${JSON.stringify(originalGlobalName)}]`; // Workaround for removing the .default access in esbuild IIFE. // https://github.com/mermaid-js/mermaid/pull/4109#discussion_r1292317396 output.footer = { - js: 'globalThis.mermaid = globalThis.__esbuild_esm_mermaid.default;', + js: `globalThis[${JSON.stringify(originalGlobalName)}] = globalThis.${output.globalName}.default;`, }; output.outExtension = { '.js': '.js' }; } else { diff --git a/.eslintignore b/.eslintignore deleted file mode 120000 index 3e4e48b0b..000000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -.gitignore \ No newline at end of file diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index c9428c9f5..000000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,190 +0,0 @@ -module.exports = { - env: { - browser: true, - es6: true, - 'jest/globals': true, - node: true, - }, - root: true, - parser: '@typescript-eslint/parser', - parserOptions: { - ecmaFeatures: { - experimentalObjectRestSpread: true, - jsx: true, - }, - tsconfigRootDir: __dirname, - sourceType: 'module', - ecmaVersion: 2022, - allowAutomaticSingleRunInference: true, - project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'], - parser: '@typescript-eslint/parser', - }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:json/recommended', - 'plugin:markdown/recommended-legacy', - 'plugin:@cspell/recommended', - 'prettier', - ], - plugins: [ - '@typescript-eslint', - 'no-only-tests', - 'html', - 'jest', - 'jsdoc', - 'json', - '@cspell', - 'lodash', - 'unicorn', - ], - ignorePatterns: [ - // this file is automatically generated by `pnpm run --filter mermaid types:build-config` - 'packages/mermaid/src/config.type.ts', - ], - rules: { - curly: 'error', - 'no-console': 'error', - 'no-prototype-builtins': 'off', - 'no-unused-vars': 'off', - 'cypress/no-async-tests': 'off', - '@typescript-eslint/consistent-type-imports': 'error', - '@typescript-eslint/no-explicit-any': 'warn', - '@typescript-eslint/no-floating-promises': 'error', - '@typescript-eslint/no-misused-promises': 'error', - '@typescript-eslint/no-unused-vars': 'warn', - '@typescript-eslint/consistent-type-definitions': 'error', - '@typescript-eslint/ban-ts-comment': [ - 'error', - { - 'ts-expect-error': 'allow-with-description', - 'ts-ignore': 'allow-with-description', - 'ts-nocheck': 'allow-with-description', - 'ts-check': 'allow-with-description', - minimumDescriptionLength: 10, - }, - ], - '@typescript-eslint/naming-convention': [ - 'error', - { - selector: 'typeLike', - format: ['PascalCase'], - custom: { - regex: '^I[A-Z]', - match: false, - }, - }, - ], - 'json/*': ['error', 'allowComments'], - '@cspell/spellchecker': [ - 'error', - { - checkIdentifiers: true, - checkStrings: true, - checkStringTemplates: true, - }, - ], - 'no-empty': [ - 'error', - { - allowEmptyCatch: true, - }, - ], - 'no-only-tests/no-only-tests': 'error', - 'lodash/import-scope': ['error', 'method'], - 'unicorn/better-regex': 'error', - 'unicorn/no-abusive-eslint-disable': 'error', - 'unicorn/no-array-push-push': 'error', - 'unicorn/no-for-loop': 'error', - 'unicorn/no-instanceof-array': 'error', - 'unicorn/no-typeof-undefined': 'error', - 'unicorn/no-unnecessary-await': 'error', - 'unicorn/no-unsafe-regex': 'warn', - 'unicorn/no-useless-promise-resolve-reject': 'error', - 'unicorn/prefer-array-find': 'error', - 'unicorn/prefer-array-flat-map': 'error', - 'unicorn/prefer-array-index-of': 'error', - 'unicorn/prefer-array-some': 'error', - 'unicorn/prefer-default-parameters': 'error', - 'unicorn/prefer-includes': 'error', - 'unicorn/prefer-negative-index': 'error', - 'unicorn/prefer-object-from-entries': 'error', - 'unicorn/prefer-string-starts-ends-with': 'error', - 'unicorn/prefer-string-trim-start-end': 'error', - 'unicorn/string-content': 'error', - 'unicorn/prefer-spread': 'error', - 'unicorn/no-lonely-if': 'error', - }, - overrides: [ - { - files: ['cypress/**', 'demos/**'], - rules: { - 'no-console': 'off', - }, - }, - { - files: ['*.{js,jsx,mjs,cjs}'], - extends: ['plugin:jsdoc/recommended'], - rules: { - 'jsdoc/check-indentation': 'off', - 'jsdoc/check-alignment': 'off', - 'jsdoc/check-line-alignment': 'off', - 'jsdoc/multiline-blocks': 'off', - 'jsdoc/newline-after-description': 'off', - 'jsdoc/tag-lines': 'off', - 'jsdoc/require-param-description': 'off', - 'jsdoc/require-param-type': 'off', - 'jsdoc/require-returns': 'off', - 'jsdoc/require-returns-description': 'off', - }, - }, - { - files: ['*.{ts,tsx}'], - plugins: ['tsdoc'], - rules: { - 'no-restricted-syntax': [ - 'error', - { - selector: 'TSEnumDeclaration', - message: - 'Prefer using TypeScript union types over TypeScript enum, since TypeScript enums have a bunch of issues, see https://dev.to/dvddpl/whats-the-problem-with-typescript-enums-2okj', - }, - ], - 'tsdoc/syntax': 'error', - }, - }, - { - files: ['*.spec.{ts,js}', 'cypress/**', 'demos/**', '**/docs/**'], - rules: { - 'jsdoc/require-jsdoc': 'off', - '@typescript-eslint/no-unused-vars': 'off', - }, - }, - { - files: ['*.spec.{ts,js}', 'tests/**', 'cypress/**/*.js'], - rules: { - '@cspell/spellchecker': [ - 'error', - { - checkIdentifiers: false, - checkStrings: false, - checkStringTemplates: false, - }, - ], - }, - }, - { - files: ['*.html', '*.md', '**/*.md/*'], - rules: { - 'no-var': 'error', - 'no-undef': 'off', - '@typescript-eslint/no-unused-vars': 'off', - '@typescript-eslint/no-floating-promises': 'off', - '@typescript-eslint/no-misused-promises': 'off', - }, - parserOptions: { - project: null, - }, - }, - ], -}; diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 6be6f3b5d..b7313b621 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -4,7 +4,7 @@ contact_links: url: https://github.com/mermaid-js/mermaid/discussions about: Ask the Community questions or share your own graphs in our discussions. - name: Discord - url: https://discord.gg/AgrbSrBer3 + url: https://discord.gg/sKeNQX4Wtj about: Join our Community on Discord for Help and a casual chat. - name: Documentation url: https://mermaid.js.org diff --git a/.github/ISSUE_TEMPLATE/theme_proposal.yml b/.github/ISSUE_TEMPLATE/theme_proposal.yml index da4fddbec..2e55b71d6 100644 --- a/.github/ISSUE_TEMPLATE/theme_proposal.yml +++ b/.github/ISSUE_TEMPLATE/theme_proposal.yml @@ -29,7 +29,7 @@ body: label: Colors description: |- A detailed list of the different colour values to use. - A list of currently used variable names can be found [here](https://mermaid-js.github.io/mermaid/#/theming?id=theme-variables-reference-table) + See the [list of currently used variable names](https://mermaid-js.github.io/mermaid/#/theming?id=theme-variables-reference-table) placeholder: |- - background: #f4f4f4 - primaryColor: #fff4dd diff --git a/.github/lychee.toml b/.github/lychee.toml index c5a2f0e45..b4e8ba0fb 100644 --- a/.github/lychee.toml +++ b/.github/lychee.toml @@ -41,7 +41,18 @@ exclude = [ "https://bundlephobia.com", # Chrome webstore migration issue. Temporary -"https://chromewebstore.google.com" +"https://chromewebstore.google.com", + +# Drupal 403 +"https://(www.)?drupal.org", + +# Swimm returns 404, even though the link is valid +"https://docs.swimm.io", + +# Timeout +"https://huehive.co", +"https://foswiki.org", +"https://www.gnu.org", ] # Exclude all private IPs from checking. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index cfd22a293..c22166619 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -15,4 +15,4 @@ Make sure you - [ ] :book: have read the [contribution guidelines](https://mermaid.js.org/community/contributing.html) - [ ] :computer: have added necessary unit/e2e tests. - [ ] :notebook: have added documentation. Make sure [`MERMAID_RELEASE_VERSION`](https://mermaid.js.org/community/contributing.html#update-documentation) is used for all new features. -- [ ] :bookmark: targeted `develop` branch +- [ ] :butterfly: If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. Changesets that add features should be `minor` and those that fix bugs should be `patch`. Please prefix changeset messages with `feat:`, `fix:`, or `chore:`. diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml deleted file mode 100644 index 83138c3d4..000000000 --- a/.github/release-drafter.yml +++ /dev/null @@ -1,36 +0,0 @@ -name-template: '$NEXT_PATCH_VERSION' -tag-template: '$NEXT_PATCH_VERSION' -categories: - - title: '🚨 **Breaking Changes**' - labels: - - 'Breaking Change' - - title: '🚀 Features' - labels: - - 'Type: Enhancement' - - 'feature' # deprecated, new PRs shouldn't have this - - title: '🐛 Bug Fixes' - labels: - - 'Type: Bug / Error' - - 'fix' # deprecated, new PRs shouldn't have this - - title: '🧰 Maintenance' - labels: - - 'Type: Other' - - 'chore' # deprecated, new PRs shouldn't have this - - title: 'âšĄī¸ Performance' - labels: - - 'Type: Performance' - - title: '📚 Documentation' - labels: - - 'Area: Documentation' -change-template: '- $TITLE (#$NUMBER) @$AUTHOR' -sort-by: title -sort-direction: ascending -exclude-labels: - - 'Skip changelog' -no-changes-template: 'This release contains minor changes and bugfixes.' -template: | - # Release Notes - - $CHANGES - - 🎉 **Thanks to all contributors helping with this release!** 🎉 diff --git a/.github/stale.yml b/.github/stale.yml index 30c4ca4a0..94a16dfbd 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -15,5 +15,5 @@ markComment: > If you are still interested in this issue and it is still relevant you can comment to revive it. # Comment to post when closing a stale issue. Set to `false` to disable closeComment: > - This issue has been been automatically closed due to a lack of activity. + This issue has been automatically closed due to a lack of activity. This is done to maintain a clean list of issues that the community is interested in developing. diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml new file mode 100644 index 000000000..5b1066661 --- /dev/null +++ b/.github/workflows/autofix.yml @@ -0,0 +1,45 @@ +name: autofix.ci # needed to securely identify the workflow + +on: + pull_request: + branches-ignore: + - 'renovate/**' +permissions: + contents: read + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +jobs: + autofix: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 + # uses version from "packageManager" field in package.json + + - name: Setup Node.js + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 + with: + cache: pnpm + node-version-file: '.node-version' + + - name: Install Packages + run: | + pnpm install --frozen-lockfile + env: + CYPRESS_CACHE_FOLDER: .cache/Cypress + + - name: Fix Linting + shell: bash + run: pnpm -w run lint:fix + + - name: Sync `./src/config.type.ts` with `./src/schemas/config.schema.yaml` + shell: bash + run: pnpm run --filter mermaid types:build-config + + - name: Build Docs + working-directory: ./packages/mermaid + run: pnpm run docs:build + + - uses: autofix-ci/action@551dded8c6cc8a1054039c8bc0b8b48c51dfc6ef # main diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 87607bc2f..79ed53de1 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -8,6 +8,8 @@ on: pull_request: merge_group: +concurrency: ${{ github.workflow }}-${{ github.ref }} + permissions: contents: read @@ -16,12 +18,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: pnpm node-version-file: '.node-version' diff --git a/.github/workflows/check-readme-in-sync.yml b/.github/workflows/check-readme-in-sync.yml index ad6df66b5..ed5c70208 100644 --- a/.github/workflows/check-readme-in-sync.yml +++ b/.github/workflows/check-readme-in-sync.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Check for difference in README.md and docs/README.md run: | diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml deleted file mode 100644 index 012fbf19d..000000000 --- a/.github/workflows/checks.yml +++ /dev/null @@ -1,26 +0,0 @@ -on: - push: - merge_group: - pull_request: - types: - - opened - - synchronize - - ready_for_review - -name: Static analysis on Test files - -jobs: - check-tests: - runs-on: ubuntu-latest - name: check tests - if: github.repository_owner == 'mermaid-js' - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: testomatio/check-tests@stable - with: - framework: cypress - tests: './cypress/e2e/**/**.spec.js' - token: ${{ secrets.GITHUB_TOKEN }} - has-tests-label: true diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 764ec598c..a6400a86a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -11,6 +11,9 @@ on: - synchronize - ready_for_review +permissions: # added using https://github.com/step-security/secure-repo + contents: read + jobs: analyze: name: Analyze @@ -29,11 +32,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 with: config-file: ./.github/codeql/codeql-config.yml languages: ${{ matrix.language }} @@ -45,7 +48,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v3 + uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 # â„šī¸ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -59,4 +62,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 0d4a01360..69c435631 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -15,6 +15,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: 'Dependency Review' - uses: actions/dependency-review-action@v4 + uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0 diff --git a/.github/workflows/e2e-applitools.yml b/.github/workflows/e2e-applitools.yml index 1238fe371..9c357a581 100644 --- a/.github/workflows/e2e-applitools.yml +++ b/.github/workflows/e2e-applitools.yml @@ -11,6 +11,8 @@ on: default: master description: 'Parent branch to use for PRs' +concurrency: ${{ github.workflow }}-${{ github.ref }} + permissions: contents: read @@ -30,13 +32,13 @@ jobs: run: | echo "::error,title=Not using Applitools::APPLITOOLS_API_KEY is empty, disabling Applitools for this run." - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 # uses version from "packageManager" field in package.json - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version-file: '.node-version' @@ -52,7 +54,7 @@ jobs: APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com' - name: Cypress run - uses: cypress-io/github-action@v4 + uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 id: cypress with: start: pnpm run dev diff --git a/.github/workflows/e2e-timings.yml b/.github/workflows/e2e-timings.yml new file mode 100644 index 000000000..b048cc1c5 --- /dev/null +++ b/.github/workflows/e2e-timings.yml @@ -0,0 +1,70 @@ +name: E2E - Generate Timings + +on: + # run this workflow every night at 3am + schedule: + - cron: '28 3 * * *' + # or when the user triggers it from GitHub Actions page + workflow_dispatch: + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +permissions: + contents: write + pull-requests: write + +jobs: + timings: + runs-on: ubuntu-latest + container: + image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1 + options: --user 1001 + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 + - name: Setup Node.js + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 + with: + node-version-file: '.node-version' + - name: Install dependencies + uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 + with: + runTests: false + + - name: Cypress run + uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 + id: cypress + with: + install: false + start: pnpm run dev:coverage + wait-on: 'http://localhost:9000' + browser: chrome + publish-summary: false + env: + VITEST_COVERAGE: true + CYPRESS_COMMIT: ${{ github.sha }} + SPLIT: 1 + SPLIT_INDEX: 0 + SPLIT_FILE: 'cypress/timings.json' + + - name: Compare timings + id: compare + run: | + OUTPUT=$(pnpm tsx scripts/compare-timings.ts) + echo "$OUTPUT" >> $GITHUB_STEP_SUMMARY + + echo "output<> $GITHUB_OUTPUT + echo "$OUTPUT" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Commit and create pull request + uses: peter-evans/create-pull-request@a7b20e1da215b3ef3ccddb48ff65120256ed6226 + with: + add-paths: | + cypress/timings.json + commit-message: 'chore: update E2E timings' + branch: update-timings + title: Update E2E Timings + body: ${{ steps.compare.outputs.output }} + delete-branch: true + sign-commits: true diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 6477c9eb5..56883b987 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -1,18 +1,16 @@ -# We use github cache to save snapshots between runs. -# For PRs and MergeQueues, the target commit is used, and for push events, github.event.previous is used. -# If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots. -# These are then downloaded before running the E2E, providing the reference snapshots. -# If there are any errors, the diff image is uploaded to artifacts, and the user is notified. - name: E2E on: push: - branches-ignore: - - 'gh-readonly-queue/**' + branches: + - develop + - master + - release/** pull_request: merge_group: +concurrency: ${{ github.workflow }}-${{ github.ref }} + permissions: contents: read @@ -30,6 +28,8 @@ env: ) || github.event.before }} + RUN_VISUAL_TEST: >- + ${{ github.repository == 'mermaid-js/mermaid' && (github.event_name != 'pull_request' || !startsWith(github.head_ref, 'renovate/')) }} jobs: cache: runs-on: ubuntu-latest @@ -37,30 +37,29 @@ jobs: image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1 options: --user 1001 steps: - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version-file: '.node-version' - name: Cache snapshots id: cache-snapshot - uses: actions/cache@v4 + uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 with: - save-always: true path: ./cypress/snapshots key: ${{ runner.os }}-snapshots-${{ env.targetHash }} # If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots. - name: Switch to base branch if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ env.targetHash }} - name: Install dependencies if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} - uses: cypress-io/github-action@v6 + uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 with: # just perform install runTests: false @@ -72,16 +71,6 @@ jobs: mkdir -p cypress/snapshots/stats/base mv stats cypress/snapshots/stats/base - - name: Cypress run - uses: cypress-io/github-action@v6 - id: cypress-snapshot-gen - if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} - with: - install: false - start: pnpm run dev - wait-on: 'http://localhost:9000' - browser: chrome - e2e: runs-on: ubuntu-latest container: @@ -91,28 +80,28 @@ jobs: strategy: fail-fast: false matrix: - containers: [1, 2, 3, 4] + containers: [1, 2, 3, 4, 5] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 # uses version from "packageManager" field in package.json - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version-file: '.node-version' # These cached snapshots are downloaded, providing the reference snapshots. - name: Cache snapshots id: cache-snapshot - uses: actions/cache/restore@v4 + uses: actions/cache/restore@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 with: path: ./cypress/snapshots key: ${{ runner.os }}-snapshots-${{ env.targetHash }} - name: Install dependencies - uses: cypress-io/github-action@v6 + uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 with: runTests: false @@ -128,11 +117,8 @@ jobs: # Install NPM dependencies, cache them correctly # and run all Cypress tests - name: Cypress run - uses: cypress-io/github-action@v6 + uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 id: cypress - # If CYPRESS_RECORD_KEY is set, run in parallel on all containers - # Otherwise (e.g. if running from fork), we run on a single container only - if: ${{ ( env.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }} with: install: false start: pnpm run dev:coverage @@ -140,15 +126,20 @@ jobs: browser: chrome # Disable recording if we don't have an API key # e.g. if this action was run from a fork - record: ${{ secrets.CYPRESS_RECORD_KEY != '' }} - parallel: ${{ secrets.CYPRESS_RECORD_KEY != '' }} + record: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY != '' }} env: - CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} - VITEST_COVERAGE: true + ARGOS_PARALLEL: ${{ env.RUN_VISUAL_TEST == 'true' }} + ARGOS_PARALLEL_TOTAL: ${{ env.RUN_VISUAL_TEST == 'true' && strategy.job-total || 1 }} + ARGOS_PARALLEL_INDEX: ${{ env.RUN_VISUAL_TEST == 'true' && matrix.containers || 1 }} CYPRESS_COMMIT: ${{ github.sha }} + CYPRESS_RECORD_KEY: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY || ''}} + SPLIT: ${{ strategy.job-total }} + SPLIT_INDEX: ${{ strategy.job-index }} + SPLIT_FILE: 'cypress/timings.json' + VITEST_COVERAGE: true - name: Upload Coverage to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 # Run step only pushes to develop and pull_requests if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}} with: @@ -158,55 +149,3 @@ jobs: fail_ci_if_error: false verbose: true token: 6845cc80-77ee-4e17-85a1-026cd95e0766 - - # We upload the artifacts into numbered archives to prevent overwriting - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - if: ${{ always() }} - with: - name: snapshots-${{ matrix.containers }} - retention-days: 1 - path: ./cypress/snapshots - - combineArtifacts: - needs: e2e - runs-on: ubuntu-latest - if: ${{ always() }} - steps: - # Download all snapshot artifacts and merge them into a single folder - - name: Download All Artifacts - uses: actions/download-artifact@v4 - with: - path: snapshots - pattern: snapshots-* - merge-multiple: true - - # For successful push events, we save the snapshots cache - - name: Save snapshots cache - id: cache-upload - if: ${{ github.event_name == 'push' && needs.e2e.result != 'failure' }} - uses: actions/cache/save@v4 - with: - path: ./snapshots - key: ${{ runner.os }}-snapshots-${{ github.event.after }} - - - name: Flatten images to a folder - if: ${{ needs.e2e.result == 'failure' }} - run: | - mkdir errors - cd snapshots - find . -mindepth 2 -type d -name "*__diff_output__*" -exec sh -c 'mv "$0"/*.png ../errors/' {} \; - - - name: Upload Error snapshots - if: ${{ needs.e2e.result == 'failure' }} - uses: actions/upload-artifact@v4 - id: upload-artifacts - with: - name: error-snapshots - retention-days: 10 - path: errors/ - - - name: Notify Users - if: ${{ needs.e2e.result == 'failure' }} - run: | - echo "::error title=Visual tests failed::You can view images that failed by downloading the error-snapshots artifact: ${{ steps.upload-artifacts.outputs.artifact-url }}" diff --git a/.github/workflows/issue-triage.yml b/.github/workflows/issue-triage.yml index 129bd62b6..87a6e958b 100644 --- a/.github/workflows/issue-triage.yml +++ b/.github/workflows/issue-triage.yml @@ -4,11 +4,17 @@ on: issues: types: [opened] +permissions: # added using https://github.com/step-security/secure-repo + contents: read + jobs: triage: + permissions: + issues: write # for andymckay/labeler to label issues + pull-requests: write # for andymckay/labeler to label PRs runs-on: ubuntu-latest steps: - - uses: andymckay/labeler@1.0.4 + - uses: andymckay/labeler@e6c4322d0397f3240f0e7e30a33b5c5df2d39e90 # 1.0.4 with: repo-token: '${{ secrets.GITHUB_TOKEN }}' add-labels: 'Status: Triage' diff --git a/.github/workflows/link-checker.yml b/.github/workflows/link-checker.yml index bf54d7df2..f855ed23b 100644 --- a/.github/workflows/link-checker.yml +++ b/.github/workflows/link-checker.yml @@ -19,6 +19,9 @@ on: # * is a special character in YAML so you have to quote this string - cron: '30 8 * * *' +permissions: # added using https://github.com/step-security/secure-repo + contents: read + jobs: link-checker: runs-on: ubuntu-latest @@ -26,17 +29,17 @@ jobs: # lychee only uses the GITHUB_TOKEN to avoid rate-limiting contents: read steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Restore lychee cache - uses: actions/cache@v4 + uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 with: path: .lycheecache key: cache-lychee-${{ github.sha }} restore-keys: cache-lychee- - name: Link Checker - uses: lycheeverse/lychee-action@v1.9.3 + uses: lycheeverse/lychee-action@f613c4a64e50d792e0b31ec34bbcbba12263c6a6 # v2.3.0 with: args: >- --config .github/lychee.toml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8f5995d71..50edaa271 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -4,26 +4,32 @@ on: push: merge_group: pull_request: - types: - - opened - - synchronize - - ready_for_review workflow_dispatch: +concurrency: ${{ github.workflow }}-${{ github.ref }} + permissions: contents: write jobs: + docker-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - uses: hadolint/hadolint-action@54c9adbab1582c2ef04b2016b760714a4bfde3cf # v3.1.0 + with: + verbose: true lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 # uses version from "packageManager" field in package.json - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: pnpm node-version-file: '.node-version' @@ -83,14 +89,9 @@ jobs: continue-on-error: ${{ github.event_name == 'push' }} run: pnpm run docs:verify - - name: Rebuild Docs - if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }} - working-directory: ./packages/mermaid - run: pnpm run docs:build - - - name: Commit changes - uses: EndBug/add-and-commit@v9 - if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }} + - uses: testomatio/check-tests@0ea638fcec1820cf2e7b9854fdbdd04128a55bd4 # stable with: - message: 'Update docs' - add: 'docs/*' + framework: cypress + tests: './cypress/e2e/**/**.spec.js' + token: ${{ secrets.GITHUB_TOKEN }} + has-tests-label: true diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index 096590346..44860845f 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -22,7 +22,7 @@ jobs: pull-requests: write # write permission is required to label PRs steps: - name: Label PR - uses: release-drafter/release-drafter@v6 + uses: release-drafter/release-drafter@b1476f6e6eb133afa41ed8589daba6dc69b4d3f5 # v6.1.0 with: config-name: pr-labeler.yml disable-autolabeler: false diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index fb70a90ec..1a9ccafb6 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -23,12 +23,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: pnpm node-version-file: '.node-version' @@ -37,13 +37,13 @@ jobs: run: pnpm install --frozen-lockfile - name: Setup Pages - uses: actions/configure-pages@v4 + uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 - name: Run Build run: pnpm --filter mermaid run docs:build:vitepress - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 with: path: packages/mermaid/src/vitepress/.vitepress/dist @@ -56,4 +56,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/.github/workflows/release-draft.yml b/.github/workflows/release-draft.yml deleted file mode 100644 index 657bc767a..000000000 --- a/.github/workflows/release-draft.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Draft Release - -on: - push: - branches: - - master - -permissions: - contents: read - -jobs: - draft-release: - runs-on: ubuntu-latest - permissions: - contents: write # write permission is required to create a GitHub release - pull-requests: read # required to read PR titles/labels - steps: - - name: Draft Release - uses: release-drafter/release-drafter@v6 - with: - disable-autolabeler: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-preview-publish.yml b/.github/workflows/release-preview-publish.yml index c763430b0..665222b35 100644 --- a/.github/workflows/release-preview-publish.yml +++ b/.github/workflows/release-preview-publish.yml @@ -9,14 +9,14 @@ jobs: publish-preview: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: pnpm node-version-file: '.node-version' @@ -28,7 +28,7 @@ jobs: CYPRESS_CACHE_FOLDER: .cache/Cypress - name: Install Json - run: npm i json --global + run: npm i json@11.0.0 --global - name: Publish working-directory: ./packages/mermaid diff --git a/.github/workflows/release-preview.yml b/.github/workflows/release-preview.yml new file mode 100644 index 000000000..38938dff4 --- /dev/null +++ b/.github/workflows/release-preview.yml @@ -0,0 +1,43 @@ +name: Preview release + +on: + pull_request: + branches: [develop] + types: [opened, synchronize, labeled, ready_for_review] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.number }} + cancel-in-progress: true + +permissions: + contents: read + actions: write + +jobs: + preview: + if: ${{ github.repository_owner == 'mermaid-js' }} + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + issues: write + pull-requests: write + name: Publish preview release + timeout-minutes: 5 + steps: + - name: Checkout Repo + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 + + - name: Setup Node.js + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 + with: + cache: pnpm + node-version-file: '.node-version' + + - name: Install Packages + run: pnpm install --frozen-lockfile + + - name: Publish packages + run: pnpx pkg-pr-new publish --pnpm './packages/*' diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml deleted file mode 100644 index dce461cf5..000000000 --- a/.github/workflows/release-publish.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Publish release - -on: - release: - types: [published] - -jobs: - publish: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: fregante/setup-git-user@v2 - - - uses: pnpm/action-setup@v2 - # uses version from "packageManager" field in package.json - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - cache: pnpm - node-version-file: '.node-version' - - - name: Install Packages - run: | - pnpm install --frozen-lockfile - npm i json --global - env: - CYPRESS_CACHE_FOLDER: .cache/Cypress - - - name: Prepare release - run: | - VERSION=${GITHUB_REF:10} - echo "Preparing release $VERSION" - git checkout -t origin/release/$VERSION - npm version --no-git-tag-version --allow-same-version $VERSION - git add package.json - git commit -nm "Bump version $VERSION" - git checkout -t origin/master - git merge -m "Release $VERSION" --no-ff release/$VERSION - git push --no-verify - - - name: Publish - run: | - npm set //registry.npmjs.org/:_authToken $NPM_TOKEN - npm publish - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..649c40034 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,46 @@ +name: Release + +on: + push: + branches: + - master + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +permissions: # added using https://github.com/step-security/secure-repo + contents: read + +jobs: + release: + if: github.repository == 'mermaid-js/mermaid' + permissions: + contents: write # to create release (changesets/action) + id-token: write # OpenID Connect token needed for provenance + pull-requests: write # to create pull request (changesets/action) + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 + + - name: Setup Node.js + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 + with: + cache: pnpm + node-version-file: '.node-version' + + - name: Install Packages + run: pnpm install --frozen-lockfile + + - name: Create Release Pull Request or Publish to npm + id: changesets + uses: changesets/action@c8bada60c408975afd1a20b3db81d6eee6789308 # v1.4.9 + with: + version: pnpm changeset:version + publish: pnpm changeset:publish + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + NPM_CONFIG_PROVENANCE: true diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 000000000..4901b3781 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,37 @@ +name: Scorecard supply-chain security +on: + branch_protection_rule: + push: + branches: + - develop + schedule: + - cron: 29 15 * * 0 +permissions: read-all +jobs: + analysis: + name: Scorecard analysis + permissions: + id-token: write + security-events: write + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - name: Run analysis + uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + - name: Upload artifact + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + - name: Upload to code-scanning + uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 + with: + sarif_file: results.sarif diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a4bd264e0..527ab7401 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,13 +9,13 @@ jobs: unit-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 # uses version from "packageManager" field in package.json - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: pnpm node-version-file: '.node-version' @@ -38,8 +38,12 @@ jobs: run: | pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage + - name: Verify out-of-tree build with TypeScript + run: | + pnpm test:check:tsc + - name: Upload Coverage to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 # Run step only pushes to develop and pull_requests if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }} with: diff --git a/.github/workflows/unlock-reopened-issues.yml b/.github/workflows/unlock-reopened-issues.yml index 4c5379729..b854eeb4b 100644 --- a/.github/workflows/unlock-reopened-issues.yml +++ b/.github/workflows/unlock-reopened-issues.yml @@ -8,6 +8,6 @@ jobs: triage: runs-on: ubuntu-latest steps: - - uses: Dunning-Kruger/unlock-issues@v1 + - uses: Dunning-Kruger/unlock-issues@b06b7f7e5c3f2eaa1c6d5d89f40930e4d6d9699e # v1 with: repo-token: '${{ secrets.GITHUB_TOKEN }}' diff --git a/.github/workflows/update-browserlist.yml b/.github/workflows/update-browserlist.yml index 9aac3d7b3..94de12ad3 100644 --- a/.github/workflows/update-browserlist.yml +++ b/.github/workflows/update-browserlist.yml @@ -8,18 +8,18 @@ jobs: update-browser-list: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - run: npx update-browserslist-db@latest - name: Commit changes - uses: EndBug/add-and-commit@v9 + uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 with: author_name: ${{ github.actor }} author_email: ${{ github.actor }}@users.noreply.github.com message: 'chore: update browsers list' push: false - name: Create Pull Request - uses: peter-evans/create-pull-request@v6 + uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 with: branch: update-browserslist title: Update Browserslist diff --git a/.gitignore b/.gitignore index a0fd1c50b..7448f2a81 100644 --- a/.gitignore +++ b/.gitignore @@ -35,7 +35,7 @@ cypress/snapshots/ .tsbuildinfo tsconfig.tsbuildinfo -knsv*.html +#knsv*.html local*.html stats/ @@ -48,6 +48,7 @@ demos/dev/** !/demos/dev/example.html !/demos/dev/reload.js tsx-0/** +vite.config.ts.timestamp-* # autogenereated by langium-cli -generated/ \ No newline at end of file +generated/ diff --git a/.hadolint.yaml b/.hadolint.yaml new file mode 100644 index 000000000..280ff9592 --- /dev/null +++ b/.hadolint.yaml @@ -0,0 +1,2 @@ +ignored: + - DL3002 # TODO: Last USER should not be root diff --git a/.husky/pre-commit b/.husky/pre-commit index ad85fc42c..cc173f4a5 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,2 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - +#!/usr/bin/env sh NODE_OPTIONS="--max_old_space_size=8192" pnpm run pre-commit diff --git a/.node-version b/.node-version index 87834047a..7d41c735d 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -20.12.2 +22.14.0 diff --git a/.prettierignore b/.prettierignore index 7da0646e3..c70080426 100644 --- a/.prettierignore +++ b/.prettierignore @@ -16,3 +16,5 @@ generated/ # Ignore the files creates in /demos/dev except for example.html demos/dev/** !/demos/dev/example.html +# TODO: Lots of errors to fix +cypress/platform/state-refactor.html diff --git a/.vite/build.ts b/.vite/build.ts index a7e3cb0a4..480dd6b30 100644 --- a/.vite/build.ts +++ b/.vite/build.ts @@ -1,4 +1,5 @@ -import { build, InlineConfig, type PluginOption } from 'vite'; +import type { InlineConfig } from 'vite'; +import { build, type PluginOption } from 'vite'; import { resolve } from 'path'; import { fileURLToPath } from 'url'; import jisonPlugin from './jisonPlugin.js'; @@ -46,9 +47,10 @@ interface BuildOptions { export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions): InlineConfig => { const external: (string | RegExp)[] = ['require', 'fs', 'path']; + // eslint-disable-next-line no-console console.log(entryName, packageOptions[entryName]); const { name, file, packageName } = packageOptions[entryName]; - let output: OutputOptions = [ + const output: OutputOptions = [ { name, format: 'esm', @@ -83,7 +85,6 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions) plugins: [ jisonPlugin(), jsonSchemaPlugin(), // handles `.schema.yaml` files - // @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite typescript({ compilerOptions: { declaration: false } }), istanbul({ exclude: ['node_modules', 'test/', '__mocks__', 'generated'], @@ -125,10 +126,10 @@ await generateLangium(); if (watch) { await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' })); - build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' })); + void build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' })); if (!mermaidOnly) { - build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' })); - build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' })); + void build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' })); + void build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' })); } } else if (visualize) { await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' })); diff --git a/.vite/jsonSchemaPlugin.ts b/.vite/jsonSchemaPlugin.ts index 2e5b5cc0b..3614d5b45 100644 --- a/.vite/jsonSchemaPlugin.ts +++ b/.vite/jsonSchemaPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOption } from 'vite'; +import type { PluginOption } from 'vite'; import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js'; /** diff --git a/.vite/server.ts b/.vite/server.ts index 99d16f6f2..078599dc1 100644 --- a/.vite/server.ts +++ b/.vite/server.ts @@ -23,8 +23,9 @@ async function createServer() { app.use(express.static('cypress/platform')); app.listen(9000, () => { + // eslint-disable-next-line no-console console.log(`Listening on http://localhost:9000`); }); } -createServer(); +void createServer(); diff --git a/CHANGELOG.md b/CHANGELOG.md index ede5e19ad..8a4c0a414 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -256,7 +256,7 @@ mermaid.run({ - Problem showing graph with php on localhost [\#502](https://github.com/knsv/mermaid/issues/502) - logLevel's option doesnt work at 7.0.0 [\#501](https://github.com/knsv/mermaid/issues/501) - How do I get the log for a render or parse attempt? [\#500](https://github.com/knsv/mermaid/issues/500) -- Mermaid neutral style style to built in latest release [\#499](https://github.com/knsv/mermaid/issues/499) +- Mermaid neutral style to built in latest release [\#499](https://github.com/knsv/mermaid/issues/499) - Any plans for adding a typescript definition file? [\#495](https://github.com/knsv/mermaid/issues/495) - Gantt diagrams too narrow [\#493](https://github.com/knsv/mermaid/issues/493) - Flowchart edge labels placement [\#490](https://github.com/knsv/mermaid/issues/490) @@ -833,7 +833,7 @@ mermaid.run({ - Merge pull request \#1 from knsv/master [\#96](https://github.com/knsv/mermaid/pull/96) ([gkchic](https://github.com/gkchic)) - Removed duplicated section in flowchart docs [\#94](https://github.com/knsv/mermaid/pull/94) ([kaime](https://github.com/kaime)) - Grammar changes to sequence page [\#93](https://github.com/knsv/mermaid/pull/93) ([gkchic](https://github.com/gkchic)) -- Github buttons [\#89](https://github.com/knsv/mermaid/pull/89) ([gkchic](https://github.com/gkchic)) +- GitHub buttons [\#89](https://github.com/knsv/mermaid/pull/89) ([gkchic](https://github.com/gkchic)) - Template change [\#88](https://github.com/knsv/mermaid/pull/88) ([gkchic](https://github.com/gkchic)) ## [0.3.1](https://github.com/knsv/mermaid/tree/0.3.1) (2015-01-05) @@ -1002,4 +1002,4 @@ mermaid.run({ ## [0.1.0](https://github.com/knsv/mermaid/tree/0.1.0) (2014-11-16) -\* _This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)_ +\* _This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/GitHub-Changelog-Generator)_ diff --git a/Dockerfile b/Dockerfile index 7bec3bd4b..533604407 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,2 +1,13 @@ -FROM node:20.12.2-alpine3.19 AS base -RUN wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" sh - +FROM node:22.12.0-alpine3.19@sha256:40dc4b415c17b85bea9be05314b4a753f45a4e1716bb31c01182e6c53d51a654 + +USER 0:0 + +RUN corepack enable \ + && corepack enable pnpm + +RUN apk add --no-cache git~=2.43.4 \ + && git config --add --system safe.directory /mermaid + +ENV NODE_OPTIONS="--max_old_space_size=8192" + +EXPOSE 9000 3333 diff --git a/FUNDING.json b/FUNDING.json new file mode 100644 index 000000000..a1df876f4 --- /dev/null +++ b/FUNDING.json @@ -0,0 +1,7 @@ +{ + "drips": { + "ethereum": { + "ownedBy": "0x0831DDFe60d009d9448CC976157b539089aB821E" + } + } +} diff --git a/README.md b/README.md index d368a4349..760ce0f25 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Generate diagrams from markdown-like text. Live Editor!

- 📖 Documentation | 🚀 Getting Started | 🌐 CDN | 🙌 Join Us + 📖 Documentation | 🚀 Getting Started | 🌐 CDN | 🙌 Join Us

įŽ€äŊ“中文 @@ -33,8 +33,10 @@ Try Live Editor previews of future releases: @@ -42,7 +44,7 @@ Try Live Editor previews of future releases: Explore Mermaid.js in depth, with real-world examples, tips & tricks from the creator... The first official book on Mermaid is available for purchase. Check it out! +Banner for "The Official Guide to Mermaid.js" book ## Table of content @@ -81,6 +83,10 @@ You can also use Mermaid within [GitHub](https://github.blog/2022-02-14-include- For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](https://mermaid.js.org/intro/getting-started.html), [Usage](https://mermaid.js.org/config/usage.html) and [Tutorials](https://mermaid.js.org/ecosystem/tutorials.html). +Our PR Visual Regression Testing is powered by [Argos](https://argos-ci.com/?utm_source=mermaid&utm_campaign=oss) with their generous Open Source plan. It makes the process of reviewing PRs with visual changes a breeze. + +[![Covered by Argos Visual Testing](https://argos-ci.com/badge-large.svg)](https://argos-ci.com?utm_source=mermaid&utm_campaign=oss) + In our release process we rely heavily on visual regression tests using [applitools](https://applitools.com/). Applitools is a great service which has been easy to use and integrate with our tests. @@ -89,6 +95,10 @@ In our release process we rely heavily on visual regression tests using [applito +## Mermaid AI Bot + +[Mermaid](https://codeparrot.ai/oracle?owner=mermaid-js&repo=mermaid) Bot will help you understand this repository better. You can ask for code examples, installation guide, debugging help and much more. + ## Examples **The following are some examples of the diagrams, charts and graphs that can be made using Mermaid. Click here to jump into the [text syntax](https://mermaid.js.org/intro/syntax-reference.html).** @@ -247,6 +257,34 @@ pie ### Git graph [experimental - live editor] +``` +gitGraph + commit + commit + branch develop + checkout develop + commit + commit + checkout main + merge develop + commit + commit +``` + +```mermaid +gitGraph + commit + commit + branch develop + checkout develop + commit + commit + checkout main + merge develop + commit + commit +``` + ### Bar chart (using gantt chart) [docs - live editor] ``` @@ -413,7 +451,7 @@ For public sites, it can be precarious to retrieve text from users on the intern As an extra level of security for sites with external users we are happy to introduce a new security level in which the diagram is rendered in a sandboxed iframe preventing javascript in the code from being executed. This is a great step forward for better security. -_Unfortunately you can not have a cake and eat it at the same time which in this case means that some of the interactive functionality gets blocked along with the possible malicious code._ +_Unfortunately you cannot have a cake and eat it at the same time which in this case means that some of the interactive functionality gets blocked along with the possible malicious code._ ## Reporting vulnerabilities @@ -429,7 +467,7 @@ A quick note from Knut Sveidqvist: > > _Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017._ > -> _Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!_ +> _Thank you to the ever-growing list of [contributors](https://github.com/mermaid-js/mermaid/graphs/contributors) that brought the project this far!_ --- diff --git a/README.zh-CN.md b/README.zh-CN.md index 942f54bff..cd44e56b6 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -15,7 +15,7 @@ Mermaid 厞æ—ļįŧ–čž‘å™¨!

- 📖 æ–‡æĄŖ | 🚀 å…Ĩ门 | 🌐 CDN | 🙌 加å…Ĩ我äģŦ + 📖 æ–‡æĄŖ | 🚀 å…Ĩ门 | 🌐 CDN | 🙌 加å…Ĩ我äģŦ

English @@ -34,7 +34,7 @@ Mermaid [![Coverage Status](https://codecov.io/github/mermaid-js/mermaid/branch/develop/graph/badge.svg)](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop) [![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid) [![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid) -[![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/AgrbSrBer3) +[![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/sKeNQX4Wtj) [![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_) @@ -43,13 +43,13 @@ Mermaid **感č°ĸ所有参与čŋ›æĨ提äē¤ PRīŧŒč§Ŗį­”į–‘é—Žįš„äēēäģŦ! 🙏** -Explore Mermaid.js in depth, with real-world examples, tips & tricks from the creator... The first official book on Mermaid is available for purchase. Check it out! +Banner for "The Official Guide to Mermaid.js" book ## å…ŗäēŽ Mermaid -Mermaid 是一ä¸ĒåŸēäēŽ Javascript įš„å›žčĄ¨įģ˜åˆļåˇĨå…ˇīŧŒé€ščŋ‡č§Ŗæžįąģ Markdown įš„æ–‡æœŦč¯­æŗ•æĨåŽžįŽ°å›žčĄ¨įš„åˆ›åģē和动态äŋŽæ”šã€‚Mermaid č¯žį”Ÿįš„ä¸ģčĻį›Žįš„æ˜¯čŽŠæ–‡æĄŖįš„æ›´æ–°čƒŊ够及æ—ļ莟䏊åŧ€å‘čŋ›åēĻ。 +Mermaid 是一ä¸ĒåŸēäēŽ JavaScript įš„å›žčĄ¨įģ˜åˆļåˇĨå…ˇīŧŒé€ščŋ‡č§Ŗæžįąģ Markdown įš„æ–‡æœŦč¯­æŗ•æĨåŽžįŽ°å›žčĄ¨įš„åˆ›åģē和动态äŋŽæ”šã€‚Mermaid č¯žį”Ÿįš„ä¸ģčĻį›Žįš„æ˜¯čŽŠæ–‡æĄŖįš„æ›´æ–°čƒŊ够及æ—ļ莟䏊åŧ€å‘čŋ›åēĻ。 > Doc-Rot 是 Mermaid č‡´åŠ›äēŽč§Ŗå†ŗįš„一ä¸Ē难éĸ˜ã€‚ @@ -358,7 +358,7 @@ _åžˆä¸åš¸įš„æ˜¯īŧŒéąŧä¸Žį†ŠæŽŒä¸å¯å…ŧåž—īŧŒåœ¨čŋ™ä¸Ēåœēæ™¯ä¸‹åŽƒæ„å‘ŗį€åœ¨ > _į‰šåˆĢ感č°ĸ [d3](https://d3js.org/) 和 [dagre-d3](https://github.com/cpettitt/dagre-d3) čŋ™ä¸¤ä¸Ēäŧ˜į§€įš„éĄšį›ŽīŧŒåރäģŦ提䞛äē†å›žåŊĸå¸ƒåą€å’Œįģ˜å›žåˇĨå…ˇåē“īŧ_ > _åŒæ ˇæ„Ÿč°ĸ [js-sequence-diagram](https://bramp.github.io/js-sequence-diagrams) 提䞛ä熿—ļåēå›žč¯­æŗ•įš„äŊŋį”¨ã€‚ 感č°ĸ Jessica Peter 提䞛äē†į”˜į‰šå›žæ¸˛æŸ“įš„įĩ感。_ > _感č°ĸ [Tyler Long](https://github.com/tylerlong) äģŽ 2017 嚴四月åŧ€å§‹æˆä¸ēäē†éĄšį›Žįš„合äŊœč€…。_ > -> _感č°ĸčĨčļŠå¤šįš„ [č´ĄįŒŽč€…äģŦ](https://github.com/knsv/mermaid/graphs/contributors)īŧŒæ˛Ąæœ‰äŊ äģŦīŧŒå°ąæ˛Ąæœ‰čŋ™ä¸ĒéĄšį›Žįš„äģŠå¤Šīŧ_ +> _感č°ĸčĨčļŠå¤šįš„ [č´ĄįŒŽč€…äģŦ](https://github.com/mermaid-js/mermaid/graphs/contributors)īŧŒæ˛Ąæœ‰äŊ äģŦīŧŒå°ąæ˛Ąæœ‰čŋ™ä¸ĒéĄšį›Žįš„äģŠå¤Šīŧ_ --- diff --git a/cypress.config.ts b/cypress.config.ts index 4182d92a8..50ea940e9 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -1,7 +1,10 @@ -import { defineConfig } from 'cypress'; -import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin'; -import coverage from '@cypress/code-coverage/task'; import eyesPlugin from '@applitools/eyes-cypress'; +import { registerArgosTask } from '@argos-ci/cypress/task'; +import coverage from '@cypress/code-coverage/task.js'; +import { defineConfig } from 'cypress'; +import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin.js'; +import cypressSplit from 'cypress-split'; + export default eyesPlugin( defineConfig({ projectId: 'n2sma2', @@ -11,16 +14,22 @@ export default eyesPlugin( specPattern: 'cypress/integration/**/*.{js,ts}', setupNodeEvents(on, config) { coverage(on, config); + cypressSplit(on, config); on('before:browser:launch', (browser, launchOptions) => { if (browser.name === 'chrome' && browser.isHeadless) { launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1'); } return launchOptions; }); - addMatchImageSnapshotPlugin(on, config); // copy any needed variables from process.env to config.env config.env.useAppli = process.env.USE_APPLI ? true : false; + config.env.useArgos = process.env.RUN_VISUAL_TEST === 'true'; + if (config.env.useArgos) { + registerArgosTask(on, config); + } else { + addMatchImageSnapshotPlugin(on, config); + } // do not forget to return the changed config object! return config; }, diff --git a/cypress/helpers/util.ts b/cypress/helpers/util.ts index aed5d7973..81b7036af 100644 --- a/cypress/helpers/util.ts +++ b/cypress/helpers/util.ts @@ -29,13 +29,14 @@ export const mermaidUrl = ( options: CypressMermaidConfig, api: boolean ): string => { + options.handDrawnSeed = 1; const codeObject: CodeObject = { code: graphStr, mermaid: options, }; const objStr: string = JSON.stringify(codeObject); let url = `http://localhost:9000/e2e.html?graph=${utf8ToB64(objStr)}`; - if (api) { + if (api && typeof graphStr === 'string') { url = `http://localhost:9000/xss.html?graph=${graphStr}`; } @@ -54,16 +55,15 @@ export const imgSnapshotTest = ( ): void => { const options: CypressMermaidConfig = { ..._options, - fontFamily: _options.fontFamily || 'courier', + fontFamily: _options.fontFamily ?? 'courier', // @ts-ignore TODO: Fix type of fontSize - fontSize: _options.fontSize || '16px', + fontSize: _options.fontSize ?? '16px', sequence: { - ...(_options.sequence || {}), + ...(_options.sequence ?? {}), actorFontFamily: 'courier', - noteFontFamily: - _options.sequence && _options.sequence.noteFontFamily - ? _options.sequence.noteFontFamily - : 'courier', + noteFontFamily: _options.sequence?.noteFontFamily + ? _options.sequence.noteFontFamily + : 'courier', messageFontFamily: 'courier', }, }; @@ -74,7 +74,7 @@ export const imgSnapshotTest = ( export const urlSnapshotTest = ( url: string, - options: CypressMermaidConfig, + options: CypressMermaidConfig = {}, _api = false, validation?: any ): void => { @@ -95,18 +95,7 @@ export const openURLAndVerifyRendering = ( options: CypressMermaidConfig, validation?: any ): void => { - const useAppli: boolean = Cypress.env('useAppli'); - const name: string = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-'); - - if (useAppli) { - cy.log(`Opening eyes ${Cypress.spec.name} --- ${name}`); - cy.eyesOpen({ - appName: 'Mermaid', - testName: name, - batchName: Cypress.spec.name, - batchId: batchId + Cypress.spec.name, - }); - } + const name: string = (options.name ?? cy.state('runnable').fullTitle()).replace(/\s+/g, '-'); cy.visit(url); cy.window().should('have.property', 'rendered', true); @@ -116,12 +105,37 @@ export const openURLAndVerifyRendering = ( cy.get('svg').should(validation); } + verifyScreenshot(name); +}; + +export const verifyScreenshot = (name: string): void => { + const useAppli: boolean = Cypress.env('useAppli'); + const useArgos: boolean = Cypress.env('useArgos'); + if (useAppli) { + cy.log(`Opening eyes ${Cypress.spec.name} --- ${name}`); + cy.eyesOpen({ + appName: 'Mermaid', + testName: name, + batchName: Cypress.spec.name, + batchId: batchId + Cypress.spec.name, + }); cy.log(`Check eyes ${Cypress.spec.name}`); cy.eyesCheckWindow('Click!'); cy.log(`Closing eyes ${Cypress.spec.name}`); cy.eyesClose(); + } else if (useArgos) { + cy.argosScreenshot(name, { + threshold: 0.01, + }); } else { cy.matchImageSnapshot(name); } }; + +export const verifyNumber = (value: number, expected: number, deltaPercent = 10): void => { + expect(value).to.be.within( + expected * (1 - deltaPercent / 100), + expected * (1 + deltaPercent / 100) + ); +}; diff --git a/cypress/integration/other/configuration.spec.js b/cypress/integration/other/configuration.spec.js index 544eab40f..ad6b21e29 100644 --- a/cypress/integration/other/configuration.spec.js +++ b/cypress/integration/other/configuration.spec.js @@ -1,4 +1,4 @@ -import { renderGraph } from '../../helpers/util.ts'; +import { renderGraph, verifyScreenshot } from '../../helpers/util.ts'; describe('Configuration', () => { describe('arrowMarkerAbsolute', () => { it('should handle default value false of arrowMarkerAbsolute', () => { @@ -119,8 +119,7 @@ describe('Configuration', () => { const url = 'http://localhost:9000/regression/issue-1874.html'; cy.visit(url); cy.window().should('have.property', 'rendered', true); - cy.get('svg').should('be.visible'); - cy.matchImageSnapshot( + verifyScreenshot( 'configuration.spec-should-not-taint-initial-configuration-when-using-multiple-directives' ); }); @@ -145,7 +144,7 @@ describe('Configuration', () => { // none of the diagrams should be error diagrams expect($svg).to.not.contain('Syntax error'); }); - cy.matchImageSnapshot( + verifyScreenshot( 'configuration.spec-should-not-render-error-diagram-if-suppressErrorRendering-is-set' ); }); @@ -162,7 +161,7 @@ describe('Configuration', () => { // some of the diagrams should be error diagrams expect($svg).to.contain('Syntax error'); }); - cy.matchImageSnapshot( + verifyScreenshot( 'configuration.spec-should-render-error-diagram-if-suppressErrorRendering-is-not-set' ); }); diff --git a/cypress/integration/other/flowchart-elk.spec.js b/cypress/integration/other/flowchart-elk.spec.js deleted file mode 100644 index 22a6efc0f..000000000 --- a/cypress/integration/other/flowchart-elk.spec.js +++ /dev/null @@ -1,14 +0,0 @@ -import { urlSnapshotTest, openURLAndVerifyRendering } from '../../helpers/util.ts'; - -describe('Flowchart elk', () => { - it('should use dagre as fallback', () => { - urlSnapshotTest('http://localhost:9000/flow-elk.html', { - name: 'flow-elk fallback to dagre', - }); - }); - it('should allow overriding with external package', () => { - urlSnapshotTest('http://localhost:9000/flow-elk.html?elk=true', { - name: 'flow-elk overriding dagre with elk', - }); - }); -}); diff --git a/cypress/integration/other/interaction.spec.js b/cypress/integration/other/interaction.spec.js index 857141b5b..e57701fd9 100644 --- a/cypress/integration/other/interaction.spec.js +++ b/cypress/integration/other/interaction.spec.js @@ -20,7 +20,7 @@ describe('Interaction', () => { }); it('Graph: should handle a click on a node with a bound url', () => { - // When there is a URL, cy.contains selects the a tag instead of the span. The .node is a child of a, so we have to use find instead of parent. + // When there is a URL, `cy.contains()` selects the `a` tag instead of the `span` tag. The .node is a child of `a`, so we have to use `find()` instead of `parent`. cy.contains('URLTest1').find('.node').click(); cy.location().should(({ href }) => { expect(href).to.eq('http://localhost:9000/empty.html'); @@ -146,7 +146,7 @@ describe('Interaction', () => { }); }); - describe('Interaction - security level other, missspelling', () => { + describe('Interaction - security level other, misspelling', () => { beforeEach(() => { cy.visit('http://localhost:9000/click_security_other.html'); }); diff --git a/cypress/integration/other/xss.spec.js b/cypress/integration/other/xss.spec.js index 678040f98..1e51d2f23 100644 --- a/cypress/integration/other/xss.spec.js +++ b/cypress/integration/other/xss.spec.js @@ -10,7 +10,6 @@ describe('XSS', () => { cy.wait(1000).then(() => { cy.get('.mermaid').should('exist'); }); - cy.get('svg'); }); it('should not allow tags in the css', () => { @@ -137,4 +136,9 @@ describe('XSS', () => { cy.wait(1000); cy.get('#the-malware').should('not.exist'); }); + it('should sanitize backticks block diagram labels properly', () => { + cy.visit('http://localhost:9000/xss25.html'); + cy.wait(1000); + cy.get('#the-malware').should('not.exist'); + }); }); diff --git a/cypress/integration/rendering/appli.spec.js b/cypress/integration/rendering/appli.spec.js index 5def96815..51eeb657e 100644 --- a/cypress/integration/rendering/appli.spec.js +++ b/cypress/integration/rendering/appli.spec.js @@ -11,6 +11,27 @@ describe('Git Graph diagram', () => { {} ); }); + it('Should render subgraphs with title margins and edge labels', () => { + imgSnapshotTest( + `flowchart LR + + subgraph TOP + direction TB + subgraph B1 + direction RL + i1 --lb1-->f1 + end + subgraph B2 + direction BT + i2 --lb2-->f2 + end + end + A --lb3--> TOP --lb4--> B + B1 --lb5--> B2 + `, + { flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } } + ); + }); // it(`ultraFastTest`, function () { // // Navigate to the url we want to test // // â­ī¸ Note to see visual bugs, run the test using the above URL for the 1st run. diff --git a/cypress/integration/rendering/architecture.spec.ts b/cypress/integration/rendering/architecture.spec.ts new file mode 100644 index 000000000..997a6654e --- /dev/null +++ b/cypress/integration/rendering/architecture.spec.ts @@ -0,0 +1,252 @@ +import { imgSnapshotTest, urlSnapshotTest } from '../../helpers/util.ts'; + +describe.skip('architecture diagram', () => { + it('should render a simple architecture diagram with groups', () => { + imgSnapshotTest( + `architecture-beta + group api(cloud)[API] + + service db(database)[Database] in api + service disk1(disk)[Storage] in api + service disk2(disk)[Storage] in api + service server(server)[Server] in api + service gateway(internet)[Gateway] + + db L--R server + disk1 T--B server + disk2 T--B db + server T--B gateway + ` + ); + }); + it('should render a simple architecture diagram with titleAndAccessibilities', () => { + imgSnapshotTest( + `architecture-beta + title Simple Architecture Diagram + accTitle: Accessibility Title + accDescr: Accessibility Description + group api(cloud)[API] + + service db(database)[Database] in api + service disk1(disk)[Storage] in api + service disk2(disk)[Storage] in api + service server(server)[Server] in api + + db:L -- R:server + disk1:T -- B:server + disk2:T -- B:db + ` + ); + }); + it('should render an architecture diagram with groups within groups', () => { + imgSnapshotTest( + `architecture-beta + group api[API] + group public[Public API] in api + group private[Private API] in api + + service serv1(server)[Server] in public + + service serv2(server)[Server] in private + service db(database)[Database] in private + + service gateway(internet)[Gateway] in api + + serv1 B--T serv2 + serv2 L--R db + serv1 L--R gateway + ` + ); + }); + it('should render an architecture diagram with the fallback icon', () => { + imgSnapshotTest( + `architecture-beta + service unknown(iconnamedoesntexist)[Unknown Icon] + ` + ); + }); + it('should render an architecture diagram with split directioning', () => { + imgSnapshotTest( + `architecture-beta + service db(database)[Database] + service s3(disk)[Storage] + service serv1(server)[Server 1] + service serv2(server)[Server 2] + service disk(disk)[Disk] + + db L--R s3 + serv1 L--T s3 + serv2 L--B s3 + serv1 T--B disk + ` + ); + }); + it('should render an architecture diagram with directional arrows', () => { + imgSnapshotTest( + `architecture-beta + service servC(server)[Server 1] + service servL(server)[Server 2] + service servR(server)[Server 3] + service servT(server)[Server 4] + service servB(server)[Server 5] + + servC (L--R) servL + servC (R--L) servR + servC (T--B) servT + servC (B--T) servB + + servL (T--L) servT + servL (B--L) servB + servR (T--R) servT + servR (B--R) servB + ` + ); + }); + it('should render an architecture diagram with group edges', () => { + imgSnapshotTest( + `architecture-beta + group left_group(cloud)[Left] + group right_group(cloud)[Right] + group top_group(cloud)[Top] + group bottom_group(cloud)[Bottom] + group center_group(cloud)[Center] + + service left_disk(disk)[Disk] in left_group + service right_disk(disk)[Disk] in right_group + service top_disk(disk)[Disk] in top_group + service bottom_disk(disk)[Disk] in bottom_group + service center_disk(disk)[Disk] in center_group + + left_disk{group} (R--L) center_disk{group} + right_disk{group} (L--R) center_disk{group} + top_disk{group} (B--T) center_disk{group} + bottom_disk{group} (T--B) center_disk{group} + ` + ); + }); + it('should render an architecture diagram with edge labels', () => { + imgSnapshotTest( + `architecture-beta + service servC(server)[Server 1] + service servL(server)[Server 2] + service servR(server)[Server 3] + service servT(server)[Server 4] + service servB(server)[Server 5] + + servC L-[Label]-R servL + servC R-[Label]-L servR + servC T-[Label]-B servT + servC B-[Label]-T servB + + servL T-[Label]-L servT + servL B-[Label]-L servB + servR T-[Label]-R servT + servR B-[Label]-R servB + ` + ); + }); + it('should render an architecture diagram with simple junction edges', () => { + imgSnapshotTest( + `architecture-beta + service left_disk(disk)[Disk] + service top_disk(disk)[Disk] + service bottom_disk(disk)[Disk] + service top_gateway(internet)[Gateway] + service bottom_gateway(internet)[Gateway] + junction juncC + junction juncR + + left_disk R--L juncC + top_disk B--T juncC + bottom_disk T--B juncC + juncC R--L juncR + top_gateway B--T juncR + bottom_gateway T--B juncR + ` + ); + }); + it('should render an architecture diagram with complex junction edges', () => { + imgSnapshotTest( + `architecture-beta + group left + group right + service left_disk(disk)[Disk] in left + service top_disk(disk)[Disk] in left + service bottom_disk(disk)[Disk] in left + service top_gateway(internet)[Gateway] in right + service bottom_gateway(internet)[Gateway] in right + junction juncC in left + junction juncR in right + + left_disk R--L juncC + top_disk B--T juncC + bottom_disk T--B juncC + + + top_gateway (B--T juncR + bottom_gateway (T--B juncR + + juncC{group} R--L) juncR{group} + ` + ); + }); + + it('should render an architecture diagram with a reasonable height', () => { + imgSnapshotTest( + `architecture-beta + group federated(cloud)[Federated Environment] + service server1(server)[System] in federated + service edge(server)[Edge Device] in federated + server1:R -- L:edge + + group on_prem(cloud)[Hub] + service firewall(server)[Firewall Device] in on_prem + service server(server)[Server] in on_prem + firewall:R -- L:server + + service db1(database)[db1] in on_prem + service db2(database)[db2] in on_prem + service db3(database)[db3] in on_prem + service db4(database)[db4] in on_prem + service db5(database)[db5] in on_prem + service db6(database)[db6] in on_prem + + junction mid in on_prem + server:B -- T:mid + + junction 1Leftofmid in on_prem + 1Leftofmid:R -- L:mid + 1Leftofmid:B -- T:db1 + + junction 2Leftofmid in on_prem + 2Leftofmid:R -- L:1Leftofmid + 2Leftofmid:B -- T:db2 + + junction 3Leftofmid in on_prem + 3Leftofmid:R -- L:2Leftofmid + 3Leftofmid:B -- T:db3 + + junction 1RightOfMid in on_prem + mid:R -- L:1RightOfMid + 1RightOfMid:B -- T:db4 + + junction 2RightOfMid in on_prem + 1RightOfMid:R -- L:2RightOfMid + 2RightOfMid:B -- T:db5 + + junction 3RightOfMid in on_prem + 2RightOfMid:R -- L:3RightOfMid + 3RightOfMid:B -- T:db6 + + edge:R -- L:firewall + ` + ); + }); +}); + +// Skipped as the layout is not deterministic, and causes issues in E2E tests. +describe.skip('architecture - external', () => { + it('should allow adding external icons', () => { + urlSnapshotTest('http://localhost:9000/architecture-external.html'); + }); +}); diff --git a/cypress/integration/rendering/block.spec.js b/cypress/integration/rendering/block.spec.js index 9d62c642d..589a30fde 100644 --- a/cypress/integration/rendering/block.spec.js +++ b/cypress/integration/rendering/block.spec.js @@ -14,7 +14,7 @@ describe('Block diagram', () => { ); }); - it('BL2: should handle colums statement in sub-blocks', () => { + it('BL2: should handle columns statement in sub-blocks', () => { imgSnapshotTest( `block-beta id1["Hello"] @@ -30,7 +30,7 @@ describe('Block diagram', () => { ); }); - it('BL3: should align block widths and handle colums statement in sub-blocks', () => { + it('BL3: should align block widths and handle columns statement in sub-blocks', () => { imgSnapshotTest( `block-beta block @@ -46,7 +46,7 @@ describe('Block diagram', () => { ); }); - it('BL4: should align block widths and handle colums statements in deeper sub-blocks then 1 level', () => { + it('BL4: should align block widths and handle columns statements in deeper sub-blocks then 1 level', () => { imgSnapshotTest( `block-beta columns 1 @@ -66,7 +66,7 @@ describe('Block diagram', () => { ); }); - it('BL5: should align block widths and handle colums statements in deeper sub-blocks then 1 level (alt)', () => { + it('BL5: should align block widths and handle columns statements in deeper sub-blocks then 1 level (alt)', () => { imgSnapshotTest( `block-beta columns 1 @@ -236,7 +236,7 @@ describe('Block diagram', () => { ); }); - it('BL16: width alignment - blocks shold be equal in width', () => { + it('BL17: width alignment - blocks should be equal in width', () => { imgSnapshotTest( `block-beta A("This is the text") @@ -247,7 +247,7 @@ describe('Block diagram', () => { ); }); - it('BL17: block types 1 - square, rounded and circle', () => { + it('BL18: block types 1 - square, rounded and circle', () => { imgSnapshotTest( `block-beta A["square"] @@ -258,7 +258,7 @@ describe('Block diagram', () => { ); }); - it('BL18: block types 2 - odd, diamond and hexagon', () => { + it('BL19: block types 2 - odd, diamond and hexagon', () => { imgSnapshotTest( `block-beta A>"rect_left_inv_arrow"] @@ -269,7 +269,7 @@ describe('Block diagram', () => { ); }); - it('BL19: block types 3 - stadium', () => { + it('BL20: block types 3 - stadium', () => { imgSnapshotTest( `block-beta A(["stadium"]) @@ -278,7 +278,7 @@ describe('Block diagram', () => { ); }); - it('BL20: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => { + it('BL21: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => { imgSnapshotTest( `block-beta A[/"lean right"/] @@ -290,7 +290,7 @@ describe('Block diagram', () => { ); }); - it('BL21: block types 1 - square, rounded and circle', () => { + it('BL22: block types 1 - square, rounded and circle', () => { imgSnapshotTest( `block-beta A["square"] @@ -301,7 +301,7 @@ describe('Block diagram', () => { ); }); - it('BL22: sizing - it should be possible to make a block wider', () => { + it('BL23: sizing - it should be possible to make a block wider', () => { imgSnapshotTest( `block-beta A("rounded"):2 @@ -312,7 +312,7 @@ describe('Block diagram', () => { ); }); - it('BL23: sizing - it should be possible to make a composite block wider', () => { + it('BL24: sizing - it should be possible to make a composite block wider', () => { imgSnapshotTest( `block-beta block:2 @@ -324,7 +324,7 @@ describe('Block diagram', () => { ); }); - it('BL24: block in the middle with space on each side', () => { + it('BL25: block in the middle with space on each side', () => { imgSnapshotTest( `block-beta columns 3 @@ -335,7 +335,7 @@ describe('Block diagram', () => { {} ); }); - it('BL25: space and an edge', () => { + it('BL26: space and an edge', () => { imgSnapshotTest( `block-beta columns 5 @@ -345,7 +345,7 @@ describe('Block diagram', () => { {} ); }); - it('BL26: block sizes for regular blocks', () => { + it('BL27: block sizes for regular blocks', () => { imgSnapshotTest( `block-beta columns 3 @@ -354,7 +354,7 @@ describe('Block diagram', () => { {} ); }); - it('BL27: composite block with a set width - f should use the available space', () => { + it('BL28: composite block with a set width - f should use the available space', () => { imgSnapshotTest( `block-beta columns 3 @@ -363,11 +363,12 @@ describe('Block diagram', () => { f end g - `, + `, {} ); }); - it('BL23: composite block with a set width - f and g should split the available space', () => { + + it('BL29: composite block with a set width - f and g should split the available space', () => { imgSnapshotTest( `block-beta columns 3 @@ -379,7 +380,7 @@ describe('Block diagram', () => { h i j - `, + `, {} ); }); diff --git a/cypress/integration/rendering/c4.spec.js b/cypress/integration/rendering/c4.spec.js index 59af6504b..00e71adec 100644 --- a/cypress/integration/rendering/c4.spec.js +++ b/cypress/integration/rendering/c4.spec.js @@ -1,7 +1,7 @@ import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; describe('C4 diagram', () => { - it('should render a simple C4Context diagram', () => { + it('C4.1 should render a simple C4Context diagram', () => { imgSnapshotTest( ` C4Context @@ -30,9 +30,8 @@ describe('C4 diagram', () => { `, {} ); - cy.get('svg'); }); - it('should render a simple C4Container diagram', () => { + it('C4.2 should render a simple C4Container diagram', () => { imgSnapshotTest( ` C4Container @@ -50,9 +49,8 @@ describe('C4 diagram', () => { `, {} ); - cy.get('svg'); }); - it('should render a simple C4Component diagram', () => { + it('C4.3 should render a simple C4Component diagram', () => { imgSnapshotTest( ` C4Component @@ -69,9 +67,8 @@ describe('C4 diagram', () => { `, {} ); - cy.get('svg'); }); - it('should render a simple C4Dynamic diagram', () => { + it('C4.4 should render a simple C4Dynamic diagram', () => { imgSnapshotTest( ` C4Dynamic @@ -93,9 +90,8 @@ describe('C4 diagram', () => { `, {} ); - cy.get('svg'); }); - it('should render a simple C4Deployment diagram', () => { + it('C4.5 should render a simple C4Deployment diagram', () => { imgSnapshotTest( ` C4Deployment @@ -117,6 +113,5 @@ describe('C4 diagram', () => { `, {} ); - cy.get('svg'); }); }); diff --git a/cypress/integration/rendering/classDiagram-elk-v3.spec.js b/cypress/integration/rendering/classDiagram-elk-v3.spec.js new file mode 100644 index 000000000..ee6ca0b2b --- /dev/null +++ b/cypress/integration/rendering/classDiagram-elk-v3.spec.js @@ -0,0 +1,1037 @@ +import { imgSnapshotTest } from '../../helpers/util.ts'; +describe('Class diagram V3 ELK', () => { + it('ELK-0: should render a simple class diagram', () => { + imgSnapshotTest( + ` + classDiagram + + classA -- classB : Inheritance + classA -- classC : link + classC -- classD : link + classB -- classD + + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-1: should render a simple class diagram', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-1.1: should render a simple class diagram without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: false, layout: 'elk' } + ); + }); + + it('ELK-2: should render a simple class diagrams with cardinality', () => { + imgSnapshotTest( + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-2.1: should render a simple class diagrams with cardinality without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: false, layout: 'elk' } + ); + }); + + it('ELK-2.2 should render a simple class diagram with different visibilities', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class01 : -privateMethod() + Class01 : +publicMethod() + Class01 : #protectedMethod() + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK-2.3 should render a simple class diagram with different visibilities without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class01 : -privateMethod() + Class01 : +publicMethod() + Class01 : #protectedMethod() + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + `, + { logLevel: 1, htmlLabels: false, layout: 'elk' } + ); + }); + + it('ELK-3: should render multiple class diagrams', () => { + imgSnapshotTest( + [ + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + ], + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-4: should render a simple class diagram with comments', () => { + imgSnapshotTest( + ` + classDiagram + %% this is a comment + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-5: should render a simple class diagram with abstract method', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : someMethod()* + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-5.1: should render a simple class diagram with abstract method without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : someMethod()* + `, + { logLevel: 1, htmlLabels: false, layout: 'elk' } + ); + }); + + it('ELK-6: should render a simple class diagram with static method', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : someMethod()$ + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-6.1: should render a simple class diagram with static method without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : someMethod()$ + `, + { logLevel: 1, htmlLabels: false, layout: 'elk' } + ); + }); + + it('ELK-7: should render a simple class diagram with Generic class', () => { + imgSnapshotTest( + ` + classDiagram + class Class01~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-7.1: should render a simple class diagram with Generic class without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class01~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: false, layout: 'elk' } + ); + }); + + it('ELK-8: should render a simple class diagram with Generic class and relations', () => { + imgSnapshotTest( + ` + classDiagram + Class01~T~ <|-- AveryLongClass : Cool + Class03~T~ *-- Class04~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-9: should render a simple class diagram with clickable link', () => { + imgSnapshotTest( + ` + classDiagram + Class01~T~ <|-- AveryLongClass : Cool + Class03~T~ *-- Class04~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + link Class01 "google.com" "A Tooltip" + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-10: should render a simple class diagram with clickable callback', () => { + imgSnapshotTest( + ` + classDiagram + Class01~T~ <|-- AveryLongClass : Cool + Class03~T~ *-- Class04~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + callback Class01 "functionCall" "A Tooltip" + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-11: should render a simple class diagram with return type on method', () => { + imgSnapshotTest( + ` + classDiagram + class Class10~T~ { + int[] id + test(int[] ids) bool + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-11.1: should render a simple class diagram with return type on method without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10~T~ { + int[] id + test(int[] ids) bool + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: false, layout: 'elk' } + ); + }); + + it('ELK-12: should render a simple class diagram with generic types', () => { + imgSnapshotTest( + ` + classDiagram + class Class10~T~ { + int[] id + List~int~ ids + test(List~int~ ids) List~bool~ + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-12.1: should render a simple class diagram with generic types without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10~T~ { + int[] id + List~int~ ids + test(List~int~ ids) List~bool~ + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: false, layout: 'elk' } + ); + }); + + it('ELK-13: should render a simple class diagram with css classes applied', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 { + int[] id + List~int~ ids + test(List~int~ ids) List~bool~ + testArray() bool[] + } + + cssClass "Class10" exClass2 + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-14: should render a simple class diagram with css classes applied directly', () => { + imgSnapshotTest( + ` + classDiagram + class Class10:::exClass2 { + int[] id + List~int~ ids + test(List~int~ ids) List~bool~ + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-15: should render a simple class diagram with css classes applied two multiple classes', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + class Class20 + + cssClass "Class10, class20" exClass2 + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-16a: should render a simple class diagram with static field', () => { + imgSnapshotTest( + ` + classDiagram + class Foo { + +String bar$ + } + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-16b: should handle the direction statement with TB', () => { + imgSnapshotTest( + ` + classDiagram + direction TB + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides + + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK-17a: should handle the direction statement with BT', () => { + imgSnapshotTest( + ` + classDiagram + direction BT + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides + + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK-17b: should handle the direction statement with RL', () => { + imgSnapshotTest( + ` + classDiagram + direction RL + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides + + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-18a: should handle the direction statement with LR', () => { + imgSnapshotTest( + ` + classDiagram + direction LR + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides + + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-18b: should render a simple class diagram with notes', () => { + imgSnapshotTest( + ` + classDiagram + note "I love this diagram!\nDo you love it?" + class Class10 { + int id + size() + } + note for Class10 "Cool class\nI said it's very cool class!" + + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK-1433: should render a simple class with a title', () => { + imgSnapshotTest( + `--- +title: simple class diagram +--- +classDiagram +class Class10 +`, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK: should render a class with text label', () => { + imgSnapshotTest( + `classDiagram + class C1["Class 1 with text label"] + C1 --> C2`, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK: should render two classes with text labels', () => { + imgSnapshotTest( + `classDiagram + class C1["Class 1 with text label"] + class C2["Class 2 with chars @?"] + C1 --> C2`, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK: should render a class with a text label, members and annotation', () => { + imgSnapshotTest( + `classDiagram + class C1["Class 1 with text label"] { + <<interface>> + +member1 + } + C1 --> C2`, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK: should render multiple classes with same text labels', () => { + imgSnapshotTest( + `classDiagram + class C1["Class with text label"] + class C2["Class with text label"] + class C3["Class with text label"] + C1 --> C2 + C3 ..> C2 + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK: should render classes with different text labels', () => { + imgSnapshotTest( + `classDiagram + class C1["OneWord"] + class C2["With, Comma"] + class C3["With (Brackets)"] + class C4["With [Brackets]"] + class C5["With {Brackets}"] + class C7["With 1 number"] + class C8["With . period..."] + class C9["With - dash"] + class C10["With _ underscore"] + class C11["With ' single quote"] + class C12["With ~!@#$%^&*()_+=-/?"] + class C13["With Città foreign language"] + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + + it('ELK: should render classLabel if class has already been defined earlier', () => { + imgSnapshotTest( + `classDiagram + Animal <|-- Duck + class Duck["Duck with text label"] + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK: should add classes namespaces', function () { + imgSnapshotTest( + ` + classDiagram + namespace Namespace1 { + class C1 + class C2 + } + C1 --> C2 + class C3 + class C4 + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with no members', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with no members if hideEmptyMembersBox is enabled', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + `, + { logLevel: 1, class: { htmlLabels: true, hideEmptyMembersBox: true }, layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with no attributes, only methods', () => { + imgSnapshotTest( + ` + classDiagram + class Duck { + +swim() + +quack() + } + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with no methods, only attributes', () => { + imgSnapshotTest( + ` + classDiagram + class Duck { + +String beakColor + +int age + +float weight + } + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with style definition', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + style Class10 fill:#f9f,stroke:#333,stroke-width:4px + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with style definition without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + style Class10 fill:#f9f,stroke:#333,stroke-width:4px + `, + { logLevel: 1, htmlLabels: false, layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with classDef definitions', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + classDef pink fill:#f9f + classDef bold stroke:#333,stroke-width:6px,color:#fff + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with classDefs being applied', () => { + imgSnapshotTest( + ` + classDiagram + class Class10:::pink + cssClass "Class10" bold + classDef pink fill:#f9f + classDef bold stroke:#333,stroke-width:6px,color:#fff + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with classDefs being applied without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10:::pink + cssClass "Class10" bold + classDef pink fill:#f9f + classDef bold stroke:#333,stroke-width:6px,color:#fff + `, + { logLevel: 1, htmlLabels: false, layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with markdown styling', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 { + +attribute *italic** + ~attribute **bold*** + _italicmethod_() + __boldmethod__() + _+_swim_()a_ + __+quack() test__ + } + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with markdown styling without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 { + +attribute *italic** + ~attribute **bold*** + _italicmethod_() + __boldmethod__() + _+_swim_()a_ + __+quack() test__ + } + `, + { logLevel: 1, htmlLabels: false, layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with the handDrawn look', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn', layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with styles and the handDrawn look', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + style Class10 fill:#f9f,stroke:#333,stroke-width:4px,color:white + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn', layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with styles and the handDrawn look without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + style Class10 fill:#f9f,stroke:#333,stroke-width:4px,color:white + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn', layout: 'elk' } + ); + }); + it('ELK: should render a full class diagram with the handDrawn look', () => { + imgSnapshotTest( + ` + classDiagram + note "I love this diagram!\nDo you love it?" + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + note for Class10 "Cool class\nI said it's very cool class!" + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn', layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with a custom theme', () => { + imgSnapshotTest( + ` + %%{ + init: { + 'theme': 'base', + 'themeVariables': { + 'primaryColor': '#BB2528', + 'primaryTextColor': '#fff', + 'primaryBorderColor': '#7C0000', + 'lineColor': '#F83d29', + 'secondaryColor': '#006100', + 'tertiaryColor': '#fff' + } + } + }%% + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); + it('ELK: should render a simple class diagram with a custom theme and the handDrawn look', () => { + imgSnapshotTest( + ` + %%{ + init: { + 'theme': 'base', + 'themeVariables': { + 'primaryColor': '#BB2528', + 'primaryTextColor': '#fff', + 'primaryBorderColor': '#7C0000', + 'lineColor': '#F83d29', + 'secondaryColor': '#006100', + 'tertiaryColor': '#fff' + } + } + }%% + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn', layout: 'elk' } + ); + }); + it('ELK: should render a full class diagram using elk', () => { + imgSnapshotTest( + ` + classDiagram + note "I love this diagram!\nDo you love it?" + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + note for Class10 "Cool class\nI said it's very cool class!" + `, + { logLevel: 1, htmlLabels: true, layout: 'elk' } + ); + }); +}); diff --git a/cypress/integration/rendering/classDiagram-handDrawn-v3.spec.js b/cypress/integration/rendering/classDiagram-handDrawn-v3.spec.js new file mode 100644 index 000000000..32a82c089 --- /dev/null +++ b/cypress/integration/rendering/classDiagram-handDrawn-v3.spec.js @@ -0,0 +1,1041 @@ +import { imgSnapshotTest } from '../../helpers/util.ts'; +describe('Class diagram V3 HD', () => { + it('HD-0: should render a simple class diagram', () => { + imgSnapshotTest( + ` + classDiagram + + classA -- classB : Inheritance + classA -- classC : link + classC -- classD : link + classB -- classD + + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-1: should render a simple class diagram', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-1.1: should render a simple class diagram without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn' } + ); + }); + + it('HD-2: should render a simple class diagrams with cardinality', () => { + imgSnapshotTest( + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-2.1: should render a simple class diagrams with cardinality without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn' } + ); + }); + + it('HD-2.2 should render a simple class diagram with different visibilities', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class01 : -privateMethod() + Class01 : +publicMethod() + Class01 : #protectedMethod() + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD-2.3 should render a simple class diagram with different visibilities without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class01 : -privateMethod() + Class01 : +publicMethod() + Class01 : #protectedMethod() + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn' } + ); + }); + + it('HD-3: should render multiple class diagrams', () => { + imgSnapshotTest( + [ + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + ], + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-4: should render a simple class diagram with comments', () => { + imgSnapshotTest( + ` + classDiagram + %% this is a comment + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-5: should render a simple class diagram with abstract method', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : someMethod()* + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-5.1: should render a simple class diagram with abstract method without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : someMethod()* + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn' } + ); + }); + + it('HD-6: should render a simple class diagram with static method', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : someMethod()$ + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-6.1: should render a simple class diagram with static method without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : someMethod()$ + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn' } + ); + }); + + it('HD-7: should render a simple class diagram with Generic class', () => { + imgSnapshotTest( + ` + classDiagram + class Class01~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-7.1: should render a simple class diagram with Generic class without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class01~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn' } + ); + }); + + it('HD-8: should render a simple class diagram with Generic class and relations', () => { + imgSnapshotTest( + ` + classDiagram + Class01~T~ <|-- AveryLongClass : Cool + Class03~T~ *-- Class04~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-9: should render a simple class diagram with clickable link', () => { + imgSnapshotTest( + ` + classDiagram + Class01~T~ <|-- AveryLongClass : Cool + Class03~T~ *-- Class04~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + link Class01 "google.com" "A Tooltip" + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-10: should render a simple class diagram with clickable callback', () => { + imgSnapshotTest( + ` + classDiagram + Class01~T~ <|-- AveryLongClass : Cool + Class03~T~ *-- Class04~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + callback Class01 "functionCall" "A Tooltip" + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-11: should render a simple class diagram with return type on method', () => { + imgSnapshotTest( + ` + classDiagram + class Class10~T~ { + int[] id + test(int[] ids) bool + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-11.1: should render a simple class diagram with return type on method without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10~T~ { + int[] id + test(int[] ids) bool + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn' } + ); + }); + + it('HD-12: should render a simple class diagram with generic types', () => { + imgSnapshotTest( + ` + classDiagram + class Class10~T~ { + int[] id + List~int~ ids + test(List~int~ ids) List~bool~ + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-12.1: should render a simple class diagram with generic types without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10~T~ { + int[] id + List~int~ ids + test(List~int~ ids) List~bool~ + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn' } + ); + }); + + it('HD-13: should render a simple class diagram with css classes applied', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 { + int[] id + List~int~ ids + test(List~int~ ids) List~bool~ + testArray() bool[] + } + + cssClass "Class10" exClass2 + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-14: should render a simple class diagram with css classes applied directly', () => { + imgSnapshotTest( + ` + classDiagram + class Class10:::exClass2 { + int[] id + List~int~ ids + test(List~int~ ids) List~bool~ + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-15: should render a simple class diagram with css classes applied two multiple classes', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + class Class20 + + cssClass "Class10, class20" exClass2 + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-16a: should render a simple class diagram with static field', () => { + imgSnapshotTest( + ` + classDiagram + class Foo { + +String bar$ + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-16b: should handle the direction statement with TB', () => { + imgSnapshotTest( + ` + classDiagram + direction TB + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides + + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD-17a: should handle the direction statement with BT', () => { + imgSnapshotTest( + ` + classDiagram + direction BT + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides + + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD-17b: should handle the direction statement with RL', () => { + imgSnapshotTest( + ` + classDiagram + direction RL + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides + + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-18a: should handle the direction statement with LR', () => { + imgSnapshotTest( + ` + classDiagram + direction LR + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides + + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-18b: should render a simple class diagram with notes', () => { + imgSnapshotTest( + ` + classDiagram + note "I love this diagram!\nDo you love it?" + class Class10 { + int id + size() + } + note for Class10 "Cool class\nI said it's very cool class!" + + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD-1433: should render a simple class with a title', () => { + imgSnapshotTest( + `--- +title: simple class diagram +--- +classDiagram +class Class10 +`, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD: should render a class with text label', () => { + imgSnapshotTest( + `classDiagram + class C1["Class 1 with text label"] + C1 --> C2`, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD: should render two classes with text labels', () => { + imgSnapshotTest( + `classDiagram + class C1["Class 1 with text label"] + class C2["Class 2 with chars @?"] + C1 --> C2`, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a class with a text label, members and annotation', () => { + imgSnapshotTest( + `classDiagram + class C1["Class 1 with text label"] { + <<interface>> + +member1 + } + C1 --> C2`, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render multiple classes with same text labels', () => { + imgSnapshotTest( + `classDiagram +class C1["Class with text label"] +class C2["Class with text label"] +class C3["Class with text label"] +C1 --> C2 +C3 ..> C2 + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render classes with different text labels', () => { + imgSnapshotTest( + `classDiagram +class C1["OneWord"] +class C2["With, Comma"] +class C3["With (Brackets)"] +class C4["With [Brackets]"] +class C5["With {Brackets}"] +class C7["With 1 number"] +class C8["With . period..."] +class C9["With - dash"] +class C10["With _ underscore"] +class C11["With ' single quote"] +class C12["With ~!@#$%^&*()_+=-/?"] +class C13["With Città foreign language"] + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + + it('HD: should render classLabel if class has already been defined earlier', () => { + imgSnapshotTest( + `classDiagram + Animal <|-- Duck + class Duck["Duck with text label"] +`, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should add classes namespaces', function () { + imgSnapshotTest( + ` + classDiagram + namespace Namespace1 { + class C1 + class C2 + } + C1 --> C2 + class C3 + class C4 + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with no members', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with no members if hideEmptyMembersBox is enabled', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + `, + { logLevel: 1, class: { htmlLabels: true, hideEmptyMembersBox: true }, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with no attributes, only methods', () => { + imgSnapshotTest( + ` + classDiagram + class Duck { + +swim() + +quack() + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with no methods, only attributes', () => { + imgSnapshotTest( + ` + classDiagram + class Duck { + +String beakColor + +int age + +float weight + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with style definition', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + style Class10 fill:#f9f,stroke:#333,stroke-width:4px + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with style definition without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + style Class10 fill:#f9f,stroke:#333,stroke-width:4px + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with classDef definitions', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + classDef pink fill:#f9f + classDef bold stroke:#333,stroke-width:6px,color:#fff + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with classDefs being applied', () => { + imgSnapshotTest( + ` + classDiagram + class Class10:::pink + cssClass "Class10" bold + classDef pink fill:#f9f + classDef bold stroke:#333,stroke-width:6px,color:#fff + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with classDefs being applied without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10:::pink + cssClass "Class10" bold + classDef pink fill:#f9f + classDef bold stroke:#333,stroke-width:6px,color:#fff + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with markdown styling', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 { + +attribute *italic** + ~attribute **bold*** + _italicmethod_() + __boldmethod__() + _+_swim_()a_ + __+quack() test__ + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with markdown styling without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 { + +attribute *italic** + ~attribute **bold*** + _italicmethod_() + __boldmethod__() + _+_swim_()a_ + __+quack() test__ + } + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with the handDrawn look', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with styles and the handDrawn look', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + style Class10 fill:#f9f,stroke:#333,stroke-width:4px,color:white + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with styles and the handDrawn look without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + style Class10 fill:#f9f,stroke:#333,stroke-width:4px,color:white + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn' } + ); + }); + it('HD: should render a full class diagram with the handDrawn look', () => { + imgSnapshotTest( + ` + classDiagram + note "I love this diagram!\nDo you love it?" + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + note for Class10 "Cool class\nI said it's very cool class!" + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with a custom theme', () => { + imgSnapshotTest( + ` + %%{ + init: { + 'theme': 'base', + 'themeVariables': { + 'primaryColor': '#BB2528', + 'primaryTextColor': '#fff', + 'primaryBorderColor': '#7C0000', + 'lineColor': '#F83d29', + 'secondaryColor': '#006100', + 'tertiaryColor': '#fff' + } + } + }%% + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a simple class diagram with a custom theme and the handDrawn look', () => { + imgSnapshotTest( + ` + %%{ + init: { + 'theme': 'base', + 'themeVariables': { + 'primaryColor': '#BB2528', + 'primaryTextColor': '#fff', + 'primaryBorderColor': '#7C0000', + 'lineColor': '#F83d29', + 'secondaryColor': '#006100', + 'tertiaryColor': '#fff' + } + } + }%% + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('HD: should render a full class diagram using elk', () => { + imgSnapshotTest( + ` +--- + config: + layout: elk +--- + classDiagram + note "I love this diagram!\nDo you love it?" + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + note for Class10 "Cool class\nI said it's very cool class!" + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); +}); diff --git a/cypress/integration/rendering/classDiagram-v2.spec.js b/cypress/integration/rendering/classDiagram-v2.spec.js index 20a1aea0a..0c5dbc04b 100644 --- a/cypress/integration/rendering/classDiagram-v2.spec.js +++ b/cypress/integration/rendering/classDiagram-v2.spec.js @@ -76,7 +76,7 @@ describe('Class diagram V2', () => { ); }); - it('should render a simple class diagram with different visibilities', () => { + it('2.1 should render a simple class diagram with different visibilities', () => { imgSnapshotTest( ` classDiagram-v2 @@ -93,7 +93,7 @@ describe('Class diagram V2', () => { ); }); - it('should render multiple class diagrams', () => { + it('3: should render multiple class diagrams', () => { imgSnapshotTest( [ ` @@ -581,4 +581,63 @@ class C13["With Città foreign language"] { logLevel: 1, flowchart: { htmlLabels: false } } ); }); + + it('renders a class diagram with a generic class in a namespace', () => { + const diagramDefinition = ` + classDiagram-v2 + namespace Company.Project.Module { + class GenericClass~T~ { + +addItem(item: T) + +getItem() T + } + } + `; + + imgSnapshotTest(diagramDefinition); + }); + + it('renders a class diagram with nested namespaces and relationships', () => { + const diagramDefinition = ` + classDiagram-v2 + namespace Company.Project.Module.SubModule { + class Report { + +generatePDF(data: List) + +generateCSV(data: List) + } + } + namespace Company.Project.Module { + class Admin { + +generateReport() + } + } + Admin --> Report : generates + `; + + imgSnapshotTest(diagramDefinition); + }); + + it('renders a class diagram with multiple classes and relationships in a namespace', () => { + const diagramDefinition = ` + classDiagram-v2 + namespace Company.Project.Module { + class User { + +login(username: String, password: String) + +logout() + } + class Admin { + +addUser(user: User) + +removeUser(user: User) + +generateReport() + } + class Report { + +generatePDF(reportData: List) + +generateCSV(reportData: List) + } + } + Admin --> User : manages + Admin --> Report : generates + `; + + imgSnapshotTest(diagramDefinition); + }); }); diff --git a/cypress/integration/rendering/classDiagram-v3.spec.js b/cypress/integration/rendering/classDiagram-v3.spec.js new file mode 100644 index 000000000..626d6fcea --- /dev/null +++ b/cypress/integration/rendering/classDiagram-v3.spec.js @@ -0,0 +1,1031 @@ +import { imgSnapshotTest } from '../../helpers/util.ts'; +describe('Class diagram V3', () => { + it('0: should render a simple class diagram', () => { + imgSnapshotTest( + ` + classDiagram + + classA -- classB : Inheritance + classA -- classC : link + classC -- classD : link + classB -- classD + + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('1: should render a simple class diagram', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('1.1: should render a simple class diagram without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: false } + ); + }); + + it('2: should render a simple class diagrams with cardinality', () => { + imgSnapshotTest( + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('2.1: should render a simple class diagrams with cardinality without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: false } + ); + }); + + it('2.2 should render a simple class diagram with different visibilities', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class01 : -privateMethod() + Class01 : +publicMethod() + Class01 : #protectedMethod() + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + `, + { logLevel: 1, htmlLabels: true } + ); + }); + it('2.3 should render a simple class diagram with different visibilities without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class01 : -privateMethod() + Class01 : +publicMethod() + Class01 : #protectedMethod() + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + `, + { logLevel: 1, htmlLabels: false } + ); + }); + + it('3: should render multiple class diagrams', () => { + imgSnapshotTest( + [ + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + ` + classDiagram + Class01 "1" <|--|> "*" AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 "1" <--> "*" C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + ], + { logLevel: 1, htmlLabels: true } + ); + }); + + it('4: should render a simple class diagram with comments', () => { + imgSnapshotTest( + ` + classDiagram + %% this is a comment + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('5: should render a simple class diagram with abstract method', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : someMethod()* + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('5.1: should render a simple class diagram with abstract method without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : someMethod()* + `, + { logLevel: 1, htmlLabels: false } + ); + }); + + it('6: should render a simple class diagram with static method', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : someMethod()$ + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('6.1: should render a simple class diagram with static method without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + Class01 <|-- AveryLongClass : Cool + Class01 : someMethod()$ + `, + { logLevel: 1, htmlLabels: false } + ); + }); + + it('7: should render a simple class diagram with Generic class', () => { + imgSnapshotTest( + ` + classDiagram + class Class01~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('7.1: should render a simple class diagram with Generic class without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class01~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: false } + ); + }); + + it('8: should render a simple class diagram with Generic class and relations', () => { + imgSnapshotTest( + ` + classDiagram + Class01~T~ <|-- AveryLongClass : Cool + Class03~T~ *-- Class04~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('9: should render a simple class diagram with clickable link', () => { + imgSnapshotTest( + ` + classDiagram + Class01~T~ <|-- AveryLongClass : Cool + Class03~T~ *-- Class04~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + link Class01 "google.com" "A Tooltip" + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('10: should render a simple class diagram with clickable callback', () => { + imgSnapshotTest( + ` + classDiagram + Class01~T~ <|-- AveryLongClass : Cool + Class03~T~ *-- Class04~T~ + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class08 <--> C2: Cool label + class Class10~T~ { + <<service>> + int id + test() + } + callback Class01 "functionCall" "A Tooltip" + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('11: should render a simple class diagram with return type on method', () => { + imgSnapshotTest( + ` + classDiagram + class Class10~T~ { + int[] id + test(int[] ids) bool + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('11.1: should render a simple class diagram with return type on method without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10~T~ { + int[] id + test(int[] ids) bool + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: false } + ); + }); + + it('12: should render a simple class diagram with generic types', () => { + imgSnapshotTest( + ` + classDiagram + class Class10~T~ { + int[] id + List~int~ ids + test(List~int~ ids) List~bool~ + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('12.1: should render a simple class diagram with generic types without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10~T~ { + int[] id + List~int~ ids + test(List~int~ ids) List~bool~ + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: false } + ); + }); + + it('13: should render a simple class diagram with css classes applied', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 { + int[] id + List~int~ ids + test(List~int~ ids) List~bool~ + testArray() bool[] + } + + cssClass "Class10" exClass2 + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('14: should render a simple class diagram with css classes applied directly', () => { + imgSnapshotTest( + ` + classDiagram + class Class10:::exClass2 { + int[] id + List~int~ ids + test(List~int~ ids) List~bool~ + testArray() bool[] + } + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('15: should render a simple class diagram with css classes applied two multiple classes', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + class Class20 + + cssClass "Class10, class20" exClass2 + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('16a: should render a simple class diagram with static field', () => { + imgSnapshotTest( + ` + classDiagram + class Foo { + +String bar$ + } + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('16b: should handle the direction statement with TB', () => { + imgSnapshotTest( + ` + classDiagram + direction TB + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides + + `, + { logLevel: 1, htmlLabels: true } + ); + }); + it('17a: should handle the direction statement with BT', () => { + imgSnapshotTest( + ` + classDiagram + direction BT + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides + + `, + { logLevel: 1, htmlLabels: true } + ); + }); + it('17b: should handle the direction statement with RL', () => { + imgSnapshotTest( + ` + classDiagram + direction RL + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides + + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('18a: should handle the direction statement with LR', () => { + imgSnapshotTest( + ` + classDiagram + direction LR + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides + + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('18b: should render a simple class diagram with notes', () => { + imgSnapshotTest( + ` + classDiagram + note "I love this diagram!\nDo you love it?" + class Class10 { + int id + size() + } + note for Class10 "Cool class\nI said it's very cool class!" + + `, + { logLevel: 1, htmlLabels: true } + ); + }); + + it('1433: should render a simple class with a title', () => { + imgSnapshotTest( + `--- +title: simple class diagram +--- +classDiagram +class Class10 +` + ); + }); + + it('should render a class with text label', () => { + imgSnapshotTest( + `classDiagram + class C1["Class 1 with text label"] + C1 --> C2` + ); + }); + + it('should render two classes with text labels', () => { + imgSnapshotTest( + `classDiagram + class C1["Class 1 with text label"] + class C2["Class 2 with chars @?"] + C1 --> C2` + ); + }); + it('should render a class with a text label, members and annotation', () => { + imgSnapshotTest( + `classDiagram + class C1["Class 1 with text label"] { + <<interface>> + +member1 + } + C1 --> C2` + ); + }); + it('should render multiple classes with same text labels', () => { + imgSnapshotTest( + `classDiagram +class C1["Class with text label"] +class C2["Class with text label"] +class C3["Class with text label"] +C1 --> C2 +C3 ..> C2 + ` + ); + }); + it('should render classes with different text labels', () => { + imgSnapshotTest( + `classDiagram +class C1["OneWord"] +class C2["With, Comma"] +class C3["With (Brackets)"] +class C4["With [Brackets]"] +class C5["With {Brackets}"] +class C7["With 1 number"] +class C8["With . period..."] +class C9["With - dash"] +class C10["With _ underscore"] +class C11["With ' single quote"] +class C12["With ~!@#$%^&*()_+=-/?"] +class C13["With Città foreign language"] + ` + ); + }); + + it('should render classLabel if class has already been defined earlier', () => { + imgSnapshotTest( + `classDiagram + Animal <|-- Duck + class Duck["Duck with text label"] +` + ); + }); + it('should add classes namespaces', function () { + imgSnapshotTest( + ` + classDiagram + namespace Namespace1 { + class C1 + class C2 + } + C1 --> C2 + class C3 + class C4 + ` + ); + }); + it('should render a simple class diagram with no members', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + `, + { logLevel: 1, htmlLabels: true } + ); + }); + it('should render a simple class diagram with no members if hideEmptyMembersBox is enabled', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + `, + { logLevel: 1, class: { htmlLabels: true, hideEmptyMembersBox: true } } + ); + }); + it('should render a simple class diagram with no attributes, only methods', () => { + imgSnapshotTest( + ` + classDiagram + class Duck { + +swim() + +quack() + } + ` + ); + }); + it('should render a simple class diagram with no methods, only attributes', () => { + imgSnapshotTest( + ` + classDiagram + class Duck { + +String beakColor + +int age + +float weight + } + ` + ); + }); + it('should render a simple class diagram with style definition', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + style Class10 fill:#f9f,stroke:#333,stroke-width:4px + `, + { logLevel: 1, htmlLabels: true } + ); + }); + it('should render a simple class diagram with style definition without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + style Class10 fill:#f9f,stroke:#333,stroke-width:4px + `, + { logLevel: 1, htmlLabels: false } + ); + }); + it('should render a simple class diagram with classDef definitions', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + classDef pink fill:#f9f + classDef bold stroke:#333,stroke-width:6px,color:#fff + `, + { logLevel: 1, htmlLabels: true } + ); + }); + it('should render a simple class diagram with classDefs being applied', () => { + imgSnapshotTest( + ` + classDiagram + class Class10:::pink + cssClass "Class10" bold + classDef pink fill:#f9f + classDef bold stroke:#333,stroke-width:6px,color:#fff + `, + { logLevel: 1, htmlLabels: true } + ); + }); + it('should render a simple class diagram with classDefs being applied without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10:::pink + cssClass "Class10" bold + classDef pink fill:#f9f + classDef bold stroke:#333,stroke-width:6px,color:#fff + `, + { logLevel: 1, htmlLabels: false } + ); + }); + it('should render a simple class diagram with markdown styling', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 { + +attribute *italic** + ~attribute **bold*** + _italicmethod_() + __boldmethod__() + _+_swim_()a_ + __+quack() test__ + } + `, + { logLevel: 1, htmlLabels: true } + ); + }); + it('should render a simple class diagram with markdown styling without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 { + +attribute *italic** + ~attribute **bold*** + _italicmethod_() + __boldmethod__() + _+_swim_()a_ + __+quack() test__ + } + `, + { logLevel: 1, htmlLabels: false } + ); + }); + it('should render a simple class diagram with the handDrawn look', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('should render a simple class diagram with styles and the handDrawn look', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + style Class10 fill:#f9f,stroke:#333,stroke-width:4px,color:white + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('should render a simple class diagram with styles and the handDrawn look without htmlLabels', () => { + imgSnapshotTest( + ` + classDiagram + class Class10 + style Class10 fill:#f9f,stroke:#333,stroke-width:4px,color:white + `, + { logLevel: 1, htmlLabels: false, look: 'handDrawn' } + ); + }); + it('should render a full class diagram with the handDrawn look', () => { + imgSnapshotTest( + ` + classDiagram + note "I love this diagram!\nDo you love it?" + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + note for Class10 "Cool class\nI said it's very cool class!" + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('should render a simple class diagram with a custom theme', () => { + imgSnapshotTest( + ` + %%{ + init: { + 'theme': 'base', + 'themeVariables': { + 'primaryColor': '#BB2528', + 'primaryTextColor': '#fff', + 'primaryBorderColor': '#7C0000', + 'lineColor': '#F83d29', + 'secondaryColor': '#006100', + 'tertiaryColor': '#fff' + } + } + }%% + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true } + ); + }); + it('should render a simple class diagram with a custom theme and the handDrawn look', () => { + imgSnapshotTest( + ` + %%{ + init: { + 'theme': 'base', + 'themeVariables': { + 'primaryColor': '#BB2528', + 'primaryTextColor': '#fff', + 'primaryBorderColor': '#7C0000', + 'lineColor': '#F83d29', + 'secondaryColor': '#006100', + 'tertiaryColor': '#fff' + } + } + }%% + classDiagram + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 *-- Class04 + Class05 o-- Class06 + Class07 .. Class08 + Class09 --> C2 : Where am i? + Class09 --* C3 + Class09 --|> Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + `, + { logLevel: 1, htmlLabels: true, look: 'handDrawn' } + ); + }); + it('should render a full class diagram using elk', () => { + imgSnapshotTest( + ` +--- + config: + layout: elk +--- + classDiagram + note "I love this diagram!\nDo you love it?" + Class01 <|-- AveryLongClass : Cool + <<interface>> Class01 + Class03 "1" *-- "*" Class04 + Class05 "1" o-- "many" Class06 + Class07 "1" .. "*" Class08 + Class09 "1" --> "*" C2 : Where am i? + Class09 "*" --* "*" C3 + Class09 "1" --|> "1" Class07 + Class12 <|.. Class08 + Class11 ..>Class12 + Class07 : equals() + Class07 : Object[] elementData + Class01 : size() + Class01 : int chimp + Class01 : int gorilla + Class01 : -int privateChimp + Class01 : +int publicGorilla + Class01 : #int protectedMarmoset + Class08 <--> C2: Cool label + class Class10 { + <<service>> + int id + test() + } + note for Class10 "Cool class\nI said it's very cool class!" + `, + { logLevel: 1, htmlLabels: true } + ); + }); +}); diff --git a/cypress/integration/rendering/classDiagram.spec.js b/cypress/integration/rendering/classDiagram.spec.js index cab3649df..e7d201b5d 100644 --- a/cypress/integration/rendering/classDiagram.spec.js +++ b/cypress/integration/rendering/classDiagram.spec.js @@ -32,7 +32,6 @@ describe('Class diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('2: should render a simple class diagrams with cardinality', () => { @@ -61,7 +60,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('3: should render a simple class diagram with different visibilities', () => { @@ -79,7 +77,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('4: should render a simple class diagram with comments', () => { @@ -109,7 +106,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('5: should render a simple class diagram with abstract method', () => { @@ -121,7 +117,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('6: should render a simple class diagram with static method', () => { @@ -133,7 +128,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('7: should render a simple class diagram with Generic class', () => { @@ -153,7 +147,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('8: should render a simple class diagram with Generic class and relations', () => { @@ -174,7 +167,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('9: should render a simple class diagram with clickable link', () => { @@ -196,7 +188,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('10: should render a simple class diagram with clickable callback', () => { @@ -218,7 +209,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('11: should render a simple class diagram with return type on method', () => { @@ -233,7 +223,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('12: should render a simple class diagram with generic types', () => { @@ -249,7 +238,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('13: should render a simple class diagram with css classes applied', () => { @@ -267,7 +255,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('14: should render a simple class diagram with css classes applied directly', () => { @@ -283,7 +270,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('15: should render a simple class diagram with css classes applied to multiple classes', () => { @@ -298,7 +284,6 @@ describe('Class diagram', () => { `, {} ); - cy.get('svg'); }); it('16: should render multiple class diagrams', () => { @@ -351,7 +336,6 @@ describe('Class diagram', () => { ], {} ); - cy.get('svg'); }); // it('17: should render a class diagram when useMaxWidth is true (default)', () => { @@ -421,7 +405,6 @@ describe('Class diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render class diagram with newlines in title', () => { @@ -439,7 +422,6 @@ describe('Class diagram', () => { +quack() } `); - cy.get('svg'); }); it('should render class diagram with many newlines in title', () => { @@ -447,7 +429,7 @@ describe('Class diagram', () => { classDiagram class \`This\nTitle\nHas\nMany\nNewlines\` { +String Also - -Stirng Many + -String Many #int Members +And() -Many() @@ -461,7 +443,7 @@ describe('Class diagram', () => { classDiagram class \`This\nTitle\nHas\nMany\nNewlines\` { +String Also - -Stirng Many + -String Many #int Members +And() -Many() @@ -477,7 +459,7 @@ describe('Class diagram', () => { namespace testingNamespace { class \`This\nTitle\nHas\nMany\nNewlines\` { +String Also - -Stirng Many + -String Many #int Members +And() -Many() diff --git a/cypress/integration/rendering/erDiagram-unified.spec.js b/cypress/integration/rendering/erDiagram-unified.spec.js new file mode 100644 index 000000000..8cecba21d --- /dev/null +++ b/cypress/integration/rendering/erDiagram-unified.spec.js @@ -0,0 +1,652 @@ +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; + +const testOptions = [ + { description: '', options: { logLevel: 1 } }, + { description: 'ELK: ', options: { logLevel: 1, layout: 'elk' } }, + { description: 'HD: ', options: { logLevel: 1, look: 'handDrawn' } }, +]; + +describe('Entity Relationship Diagram Unified', () => { + testOptions.forEach(({ description, options }) => { + it(`${description}should render a simple ER diagram`, () => { + imgSnapshotTest( + ` + erDiagram + CUSTOMER ||--o{ ORDER : places + ORDER ||--|{ LINE-ITEM : contains + `, + options + ); + }); + + it(`${description}should render a simple ER diagram without htmlLabels`, () => { + imgSnapshotTest( + ` + erDiagram + CUSTOMER ||--o{ ORDER : places + ORDER ||--|{ LINE-ITEM : contains + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render an ER diagram with a recursive relationship`, () => { + imgSnapshotTest( + ` + erDiagram + CUSTOMER ||..o{ CUSTOMER : refers + CUSTOMER ||--o{ ORDER : places + ORDER ||--|{ LINE-ITEM : contains + `, + options + ); + }); + + it(`${description}should render an ER diagram with multiple relationships between the same two entities`, () => { + imgSnapshotTest( + ` + erDiagram + CUSTOMER ||--|{ ADDRESS : "invoiced at" + CUSTOMER ||--|{ ADDRESS : "receives goods at" + `, + options + ); + }); + + it(`${description}should render a cyclical ER diagram`, () => { + imgSnapshotTest( + ` + erDiagram + A ||--|{ B : likes + B ||--|{ C : likes + C ||--|{ A : likes + `, + options + ); + }); + + it(`${description}should render a not-so-simple ER diagram`, () => { + imgSnapshotTest( + ` + erDiagram + CUSTOMER }|..|{ DELIVERY-ADDRESS : has + CUSTOMER ||--o{ ORDER : places + CUSTOMER ||--o{ INVOICE : "liable for" + DELIVERY-ADDRESS ||--o{ ORDER : receives + INVOICE ||--|{ ORDER : covers + ORDER ||--|{ ORDER-ITEM : includes + PRODUCT-CATEGORY ||--|{ PRODUCT : contains + PRODUCT ||--o{ ORDER-ITEM : "ordered in" + `, + options + ); + }); + + it(`${description}should render a not-so-simple ER diagram without htmlLabels`, () => { + imgSnapshotTest( + ` + erDiagram + CUSTOMER }|..|{ DELIVERY-ADDRESS : has + CUSTOMER ||--o{ ORDER : places + CUSTOMER ||--o{ INVOICE : "liable for" + DELIVERY-ADDRESS ||--o{ ORDER : receives + INVOICE ||--|{ ORDER : covers + ORDER ||--|{ ORDER-ITEM : includes + PRODUCT-CATEGORY ||--|{ PRODUCT : contains + PRODUCT ||--o{ ORDER-ITEM : "ordered in" + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render multiple ER diagrams`, () => { + imgSnapshotTest( + [ + ` + erDiagram + CUSTOMER ||--o{ ORDER : places + ORDER ||--|{ LINE-ITEM : contains + `, + ` + erDiagram + CUSTOMER ||--o{ ORDER : places + ORDER ||--|{ LINE-ITEM : contains + `, + ], + options + ); + }); + + it(`${description}should render an ER diagram with blank or empty labels`, () => { + imgSnapshotTest( + ` + erDiagram + BOOK }|..|{ AUTHOR : "" + BOOK }|..|{ GENRE : " " + AUTHOR }|..|{ GENRE : " " + `, + options + ); + }); + + it(`${description}should render entities that have no relationships`, () => { + renderGraph( + ` + erDiagram + DEAD_PARROT + HERMIT + RECLUSE + SOCIALITE }o--o{ SOCIALITE : "interacts with" + RECLUSE }o--o{ SOCIALITE : avoids + `, + options + ); + }); + + it(`${description}should render entities with and without attributes`, () => { + renderGraph( + ` + erDiagram + BOOK { string title } + AUTHOR }|..|{ BOOK : writes + BOOK { float price } + `, + options + ); + }); + + it(`${description}should render entities with generic and array attributes`, () => { + renderGraph( + ` + erDiagram + BOOK { + string title + string[] authors + type~T~ type + } + `, + options + ); + }); + + it(`${description}should render entities with generic and array attributes without htmlLabels`, () => { + renderGraph( + ` + erDiagram + BOOK { + string title + string[] authors + type~T~ type + } + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render entities with length in attributes type`, () => { + renderGraph( + ` + erDiagram + CLUSTER { + varchar(99) name + string(255) description + } + `, + options + ); + }); + + it(`${description}should render entities with length in attributes type without htmlLabels`, () => { + renderGraph( + ` + erDiagram + CLUSTER { + varchar(99) name + string(255) description + } + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render entities and attributes with big and small entity names`, () => { + renderGraph( + ` + erDiagram + PRIVATE_FINANCIAL_INSTITUTION { + string name + int turnover + } + PRIVATE_FINANCIAL_INSTITUTION ||..|{ EMPLOYEE : employs + EMPLOYEE { bool officer_of_firm } + `, + options + ); + }); + + it(`${description}should render entities and attributes with big and small entity names without htmlLabels`, () => { + renderGraph( + ` + erDiagram + PRIVATE_FINANCIAL_INSTITUTION { + string name + int turnover + } + PRIVATE_FINANCIAL_INSTITUTION ||..|{ EMPLOYEE : employs + EMPLOYEE { bool officer_of_firm } + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render entities with attributes that begin with asterisk`, () => { + imgSnapshotTest( + ` + erDiagram + BOOK { + int *id + string name + varchar(99) summary + } + BOOK }o..o{ STORE : soldBy + STORE { + int *id + string name + varchar(50) address + } + `, + options + ); + }); + + it(`${description}should render entities with attributes that begin with asterisk without htmlLabels`, () => { + imgSnapshotTest( + ` + erDiagram + BOOK { + int *id + string name + varchar(99) summary + } + BOOK }o..o{ STORE : soldBy + STORE { + int *id + string name + varchar(50) address + } + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render entities with keys`, () => { + renderGraph( + ` + erDiagram + AUTHOR_WITH_LONG_ENTITY_NAME { + string name PK + } + AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes + BOOK { + float price + string author FK + string title PK + } + `, + options + ); + }); + + it(`${description}should render entities with keys without htmlLabels`, () => { + renderGraph( + ` + erDiagram + AUTHOR_WITH_LONG_ENTITY_NAME { + string name PK + } + AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes + BOOK { + float price + string author FK + string title PK + } + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render entities with comments`, () => { + renderGraph( + ` + erDiagram + AUTHOR_WITH_LONG_ENTITY_NAME { + string name "comment" + } + AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes + BOOK { + string author + string title "author comment" + float price "price comment" + } + `, + options + ); + }); + + it(`${description}should render entities with comments without htmlLabels`, () => { + renderGraph( + ` + erDiagram + AUTHOR_WITH_LONG_ENTITY_NAME { + string name "comment" + } + AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes + BOOK { + string author + string title "author comment" + float price "price comment" + } + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render entities with keys and comments`, () => { + renderGraph( + ` + erDiagram + AUTHOR_WITH_LONG_ENTITY_NAME { + string name PK "comment" + } + AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes + BOOK { + string description + float price "price comment" + string title PK "title comment" + string author FK + } + `, + options + ); + }); + + it(`${description}should render entities with keys and comments without htmlLabels`, () => { + renderGraph( + ` + erDiagram + AUTHOR_WITH_LONG_ENTITY_NAME { + string name PK "comment" + } + AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes + BOOK { + string description + float price "price comment" + string title PK "title comment" + string author FK + } + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render entities with aliases`, () => { + renderGraph( + ` + erDiagram + T1 one or zero to one or more T2 : test + T2 one or many optionally to zero or one T3 : test + T3 zero or more to zero or many T4 : test + T4 many(0) to many(1) T5 : test + T5 many optionally to one T6 : test + T6 only one optionally to only one T1 : test + T4 0+ to 1+ T6 : test + T1 1 to 1 T3 : test + `, + options + ); + }); + + it(`${description}should render a simple ER diagram with a title`, () => { + imgSnapshotTest( + `--- + title: simple ER diagram + --- + erDiagram + CUSTOMER ||--o{ ORDER : places + ORDER ||--|{ LINE-ITEM : contains + `, + options + ); + }); + + it(`${description}should render entities with entity name aliases`, () => { + imgSnapshotTest( + ` + erDiagram + p[Person] { + varchar(64) firstName + varchar(64) lastName + } + c["Customer Account"] { + varchar(128) email + } + p ||--o| c : has + `, + options + ); + }); + + it(`${description}should render relationship labels with line breaks`, () => { + imgSnapshotTest( + ` + erDiagram + p[Person] { + string firstName + string lastName + } + a["Customer Account"] { + string email + } + + b["Customer Account Secondary"] { + string email + } + + c["Customer Account Tertiary"] { + string email + } + + d["Customer Account Nth"] { + string email + } + + p ||--o| a : "has
one" + p ||--o| b : "has
one
two" + p ||--o| c : "has
one
two
three" + p ||--o| d : "has
one
two
three
...
Nth" + `, + options + ); + }); + + it(`${description}should render an ER diagram with unicode text`, () => { + imgSnapshotTest( + ` + erDiagram + _**testáēŊÎļâž•Ã˜đŸ˜€ãŒ•ãŧ**_ { + *__List~List~int~~sdfds__* **driversLicense** PK "***The l😀icense #***" + *string(99)~T~~~~~~* firstName "Only __99__
characters are a
llowed dsfsdfsdfsdfs" + string last*Name* + string __phone__ UK + int _age_ + } + `, + options + ); + }); + + it(`${description}should render an ER diagram with unicode text without htmlLabels`, () => { + imgSnapshotTest( + ` + erDiagram + _**testáēŊÎļâž•Ã˜đŸ˜€ãŒ•ãŧ**_ { + *__List~List~int~~sdfds__* **driversLicense** PK "***The l😀icense #***" + *string(99)~T~~~~~~* firstName "Only __99__
characters are a
llowed dsfsdfsdfsdfs" + string last*Name* + string __phone__ UK + int _age_ + } + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render an ER diagram with relationships with unicode text`, () => { + imgSnapshotTest( + ` + erDiagram + person[😀] { + string *first*Name + string _**last**Name_ + } + a["*Customer Account*"] { + **string** ema*i*l + } + person ||--o| a : __háēŊ😀__ + `, + options + ); + }); + + it(`${description}should render an ER diagram with relationships with unicode text without htmlLabels`, () => { + imgSnapshotTest( + ` + erDiagram + person[😀] { + string *first*Name + string _**last**Name_ + } + a["*Customer Account*"] { + **string** ema*i*l + } + person ||--o| a : __háēŊ😀__ + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render an ER diagram with TB direction`, () => { + imgSnapshotTest( + ` + erDiagram + direction TB + CAR ||--|{ NAMED-DRIVER : allows + PERSON ||..o{ NAMED-DRIVER : is + `, + options + ); + }); + + it(`${description}should render an ER diagram with BT direction`, () => { + imgSnapshotTest( + ` + erDiagram + direction BT + CAR ||--|{ NAMED-DRIVER : allows + PERSON ||..o{ NAMED-DRIVER : is + `, + options + ); + }); + + it(`${description}should render an ER diagram with LR direction`, () => { + imgSnapshotTest( + ` + erDiagram + direction LR + CAR ||--|{ NAMED-DRIVER : allows + PERSON ||..o{ NAMED-DRIVER : is + `, + options + ); + }); + + it(`${description}should render an ER diagram with RL direction`, () => { + imgSnapshotTest( + ` + erDiagram + direction RL + CAR ||--|{ NAMED-DRIVER : allows + PERSON ||..o{ NAMED-DRIVER : is + `, + options + ); + }); + + it(`${description}should render entities with styles applied from style statement`, () => { + imgSnapshotTest( + ` + erDiagram + c[CUSTOMER] + p[PERSON] + style c,p fill:#f9f,stroke:blue, color:grey, font-size:24px,font-weight:bold + `, + options + ); + }); + + it(`${description}should render entities with styles applied from style statement without htmlLabels`, () => { + imgSnapshotTest( + ` + erDiagram + c[CUSTOMER] + p[PERSON] + style c,p fill:#f9f,stroke:blue, color:grey, font-size:24px,font-weight:bold + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render entities with styles applied from class statement`, () => { + imgSnapshotTest( + ` + erDiagram + c[CUSTOMER] + p[PERSON]:::blue + classDef bold font-size:24px, font-weight: bold + classDef blue stroke:lightblue, color: #0000FF + class c,p bold + `, + options + ); + }); + + it(`${description}should render entities with styles applied from class statement without htmlLabels`, () => { + imgSnapshotTest( + ` + erDiagram + c[CUSTOMER] + p[PERSON]:::blue + classDef bold font-size:24px, font-weight: bold + classDef blue stroke:lightblue, color: #0000FF + class c,p bold + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render entities with styles applied from the default class and other styles`, () => { + imgSnapshotTest( + ` + erDiagram + c[CUSTOMER] + p[PERSON]:::blue + classDef blue stroke:lightblue, color: #0000FF + classDef default fill:pink + style c color:green + `, + { ...options } + ); + }); + }); +}); diff --git a/cypress/integration/rendering/erDiagram.spec.js b/cypress/integration/rendering/erDiagram.spec.js index 578f5a398..cbfec8218 100644 --- a/cypress/integration/rendering/erDiagram.spec.js +++ b/cypress/integration/rendering/erDiagram.spec.js @@ -109,8 +109,8 @@ describe('Entity Relationship Diagram', () => { const style = svg.attr('style'); expect(style).to.match(/^max-width: [\d.]+px;$/); const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); - // use within because the absolute value can be slightly different depending on the environment Âą5% - expect(maxWidthValue).to.be.within(140 * 0.95, 140 * 1.05); + // use within because the absolute value can be slightly different depending on the environment Âą6% + expect(maxWidthValue).to.be.within(140 * 0.96, 140 * 1.06); }); }); @@ -125,8 +125,8 @@ describe('Entity Relationship Diagram', () => { ); cy.get('svg').should((svg) => { const width = parseFloat(svg.attr('width')); - // use within because the absolute value can be slightly different depending on the environment Âą5% - expect(width).to.be.within(140 * 0.95, 140 * 1.05); + // use within because the absolute value can be slightly different depending on the environment Âą6% + expect(width).to.be.within(140 * 0.96, 140 * 1.06); // expect(svg).to.have.attr('height', '465'); expect(svg).to.not.have.attr('style'); }); @@ -218,7 +218,6 @@ describe('Entity Relationship Diagram', () => { `, { loglevel: 1 } ); - cy.get('svg'); }); it('should render entities with keys', () => { @@ -322,4 +321,37 @@ ORDER ||--|{ LINE-ITEM : contains { logLevel: 1 } ); }); + + it('should render relationship labels with line breaks', () => { + imgSnapshotTest( + ` + erDiagram + p[Person] { + string firstName + string lastName + } + a["Customer Account"] { + string email + } + + b["Customer Account Secondary"] { + string email + } + + c["Customer Account Tertiary"] { + string email + } + + d["Customer Account Nth"] { + string email + } + + p ||--o| a : "has
one" + p ||--o| b : "has
one
two" + p ||--o| c : "has
one
two
three" + p ||--o| d : "has
one
two
three
...
Nth" + `, + { logLevel: 1 } + ); + }); }); diff --git a/cypress/integration/rendering/errorDiagram.spec.js b/cypress/integration/rendering/errorDiagram.spec.js index e837565d3..9eeb2e310 100644 --- a/cypress/integration/rendering/errorDiagram.spec.js +++ b/cypress/integration/rendering/errorDiagram.spec.js @@ -3,7 +3,7 @@ import { imgSnapshotTest } from '../../helpers/util'; describe('Error Diagrams', () => { beforeEach(() => { cy.on('uncaught:exception', (err) => { - expect(err.message).to.include('Parse error'); + expect(err.message).to.include('error'); // return false to prevent the error from // failing this test return false; diff --git a/cypress/integration/rendering/flowchart-elk.spec.js b/cypress/integration/rendering/flowchart-elk.spec.js index e931025e9..27af2c40c 100644 --- a/cypress/integration/rendering/flowchart-elk.spec.js +++ b/cypress/integration/rendering/flowchart-elk.spec.js @@ -1,6 +1,6 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; +import { imgSnapshotTest, renderGraph, verifyNumber } from '../../helpers/util.ts'; -describe.skip('Flowchart ELK', () => { +describe('Flowchart ELK', () => { it('1-elk: should render a simple flowchart', () => { imgSnapshotTest( `flowchart-elk TD @@ -109,7 +109,7 @@ describe.skip('Flowchart ELK', () => { const style = svg.attr('style'); expect(style).to.match(/^max-width: [\d.]+px;$/); const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); - expect(maxWidthValue).to.be.within(230 * 0.95, 230 * 1.05); + verifyNumber(maxWidthValue, 380); }); }); it('8-elk: should render a flowchart when useMaxWidth is false', () => { @@ -128,7 +128,7 @@ describe.skip('Flowchart ELK', () => { const width = parseFloat(svg.attr('width')); // use within because the absolute value can be slightly different depending on the environment Âą5% // expect(height).to.be.within(446 * 0.95, 446 * 1.05); - expect(width).to.be.within(230 * 0.95, 230 * 1.05); + verifyNumber(width, 380); expect(svg).to.not.have.attr('style'); }); }); @@ -208,13 +208,13 @@ describe.skip('Flowchart ELK', () => { `flowchart-elk TB internet nat - routeur + router lb1 lb2 compute1 compute2 subgraph project - routeur + router nat subgraph subnet1 compute1 @@ -225,8 +225,8 @@ describe.skip('Flowchart ELK', () => { lb2 end end - internet --> routeur - routeur --> subnet1 & subnet2 + internet --> router + router --> subnet1 & subnet2 subnet1 & subnet2 --> nat --> internet `, { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } @@ -443,7 +443,7 @@ flowchart-elk TD { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } ); }); - it('63-elk: title on subgraphs should be themable', () => { + it('63-elk: title on subgraphs should be themeable', () => { imgSnapshotTest( ` %%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%% @@ -692,7 +692,7 @@ A --> B {} ); cy.get('svg').should((svg) => { - const edges = svg.querySelectorAll('.edges > path'); + const edges = svg[0].querySelectorAll('.edges > path'); edges.forEach((edge) => { expect(edge).to.have.class('flowchart-link'); }); @@ -739,7 +739,7 @@ NL\`") --"\`1o **bold**\`"--> c { flowchart: { titleTopMargin: 0 } } ); }); - it('Wrapping long text with a new line', () => { + it.skip('Wrapping long text with a new line', () => { imgSnapshotTest( `%%{init: {"flowchart": {"htmlLabels": true}} }%% flowchart-elk LR @@ -837,6 +837,216 @@ subgraph "\`**Two**\`" in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog") end +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('Sub graphs', () => { + imgSnapshotTest( + `--- +config: + layout: elk +--- + +flowchart LR + subgraph subgraph_ko6czgs5u["Untitled subgraph"] + D["Option 1"] + end + C{"Evaluate"} -- One --> D + C -- Two --> E(("Option 2")) + D --> E + A["A"] + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('6080: should handle diamond shape intersections', () => { + imgSnapshotTest( + `--- +config: + layout: elk +--- +flowchart LR + subgraph s1["Untitled subgraph"] + n1["Evaluate"] + n2["Option 1"] + n3["Option 2"] + n4["fa:fa-car Option 3"] + end + subgraph s2["Untitled subgraph"] + n5["Evaluate"] + n6["Option 1"] + n7["Option 2"] + n8["fa:fa-car Option 3"] + end + A["Start"] -- Some text --> B("Continue") + B --> C{"Evaluate"} + C -- One --> D["Option 1"] + C -- Two --> E["Option 2"] + C -- Three --> F["fa:fa-car Option 3"] + n1 -- One --> n2 + n1 -- Two --> n3 + n1 -- Three --> n4 + n5 -- One --> n6 + n5 -- Two --> n7 + n5 -- Three --> n8 + n1@{ shape: diam} + n2@{ shape: rect} + n3@{ shape: rect} + n4@{ shape: rect} + n5@{ shape: diam} + n6@{ shape: rect} + n7@{ shape: rect} + n8@{ shape: rect} + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + + it('6088-1: should handle diamond shape intersections', () => { + imgSnapshotTest( + `--- +config: + layout: elk +--- + flowchart LR + subgraph S2 + subgraph s1["APA"] + D{"Use the editor"} + end + + + D -- Mermaid js --> I{"fa:fa-code Text"} + D --> I + D --> I + + end +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + + it('6088-2: should handle diamond shape intersections', () => { + imgSnapshotTest( + `--- +config: + layout: elk +--- + flowchart LR + a + subgraph s0["APA"] + subgraph s8["APA"] + subgraph s1["APA"] + D{"X"} + E[Q] + end + subgraph s3["BAPA"] + F[Q] + I + end + D --> I + D --> I + D --> I + + I{"X"} + end + end + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + + it('6088-3: should handle diamond shape intersections', () => { + imgSnapshotTest( + `--- +config: + layout: elk +--- + flowchart LR + a + D{"Use the editor"} + + D -- Mermaid js --> I{"fa:fa-code Text"} + D-->I + D-->I + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + + it('6088-4: should handle diamond shape intersections', () => { + imgSnapshotTest( + `--- +config: + layout: elk +--- +flowchart LR + subgraph s1["Untitled subgraph"] + n1["Evaluate"] + n2["Option 1"] + n3["Option 2"] + n4["fa:fa-car Option 3"] + end + subgraph s2["Untitled subgraph"] + n5["Evaluate"] + n6["Option 1"] + n7["Option 2"] + n8["fa:fa-car Option 3"] + end + A["Start"] -- Some text --> B("Continue") + B --> C{"Evaluate"} + C -- One --> D["Option 1"] + C -- Two --> E["Option 2"] + C -- Three --> F["fa:fa-car Option 3"] + n1 -- One --> n2 + n1 -- Two --> n3 + n1 -- Three --> n4 + n5 -- One --> n6 + n5 -- Two --> n7 + n5 -- Three --> n8 + n1@{ shape: diam} + n2@{ shape: rect} + n3@{ shape: rect} + n4@{ shape: rect} + n5@{ shape: diam} + n6@{ shape: rect} + n7@{ shape: rect} + n8@{ shape: rect} + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + + it('6088-5: should handle diamond shape intersections', () => { + imgSnapshotTest( + `--- +config: + layout: elk +--- +flowchart LR + A{A} --> B & C + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('6088-6: should handle diamond shape intersections', () => { + imgSnapshotTest( + `--- +config: + layout: elk +--- +flowchart LR + A{A} --> B & C + subgraph "subbe" + A + end + `, { flowchart: { titleTopMargin: 0 } } ); @@ -855,7 +1065,7 @@ describe('Title and arrow styling #4813', () => { flowchart LR A-->B A-->C`, - { flowchart: { defaultRenderer: 'elk' } } + { layout: 'elk' } ); cy.get('svg').should((svg) => { const title = svg[0].querySelector('text'); @@ -871,15 +1081,14 @@ describe('Title and arrow styling #4813', () => { B-.-oC C==xD D ~~~ A`, - { flowchart: { defaultRenderer: 'elk' } } + { layout: 'elk' } ); cy.get('svg').should((svg) => { const edges = svg[0].querySelectorAll('.edges path'); - console.log(edges); - expect(edges[0]).to.have.attr('pattern', 'solid'); - expect(edges[1]).to.have.attr('pattern', 'dotted'); - expect(edges[2]).to.have.css('stroke-width', '3.5px'); - expect(edges[3]).to.have.css('stroke-width', '1.5px'); + expect(edges[0].getAttribute('class')).to.contain('edge-pattern-solid'); + expect(edges[1].getAttribute('class')).to.contain('edge-pattern-dotted'); + expect(edges[2].getAttribute('class')).to.contain('edge-thickness-thick'); + expect(edges[3].getAttribute('class')).to.contain('edge-thickness-invisible'); }); }); }); diff --git a/cypress/integration/rendering/flowchart-handDrawn.spec.js b/cypress/integration/rendering/flowchart-handDrawn.spec.js new file mode 100644 index 000000000..49c55c628 --- /dev/null +++ b/cypress/integration/rendering/flowchart-handDrawn.spec.js @@ -0,0 +1,1032 @@ +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; + +describe('Flowchart HandDrawn', () => { + it('FHD1: should render a simple flowchart no htmlLabels', () => { + imgSnapshotTest( + `graph TD + A[Christmas] -->|Get money| B(Go shopping) + B --> C{Let me think} + C -->|One| D[Laptop] + C -->|Two| E[iPhone] + C -->|Three| F[fa:fa-car Car] + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FHD2: should render a simple flowchart with htmlLabels', () => { + imgSnapshotTest( + `graph TD + A[Christmas] -->|Get money| B(Go shopping) + B --> C{Let me think} + C -->|One| D[Laptop] + C -->|Two| E[iPhone] + C -->|Three| F[fa:fa-car Car] + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: true }, + fontFamily: 'courier', + } + ); + }); + + it('FHD3: should render a simple flowchart with line breaks', () => { + imgSnapshotTest( + ` + graph TD + A[Christmas] -->|Get money| B(Go shopping) + B --> C{Let me thinksssss
ssssssssssssssssssssss
sssssssssssssssssssssssssss} + C -->|One| D[Laptop] + C -->|Two| E[iPhone] + C -->|Three| F[Car] + `, + { look: 'handDrawn', fontFamily: 'courier' } + ); + }); + + it('FHD4: should render a simple flowchart with trapezoid and inverse trapezoid vertex options.', () => { + imgSnapshotTest( + ` + graph TD + A[/Christmas\\] + A -->|Get money| B[\\Go shopping/] + B --> C{Let me thinksssss
ssssssssssssssssssssss
sssssssssssssssssssssssssss} + C -->|One| D[/Laptop/] + C -->|Two| E[\\iPhone\\] + C -->|Three| F[Car] + `, + { look: 'handDrawn', fontFamily: 'courier' } + ); + }); + + it('FHD5: should style nodes via a class.', () => { + imgSnapshotTest( + ` + graph TD + 1A --> 1B + 1B --> 1C + 1C --> D + 1C --> E + + classDef processHead fill:#888888,color:white,font-weight:bold,stroke-width:3px,stroke:#001f3f + class 1A,1B,D,E processHead + `, + { look: 'handDrawn', fontFamily: 'courier' } + ); + }); + + it('FHD6: should render a flowchart full of circles', () => { + imgSnapshotTest( + ` + graph LR + 47(SAM.CommonFA.FMESummary)-->48(SAM.CommonFA.CommonFAFinanceBudget) + 37(SAM.CommonFA.BudgetSubserviceLineVolume)-->48(SAM.CommonFA.CommonFAFinanceBudget) + 35(SAM.CommonFA.PopulationFME)-->47(SAM.CommonFA.FMESummary) + 41(SAM.CommonFA.MetricCost)-->47(SAM.CommonFA.FMESummary) + 44(SAM.CommonFA.MetricOutliers)-->47(SAM.CommonFA.FMESummary) + 46(SAM.CommonFA.MetricOpportunity)-->47(SAM.CommonFA.FMESummary) + 40(SAM.CommonFA.OPVisits)-->47(SAM.CommonFA.FMESummary) + 38(SAM.CommonFA.CommonFAFinanceRefund)-->47(SAM.CommonFA.FMESummary) + 43(SAM.CommonFA.CommonFAFinancePicuDays)-->47(SAM.CommonFA.FMESummary) + 42(SAM.CommonFA.CommonFAFinanceNurseryDays)-->47(SAM.CommonFA.FMESummary) + 45(SAM.CommonFA.MetricPreOpportunity)-->46(SAM.CommonFA.MetricOpportunity) + 35(SAM.CommonFA.PopulationFME)-->45(SAM.CommonFA.MetricPreOpportunity) + 41(SAM.CommonFA.MetricCost)-->45(SAM.CommonFA.MetricPreOpportunity) + 41(SAM.CommonFA.MetricCost)-->44(SAM.CommonFA.MetricOutliers) + 39(SAM.CommonFA.ChargeDetails)-->43(SAM.CommonFA.CommonFAFinancePicuDays) + 39(SAM.CommonFA.ChargeDetails)-->42(SAM.CommonFA.CommonFAFinanceNurseryDays) + 39(SAM.CommonFA.ChargeDetails)-->41(SAM.CommonFA.MetricCost) + 39(SAM.CommonFA.ChargeDetails)-->40(SAM.CommonFA.OPVisits) + 35(SAM.CommonFA.PopulationFME)-->39(SAM.CommonFA.ChargeDetails) + 36(SAM.CommonFA.PremetricCost)-->39(SAM.CommonFA.ChargeDetails) + `, + { look: 'handDrawn', fontFamily: 'courier' } + ); + }); + + it('FHD7: should render a flowchart full of icons', () => { + imgSnapshotTest( + ` + graph TD + 9e122290_1ec3_e711_8c5a_005056ad0002("fa:fa-creative-commons My System | Test Environment") + 82072290_1ec3_e711_8c5a_005056ad0002("fa:fa-cogs Shared Business Logic Server:Service 1") + db052290_1ec3_e711_8c5a_005056ad0002("fa:fa-cogs Shared Business Logic Server:Service 2") + 4e112290_1ec3_e711_8c5a_005056ad0002("fa:fa-cogs Shared Report Server:Service 1") + 30122290_1ec3_e711_8c5a_005056ad0002("fa:fa-cogs Shared Report Server:Service 2") + 5e112290_1ec3_e711_8c5a_005056ad0002("fa:fa-cogs Dedicated Test Business Logic Server:Service 1") + c1112290_1ec3_e711_8c5a_005056ad0002("fa:fa-cogs Dedicated Test Business Logic Server:Service 2") + b7042290_1ec3_e711_8c5a_005056ad0002("fa:fa-circle [DBServer\\SharedDbInstance].[SupportDb]") + 8f102290_1ec3_e711_8c5a_005056ad0002("fa:fa-circle [DBServer\\SharedDbInstance].[DevelopmentDb]") + 0e102290_1ec3_e711_8c5a_005056ad0002("fa:fa-circle [DBServer\\SharedDbInstance].[TestDb]") + 07132290_1ec3_e711_8c5a_005056ad0002("fa:fa-circle [DBServer\\SharedDbInstance].[SharedReportingDb]") + c7072290_1ec3_e711_8c5a_005056ad0002("fa:fa-server Shared Business Logic Server") + ca122290_1ec3_e711_8c5a_005056ad0002("fa:fa-server Shared Report Server") + 68102290_1ec3_e711_8c5a_005056ad0002("fa:fa-server Dedicated Test Business Logic Server") + f4112290_1ec3_e711_8c5a_005056ad0002("fa:fa-database [DBServer\\SharedDbInstance]") + d6072290_1ec3_e711_8c5a_005056ad0002("fa:fa-server DBServer") + 71082290_1ec3_e711_8c5a_005056ad0002("fa:fa-cogs DBServer\\:MSSQLSERVER") + c0102290_1ec3_e711_8c5a_005056ad0002("fa:fa-cogs DBServer\\:SQLAgent") + 9a072290_1ec3_e711_8c5a_005056ad0002("fa:fa-cogs DBServer\\:SQLBrowser") + 1d0a2290_1ec3_e711_8c5a_005056ad0002("fa:fa-server VmHost1") + 200a2290_1ec3_e711_8c5a_005056ad0002("fa:fa-server VmHost2") + 1c0a2290_1ec3_e711_8c5a_005056ad0002("fa:fa-server VmHost3") + 9e122290_1ec3_e711_8c5a_005056ad0002-->82072290_1ec3_e711_8c5a_005056ad0002 + 9e122290_1ec3_e711_8c5a_005056ad0002-->db052290_1ec3_e711_8c5a_005056ad0002 + 9e122290_1ec3_e711_8c5a_005056ad0002-->4e112290_1ec3_e711_8c5a_005056ad0002 + 9e122290_1ec3_e711_8c5a_005056ad0002-->30122290_1ec3_e711_8c5a_005056ad0002 + 9e122290_1ec3_e711_8c5a_005056ad0002-->5e112290_1ec3_e711_8c5a_005056ad0002 + 9e122290_1ec3_e711_8c5a_005056ad0002-->c1112290_1ec3_e711_8c5a_005056ad0002 + 82072290_1ec3_e711_8c5a_005056ad0002-->b7042290_1ec3_e711_8c5a_005056ad0002 + 82072290_1ec3_e711_8c5a_005056ad0002-->8f102290_1ec3_e711_8c5a_005056ad0002 + 82072290_1ec3_e711_8c5a_005056ad0002-->0e102290_1ec3_e711_8c5a_005056ad0002 + 82072290_1ec3_e711_8c5a_005056ad0002-->c7072290_1ec3_e711_8c5a_005056ad0002 + db052290_1ec3_e711_8c5a_005056ad0002-->c7072290_1ec3_e711_8c5a_005056ad0002 + db052290_1ec3_e711_8c5a_005056ad0002-->82072290_1ec3_e711_8c5a_005056ad0002 + 4e112290_1ec3_e711_8c5a_005056ad0002-->b7042290_1ec3_e711_8c5a_005056ad0002 + 4e112290_1ec3_e711_8c5a_005056ad0002-->8f102290_1ec3_e711_8c5a_005056ad0002 + 4e112290_1ec3_e711_8c5a_005056ad0002-->0e102290_1ec3_e711_8c5a_005056ad0002 + 4e112290_1ec3_e711_8c5a_005056ad0002-->07132290_1ec3_e711_8c5a_005056ad0002 + 4e112290_1ec3_e711_8c5a_005056ad0002-->ca122290_1ec3_e711_8c5a_005056ad0002 + 30122290_1ec3_e711_8c5a_005056ad0002-->ca122290_1ec3_e711_8c5a_005056ad0002 + 30122290_1ec3_e711_8c5a_005056ad0002-->4e112290_1ec3_e711_8c5a_005056ad0002 + 5e112290_1ec3_e711_8c5a_005056ad0002-->8f102290_1ec3_e711_8c5a_005056ad0002 + 5e112290_1ec3_e711_8c5a_005056ad0002-->68102290_1ec3_e711_8c5a_005056ad0002 + c1112290_1ec3_e711_8c5a_005056ad0002-->68102290_1ec3_e711_8c5a_005056ad0002 + c1112290_1ec3_e711_8c5a_005056ad0002-->5e112290_1ec3_e711_8c5a_005056ad0002 + b7042290_1ec3_e711_8c5a_005056ad0002-->f4112290_1ec3_e711_8c5a_005056ad0002 + 8f102290_1ec3_e711_8c5a_005056ad0002-->f4112290_1ec3_e711_8c5a_005056ad0002 + 0e102290_1ec3_e711_8c5a_005056ad0002-->f4112290_1ec3_e711_8c5a_005056ad0002 + 07132290_1ec3_e711_8c5a_005056ad0002-->f4112290_1ec3_e711_8c5a_005056ad0002 + c7072290_1ec3_e711_8c5a_005056ad0002-->1d0a2290_1ec3_e711_8c5a_005056ad0002 + ca122290_1ec3_e711_8c5a_005056ad0002-->200a2290_1ec3_e711_8c5a_005056ad0002 + 68102290_1ec3_e711_8c5a_005056ad0002-->1c0a2290_1ec3_e711_8c5a_005056ad0002 + f4112290_1ec3_e711_8c5a_005056ad0002-->d6072290_1ec3_e711_8c5a_005056ad0002 + f4112290_1ec3_e711_8c5a_005056ad0002-->71082290_1ec3_e711_8c5a_005056ad0002 + f4112290_1ec3_e711_8c5a_005056ad0002-->c0102290_1ec3_e711_8c5a_005056ad0002 + f4112290_1ec3_e711_8c5a_005056ad0002-->9a072290_1ec3_e711_8c5a_005056ad0002 + d6072290_1ec3_e711_8c5a_005056ad0002-->1c0a2290_1ec3_e711_8c5a_005056ad0002 + 71082290_1ec3_e711_8c5a_005056ad0002-->d6072290_1ec3_e711_8c5a_005056ad0002 + c0102290_1ec3_e711_8c5a_005056ad0002-->d6072290_1ec3_e711_8c5a_005056ad0002 + c0102290_1ec3_e711_8c5a_005056ad0002-->71082290_1ec3_e711_8c5a_005056ad0002 + 9a072290_1ec3_e711_8c5a_005056ad0002-->d6072290_1ec3_e711_8c5a_005056ad0002 + 9a072290_1ec3_e711_8c5a_005056ad0002-->71082290_1ec3_e711_8c5a_005056ad0002 + `, + { look: 'handDrawn', fontFamily: 'courier' } + ); + }); + + it('FHD8: should render labels with numbers at the start', () => { + imgSnapshotTest( + ` + graph TB;subgraph "number as labels";1;end; + `, + { look: 'handDrawn', fontFamily: 'courier' } + ); + }); + + it('FHD9: should render subgraphs', () => { + imgSnapshotTest( + ` + graph TB + subgraph One + a1-->a2 + end + `, + { look: 'handDrawn', fontFamily: 'courier' } + ); + }); + + it('FHD10: should render subgraphs with a title starting with a digit', () => { + imgSnapshotTest( + ` + graph TB + subgraph 2Two + a1-->a2 + end + `, + { look: 'handDrawn', fontFamily: 'courier' } + ); + }); + + it('FHD11: should render styled subgraphs', () => { + imgSnapshotTest( + ` + graph TB + A + B + subgraph foo[Foo SubGraph] + C + D + end + subgraph bar[Bar SubGraph] + E + F + end + G + + A-->B + B-->C + C-->D + B-->D + D-->E + E-->A + E-->F + F-->D + F-->G + B-->G + G-->D + + style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred + style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue + `, + { look: 'handDrawn', fontFamily: 'courier' } + ); + }); + + it('FHD12: should render a flowchart with long names and class definitions', () => { + imgSnapshotTest( + `graph LR + sid-B3655226-6C29-4D00-B685-3D5C734DC7E1[" + + 提äē¤į”ŗč¯ˇ + į†Šå¤§ + "]; + class sid-B3655226-6C29-4D00-B685-3D5C734DC7E1 node-executed; + sid-4DA958A0-26D9-4D47-93A7-70F39FD7D51A[" + 负贪äēēåŽĄæ‰š + åŧē子 + "]; + class sid-4DA958A0-26D9-4D47-93A7-70F39FD7D51A node-executed; + sid-E27C0367-E6D6-497F-9736-3CDC21FDE221[" + DBAåŽĄæ‰š + åŧē子 + "]; + class sid-E27C0367-E6D6-497F-9736-3CDC21FDE221 node-executed; + sid-BED98281-9585-4D1B-934E-BD1AC6AC0EFD[" + SAåŽĄæ‰š + é˜ŋįžŽ + "]; + class sid-BED98281-9585-4D1B-934E-BD1AC6AC0EFD node-executed; + sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7[" + ä¸ģįŽĄåŽĄæ‰š + 光头åŧē + "]; + class sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7 node-executed; + sid-A1B3CD96-7697-4D7C-BEAA-73D187B1BE89[" + DBAįĄŽčŽ¤ + åŧē子 + "]; + class sid-A1B3CD96-7697-4D7C-BEAA-73D187B1BE89 node-executed; + sid-3E35A7FF-A2F4-4E07-9247-DBF884C81937[" + SAįĄŽčŽ¤ + é˜ŋįžŽ + "]; + class sid-3E35A7FF-A2F4-4E07-9247-DBF884C81937 node-executed; + sid-4FC27B48-A6F9-460A-A675-021F5854FE22[" + į쓿Ÿ + "]; + class sid-4FC27B48-A6F9-460A-A675-021F5854FE22 node-executed; + sid-19DD9E9F-98C1-44EE-B604-842AFEE76F1E[" + SAæ‰§čĄŒ1 + åŧē子 + "]; + class sid-19DD9E9F-98C1-44EE-B604-842AFEE76F1E node-executed; + sid-6C2120F3-D940-4958-A067-0903DCE879C4[" + SAæ‰§čĄŒ2 + åŧē子 + "]; + class sid-6C2120F3-D940-4958-A067-0903DCE879C4 node-executed; + sid-9180E2A0-5C4B-435F-B42F-0D152470A338[" + DBAæ‰§čĄŒ1 + åŧē子 + "]; + class sid-9180E2A0-5C4B-435F-B42F-0D152470A338 node-executed; + sid-03A2C3AC-5337-48A5-B154-BB3FD0EC8DAD[" + DBAæ‰§čĄŒ3 + åŧē子 + "]; + class sid-03A2C3AC-5337-48A5-B154-BB3FD0EC8DAD node-executed; + sid-D5E1F2F4-306C-47A2-BF74-F66E3D769756[" + DBAæ‰§čĄŒ2 + åŧē子 + "]; + class sid-D5E1F2F4-306C-47A2-BF74-F66E3D769756 node-executed; + sid-8C3F2F1D-F014-4F99-B966-095DC1A2BD93[" + DBAæ‰§čĄŒ4 + åŧē子 + "]; + class sid-8C3F2F1D-F014-4F99-B966-095DC1A2BD93 node-executed; + sid-1897B30A-9C5C-4D5B-B80B-76A038785070[" + 负贪äēēįĄŽčŽ¤ + æĸé™čŒš + "]; + class sid-1897B30A-9C5C-4D5B-B80B-76A038785070 node-executed; + sid-B3655226-6C29-4D00-B685-3D5C734DC7E1-->sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7; + sid-4DA958A0-26D9-4D47-93A7-70F39FD7D51A-->sid-1897B30A-9C5C-4D5B-B80B-76A038785070; + sid-E27C0367-E6D6-497F-9736-3CDC21FDE221-->sid-A1B3CD96-7697-4D7C-BEAA-73D187B1BE89; + sid-BED98281-9585-4D1B-934E-BD1AC6AC0EFD-->sid-3E35A7FF-A2F4-4E07-9247-DBF884C81937; + sid-19DD9E9F-98C1-44EE-B604-842AFEE76F1E-->sid-6C2120F3-D940-4958-A067-0903DCE879C4; + sid-9180E2A0-5C4B-435F-B42F-0D152470A338-->sid-D5E1F2F4-306C-47A2-BF74-F66E3D769756; + sid-03A2C3AC-5337-48A5-B154-BB3FD0EC8DAD-->sid-8C3F2F1D-F014-4F99-B966-095DC1A2BD93; + sid-6C2120F3-D940-4958-A067-0903DCE879C4-->sid-4DA958A0-26D9-4D47-93A7-70F39FD7D51A; + sid-1897B30A-9C5C-4D5B-B80B-76A038785070-->sid-4FC27B48-A6F9-460A-A675-021F5854FE22; + sid-3E35A7FF-A2F4-4E07-9247-DBF884C81937-->sid-19DD9E9F-98C1-44EE-B604-842AFEE76F1E; + sid-A1B3CD96-7697-4D7C-BEAA-73D187B1BE89-->sid-9180E2A0-5C4B-435F-B42F-0D152470A338; + sid-A1B3CD96-7697-4D7C-BEAA-73D187B1BE89-->sid-03A2C3AC-5337-48A5-B154-BB3FD0EC8DAD; + sid-D5E1F2F4-306C-47A2-BF74-F66E3D769756-->sid-4DA958A0-26D9-4D47-93A7-70F39FD7D51A; + sid-8C3F2F1D-F014-4F99-B966-095DC1A2BD93-->sid-4DA958A0-26D9-4D47-93A7-70F39FD7D51A; + sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-BED98281-9585-4D1B-934E-BD1AC6AC0EFD; + sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-E27C0367-E6D6-497F-9736-3CDC21FDE221; + sid-3E35A7FF-A2F4-4E07-9247-DBF884C81937-->sid-6C2120F3-D940-4958-A067-0903DCE879C4; + sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4DA958A0-26D9-4D47-93A7-70F39FD7D51A; + sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4FC27B48-A6F9-460A-A675-021F5854FE22; + `, + { look: 'handDrawn', fontFamily: 'courier' } + ); + }); + + it('FHD13: should render color of styled nodes', () => { + imgSnapshotTest( + ` + graph LR + foo-->bar + + classDef foo fill:lightblue,color:green,stroke:#FF9E2C,font-weight:bold + style foo fill:#F99,stroke-width:2px,stroke:#F0F + style bar fill:#999,color: #00ff00, stroke-width:10px,stroke:#0F0 + `, + { + look: 'handDrawn', + listUrl: false, + listId: 'color styling', + fontFamily: 'courier', + logLevel: 0, + } + ); + }); + + it('FHD14: should render hexagons', () => { + imgSnapshotTest( + ` + graph TD + A[Christmas] -->|Get money| B(Go shopping) + B --> C{{Let me think...
Do I want something for work,
something to spend every free second with,
or something to get around?}} + C -->|One| D[Laptop] + C -->|Two| E[iPhone] + C -->|Three| F[Car] + click A "index.html#link-clicked" "link test" + click B testClick "click test" + classDef someclass fill:#f96; + class A someclass; + class C someclass; + `, + { + look: 'handDrawn', + listUrl: false, + listId: 'color styling', + fontFamily: 'courier', + logLevel: 0, + } + ); + }); + + it('FHD15: should render a simple flowchart with comments', () => { + imgSnapshotTest( + `graph TD + A[Christmas] -->|Get money| B(Go shopping) + B --> C{Let me think} + %% this is a comment + C -->|One| D[Laptop] + C -->|Two| E[iPhone] + C -->|Three| F[fa:fa-car Car] + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FHD16: Render Stadium shape', () => { + imgSnapshotTest( + ` graph TD + A([stadium shape test]) + A -->|Get money| B([Go shopping]) + B --> C([Let me think...
Do I want something for work,
something to spend every free second with,
or something to get around?]) + C -->|One| D([Laptop]) + C -->|Two| E([iPhone]) + C -->|Three| F([Car
wroom wroom]) + click A "index.html#link-clicked" "link test" + click B testClick "click test" + classDef someclass fill:#f96; + class A someclass; + class C someclass; + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FHD17: Render multiline texts', () => { + imgSnapshotTest( + `graph LR + A1[Multi
Line] -->|Multi
Line| B1(Multi
Line) + C1[Multi
Line] -->|Multi
Line| D1(Multi
Line) + E1[Multi
Line] -->|Multi
Line| F1(Multi
Line) + A2[Multi
Line] -->|Multi
Line| B2(Multi
Line) + C2[Multi
Line] -->|Multi
Line| D2(Multi
Line) + E2[Multi
Line] -->|Multi
Line| F2(Multi
Line) + linkStyle 0 stroke:DarkGray,stroke-width:2px + linkStyle 1 stroke:DarkGray,stroke-width:2px + linkStyle 2 stroke:DarkGray,stroke-width:2px + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FHD18: Chaining of nodes', () => { + imgSnapshotTest( + `graph LR + a --> b --> c + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FHD19: Multiple nodes and chaining in one statement', () => { + imgSnapshotTest( + `graph LR + a --> b & c--> d + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FHD20: Multiple nodes and chaining in one statement', () => { + imgSnapshotTest( + `graph TD + A[ h ] -- hello --> B[" test "]:::exClass & C --> D; + classDef exClass background:#bbb,border:1px solid red; + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FDH21: Render cylindrical shape', () => { + imgSnapshotTest( + `graph LR + A[(cylindrical
shape
test)] + A -->|Get money| B1[(Go shopping 1)] + A -->|Get money| B2[(Go shopping 2)] + A -->|Get money| B3[(Go shopping 3)] + C[(Let me think...
Do I want something for work,
something to spend every free second with,
or something to get around?)] + B1 --> C + B2 --> C + B3 --> C + C -->|One| D[(Laptop)] + C -->|Two| E[(iPhone)] + C -->|Three| F[(Car)] + click A "index.html#link-clicked" "link test" + click B testClick "click test" + classDef someclass fill:#f96; + class A someclass;`, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FDH22: Render a simple flowchart with nodeSpacing set to 100', () => { + imgSnapshotTest( + `graph TD + A[Christmas] -->|Get money| B(Go shopping) + B --> C{Let me think} + %% this is a comment + C -->|One| D[Laptop] + C -->|Two| E[iPhone] + C -->|Three| F[fa:fa-car Car] + `, + { look: 'handDrawn', flowchart: { nodeSpacing: 50 }, fontFamily: 'courier' } + ); + }); + + it('FDH23: Render a simple flowchart with rankSpacing set to 100', () => { + imgSnapshotTest( + `graph TD + A[Christmas] -->|Get money| B(Go shopping) + B --> C{Let me think} + %% this is a comment + C -->|One| D[Laptop] + C -->|Two| E[iPhone] + C -->|Three| F[fa:fa-car Car] + `, + { + look: 'handDrawn', + flowchart: { rankSpacing: '100' }, + fontFamily: 'courier', + } + ); + }); + + it('FDH24: Keep node label text (if already defined) when a style is applied', () => { + imgSnapshotTest( + `graph LR + A(( )) -->|step 1| B(( )) + B(( )) -->|step 2| C(( )) + C(( )) -->|step 3| D(( )) + linkStyle 1 stroke:greenyellow,stroke-width:2px + style C fill:greenyellow,stroke:green,stroke-width:4px + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FDH25: Handle link click events (link, anchor, mailto, other protocol, script)', () => { + imgSnapshotTest( + `graph TB + TITLE["Link Click Events
(click the nodes below)"] + A["link test (open in same tab)"] + B["link test (open in new tab)"] + C[anchor test] + D[mailto test] + E[other protocol test] + F[script test] + TITLE --> A & B & C & D & E & F + click A "https://mermaid-js.github.io/mermaid/#/" "link test (open in same tab)" + click B "https://mermaid-js.github.io/mermaid/#/" "link test (open in new tab)" _blank + click C "#link-clicked" + click D "mailto:user@user.user" "mailto test" + click E "notes://do-your-thing/id" "other protocol test" + click F "javascript:alert('test')" "script test" + `, + { look: 'handDrawn', securityLevel: 'loose', fontFamily: 'courier' } + ); + }); + + it('FDH26: Set text color of nodes and links according to styles when html labels are enabled', () => { + imgSnapshotTest( + `graph LR + A[red
text] -->|red
text| B(blue
text) + C[/red
text/] -->|blue
text| D{blue
text} + E{{default
style}} -->|default
style| F([default
style]) + linkStyle default color:Sienna; + linkStyle 0 color:red; + linkStyle 1 stroke:DarkGray,stroke-width:2px,color:#0000ff + style A color:red; + style B color:blue; + style C stroke:#ff0000,fill:#ffcccc,color:#ff0000 + style D stroke:#0000ff,fill:#ccccff,color:#0000ff + click B "index.html#link-clicked" "link test" + click D testClick "click test" + `, + { look: 'handDrawn', flowchart: { htmlLabels: true } } + ); + }); + + it('FDH27: Set text color of nodes and links according to styles when html labels are disabled', () => { + imgSnapshotTest( + `graph LR + A[red
text] -->|red
text| B(blue
text) + C[/red
text/] -->|blue
text| D{blue
text} + E{{default
style}} -->|default
style| F([default
style]) + linkStyle default color:Sienna; + linkStyle 0 color:red; + linkStyle 1 stroke:DarkGray,stroke-width:2px,color:#0000ff + style A color:red; + style B color:blue; + style C stroke:#ff0000,fill:#ffcccc,color:#ff0000 + style D stroke:#0000ff,fill:#ccccff,color:#0000ff + click B "index.html#link-clicked" "link test" + click D testClick "click test" + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FDH28: Apply default class to all nodes which do not have another class assigned (htmlLabels enabled)', () => { + imgSnapshotTest( + `graph TD + A[myClass1] --> B[default] & C[default] + B[default] & C[default] --> D[myClass2] + classDef default stroke-width:2px,fill:none,stroke:silver + classDef node color:red + classDef myClass1 color:#0000ff + classDef myClass2 stroke:#0000ff,fill:#ccccff + class A myClass1 + class D myClass2 + `, + { look: 'handDrawn', flowchart: { htmlLabels: true } } + ); + }); + + it('FDH29: Apply default class to all nodes which do not have another class assigned (htmlLabels disabled)', () => { + imgSnapshotTest( + `graph TD + A[myClass1] --> B[default] & C[default] + B[default] & C[default] --> D[myClass2] + classDef default stroke-width:2px,fill:none,stroke:silver + classDef node color:red + classDef myClass1 color:#0000ff + classDef myClass2 stroke:#0000ff,fill:#ccccff + class A myClass1 + class D myClass2 + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FDH30: Possibility to style text color of nodes and subgraphs as well as apply classes to subgraphs', () => { + imgSnapshotTest( + `graph LR + subgraph id1 [title is set] + A-->B + end + subgraph id2 [title] + E + end + + B-->C + + subgraph id3 + C-->D + end + class id3,id2,A redBg; + class id3,A whiteTxt; + classDef redBg fill:#622; + classDef whiteTxt color: white; + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FDH31: should not slice off edges that are to the left of the left-most vertex', () => { + imgSnapshotTest( + `graph TD + work --> sleep + sleep --> work + eat --> sleep + work --> eat + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FDH32: Render Subroutine shape', () => { + imgSnapshotTest( + `graph LR + A[[subroutine shape test]] + A -->|Get money| B[[Go shopping]] + B --> C[[Let me think...
Do I want something for work,
something to spend every free second with,
or something to get around?]] + C -->|One| D[[Laptop]] + C -->|Two| E[[iPhone]] + C -->|Three| F[[Car
wroom wroom]] + click A "index.html#link-clicked" "link test" + click B testClick "click test" + classDef someclass fill:#f96; + class A someclass; + class C someclass; + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: false }, + fontFamily: 'courier', + } + ); + }); + + it('FDH33: should render a simple flowchart with diagramPadding set to 0', () => { + imgSnapshotTest( + `graph TD + A[Christmas] -->|Get money| B(Go shopping) + B --> C{Let me think} + %% this is a comment + C -->|One| D[Laptop] + C -->|Two| E[iPhone] + C -->|Three| F[fa:fa-car Car] + `, + { look: 'handDrawn', flowchart: { diagramPadding: 0 } } + ); + }); + + it('FDH34: testing the label width in percy', () => { + imgSnapshotTest( + `graph TD + A[Christmas] + `, + { look: 'handDrawn', handDrawnSeed: 1 } + ); + }); + + it('FDH35: should honor minimum edge length as specified by the user', () => { + imgSnapshotTest( + `graph TD + L1 --- L2 + L2 --- C + M1 ---> C + R1 .-> R2 + R2 <.-> C + C -->|Label 1| E1 + C -- Label 2 ---> E2 + C ----> E3 + C -----> E4 + C ======> E5 + `, + { look: 'handDrawn', handDrawnSeed: 1 } + ); + }); + it('FDH36: should render escaped without html labels', () => { + imgSnapshotTest( + `graph TD + a["Haiya"]-->b + `, + { look: 'handDrawn', htmlLabels: false, flowchart: { htmlLabels: false } } + ); + }); + it('FDH37: should render non-escaped with html labels', () => { + imgSnapshotTest( + `graph TD + a["Haiya"]-->b + `, + { + look: 'handDrawn', + htmlLabels: true, + flowchart: { htmlLabels: true }, + securityLevel: 'loose', + } + ); + }); + it('FDH38: should render a flowchart when useMaxWidth is true (default)', () => { + renderGraph( + `flowchart TD + A[Christmas] -->|Get money| B(Go shopping) + B --> C{Let me think} + C -->|One| D[Laptop] + C -->|Two| E[iPhone] + C -->|Three| F[fa:fa-car Car] + `, + { look: 'handDrawn', flowchart: { useMaxWidth: true } } + ); + cy.get('svg').should((svg) => { + expect(svg).to.have.attr('width', '100%'); + // expect(svg).to.have.attr('height'); + // use within because the absolute value can be slightly different depending on the environment Âą10% + // const height = parseFloat(svg.attr('height')); + // expect(height).to.be.within(446 * 0.95, 446 * 1.05); + const style = svg.attr('style'); + expect(style).to.match(/^max-width: [\d.]+px;$/); + const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); + expect(maxWidthValue).to.be.within(446 * 0.9, 446 * 1.1); + }); + }); + it('FDH39: should render a flowchart when useMaxWidth is false', () => { + renderGraph( + `graph TD + A[Christmas] -->|Get money| B(Go shopping) + B --> C{Let me think} + C -->|One| D[Laptop] + C -->|Two| E[iPhone] + C -->|Three| F[fa:fa-car Car] + `, + { look: 'handDrawn', flowchart: { useMaxWidth: false } } + ); + cy.get('svg').should((svg) => { + // const height = parseFloat(svg.attr('height')); + const width = parseFloat(svg.attr('width')); + // use within because the absolute value can be slightly different depending on the environment Âą10% + // expect(height).to.be.within(446 * 0.95, 446 * 1.05); + expect(width).to.be.within(446 * 0.9, 446 * 1.1); + expect(svg).to.not.have.attr('style'); + }); + }); + it('FDH40: handle styling with style expressions', () => { + imgSnapshotTest( + ` + graph LR + id1(Start)-->id2(Stop) + style id1 fill:#f9f,stroke:#333,stroke-width:4px + style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 + `, + { + look: 'handDrawn', + htmlLabels: true, + flowchart: { htmlLabels: true }, + securityLevel: 'loose', + } + ); + }); + it('FDH41: handle styling for all node shapes', () => { + imgSnapshotTest( + ` + graph LR + A[red text] -->|default style| B(blue text) + C([red text]) -->|default style| D[[blue text]] + E[(red text)] -->|default style| F((blue text)) + G>red text] -->|default style| H{blue text} + I{{red text}} -->|default style| J[/blue text/] + linkStyle default color:Sienna; + style A stroke:#ff0000,fill:#ffcccc,color:#ff0000 + style B stroke:#0000ff,fill:#ccccff,color:#0000ff + style C stroke:#ff0000,fill:#ffcccc,color:#ff0000 + style D stroke:#0000ff,fill:#ccccff,color:#0000ff + style E stroke:#ff0000,fill:#ffcccc,color:#ff0000 + style F stroke:#0000ff,fill:#ccccff,color:#0000ff + style G stroke:#ff0000,fill:#ffcccc,color:#ff0000 + style H stroke:#0000ff,fill:#ccccff,color:#0000ff + style I stroke:#ff0000,fill:#ffcccc,color:#ff0000 + style J stroke:#0000ff,fill:#ccccff,color:#0000ff + `, + { + look: 'handDrawn', + htmlLabels: true, + flowchart: { htmlLabels: true }, + securityLevel: 'loose', + } + ); + }); + it('FDH42: fontawesome icons in edge labels', () => { + imgSnapshotTest( + ` +graph TD + C -->|fa:fa-car Car| F[fa:fa-car Car] + `, + { + look: 'handDrawn', + htmlLabels: true, + flowchart: { htmlLabels: true }, + securityLevel: 'loose', + } + ); + }); + it('FDH43: fontawesome icons in edge labels', () => { + imgSnapshotTest( + ` + graph TB + subgraph bar[Bar] + F + end + style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue + `, + { + look: 'handDrawn', + htmlLabels: true, + flowchart: { htmlLabels: true }, + securityLevel: 'loose', + } + ); + }); + it('FDH44: fontawesome icons in edge labels', () => { + imgSnapshotTest( + ` + graph TB + A + B + subgraph foo[Foo SubGraph] + C + D + end + subgraph bar[Bar SubGraph] + E + F + end + G + + A-->B + B-->C + C-->D + B-->D + D-->E + E-->A + E-->F + F-->D + F-->G + B-->G + G-->D + + style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred + style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue + `, + { + look: 'handDrawn', + htmlLabels: true, + flowchart: { htmlLabels: true }, + securityLevel: 'loose', + } + ); + }); + it('FDH45: fontawesome icons in edge labels', () => { + imgSnapshotTest( + ` + %%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%% + flowchart LR + subgraph A + a --> b + end + subgraph B + i -->f + end + A --> B + `, + { + look: 'handDrawn', + htmlLabels: true, + flowchart: { htmlLabels: true }, + securityLevel: 'loose', + } + ); + }); + it('FDH46: text-color from classes', () => { + imgSnapshotTest( + ` + flowchart LR + classDef dark fill:#000,stroke:#000,stroke-width:4px,color:#fff + Lorem --> Ipsum --> Dolor + class Lorem,Dolor dark + `, + { + look: 'handDrawn', + htmlLabels: true, + flowchart: { htmlLabels: true }, + securityLevel: 'loose', + } + ); + }); + it('FDH47: apply class called default on node called default', () => { + imgSnapshotTest( + ` + graph TD + classDef default fill:#a34,stroke:#000,stroke-width:4px,color:#fff + hello --> default + `, + { + look: 'handDrawn', + htmlLabels: true, + flowchart: { htmlLabels: true }, + securityLevel: 'loose', + } + ); + }); + + it('FDH48: should be able to style default node independently', () => { + imgSnapshotTest( + ` + flowchart TD + classDef default fill:#a34 + hello --> default + + style default stroke:#000,stroke-width:4px + `, + { + look: 'handDrawn', + flowchart: { htmlLabels: true }, + securityLevel: 'loose', + } + ); + }); +}); diff --git a/cypress/integration/rendering/flowchart-shape-alias.spec.ts b/cypress/integration/rendering/flowchart-shape-alias.spec.ts new file mode 100644 index 000000000..86aef718c --- /dev/null +++ b/cypress/integration/rendering/flowchart-shape-alias.spec.ts @@ -0,0 +1,142 @@ +import { imgSnapshotTest } from '../../helpers/util.ts'; + +const aliasSet1 = ['process', 'rect', 'proc', 'rectangle'] as const; + +const aliasSet2 = ['event', 'rounded'] as const; + +const aliasSet3 = ['stadium', 'pill', 'terminal'] as const; + +const aliasSet4 = ['fr-rect', 'subproc', 'subprocess', 'framed-rectangle', 'subroutine'] as const; + +const aliasSet5 = ['db', 'database', 'cylinder', 'cyl'] as const; + +const aliasSet6 = ['diam', 'decision', 'diamond'] as const; + +const aliasSet7 = ['hex', 'hexagon', 'prepare'] as const; + +const aliasSet8 = ['lean-r', 'lean-right', 'in-out'] as const; + +const aliasSet9 = ['lean-l', 'lean-left', 'out-in'] as const; + +const aliasSet10 = ['trap-b', 'trapezoid-bottom', 'priority'] as const; + +const aliasSet11 = ['trap-t', 'trapezoid-top', 'manual'] as const; + +const aliasSet12 = ['dbl-circ', 'double-circle'] as const; + +const aliasSet13 = ['notched-rectangle', 'card', 'notch-rect'] as const; + +const aliasSet14 = [ + 'lin-rect', + 'lined-rectangle', + 'lin-proc', + 'lined-process', + 'shaded-process', +] as const; + +const aliasSet15 = ['sm-circ', 'small-circle', 'start'] as const; + +const aliasSet16 = ['fr-circ', 'framed-circle', 'stop'] as const; + +const aliasSet17 = ['fork', 'join'] as const; +// brace-r', 'braces' +const aliasSet18 = ['comment', 'brace-l'] as const; + +const aliasSet19 = ['bolt', 'com-link', 'lightning-bolt'] as const; + +const aliasSet20 = ['doc', 'document'] as const; + +const aliasSet21 = ['delay', 'half-rounded-rectangle'] as const; + +const aliasSet22 = ['h-cyl', 'das', 'horizontal-cylinder'] as const; + +const aliasSet23 = ['lin-cyl', 'disk', 'lined-cylinder'] as const; + +const aliasSet24 = ['curv-trap', 'display', 'curved-trapezoid'] as const; + +const aliasSet25 = ['div-rect', 'div-proc', 'divided-rectangle', 'divided-process'] as const; + +const aliasSet26 = ['extract', 'tri', 'triangle'] as const; + +const aliasSet27 = ['win-pane', 'internal-storage', 'window-pane'] as const; + +const aliasSet28 = ['f-circ', 'junction', 'filled-circle'] as const; + +const aliasSet29 = ['lin-doc', 'lined-document'] as const; + +const aliasSet30 = ['notch-pent', 'loop-limit', 'notched-pentagon'] as const; + +const aliasSet31 = ['flip-tri', 'manual-file', 'flipped-triangle'] as const; + +const aliasSet32 = ['sl-rect', 'manual-input', 'sloped-rectangle'] as const; + +const aliasSet33 = ['docs', 'documents', 'st-doc', 'stacked-document'] as const; + +const aliasSet34 = ['procs', 'processes', 'st-rect', 'stacked-rectangle'] as const; + +const aliasSet35 = ['flag', 'paper-tape'] as const; + +const aliasSet36 = ['bow-rect', 'stored-data', 'bow-tie-rectangle'] as const; + +const aliasSet37 = ['cross-circ', 'summary', 'crossed-circle'] as const; + +const aliasSet38 = ['tag-doc', 'tagged-document'] as const; + +const aliasSet39 = ['tag-rect', 'tag-proc', 'tagged-rectangle', 'tagged-process'] as const; + +const aliasSet40 = ['collate', 'hourglass'] as const; + +// Aggregate all alias sets into a single array +const aliasSets = [ + aliasSet1, + aliasSet2, + aliasSet3, + aliasSet4, + aliasSet5, + aliasSet6, + aliasSet7, + aliasSet8, + aliasSet9, + aliasSet10, + aliasSet11, + aliasSet12, + aliasSet13, + aliasSet14, + aliasSet15, + aliasSet16, + aliasSet17, + aliasSet18, + aliasSet19, + aliasSet20, + aliasSet21, + aliasSet22, + aliasSet23, + aliasSet24, + aliasSet25, + aliasSet26, + aliasSet27, + aliasSet28, + aliasSet29, + aliasSet30, + aliasSet31, + aliasSet32, + aliasSet33, + aliasSet34, + aliasSet35, + aliasSet36, + aliasSet37, + aliasSet38, + aliasSet39, +] as const; + +aliasSets.forEach((aliasSet) => { + describe(`Test ${aliasSet.join(',')} `, () => { + it(`All ${aliasSet.join(',')} should render same shape`, () => { + let flowchartCode = `flowchart \n`; + aliasSet.forEach((alias, index) => { + flowchartCode += ` n${index}@{ shape: ${alias}, label: "${alias}" }\n`; + }); + imgSnapshotTest(flowchartCode); + }); + }); +}); diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index 3eb2a0432..2e30d7a0c 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -99,7 +99,7 @@ describe('Flowchart v2', () => { const style = svg.attr('style'); expect(style).to.match(/^max-width: [\d.]+px;$/); const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); - expect(maxWidthValue).to.be.within(290 * 0.95 - 1, 290 * 1.05); + expect(maxWidthValue).to.be.within(417 * 0.95, 417 * 1.05); }); }); it('8: should render a flowchart when useMaxWidth is false', () => { @@ -118,7 +118,7 @@ describe('Flowchart v2', () => { const width = parseFloat(svg.attr('width')); // use within because the absolute value can be slightly different depending on the environment Âą5% // expect(height).to.be.within(446 * 0.95, 446 * 1.05); - expect(width).to.be.within(290 * 0.95 - 1, 290 * 1.05); + expect(width).to.be.within(417 * 0.95, 417 * 1.05); expect(svg).to.not.have.attr('style'); }); }); @@ -198,13 +198,13 @@ describe('Flowchart v2', () => { `flowchart TB internet nat - routeur + router lb1 lb2 compute1 compute2 subgraph project - routeur + router nat subgraph subnet1 compute1 @@ -215,8 +215,8 @@ describe('Flowchart v2', () => { lb2 end end - internet --> routeur - routeur --> subnet1 & subnet2 + internet --> router + router --> subnet1 & subnet2 subnet1 & subnet2 --> nat --> internet `, { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } @@ -433,7 +433,7 @@ flowchart TD { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } ); }); - it('63: title on subgraphs should be themable', () => { + it('63: title on subgraphs should be themeable', () => { imgSnapshotTest( ` %%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%% @@ -699,7 +699,7 @@ A --> B { flowchart: { titleTopMargin: 10 } } ); }); - it('3192: It should be possieble to render flowcharts with invisible edges', () => { + it('3192: It should be possible to render flowcharts with invisible edges', () => { imgSnapshotTest( `--- title: Simple flowchart with invisible edges @@ -786,7 +786,7 @@ A ~~~ B `--- title: Subgraph nodeSpacing and rankSpacing example config: - flowchart: + flowchart: nodeSpacing: 250 rankSpacing: 250 --- @@ -1047,7 +1047,69 @@ end A --lb3--> TOP --lb4--> B B1 --lb5--> B2 `, - { flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } } + { + flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } }, + } + ); + }); + it('Should render self-loops', () => { + imgSnapshotTest( + `flowchart + A --> A + subgraph B + B1 --> B1 + end + subgraph C + subgraph C1 + C2 --> C2 + subgraph D + D1 --> D1 + end + D --> D + end + C1 --> C1 + end + `, + { + flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } }, + } + ); + }); + }); + describe('New @ syntax for node metadata edge cases', () => { + it('should be possible to use @ syntax to add labels on multi nodes', () => { + imgSnapshotTest( + `flowchart TB + n2["label for n2"] & n4@{ label: "label for n4"} & n5@{ label: "label for n5"} + `, + {} + ); + }); + it('should be possible to use @ syntax to add labels with trail spaces and &', () => { + imgSnapshotTest( + `flowchart TB + n2["label for n2"] & n4@{ label: "label for n4"} & n5@{ label: "label for n5"} + `, + {} + ); + }); + it('should be possible to use @ syntax to add labels with trail spaces', () => { + imgSnapshotTest( + `flowchart TB + n2["label for n2"] + n4@{ label: "label for n4"} + n5@{ label: "label for n5"} + `, + {} + ); + }); + it('should be possible to use @ syntax to add labels with trail spaces and edge/link', () => { + imgSnapshotTest( + `flowchart TD + A["A"] --> B["for B"] & C@{ label: "for c"} & E@{label : "for E"} + D@{label: "for D"} + `, + {} ); }); }); diff --git a/cypress/integration/rendering/flowchart.spec.js b/cypress/integration/rendering/flowchart.spec.js index e4766e792..7b986cd2f 100644 --- a/cypress/integration/rendering/flowchart.spec.js +++ b/cypress/integration/rendering/flowchart.spec.js @@ -733,7 +733,7 @@ describe('Graph', () => { }); it('38: should render a flowchart when useMaxWidth is true (default)', () => { renderGraph( - `graph TD + `flowchart TD A[Christmas] -->|Get money| B(Go shopping) B --> C{Let me think} C -->|One| D[Laptop] @@ -751,7 +751,7 @@ describe('Graph', () => { const style = svg.attr('style'); expect(style).to.match(/^max-width: [\d.]+px;$/); const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); - expect(maxWidthValue).to.be.within(300 * 0.9, 300 * 1.1); + expect(maxWidthValue).to.be.within(446 * 0.9, 446 * 1.1); }); }); it('39: should render a flowchart when useMaxWidth is false', () => { @@ -770,7 +770,7 @@ describe('Graph', () => { const width = parseFloat(svg.attr('width')); // use within because the absolute value can be slightly different depending on the environment Âą10% // expect(height).to.be.within(446 * 0.95, 446 * 1.05); - expect(width).to.be.within(300 * 0.9, 300 * 1.1); + expect(width).to.be.within(446 * 0.9, 446 * 1.1); expect(svg).to.not.have.attr('style'); }); }); @@ -895,7 +895,7 @@ graph TD imgSnapshotTest( ` graph TD - classDef default fill:#a34,stroke:#000,stroke-width:4px,color:#fff + classDef default fill:#a34,stroke:#000,stroke-width:4px,color:#fff hello --> default `, { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } @@ -905,13 +905,33 @@ graph TD it('67: should be able to style default node independently', () => { imgSnapshotTest( ` - flowchart TD + flowchart TD classDef default fill:#a34 hello --> default style default stroke:#000,stroke-width:4px `, - { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } + { + flowchart: { htmlLabels: true }, + securityLevel: 'loose', + } + ); + }); + it('#6369: edge color should affect arrow head', () => { + imgSnapshotTest( + ` + flowchart LR + A --> B + A --> C + C --> D + + linkStyle 0 stroke:#D50000 + linkStyle 2 stroke:#D50000 + `, + { + flowchart: { htmlLabels: true }, + securityLevel: 'loose', + } ); }); }); diff --git a/cypress/integration/rendering/gantt.spec.js b/cypress/integration/rendering/gantt.spec.js index a0c2dbcb9..fc64f45d3 100644 --- a/cypress/integration/rendering/gantt.spec.js +++ b/cypress/integration/rendering/gantt.spec.js @@ -117,7 +117,7 @@ describe('Gantt diagram', () => { {} ); }); - it('should FAIL redering a gantt chart for issue #1060 with invalid date', () => { + it('should FAIL rendering a gantt chart for issue #1060 with invalid date', () => { imgSnapshotTest( ` gantt @@ -573,7 +573,7 @@ describe('Gantt diagram', () => { ` ); }); - it('should render a gantt diagram exculding friday and saturday', () => { + it('should render a gantt diagram excluding friday and saturday', () => { imgSnapshotTest( `gantt title A Gantt Diagram @@ -584,7 +584,7 @@ describe('Gantt diagram', () => { A task :a1, 2024-02-28, 10d` ); }); - it('should render a gantt diagram exculding saturday and sunday', () => { + it('should render a gantt diagram excluding saturday and sunday', () => { imgSnapshotTest( `gantt title A Gantt Diagram @@ -671,7 +671,7 @@ describe('Gantt diagram', () => { title Gantt Digram dateFormat YYYY-MM-DD section Section - ;A task with a semiclon :a1, 2014-01-01, 30d + ;A task with a semicolon :a1, 2014-01-01, 30d Another task :after a1 , 20d section Another Task in sec :2014-01-12 , 12d diff --git a/cypress/integration/rendering/gitGraph.spec.js b/cypress/integration/rendering/gitGraph.spec.js index 68b63de46..42dc57439 100644 --- a/cypress/integration/rendering/gitGraph.spec.js +++ b/cypress/integration/rendering/gitGraph.spec.js @@ -11,7 +11,7 @@ describe('Git Graph diagram', () => { {} ); }); - it('2: should render a simple gitgraph with commit on main branch with Id', () => { + it('2: should render a simple gitgraph with commit on main branch with id', () => { imgSnapshotTest( `gitGraph commit id: "One" @@ -253,7 +253,7 @@ describe('Git Graph diagram', () => { ` gitGraph checkout main - %% Make sure to manually set the ID of all commits, for consistent visual tests + %% Make sure to manually set the id of all commits, for consistent visual tests commit id: "1-abcdefg" checkout main branch branch1 @@ -343,7 +343,7 @@ gitGraph {} ); }); - it('16: should render a simple gitgraph with commit on main branch with Id | Vertical Branch', () => { + it('16: should render a simple gitgraph with commit on main branch with id | Vertical Branch', () => { imgSnapshotTest( `gitGraph TB: commit id: "One" @@ -585,7 +585,7 @@ gitGraph ` gitGraph TB: checkout main - %% Make sure to manually set the ID of all commits, for consistent visual tests + %% Make sure to manually set the id of all commits, for consistent visual tests commit id: "1-abcdefg" checkout main branch branch1 @@ -1024,7 +1024,7 @@ gitGraph TB: {} ); }); - it('51: should render a simple gitgraph with commit on main branch with Id | Vertical Branch - Bottom-to-top', () => { + it('51: should render a simple gitgraph with commit on main branch with id | Vertical Branch - Bottom-to-top', () => { imgSnapshotTest( `gitGraph BT: commit id: "One" @@ -1266,7 +1266,7 @@ gitGraph TB: ` gitGraph BT: checkout main - %% Make sure to manually set the ID of all commits, for consistent visual tests + %% Make sure to manually set the id of all commits, for consistent visual tests commit id: "1-abcdefg" checkout main branch branch1 @@ -1491,7 +1491,7 @@ gitGraph TB: ` gitGraph switch main - %% Make sure to manually set the ID of all commits, for consistent visual tests + %% Make sure to manually set the id of all commits, for consistent visual tests commit id: "1-abcdefg" switch main branch branch1 @@ -1532,5 +1532,41 @@ gitGraph TB: {} ); }); + it('75: should render a gitGraph with multiple tags on a merge commit on bottom-to-top orientation', () => { + imgSnapshotTest( + `gitGraph BT: + commit id: "ZERO" + branch develop + commit id:"A" + checkout main + commit id:"ONE" + checkout develop + commit id:"B" + checkout main + merge develop id:"Release 1.0" type:HIGHLIGHT tag: "SAML v2.0" tag: "OpenID v1.1" + commit id:"TWO" + checkout develop + commit id:"C"`, + {} + ); + }); + }); + it('76: should render a gitGraph with multiple tags on a merge commit on left-to-right orientation', () => { + imgSnapshotTest( + `gitGraph + commit id: "ZERO" + branch develop + commit id:"A" + checkout main + commit id:"ONE" + checkout develop + commit id:"B" + checkout main + merge develop id:"Release 1.0" type:HIGHLIGHT tag: "SAML v2.0" tag: "OpenID v1.1" + commit id:"TWO" + checkout develop + commit id:"C"`, + {} + ); }); }); diff --git a/cypress/integration/rendering/iconShape.spec.ts b/cypress/integration/rendering/iconShape.spec.ts new file mode 100644 index 000000000..4c12c3fa3 --- /dev/null +++ b/cypress/integration/rendering/iconShape.spec.ts @@ -0,0 +1,143 @@ +import { imgSnapshotTest } from '../../helpers/util'; + +const looks = ['classic', 'handDrawn'] as const; +const directions = [ + 'TB', + //'BT', + 'LR', + // 'RL' +] as const; +const forms = [undefined, 'square', 'circle', 'rounded'] as const; +const labelPos = [undefined, 't', 'b'] as const; + +looks.forEach((look) => { + directions.forEach((direction) => { + forms.forEach((form) => { + labelPos.forEach((pos) => { + describe(`Test iconShape in ${form ? `${form} form,` : ''} ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => { + it(`without label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + flowchartCode += ` }\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is a label for icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with very long label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is a very very very very very long long long label for icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:true`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold**
and strong for icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:false`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold**
and strong for icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }\n`; + imgSnapshotTest(flowchartCode, { + look, + htmlLabels: false, + flowchart: { htmlLabels: false }, + }); + }); + + it(`with styles`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }\n`; + flowchartCode += ` style nAA fill:#f9f,stroke:#333,stroke-width:4px \n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with classDef`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }\n`; + flowchartCode += ` nAA:::customClazz\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + }); + }); + }); + }); +}); + +describe('Test iconShape with different h', () => { + it('with different h', () => { + let flowchartCode = `flowchart TB\n`; + const icon = 'fa:bell'; + const iconHeight = 64; + flowchartCode += ` nA --> nAA@{ icon: '${icon}', label: 'icon with different h', h: ${iconHeight} }\n`; + imgSnapshotTest(flowchartCode); + }); +}); + +describe('Test colored iconShape', () => { + it('with no styles', () => { + let flowchartCode = `flowchart TB\n`; + const icon = 'fluent-emoji:tropical-fish'; + flowchartCode += ` nA --> nAA@{ icon: '${icon}', form: 'square', label: 'icon with color' }\n`; + imgSnapshotTest(flowchartCode); + }); + + it('with styles', () => { + let flowchartCode = `flowchart TB\n`; + const icon = 'fluent-emoji:tropical-fish'; + flowchartCode += ` nA --> nAA@{ icon: '${icon}', form: 'square', label: 'icon with color' }\n`; + flowchartCode += ` style nAA fill:#f9f,stroke:#333,stroke-width:4px \n`; + imgSnapshotTest(flowchartCode); + }); +}); diff --git a/cypress/integration/rendering/imageShape.spec.ts b/cypress/integration/rendering/imageShape.spec.ts new file mode 100644 index 000000000..d2e267149 --- /dev/null +++ b/cypress/integration/rendering/imageShape.spec.ts @@ -0,0 +1,103 @@ +import { imgSnapshotTest } from '../../helpers/util'; + +const looks = ['classic', 'handDrawn'] as const; +const directions = [ + 'TB', + //'BT', + 'LR', + // 'RL' +] as const; +const labelPos = [undefined, 't', 'b'] as const; + +looks.forEach((look) => { + directions.forEach((direction) => { + labelPos.forEach((pos) => { + describe(`Test imageShape in ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => { + it(`without label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', w: '100', h: '100' }\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a label for image shape'`; + + flowchartCode += `, w: '100', h: '200'`; + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with very long label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a very very very very very long long long label for image shape'`; + + flowchartCode += `, w: '100', h: '250'`; + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:true`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold**
and strong for image shape'`; + + flowchartCode += `, w: '550', h: '200'`; + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }\n`; + imgSnapshotTest(flowchartCode, { look, htmlLabels: true }); + }); + + it(`with markdown htmlLabels:false`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold**
and strong for image shape'`; + flowchartCode += `, w: '250', h: '200'`; + + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }\n`; + imgSnapshotTest(flowchartCode, { + look, + htmlLabels: false, + flowchart: { htmlLabels: false }, + }); + }); + + it(`with styles`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`; + flowchartCode += `, w: '550', h: '200'`; + + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }\n`; + flowchartCode += ` style A fill:#f9f,stroke:#333,stroke-width:4px \n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with classDef`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#000000,stroke-dasharray: 5 5\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`; + + flowchartCode += `, w: '500', h: '550'`; + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }\n`; + flowchartCode += ` A:::customClazz\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + }); + }); + }); +}); diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index d8bef6d1b..70d5574b8 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -63,4 +63,199 @@ section Checkout from website { journey: { useMaxWidth: false } } ); }); + + it('should initialize with a left margin of 150px for user journeys', () => { + renderGraph( + ` + --- + config: + journey: + maxLabelWidth: 320 + --- + journey + title User Journey Example + section Onboarding + Sign Up: 5: + Browse Features: 3: + Use Core Functionality: 4: + section Engagement + Browse Features: 3 + Use Core Functionality: 4 + `, + { journey: { useMaxWidth: true } } + ); + + let diagramStartX; + + cy.contains('foreignobject', 'Sign Up').then(($diagram) => { + diagramStartX = parseFloat($diagram.attr('x')); + expect(diagramStartX).to.be.closeTo(150, 2); + }); + }); + + it('should maintain sufficient space between legend and diagram when legend labels are longer', () => { + renderGraph( + `journey + title Web hook life cycle + section Darkoob + Make preBuilt:5: Darkoob user + register slug : 5: Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is maintained + Map slug to a Prebuilt Job:5: Darkoob user + section External Service + set Darkoob slug as hook for an Event : 5 : admin Exjjjnjjjj qwerty + listen to the events : 5 : External Service + call darkoob endpoint : 5 : External Service + section Darkoob + check for inputs : 5 : DarkoobAPI + run the prebuilt job : 5 : DarkoobAPI + `, + { journey: { useMaxWidth: true } } + ); + + let LabelEndX, diagramStartX; + + // Get right edge of the legend + cy.contains('tspan', 'Darkoob userf').then((textBox) => { + const bbox = textBox[0].getBBox(); + LabelEndX = bbox.x + bbox.width; + }); + + // Get left edge of the diagram + cy.contains('foreignobject', 'Make preBuilt').then((rect) => { + diagramStartX = parseFloat(rect.attr('x')); + }); + + // Assert right edge of the diagram is greater than or equal to the right edge of the label + cy.then(() => { + expect(diagramStartX).to.be.gte(LabelEndX); + }); + }); + + it('should wrap a single long word with hyphenation', () => { + renderGraph( + ` + --- + config: + journey: + maxLabelWidth: 100 + --- + journey + title Long Word Test + section Test + VeryLongWord: 5: Supercalifragilisticexpialidocious + `, + { journey: { useMaxWidth: true } } + ); + + // Verify that the line ends with a hyphen, indicating proper hyphenation for words exceeding maxLabelWidth. + cy.get('tspan').then((tspans) => { + const hasHyphen = [...tspans].some((t) => t.textContent.trim().endsWith('-')); + return expect(hasHyphen).to.be.true; + }); + }); + + it('should wrap text on whitespace without adding hyphens', () => { + renderGraph( + ` + --- + config: + journey: + maxLabelWidth: 200 + --- + journey + title Whitespace Test + section Test + TextWithSpaces: 5: Gustavo Fring is played by Giancarlo Esposito and is a character in Breaking Bad. + `, + { journey: { useMaxWidth: true } } + ); + + // Verify that none of the text spans end with a hyphen. + cy.get('tspan').each(($el) => { + const text = $el.text(); + expect(text.trim()).not.to.match(/-$/); + }); + }); + + it('should wrap long labels into multiple lines, keep them under max width, and maintain margins', () => { + renderGraph( + ` + --- + config: + journey: + maxLabelWidth: 320 + --- + journey + title User Journey Example + section Onboarding + Sign Up: 5: This is a long label that will be split into multiple lines to test the wrapping functionality + Browse Features: 3: This is another long label that will be split into multiple lines to test the wrapping functionality + Use Core Functionality: 4: This is yet another long label that will be split into multiple lines to test the wrapping functionality + section Engagement + Browse Features: 3 + Use Core Functionality: 4 + `, + { journey: { useMaxWidth: true } } + ); + + let diagramStartX, maxLineWidth; + + // Get the diagram's left edge x-coordinate + cy.contains('foreignobject', 'Sign Up') + .then(($diagram) => { + diagramStartX = parseFloat($diagram.attr('x')); + }) + .then(() => { + cy.get('text.legend').then(($lines) => { + // Check that there are multiple lines + expect($lines.length).to.be.equal(9); + + // Check that all lines are under the maxLabelWidth + $lines.each((index, el) => { + const bbox = el.getBBox(); + expect(bbox.width).to.be.lte(320); + maxLineWidth = Math.max(maxLineWidth || 0, bbox.width); + }); + + /** The expected margin between the diagram and the legend is 150px, as defined by + * conf.leftMargin in user-journey-config.js + */ + expect(diagramStartX - maxLineWidth).to.be.closeTo(150, 2); + }); + }); + }); + + it('should correctly render the user journey diagram title with the specified styling', () => { + renderGraph( + `--- +config: + journey: + titleColor: "#2900A5" + titleFontFamily: "Times New Roman" + titleFontSize: "5rem" +--- + +journey + title User Journey Example + section Onboarding + Sign Up: 5: John, Shahir + Complete Profile: 4: John + section Engagement + Browse Features: 3: John + Use Core Functionality: 4: John + section Retention + Revisit Application: 5: John + Invite Friends: 3: John + + size: 2rem + ` + ); + + cy.get('text').contains('User Journey Example').as('title'); + cy.get('@title').then(($title) => { + expect($title).to.have.attr('fill', '#2900A5'); + expect($title).to.have.attr('font-family', 'Times New Roman'); + expect($title).to.have.attr('font-size', '5rem'); + }); + }); }); diff --git a/cypress/integration/rendering/kanban.spec.ts b/cypress/integration/rendering/kanban.spec.ts new file mode 100644 index 000000000..0ff564cc6 --- /dev/null +++ b/cypress/integration/rendering/kanban.spec.ts @@ -0,0 +1,136 @@ +import { imgSnapshotTest } from '../../helpers/util.ts'; + +describe('Kanban diagram', () => { + it('1: should render a kanban with a single section', () => { + imgSnapshotTest( + `kanban + id1[Todo] + docs[Create Documentation] + docs[Create Blog about the new diagram] + `, + {} + ); + }); + it('2: should render a kanban with multiple sections', () => { + imgSnapshotTest( + `kanban + id1[Todo] + docs[Create Documentation] + id2 + docs[Create Blog about the new diagram] + `, + {} + ); + }); + it('3: should render a kanban with a single wrapping node', () => { + imgSnapshotTest( + `kanban + id1[Todo] + id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping] + `, + {} + ); + }); + it('4: should handle the height of a section with a wrapping node at the end', () => { + imgSnapshotTest( + `kanban + id1[Todo] + id2[One line] + id3[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping] + `, + {} + ); + }); + it('5: should handle the height of a section with a wrapping node at the top', () => { + imgSnapshotTest( + `kanban + id1[Todo] + id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping] + id3[One line] + `, + {} + ); + }); + it('6: should handle the height of a section with a wrapping node in the middle', () => { + imgSnapshotTest( + `kanban + id1[Todo] + id2[One line] + id3[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping] + id4[One line] + `, + {} + ); + }); + it('6: should handle assignments', () => { + imgSnapshotTest( + `kanban + id1[Todo] + docs[Create Documentation] + id2[In progress] + docs[Create Blog about the new diagram]@{ assigned: 'knsv' } + `, + {} + ); + }); + it('7: should handle prioritization', () => { + imgSnapshotTest( + `kanban + id2[In progress] + vh[Very High]@{ priority: 'Very High' } + h[High]@{ priority: 'High' } + m[Default priority] + l[Low]@{ priority: 'Low' } + vl[Very Low]@{ priority: 'Very Low' } + `, + {} + ); + }); + it('7: should handle external tickets', () => { + imgSnapshotTest( + `kanban + id1[Todo] + docs[Create Documentation] + id2[In progress] + docs[Create Blog about the new diagram]@{ ticket: MC-2037 } + `, + {} + ); + }); + it('8: should handle assignments, prioritization and tickets ids in the same item', () => { + imgSnapshotTest( + `kanban + id2[In progress] + docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' } + `, + {} + ); + }); + it('10: Full example', () => { + imgSnapshotTest( + `--- +config: + kanban: + ticketBaseUrl: 'https://abc123.atlassian.net/browse/#TICKET#' +--- +kanban + id1[Todo] + docs[Create Documentation] + docs[Create Blog about the new diagram] + id7[In progress] + id6[Create renderer so that it works in all cases. We also add some extra text here for testing purposes. And some more just for the extra flare.] + id8[Design grammar]@{ assigned: 'knsv' } + id9[Ready for deploy] + id10[Ready for test] + id11[Done] + id5[define getData] + id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char]@{ ticket: MC-2036, priority: 'Very High'} + id3[Update DB function]@{ ticket: MC-2037, assigned: knsv, priority: 'High' } + id4[Create parsing tests]@{ ticket: MC-2038, assigned: 'K.Sveidqvist', priority: 'High' } + id66[last item]@{ priority: 'Very Low', assigned: 'knsv' } + id12[Can't reproduce] + `, + {} + ); + }); +}); diff --git a/cypress/integration/rendering/mindmap.spec.ts b/cypress/integration/rendering/mindmap.spec.ts index a77459f58..731f861ee 100644 --- a/cypress/integration/rendering/mindmap.spec.ts +++ b/cypress/integration/rendering/mindmap.spec.ts @@ -146,7 +146,7 @@ root shouldHaveRoot ); }); - it('text shouhld wrap with icon', () => { + it('text should wrap with icon', () => { imgSnapshotTest( `mindmap root diff --git a/cypress/integration/rendering/newShapes.spec.ts b/cypress/integration/rendering/newShapes.spec.ts new file mode 100644 index 000000000..6c71a3846 --- /dev/null +++ b/cypress/integration/rendering/newShapes.spec.ts @@ -0,0 +1,146 @@ +import { imgSnapshotTest } from '../../helpers/util.ts'; + +const looks = ['classic', 'handDrawn'] as const; +const directions = [ + 'TB', + //'BT', + 'LR', + //'RL' +] as const; +const newShapesSet1 = [ + 'triangle', + 'sloped-rectangle', + 'horizontal-cylinder', + 'flipped-triangle', + 'hourglass', +] as const; +const newShapesSet2 = [ + 'tagged-rectangle', + 'documents', + 'lightning-bolt', + 'filled-circle', + 'window-pane', +] as const; + +const newShapesSet3 = [ + 'curved-trapezoid', + 'bow-rect', + 'tagged-document', + 'divided-rectangle', + 'crossed-circle', +] as const; + +const newShapesSet4 = [ + 'document', + 'notched-pentagon', + 'lined-cylinder', + 'stacked-document', + 'half-rounded-rectangle', +] as const; + +const newShapesSet5 = [ + 'lined-document', + 'tagged-document', + 'brace-l', + 'comment', + 'braces', + 'brace-r', +] as const; + +const newShapesSet6 = ['brace-r', 'braces'] as const; +// Aggregate all shape sets into a single array +const newShapesSets = [ + newShapesSet1, + newShapesSet2, + newShapesSet3, + newShapesSet4, + newShapesSet5, + newShapesSet6, +]; + +looks.forEach((look) => { + directions.forEach((direction) => { + newShapesSets.forEach((newShapesSet) => { + describe(`Test ${newShapesSet.join(', ')} in ${look} look and dir ${direction}`, () => { + it(`without label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape} }\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`connect all shapes with each other`, () => { + let flowchartCode = `flowchart ${direction}\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`; + }); + for (let i = 0; i < newShapesSet.length; i++) { + for (let j = i + 1; j < newShapesSet.length; j++) { + flowchartCode += ` n${i}${i} --> n${j}${j}\n`; + } + } + if (!(direction === 'TB' && look === 'handDrawn' && newShapesSet === newShapesSet1)) { + //skip this test, works in real. Need to look + imgSnapshotTest(flowchartCode, { look }); + } + }); + + it(`with very long label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a very very very very very long long long label for ${newShape} shape' }\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:true`, () => { + let flowchartCode = `flowchart ${direction}\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold**
and strong for ${newShape} shape' }\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:false`, () => { + let flowchartCode = `flowchart ${direction}\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold**
and strong for ${newShape} shape' }\n`; + }); + imgSnapshotTest(flowchartCode, { + look, + htmlLabels: false, + flowchart: { htmlLabels: false }, + }); + }); + + it(`with styles`, () => { + let flowchartCode = `flowchart ${direction}\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`; + flowchartCode += ` style n${index}${index} fill:#f9f,stroke:#333,stroke-width:4px \n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with classDef`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`; + flowchartCode += ` n${index}${index}:::customClazz\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + }); + }); + }); +}); diff --git a/cypress/integration/rendering/oldShapes.spec.ts b/cypress/integration/rendering/oldShapes.spec.ts new file mode 100644 index 000000000..628e70ea8 --- /dev/null +++ b/cypress/integration/rendering/oldShapes.spec.ts @@ -0,0 +1,107 @@ +import { imgSnapshotTest } from '../../helpers/util'; + +const looks = ['classic', 'handDrawn'] as const; +const directions = [ + 'TB', + //'BT', + 'LR', + //'RL' +] as const; + +const shapesSet1 = ['text', 'card', 'lin-rect', 'diamond', 'hexagon'] as const; + +// removing labelRect, need have alias for it +const shapesSet2 = ['rounded', 'rect', 'start', 'stop'] as const; + +const shapesSet3 = ['fork', 'choice', 'note', 'stadium', 'odd'] as const; + +const shapesSet4 = ['subroutine', 'cylinder', 'circle', 'doublecircle', 'odd'] as const; + +const shapesSet5 = ['anchor', 'lean-r', 'lean-l', 'trap-t', 'trap-b'] as const; + +// Aggregate all shape sets into a single array +const shapesSets = [shapesSet1, shapesSet2, shapesSet3, shapesSet4, shapesSet5] as const; + +looks.forEach((look) => { + directions.forEach((direction) => { + shapesSets.forEach((shapesSet) => { + describe(`Test ${shapesSet.join(', ')} in ${look} look and dir ${direction}`, () => { + it(`without label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + shapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape} }\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + shapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`connect all shapes with each other`, () => { + let flowchartCode = `flowchart ${direction}\n`; + shapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`; + }); + for (let i = 0; i < shapesSet.length; i++) { + for (let j = i + 1; j < shapesSet.length; j++) { + flowchartCode += ` n${i}${i} --> n${j}${j}\n`; + } + } + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with very long label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + shapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a very very very very very long long long label for ${newShape} shape' }\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:true`, () => { + let flowchartCode = `flowchart ${direction}\n`; + shapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold**
and strong for ${newShape} shape' }\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:false`, () => { + let flowchartCode = `flowchart ${direction}\n`; + shapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold**
and strong for ${newShape} shape' }\n`; + }); + imgSnapshotTest(flowchartCode, { + look, + htmlLabels: false, + flowchart: { htmlLabels: false }, + }); + }); + + it(`with styles`, () => { + let flowchartCode = `flowchart ${direction}\n`; + shapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`; + flowchartCode += ` style n${index}${index} fill:#f9f,stroke:#333,stroke-width:4px \n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with classDef`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`; + shapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`; + flowchartCode += ` n${index}${index}:::customClazz\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + }); + }); + }); +}); diff --git a/cypress/integration/rendering/packet.spec.ts b/cypress/integration/rendering/packet.spec.ts index 61555ea53..c64538875 100644 --- a/cypress/integration/rendering/packet.spec.ts +++ b/cypress/integration/rendering/packet.spec.ts @@ -10,6 +10,15 @@ describe('packet structure', () => { ); }); + it('should render a simple packet diagram without ranges', () => { + imgSnapshotTest( + `packet-beta + 0: "h" + 1: "i" +` + ); + }); + it('should render a complex packet diagram', () => { imgSnapshotTest( `packet-beta diff --git a/cypress/integration/rendering/pie.spec.ts b/cypress/integration/rendering/pie.spec.ts index 4a1d774c0..171a83057 100644 --- a/cypress/integration/rendering/pie.spec.ts +++ b/cypress/integration/rendering/pie.spec.ts @@ -64,7 +64,7 @@ describe('pie chart', () => { }); }); - it('should render a pie diagram when textPosition is setted', () => { + it('should render a pie diagram when textPosition is set', () => { imgSnapshotTest( `pie "Dogs": 50 diff --git a/cypress/integration/rendering/quadrantChart.spec.js b/cypress/integration/rendering/quadrantChart.spec.js index 83a1455c6..3a1e768aa 100644 --- a/cypress/integration/rendering/quadrantChart.spec.js +++ b/cypress/integration/rendering/quadrantChart.spec.js @@ -8,7 +8,6 @@ describe('Quadrant Chart', () => { `, {} ); - cy.get('svg'); }); it('should render a complete quadrant chart', () => { imgSnapshotTest( @@ -30,7 +29,6 @@ describe('Quadrant Chart', () => { `, {} ); - cy.get('svg'); }); it('should render without points', () => { imgSnapshotTest( @@ -46,9 +44,8 @@ describe('Quadrant Chart', () => { `, {} ); - cy.get('svg'); }); - it('should able to render y-axix on right side', () => { + it('should able to render y-axis on right side', () => { imgSnapshotTest( ` %%{init: {"quadrantChart": {"yAxisPosition": "right"}}}%% @@ -63,9 +60,8 @@ describe('Quadrant Chart', () => { `, {} ); - cy.get('svg'); }); - it('should able to render x-axix on bottom', () => { + it('should able to render x-axis on bottom', () => { imgSnapshotTest( ` %%{init: {"quadrantChart": {"xAxisPosition": "bottom"}}}%% @@ -80,9 +76,8 @@ describe('Quadrant Chart', () => { `, {} ); - cy.get('svg'); }); - it('should able to render x-axix on bottom and y-axis on right', () => { + it('should able to render x-axis on bottom and y-axis on right', () => { imgSnapshotTest( ` %%{init: {"quadrantChart": {"xAxisPosition": "bottom", "yAxisPosition": "right"}}}%% @@ -97,7 +92,6 @@ describe('Quadrant Chart', () => { `, {} ); - cy.get('svg'); }); it('should render without title', () => { imgSnapshotTest( @@ -112,7 +106,6 @@ describe('Quadrant Chart', () => { `, {} ); - cy.get('svg'); }); it('should use all the config', () => { imgSnapshotTest( @@ -135,7 +128,6 @@ describe('Quadrant Chart', () => { `, {} ); - cy.get('svg'); }); it('should use all the theme variable', () => { imgSnapshotTest( @@ -158,7 +150,6 @@ describe('Quadrant Chart', () => { `, {} ); - cy.get('svg'); }); it('should render x-axis labels in the center, if x-axis has two labels', () => { imgSnapshotTest( @@ -180,7 +171,6 @@ describe('Quadrant Chart', () => { `, {} ); - cy.get('svg'); }); it('should render y-axis labels in the center, if y-axis has two labels', () => { imgSnapshotTest( @@ -202,7 +192,6 @@ describe('Quadrant Chart', () => { `, {} ); - cy.get('svg'); }); it('should render both axes labels on the left and bottom, if both axes have only one label', () => { imgSnapshotTest( @@ -224,7 +213,6 @@ describe('Quadrant Chart', () => { `, {} ); - cy.get('svg'); }); it('it should render data points with styles', () => { @@ -249,7 +237,6 @@ describe('Quadrant Chart', () => { `, {} ); - cy.get('svg'); }); it('it should render data points with styles + classes', () => { diff --git a/cypress/integration/rendering/radar.spec.js b/cypress/integration/rendering/radar.spec.js new file mode 100644 index 000000000..b0bc3f6e0 --- /dev/null +++ b/cypress/integration/rendering/radar.spec.js @@ -0,0 +1,79 @@ +import { imgSnapshotTest } from '../../helpers/util'; + +describe('radar structure', () => { + it('should render a simple radar diagram', () => { + imgSnapshotTest( + `radar-beta + title Best Radar Ever + axis A, B, C + curve c1{1, 2, 3} + ` + ); + }); + + it('should render a radar diagram with multiple curves', () => { + imgSnapshotTest( + `radar-beta + title Best Radar Ever + axis A, B, C + curve c1{1, 2, 3} + curve c2{2, 3, 1} + ` + ); + }); + + it('should render a complex radar diagram', () => { + imgSnapshotTest( + `radar-beta + title My favorite ninjas + axis Agility, Speed, Strength + axis Stam["Stamina"] , Intel["Intelligence"] + + curve Ninja1["Naruto Uzumaki"]{ + Agility 2, Speed 2, + Strength 3, Stam 5, + Intel 0 + } + curve Ninja2["Sasuke"]{2, 3, 4, 1, 5} + curve Ninja3 {3, 2, 1, 5, 4} + + showLegend true + ticks 3 + max 8 + min 0 + graticule polygon + ` + ); + cy.get('svg').should((svg) => { + expect(svg).to.have.length(1); + }); + }); + + it('should render radar diagram with config override', () => { + imgSnapshotTest( + `radar-beta + title Best Radar Ever + axis A,B,C + curve mycurve{1,2,3}`, + { radar: { marginTop: 100, axisScaleFactor: 0.5 } } + ); + }); + + it('should parse radar diagram with theme override', () => { + imgSnapshotTest( + `radar-beta + axis A,B,C + curve mycurve{1,2,3}`, + { theme: 'base', themeVariables: { fontSize: 80, cScale0: '#FF0000' } } + ); + }); + + it('should handle radar diagram with radar style override', () => { + imgSnapshotTest( + `radar-beta + axis A,B,C + curve mycurve{1,2,3}`, + { theme: 'base', themeVariables: { radar: { axisColor: '#FF0000' } } } + ); + }); +}); diff --git a/cypress/integration/rendering/requirement.spec.js b/cypress/integration/rendering/requirement.spec.js index f33ae7a0c..343441848 100644 --- a/cypress/integration/rendering/requirement.spec.js +++ b/cypress/integration/rendering/requirement.spec.js @@ -44,6 +44,5 @@ describe('Requirement diagram', () => { `, {} ); - cy.get('svg'); }); }); diff --git a/cypress/integration/rendering/requirementDiagram-unified.spec.js b/cypress/integration/rendering/requirementDiagram-unified.spec.js new file mode 100644 index 000000000..48b1a0d61 --- /dev/null +++ b/cypress/integration/rendering/requirementDiagram-unified.spec.js @@ -0,0 +1,703 @@ +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; + +const testOptions = [ + { description: '', options: { logLevel: 1 } }, + { description: 'ELK: ', options: { logLevel: 1, layout: 'elk' } }, + { description: 'HD: ', options: { logLevel: 1, look: 'handDrawn' } }, +]; + +describe('Requirement Diagram Unified', () => { + testOptions.forEach(({ description, options }) => { + it(`${description}should render a simple Requirement diagram`, () => { + imgSnapshotTest( + ` + requirementDiagram + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + `, + options + ); + }); + + it(`${description}should render a simple Requirement diagram without htmlLabels`, () => { + imgSnapshotTest( + ` + requirementDiagram + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render a not-so-simple Requirement diagram`, () => { + imgSnapshotTest( + ` + requirementDiagram + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + functionalRequirement test_req2 { + id: 1.1 + text: the second test text. + risk: low + verifymethod: inspection + } + + performanceRequirement test_req3 { + id: 1.2 + text: the third test text. + risk: medium + verifymethod: demonstration + } + + interfaceRequirement test_req4 { + id: 1.2.1 + text: the fourth test text. + risk: medium + verifymethod: analysis + } + + physicalRequirement test_req5 { + id: 1.2.2 + text: the fifth test text. + risk: medium + verifymethod: analysis + } + + designConstraint test_req6 { + id: 1.2.3 + text: the sixth test text. + risk: medium + verifymethod: analysis + } + + element test_entity { + type: simulation + } + + element test_entity2 { + type: word doc + docRef: reqs/test_entity + } + + element test_entity3 { + type: "test suite" + docRef: github.com/all_the_tests + } + + + test_entity - satisfies -> test_req2 + test_req - traces -> test_req2 + test_req - contains -> test_req3 + test_req3 - contains -> test_req4 + test_req4 - derives -> test_req5 + test_req5 - refines -> test_req6 + test_entity3 - verifies -> test_req5 + test_req <- copies - test_entity2 + `, + options + ); + }); + + it(`${description}should render a not-so-simple Requirement diagram without htmlLabels`, () => { + imgSnapshotTest( + ` + requirementDiagram + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + functionalRequirement test_req2 { + id: 1.1 + text: the second test text. + risk: low + verifymethod: inspection + } + + performanceRequirement test_req3 { + id: 1.2 + text: the third test text. + risk: medium + verifymethod: demonstration + } + + interfaceRequirement test_req4 { + id: 1.2.1 + text: the fourth test text. + risk: medium + verifymethod: analysis + } + + physicalRequirement test_req5 { + id: 1.2.2 + text: the fifth test text. + risk: medium + verifymethod: analysis + } + + designConstraint test_req6 { + id: 1.2.3 + text: the sixth test text. + risk: medium + verifymethod: analysis + } + + element test_entity { + type: simulation + } + + element test_entity2 { + type: word doc + docRef: reqs/test_entity + } + + element test_entity3 { + type: "test suite" + docRef: github.com/all_the_tests + } + + + test_entity - satisfies -> test_req2 + test_req - traces -> test_req2 + test_req - contains -> test_req3 + test_req3 - contains -> test_req4 + test_req4 - derives -> test_req5 + test_req5 - refines -> test_req6 + test_entity3 - verifies -> test_req5 + test_req <- copies - test_entity2 + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render multiple Requirement diagrams`, () => { + imgSnapshotTest( + [ + ` + requirementDiagram + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + `, + ` + requirementDiagram + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + `, + ], + options + ); + }); + + it(`${description}should render a Requirement diagram with empty information`, () => { + imgSnapshotTest( + ` + requirementDiagram + requirement test_req { + } + element test_entity { + } + `, + options + ); + }); + + it(`${description}should render requirements and elements with and without information`, () => { + renderGraph( + ` + requirementDiagram + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + element test_entity { + } + `, + options + ); + }); + + it(`${description}should render requirements and elements with long and short text`, () => { + renderGraph( + ` + requirementDiagram + requirement test_req { + id: 1 + text: the test text that is long and takes up a lot of space. + risk: high + verifymethod: test + } + element test_entity_name_that_is_extra_long { + } + `, + options + ); + }); + + it(`${description}should render requirements and elements with long and short text without htmlLabels`, () => { + renderGraph( + ` + requirementDiagram + requirement test_req { + id: 1 + text: the test text that is long and takes up a lot of space. + risk: high + verifymethod: test + } + element test_entity_name_that_is_extra_long { + } + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render requirements and elements with quoted text for spaces`, () => { + renderGraph( + ` + requirementDiagram + requirement "test req name with spaces" { + id: 1 + text: the test text that is long and takes up a lot of space. + risk: high + verifymethod: test + } + element "test entity name that is extra long with spaces" { + } + `, + options + ); + }); + + it(`${description}should render requirements and elements with markdown text`, () => { + renderGraph( + ` + requirementDiagram + requirement "__my bolded name__" { + id: 1 + text: "**Bolded text** _italicized text_" + risk: high + verifymethod: test + } + element "*my italicized name*" { + type: "**Bolded type** _italicized type_" + docref: "*Italicized* __Bolded__" + } + `, + options + ); + }); + + it(`${description}should render requirements and elements with markdown text without htmlLabels`, () => { + renderGraph( + ` + requirementDiagram + requirement "__my bolded name__" { + id: 1 + text: "**Bolded text** _italicized text_" + risk: high + verifymethod: test + } + element "*my italicized name*" { + type: "**Bolded type** _italicized type_" + docref: "*Italicized* __Bolded__" + } + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render a simple Requirement diagram with a title`, () => { + imgSnapshotTest( + `--- + title: simple Requirement diagram + --- + requirementDiagram + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + `, + options + ); + }); + + it(`${description}should render a Requirement diagram with TB direction`, () => { + imgSnapshotTest( + ` + requirementDiagram + direction TB + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + `, + options + ); + }); + + it(`${description}should render a Requirement diagram with BT direction`, () => { + imgSnapshotTest( + ` + requirementDiagram + direction BT + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + `, + options + ); + }); + + it(`${description}should render a Requirement diagram with LR direction`, () => { + imgSnapshotTest( + ` + requirementDiagram + direction LR + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + `, + options + ); + }); + + it(`${description}should render a Requirement diagram with RL direction`, () => { + imgSnapshotTest( + ` + requirementDiagram + direction RL + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + `, + options + ); + }); + + it(`${description}should render requirements and elements with styles applied from style statement`, () => { + imgSnapshotTest( + ` + requirementDiagram + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + + style test_req,test_entity fill:#f9f,stroke:blue, color:grey, font-weight:bold + `, + options + ); + }); + + it(`${description}should render requirements and elements with styles applied from style statement without htmlLabels`, () => { + imgSnapshotTest( + ` + requirementDiagram + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + + style test_req,test_entity fill:#f9f,stroke:blue, color:grey, font-weight:bold + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render requirements and elements with styles applied from class statement`, () => { + imgSnapshotTest( + ` +requirementDiagram + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + classDef bold font-weight: bold + classDef blue stroke:lightblue, color: #0000FF + class test_entity bold + class test_req blue, bold + `, + options + ); + }); + + it(`${description}should render requirements and elements with styles applied from class statement without htmlLabels`, () => { + imgSnapshotTest( + ` + requirementDiagram + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + classDef bold font-weight: bold + classDef blue stroke:lightblue, color: #0000FF + class test_entity bold + class test_req blue, bold + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render requirements and elements with styles applied from classes with shorthand syntax`, () => { + imgSnapshotTest( + ` + requirementDiagram + + requirement test_req:::blue { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + classDef bold font-weight: bold + classDef blue stroke:lightblue, color: #0000FF + test_entity:::bold + `, + options + ); + }); + + it(`${description}should render requirements and elements with styles applied from classes with shorthand syntax without htmlLabels`, () => { + imgSnapshotTest( + ` + requirementDiagram + + requirement test_req:::blue { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + classDef bold font-weight: bold + classDef blue stroke:lightblue, color: #0000FF + test_entity:::bold + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render requirements and elements with styles applied from the default class and other styles`, () => { + imgSnapshotTest( + ` +requirementDiagram + + requirement test_req:::blue { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + classDef blue stroke:lightblue, color:blue + classDef default fill:pink + style test_entity color:green + `, + options + ); + }); + + it(`${description}should render requirements and elements with styles applied from the default class and other styles without htmlLabels`, () => { + imgSnapshotTest( + ` + requirementDiagram + + requirement test_req:::blue { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + classDef blue stroke:lightblue, color:blue + classDef default fill:pink + style test_entity color:green + `, + { ...options, htmlLabels: false } + ); + }); + + it(`${description}should render a Requirement diagram with a theme`, () => { + imgSnapshotTest( + ` +--- + theme: forest +--- + requirementDiagram + + requirement test_req:::blue { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + element test_entity { + type: simulation + } + + test_entity - satisfies -> test_req + `, + options + ); + }); + }); +}); diff --git a/cypress/integration/rendering/sequencediagram.spec.js b/cypress/integration/rendering/sequencediagram.spec.js index 1285a0832..f18e99abf 100644 --- a/cypress/integration/rendering/sequencediagram.spec.js +++ b/cypress/integration/rendering/sequencediagram.spec.js @@ -1,8 +1,6 @@ -/// - import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; -context('Sequence diagram', () => { +describe('Sequence diagram', () => { it('should render a sequence diagram with boxes', () => { renderGraph( ` @@ -68,6 +66,19 @@ context('Sequence diagram', () => { { sequence: { actorFontFamily: 'courier' } } ); }); + it('should render bidirectional arrows', () => { + imgSnapshotTest( + ` + sequenceDiagram + Alice<<->>John: Hello John, how are you? + Alice<<-->>John: Hi Alice, I can hear you! + John<<->>Alice: This also works the other way + John<<-->>Alice: Yes + Alice->John: Test + John->>Alice: Still works + ` + ); + }); it('should handle different line breaks', () => { imgSnapshotTest( ` @@ -231,7 +242,7 @@ context('Sequence diagram', () => { ` ); }); - context('font settings', () => { + describe('font settings', () => { it('should render different note fonts when configured', () => { imgSnapshotTest( ` @@ -328,7 +339,7 @@ context('Sequence diagram', () => { ); }); }); - context('auth width scaling', () => { + describe('auth width scaling', () => { it('should render long actor descriptions', () => { imgSnapshotTest( ` @@ -464,6 +475,18 @@ context('Sequence diagram', () => { {} ); }); + it('should render notes over actors and participant', () => { + imgSnapshotTest( + ` + sequenceDiagram + actor Alice + participant Charlie + note over Alice: some note + note over Charlie: other note + `, + {} + ); + }); it('should render long messages from an actor to the left to one to the right', () => { imgSnapshotTest( ` @@ -505,7 +528,7 @@ context('Sequence diagram', () => { ); }); }); - context('background rects', () => { + describe('background rects', () => { it('should render a single and nested rects', () => { imgSnapshotTest( ` @@ -785,7 +808,7 @@ context('Sequence diagram', () => { ); }); }); - context('directives', () => { + describe('directives', () => { it('should override config with directive settings', () => { imgSnapshotTest( ` @@ -817,7 +840,7 @@ context('Sequence diagram', () => { ); }); }); - context('links', () => { + describe('links', () => { it('should support actor links', () => { renderGraph( ` @@ -833,7 +856,7 @@ context('Sequence diagram', () => { ); cy.get('#actor0_popup').should((popupMenu) => { const style = popupMenu.attr('style'); - expect(style).to.undefined; + // expect(style).to.undefined; }); cy.get('#root-0').click(); cy.get('#actor0_popup').should((popupMenu) => { @@ -908,7 +931,7 @@ context('Sequence diagram', () => { ); }); }); - context('svg size', () => { + describe('svg size', () => { it('should render a sequence diagram when useMaxWidth is true (default)', () => { renderGraph( ` @@ -987,7 +1010,7 @@ context('Sequence diagram', () => { }); }); }); - context('render after error', () => { + describe('render after error', () => { it('should render diagram after fixing destroy participant error', () => { cy.on('uncaught:exception', (err) => { return false; diff --git a/cypress/integration/rendering/stateDiagram-v2.spec.js b/cypress/integration/rendering/stateDiagram-v2.spec.js index 9a1a27abe..83190dbc7 100644 --- a/cypress/integration/rendering/stateDiagram-v2.spec.js +++ b/cypress/integration/rendering/stateDiagram-v2.spec.js @@ -8,7 +8,6 @@ describe('State diagram', () => { `, { logLevel: 1, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render a simple state diagrams', () => { imgSnapshotTest( @@ -20,7 +19,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render a long descriptions instead of id when available', () => { imgSnapshotTest( @@ -32,7 +30,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render a long descriptions with additional descriptions', () => { imgSnapshotTest( @@ -44,7 +41,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render a single state with short descriptions', () => { imgSnapshotTest( @@ -55,7 +51,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render a transition descriptions with new lines', () => { imgSnapshotTest( @@ -69,7 +64,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render a state with a note', () => { imgSnapshotTest( @@ -83,7 +77,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render a state with on the left side when so specified', () => { imgSnapshotTest( @@ -97,7 +90,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render a state with a note together with another state', () => { imgSnapshotTest( @@ -113,7 +105,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render a note with multiple lines in it', () => { imgSnapshotTest( @@ -147,8 +138,8 @@ describe('State diagram', () => { imgSnapshotTest( ` stateDiagram-v2 - State1: This a a single line description - State2: This a a multi line description + State1: This a single line description + State2: This a multi line description State2: here comes the multi part [*] --> State1 State1 --> State2 @@ -156,7 +147,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render a simple state diagrams 2', () => { imgSnapshotTest( @@ -169,7 +159,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render a simple state diagrams with labels', () => { imgSnapshotTest( @@ -185,7 +174,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render state descriptions', () => { imgSnapshotTest( @@ -198,7 +186,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render composite states', () => { imgSnapshotTest( @@ -217,7 +204,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render multiple composite states', () => { imgSnapshotTest( @@ -287,7 +273,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render concurrency states', () => { imgSnapshotTest( @@ -311,7 +296,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('v2 should render a state with states in it', () => { imgSnapshotTest( @@ -361,7 +345,7 @@ stateDiagram } ); }); - it('v2 width of compond state should grow with title if title is wider', () => { + it('v2 width of compound state should grow with title if title is wider', () => { imgSnapshotTest( ` stateDiagram-v2 @@ -418,8 +402,8 @@ stateDiagram-v2 ` stateDiagram-v2 MyState - note left of MyState : I am a leftie - note right of MyState : I am a rightie + note left of MyState : I am a lefty + note right of MyState : I am a righty `, { logLevel: 0, @@ -558,6 +542,43 @@ stateDiagram-v2 { logLevel: 0, fontFamily: 'courier' } ); }); + it(' can have styles applied ', () => { + imgSnapshotTest( + ` +stateDiagram-v2 +AState +style AState fill:#636,border:1px solid red,color:white; + `, + { logLevel: 0, fontFamily: 'courier' } + ); + }); + it(' should let styles take precedence over classes', () => { + imgSnapshotTest( + ` +stateDiagram-v2 +AState: Should NOT be white +BState +classDef exampleStyleClass fill:#fff,color: blue; +class AState,BState exampleStyleClass +style AState fill:#636,border:1px solid red,color:white; + `, + { logLevel: 0, fontFamily: 'courier' } + ); + }); + it(' should allow styles to take effect in subgraphs', () => { + imgSnapshotTest( + ` + stateDiagram + state roundWithTitle { + C: Black with white text + } + D: Black with white text + + style C,D stroke:#00f, fill:black, color:white + `, + { logLevel: 0, fontFamily: 'courier' } + ); + }); }); it('1433: should render a simple state diagram with a title', () => { imgSnapshotTest( @@ -567,6 +588,20 @@ title: simple state diagram stateDiagram-v2 [*] --> State1 State1 --> [*] +`, + {} + ); + }); + it('should align dividers correctly', () => { + imgSnapshotTest( + `stateDiagram-v2 + state s2 { + s3 + -- + s4 + -- + 55 + } `, {} ); diff --git a/cypress/integration/rendering/stateDiagram.spec.js b/cypress/integration/rendering/stateDiagram.spec.js index 01e7a2b44..b4c5fa8c1 100644 --- a/cypress/integration/rendering/stateDiagram.spec.js +++ b/cypress/integration/rendering/stateDiagram.spec.js @@ -10,7 +10,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render a long descriptions instead of id when available', () => { imgSnapshotTest( @@ -22,7 +21,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render a long descriptions with additional descriptions', () => { imgSnapshotTest( @@ -34,7 +32,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render a single state with short descriptions', () => { imgSnapshotTest( @@ -45,7 +42,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render a transition descriptions with new lines', () => { imgSnapshotTest( @@ -59,7 +55,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render a state with a note', () => { imgSnapshotTest( @@ -73,7 +68,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render a state with on the left side when so specified', () => { imgSnapshotTest( @@ -87,7 +81,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render a state with a note together with another state', () => { imgSnapshotTest( @@ -103,7 +96,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render a note with multiple lines in it', () => { imgSnapshotTest( @@ -137,8 +129,8 @@ describe('State diagram', () => { imgSnapshotTest( ` stateDiagram - State1: This a a single line description - State2: This a a multi line description + State1: This a single line description + State2: This a multi line description State2: here comes the multi part [*] --> State1 State1 --> State2 @@ -146,7 +138,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render a simple state diagrams 2', () => { imgSnapshotTest( @@ -159,7 +150,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render a simple state diagrams with labels', () => { imgSnapshotTest( @@ -175,7 +165,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render state descriptions', () => { imgSnapshotTest( @@ -188,7 +177,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render composite states', () => { imgSnapshotTest( @@ -207,7 +195,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render multiple composit states', () => { imgSnapshotTest( @@ -277,7 +264,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render concurrency states', () => { imgSnapshotTest( @@ -301,7 +287,6 @@ describe('State diagram', () => { `, { logLevel: 0, fontFamily: 'courier' } ); - cy.get('svg'); }); it('should render a state with states in it', () => { imgSnapshotTest( diff --git a/cypress/integration/rendering/theme.spec.js b/cypress/integration/rendering/theme.spec.js index c84ad0c4b..1965f8c99 100644 --- a/cypress/integration/rendering/theme.spec.js +++ b/cypress/integration/rendering/theme.spec.js @@ -10,7 +10,6 @@ describe('themeCSS balancing, it', () => { `, {} ); - cy.get('svg'); }); it('should not allow unbalanced CSS definitions 2', () => { imgSnapshotTest( @@ -21,7 +20,6 @@ describe('themeCSS balancing, it', () => { `, {} ); - cy.get('svg'); }); }); @@ -45,7 +43,6 @@ describe('Pie Chart', () => { `, { theme } ); - cy.get('svg'); }); it('should render a flowchart diagram', () => { imgSnapshotTest( @@ -70,7 +67,6 @@ describe('Pie Chart', () => { `, { theme } ); - cy.get('svg'); }); it('should render a new flowchart diagram', () => { imgSnapshotTest( @@ -96,7 +92,6 @@ describe('Pie Chart', () => { `, { theme } ); - cy.get('svg'); }); it('should render a sequence diagram', () => { imgSnapshotTest( @@ -125,7 +120,6 @@ describe('Pie Chart', () => { `, { theme } ); - cy.get('svg'); }); it('should render a class diagram', () => { @@ -175,7 +169,6 @@ describe('Pie Chart', () => { `, { theme } ); - cy.get('svg'); }); it('should render a state diagram', () => { imgSnapshotTest( @@ -210,7 +203,6 @@ stateDiagram `, { theme } ); - cy.get('svg'); }); it('should render a state diagram (v2)', () => { imgSnapshotTest( @@ -245,7 +237,6 @@ stateDiagram-v2 `, { theme } ); - cy.get('svg'); }); it('should render a er diagram', () => { imgSnapshotTest( @@ -266,7 +257,6 @@ erDiagram `, { theme } ); - cy.get('svg'); }); it('should render a user journey diagram', () => { imgSnapshotTest( @@ -287,7 +277,6 @@ erDiagram `, { theme } ); - cy.get('svg'); }); it('should render a gantt diagram', () => { cy.clock(new Date('2014-01-06').getTime()); @@ -326,7 +315,6 @@ erDiagram `, { theme } ); - cy.get('svg'); }); }); }); diff --git a/cypress/integration/rendering/timeline.spec.ts b/cypress/integration/rendering/timeline.spec.ts index c748b54d3..dc6fab364 100644 --- a/cypress/integration/rendering/timeline.spec.ts +++ b/cypress/integration/rendering/timeline.spec.ts @@ -7,7 +7,7 @@ describe('Timeline diagram', () => { title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter `, {} @@ -35,7 +35,7 @@ describe('Timeline diagram', () => { section Stone Age 7600 BC : Britain's oldest known house was built in Orkney, Scotland 6000 BC : Sea levels rise and Britain becomes an island.
The people who live here are hunter-gatherers. - section Broze Age + section Bronze Age 2300 BC : People arrive from Europe and settle in Britain.
They bring farming and metalworking. : New styles of pottery and ways of burying the dead appear. 2200 BC : The last major building works are completed at Stonehenge.
People now bury their dead in stone circles. @@ -51,7 +51,7 @@ describe('Timeline diagram', () => { title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter `, {} @@ -68,7 +68,7 @@ describe('Timeline diagram', () => { title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -84,7 +84,7 @@ describe('Timeline diagram', () => { title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -101,7 +101,7 @@ describe('Timeline diagram', () => { title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -118,7 +118,7 @@ describe('Timeline diagram', () => { title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -135,7 +135,7 @@ describe('Timeline diagram', () => { title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -152,7 +152,7 @@ describe('Timeline diagram', () => { title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram diff --git a/cypress/integration/rendering/xyChart.spec.js b/cypress/integration/rendering/xyChart.spec.js index 85d998c50..a582355e8 100644 --- a/cypress/integration/rendering/xyChart.spec.js +++ b/cypress/integration/rendering/xyChart.spec.js @@ -9,7 +9,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('Should render a complete chart', () => { imgSnapshotTest( @@ -35,7 +34,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('y-axis title not required', () => { imgSnapshotTest( @@ -48,7 +46,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('Should render a chart without y-axis with different range', () => { imgSnapshotTest( @@ -60,7 +57,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('x axis title not required', () => { imgSnapshotTest( @@ -72,7 +68,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('Multiple plots can be rendered', () => { imgSnapshotTest( @@ -87,7 +82,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('Decimals and negative numbers are supported', () => { imgSnapshotTest( @@ -98,7 +92,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('Render spark line with "plotReservedSpacePercent"', () => { imgSnapshotTest( @@ -116,7 +109,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('Render spark bar without displaying other property', () => { imgSnapshotTest( @@ -143,7 +135,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('Should use all the config from directive', () => { imgSnapshotTest( @@ -158,7 +149,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('Should use all the config from yaml', () => { imgSnapshotTest( @@ -189,6 +179,7 @@ describe('XY Chart', () => { axisLineWidth: 5 chartOrientation: horizontal plotReservedSpacePercent: 60 + showDataLabel: true --- xychart-beta title "Sales Revenue" @@ -199,7 +190,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('Render with show axis title false', () => { imgSnapshotTest( @@ -221,7 +211,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('Render with show axis label false', () => { imgSnapshotTest( @@ -243,7 +232,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('Render with show axis tick false', () => { imgSnapshotTest( @@ -265,7 +253,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('Render with show axis line false', () => { imgSnapshotTest( @@ -287,7 +274,6 @@ describe('XY Chart', () => { `, {} ); - cy.get('svg'); }); it('Render all the theme color', () => { imgSnapshotTest( @@ -317,6 +303,529 @@ describe('XY Chart', () => { `, {} ); + }); + it('should use the correct distances between data points', () => { + imgSnapshotTest( + ` + xychart-beta + x-axis 0 --> 2 + line [0, 1, 0, 1] + bar [1, 0, 1, 0] + `, + {} + ); cy.get('svg'); }); + + it('should render vertical bar chart with labels', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + --- + xychart-beta + title "Sales Revenue" + x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] + y-axis "Revenue (in $)" 4000 --> 11000 + bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] + `, + {} + ); + }); + + it('should render horizontal bar chart with labels', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + chartOrientation: horizontal + --- + xychart-beta + title "Sales Revenue" + x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] + y-axis "Revenue (in $)" 4000 --> 11000 + bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] + `, + {} + ); + }); + + it('should render vertical bar chart without labels by default', () => { + imgSnapshotTest( + ` + xychart-beta + title "Sales Revenue" + x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] + y-axis "Revenue (in $)" 4000 --> 11000 + bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] + `, + {} + ); + }); + + it('should render horizontal bar chart without labels by default', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + chartOrientation: horizontal + --- + xychart-beta + title "Sales Revenue" + x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] + y-axis "Revenue (in $)" 4000 --> 11000 + bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] + `, + {} + ); + }); + + it('should render multiple bar plots vertically with labels correctly', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + --- + xychart-beta + title "Multiple Bar Plots" + x-axis Categories [A, B, C] + y-axis "Values" 0 --> 100 + bar [10, 50, 90] + `, + {} + ); + }); + + it('should render multiple bar plots horizontally with labels correctly', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + chartOrientation: horizontal + --- + xychart-beta + title "Multiple Bar Plots" + x-axis Categories [A, B, C] + y-axis "Values" 0 --> 100 + bar [10, 50, 90] + `, + {} + ); + }); + + it('should render a single bar with label for a vertical xy-chart', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + --- + xychart-beta + title "Single Bar Chart" + x-axis Categories [A] + y-axis "Value" 0 --> 100 + bar [75] + `, + {} + ); + }); + + it('should render a single bar with label for a horizontal xy-chart', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + chartOrientation: horizontal + --- + xychart-beta + title "Single Bar Chart" + x-axis Categories [A] + y-axis "Value" 0 --> 100 + bar [75] + `, + {} + ); + }); + + it('should render negative and decimal values with correct labels for vertical xy-chart', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + --- + xychart-beta + title "Decimal and Negative Values" + x-axis Categories [A, B, C] + y-axis -10 --> 10 + bar [ -2.5, 0.75, 5.1 ] + `, + {} + ); + }); + + it('should render negative and decimal values with correct labels for horizontal xy-chart', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + chartOrientation: horizontal + --- + xychart-beta + title "Decimal and Negative Values" + x-axis Categories [A, B, C] + y-axis -10 --> 10 + bar [ -2.5, 0.75, 5.1 ] + `, + {} + ); + }); + + it('should render data labels within each bar in the vertical xy-chart', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + --- + xychart-beta + title "Sales Revenue" + x-axis Months [jan,b,c] + y-axis "Revenue (in $)" 4000 --> 12000 + bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000, 3000, 2000, 500, 2000, 3000, 11000, 5000, 6000] + `, + {} + ); + + cy.get('g.bar-plot-0').within(() => { + cy.get('rect').each(($rect, index) => { + // Extract bar properties + const barProps = { + x: parseFloat($rect.attr('x')), + y: parseFloat($rect.attr('y')), + width: parseFloat($rect.attr('width')), + height: parseFloat($rect.attr('height')), + }; + + // Get the text element corresponding to this bar by index. + cy.get('text') + .eq(index) + .then(($text) => { + const bbox = $text[0].getBBox(); + const textProps = { + x: bbox.x, + y: bbox.y, + width: bbox.width, + height: bbox.height, + }; + + // Verify that the text label is positioned within the boundaries of the bar. + expect(textProps.x).to.be.greaterThan(barProps.x); + expect(textProps.x + textProps.width).to.be.lessThan(barProps.x + barProps.width); + + // Check horizontal alignment (within tolerance) + expect(textProps.x + textProps.width / 2).to.be.closeTo( + barProps.x + barProps.width / 2, + 5 + ); + + expect(textProps.y).to.be.greaterThan(barProps.y); + expect(textProps.y + textProps.height).to.be.lessThan(barProps.y + barProps.height); + }); + }); + }); + }); + + it('should render data labels within each bar in the horizontal xy-chart', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + chartOrientation: horizontal + --- + xychart-beta + title "Sales Revenue" + x-axis Months [jan,b,c] + y-axis "Revenue (in $)" 4000 --> 12000 + bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000, 3000, 2000, 500, 2000, 3000, 11000, 5000, 6000] + `, + {} + ); + + cy.get('g.bar-plot-0').within(() => { + cy.get('rect').each(($rect, index) => { + // Extract bar properties + const barProps = { + x: parseFloat($rect.attr('x')), + y: parseFloat($rect.attr('y')), + width: parseFloat($rect.attr('width')), + height: parseFloat($rect.attr('height')), + }; + + // Get the text element corresponding to this bar by index. + cy.get('text') + .eq(index) + .then(($text) => { + const bbox = $text[0].getBBox(); + const textProps = { + x: bbox.x, + y: bbox.y, + width: bbox.width, + height: bbox.height, + }; + + // Verify that the text label is positioned within the boundaries of the bar. + expect(textProps.x).to.be.greaterThan(barProps.x); + expect(textProps.x + textProps.width).to.be.lessThan(barProps.x + barProps.width); + + expect(textProps.y).to.be.greaterThan(barProps.y); + expect(textProps.y + textProps.height).to.be.lessThan(barProps.y + barProps.height); + expect(textProps.y + textProps.height / 2).to.be.closeTo( + barProps.y + barProps.height / 2, + 5 + ); + }); + }); + }); + }); + + it('should render data labels within each bar in the vertical xy-chart with a lot of bars of different sizes', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + --- + xychart-beta + title "Sales Revenue" + x-axis Months [jan,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s] + y-axis "Revenue (in $)" 4000 --> 12000 + bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000, 8000, 10000, 5000, 7600, 4999,11000 ,5000,6000] + `, + {} + ); + + cy.get('g.bar-plot-0').within(() => { + cy.get('rect').each(($rect, index) => { + // Extract bar properties + const barProps = { + x: parseFloat($rect.attr('x')), + y: parseFloat($rect.attr('y')), + width: parseFloat($rect.attr('width')), + height: parseFloat($rect.attr('height')), + }; + + // Get the text element corresponding to this bar by index. + cy.get('text') + .eq(index) + .then(($text) => { + const bbox = $text[0].getBBox(); + const textProps = { + x: bbox.x, + y: bbox.y, + width: bbox.width, + height: bbox.height, + }; + + // Verify that the text label is positioned within the boundaries of the bar. + expect(textProps.x).to.be.greaterThan(barProps.x); + expect(textProps.x + textProps.width).to.be.lessThan(barProps.x + barProps.width); + + // Check horizontal alignment (within tolerance) + expect(textProps.x + textProps.width / 2).to.be.closeTo( + barProps.x + barProps.width / 2, + 5 + ); + + expect(textProps.y).to.be.greaterThan(barProps.y); + expect(textProps.y + textProps.height).to.be.lessThan(barProps.y + barProps.height); + }); + }); + }); + }); + + it('should render data labels within each bar in the horizontal xy-chart with a lot of bars of different sizes', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + chartOrientation: horizontal + --- + xychart-beta + title "Sales Revenue" + x-axis Months [jan,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s] + y-axis "Revenue (in $)" 4000 --> 12000 + bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000, 8000, 10000, 5000, 7600, 4999,11000 ,5000,6000] + `, + {} + ); + + cy.get('g.bar-plot-0').within(() => { + cy.get('rect').each(($rect, index) => { + // Extract bar properties + const barProps = { + x: parseFloat($rect.attr('x')), + y: parseFloat($rect.attr('y')), + width: parseFloat($rect.attr('width')), + height: parseFloat($rect.attr('height')), + }; + + // Get the text element corresponding to this bar by index. + cy.get('text') + .eq(index) + .then(($text) => { + const bbox = $text[0].getBBox(); + const textProps = { + x: bbox.x, + y: bbox.y, + width: bbox.width, + height: bbox.height, + }; + + // Verify that the text label is positioned within the boundaries of the bar. + expect(textProps.x).to.be.greaterThan(barProps.x); + expect(textProps.x + textProps.width).to.be.lessThan(barProps.x + barProps.width); + + expect(textProps.y).to.be.greaterThan(barProps.y); + expect(textProps.y + textProps.height).to.be.lessThan(barProps.y + barProps.height); + expect(textProps.y + textProps.height / 2).to.be.closeTo( + barProps.y + barProps.height / 2, + 5 + ); + }); + }); + }); + }); + + it('should render data labels correctly for a bar in the vertical xy-chart', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + --- + xychart-beta + title "Sales Revenue" + x-axis Months [jan] + y-axis "Revenue (in $)" 3000 --> 12000 + bar [4000] + `, + {} + ); + + cy.get('g.bar-plot-0').within(() => { + cy.get('rect').each(($rect, index) => { + // Extract bar properties + const barProps = { + x: parseFloat($rect.attr('x')), + y: parseFloat($rect.attr('y')), + width: parseFloat($rect.attr('width')), + height: parseFloat($rect.attr('height')), + }; + + // Get the text element corresponding to this bar by index. + cy.get('text') + .eq(index) + .then(($text) => { + const bbox = $text[0].getBBox(); + const textProps = { + x: bbox.x, + y: bbox.y, + width: bbox.width, + height: bbox.height, + }; + + // Verify that the text label is positioned within the boundaries of the bar. + expect(textProps.x).to.be.greaterThan(barProps.x); + expect(textProps.x + textProps.width).to.be.lessThan(barProps.x + barProps.width); + + // Check horizontal alignment (within tolerance) + expect(textProps.x + textProps.width / 2).to.be.closeTo( + barProps.x + barProps.width / 2, + 5 + ); + + expect(textProps.y).to.be.greaterThan(barProps.y); + expect(textProps.y + textProps.height).to.be.lessThan(barProps.y + barProps.height); + }); + }); + }); + }); + + it('should render data labels correctly for a bar in the horizontal xy-chart', () => { + imgSnapshotTest( + ` + --- + config: + xyChart: + showDataLabel: true + chartOrientation: horizontal + --- + xychart-beta + title "Sales Revenue" + x-axis Months [jan] + y-axis "Revenue (in $)" 3000 --> 12000 + bar [4000] + `, + {} + ); + + cy.get('g.bar-plot-0').within(() => { + cy.get('rect').each(($rect, index) => { + // Extract bar properties + const barProps = { + x: parseFloat($rect.attr('x')), + y: parseFloat($rect.attr('y')), + width: parseFloat($rect.attr('width')), + height: parseFloat($rect.attr('height')), + }; + + // Get the text element corresponding to this bar by index. + cy.get('text') + .eq(index) + .then(($text) => { + const bbox = $text[0].getBBox(); + const textProps = { + x: bbox.x, + y: bbox.y, + width: bbox.width, + height: bbox.height, + }; + + // Verify that the text label is positioned within the boundaries of the bar. + expect(textProps.x).to.be.greaterThan(barProps.x); + expect(textProps.x + textProps.width).to.be.lessThan(barProps.x + barProps.width); + + expect(textProps.y).to.be.greaterThan(barProps.y); + expect(textProps.y + textProps.height).to.be.lessThan(barProps.y + barProps.height); + expect(textProps.y + textProps.height / 2).to.be.closeTo( + barProps.y + barProps.height / 2, + 5 + ); + }); + }); + }); + }); }); diff --git a/cypress/platform/architecture-external.html b/cypress/platform/architecture-external.html new file mode 100644 index 000000000..71770425d --- /dev/null +++ b/cypress/platform/architecture-external.html @@ -0,0 +1,52 @@ + + + + + + Architecture Mermaid Test Page + + + + + +

External Icons Demo

+
+    architecture-beta
+      service s3(logos:aws-s3)[Cloud Store]
+      service ec2(logos:aws-ec2)[Server]
+      service api(logos:aws-api-gateway)[Api Gateway]
+      service fa(fa:image)[Font Awesome Icon]
+    
+ + + + diff --git a/cypress/platform/ashish2.html b/cypress/platform/ashish2.html index f9132d2e2..30584295d 100644 --- a/cypress/platform/ashish2.html +++ b/cypress/platform/ashish2.html @@ -4,7 +4,7 @@ timeline title My day - section section with no tasks + section Section with no tasks section Go to work at the dog office 1930 : first step : second step is a long step : third step @@ -70,18 +70,18 @@ 1960 : India fights poverty, looses war to China and gets nuclear weapons from USA and USSR 1970 : Green Revolution comes to india section Another section with no tasks - I am a big big big tasks - I am not so big tasks + I am a very, very big task + I am not so big task
  timeline
         title MermaidChart 2023 Timeline
         section 2023 Q1 
Release Personal Tier - Buttet 1 : sub-point 1a : sub-point 1b + Bullet 1 : sub-point 1a : sub-point 1b : sub-point 1c Bullet 2 : sub-point 2a : sub-point 2b section 2023 Q2
Release XYZ Tier - Buttet 3 : sub-point
3a : sub-point 3b + Bullet 3 : sub-point
3a : sub-point 3b : sub-point 3c Bullet 4 : sub-point 4a : sub-point 4b @@ -93,7 +93,7 @@ section Stone Age 7600 BC : Britain's oldest known house was built in Orkney, Scotland 6000 BC : Sea levels rise and Britain becomes an island. The people who live here are hunter-gatherers. - section Broze Age + section Bronze Age 2300 BC : People arrive from Europe and settle in Britain. They bring farming and metalworking. : New styles of pottery and ways of burying the dead appear. 2200 BC : The last major building works are completed at Stonehenge. People now bury their dead in stone circles. @@ -106,7 +106,7 @@ title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google : Pixar - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008s : Instagram @@ -122,7 +122,7 @@ title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google : Pixar - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008s : Instagram @@ -139,7 +139,7 @@ title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -152,7 +152,7 @@ title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008s : Instagram diff --git a/cypress/platform/bundle-test.js b/cypress/platform/bundle-test.js index f5bf0ecd6..24ce8d753 100644 --- a/cypress/platform/bundle-test.js +++ b/cypress/platform/bundle-test.js @@ -27,7 +27,7 @@ const code3 = `flowchart TD A() B(Bold text!)`; -if (location.href.match('test-html-escaping')) { +if (/test-html-escaping/.exec(location.href)) { code = code3; } diff --git a/cypress/platform/class.html b/cypress/platform/class.html index 0b1a5729a..b649d1184 100644 --- a/cypress/platform/class.html +++ b/cypress/platform/class.html @@ -3,7 +3,7 @@ diff --git a/cypress/platform/current.html b/cypress/platform/current.html index ab017806f..6502fe1e8 100644 --- a/cypress/platform/current.html +++ b/cypress/platform/current.html @@ -4,7 +4,7 @@ sub2 end subgraph S2 sub4 end S1 --> S2 sub1 --> sub4
- sequenceDiagram Alice->>Bob:Extremely utterly long line of longness which had preivously + sequenceDiagram Alice->>Bob:Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be Bob->>Alice: I'm short though
@@ -61,9 +61,9 @@ #quot;elit#quot;."}}
- flowchart TB internet nat routeur lb1 lb2 compute1 compute2 subgraph project routeur nat - subgraph subnet1 compute1 lb1 end subgraph subnet2 compute2 lb2 end end internet --> routeur - routeur --> subnet1 & subnet2 subnet1 & subnet2 --> nat --> internet + flowchart TB internet nat router lb1 lb2 compute1 compute2 subgraph project router nat + subgraph subnet1 compute1 lb1 end subgraph subnet2 compute2 lb2 end end internet --> router + router --> subnet1 & subnet2 subnet1 & subnet2 --> nat --> internet
flowchart TD subgraph one[One] subgraph sub_one[Sub One] _sub_one end end subgraph two[Two] diff --git a/cypress/platform/current2.html b/cypress/platform/current2.html index cd3ed6401..7bbf635ed 100644 --- a/cypress/platform/current2.html +++ b/cypress/platform/current2.html @@ -4,7 +4,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DagreDagre with roughELKELK with rough
+ +
+
+
+              flowchart LR
+              id1([This is the text in the box])
+            
+
+
+
+
+flowchart LR
+    id1([This is the text in the box])
+
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+flowchart LR
+    id1([This is the text in the box])
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+flowchart LR
+    id1([This is the text in the box])
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+flowchart LR
+    id1([This is the text in the box])
+      
+
+ +
+
+
+      flowchart LR
+    id1[[This is the text in the box]]
+    
+
+
+
+
+flowchart LR
+    id1[[This is the text in the box]]
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+flowchart LR
+    id1[[This is the text in the box]]
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+flowchart LR
+    id1[[This is the text in the box]]
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+flowchart LR
+    id1[[This is the text in the box]]
+      
+
+ +
+
+
+              flowchart LR
+    id1[(Database)]
+    
+
+
+
+
+          flowchart LR
+    id1[(Database)]
+      
+
+
+          %%{init: {"look": "handDrawn"} }%%
+          flowchart LR
+    id1[(Database)]
+      
+
+
+          %%{init: {"handDrawn": false, "layout": "elk"} }%%
+          flowchart LR
+    id1[(Database)]
+      
+
+
+          %%{init: {"look": "handDrawn", "layout": "elk"} }%%
+          flowchart LR
+    id1[(Database)]
+      
+
+ +
+
+
+              flowchart LR
+    id1((This is the text in the circle))
+    
+
+
+
+
+          flowchart LR
+    id1((This is the text in the circle))
+      
+
+
+          %%{init: {"look": "handDrawn"} }%%
+          flowchart LR
+    id1((This is the text in the circle))
+      
+
+
+          %%{init: {"handDrawn": false, "layout": "elk"} }%%
+          flowchart LR
+    id1((This is the text in the circle))
+      
+
+
+          %%{init: {"look": "handDrawn", "layout": "elk"} }%%
+          flowchart LR
+    id1((This is the text in the circle))
+      
+
+ +
+
+
+              flowchart TD
+    id1(((This is the text in the circle)))
+    
+
+
+
+
+          flowchart TD
+    id1(((This is the text in the circle)))
+      
+
+
+          %%{init: {"look": "handDrawn"} }%%
+          flowchart TD
+    id1(((This is the text in the circle)))
+      
+
+
+          %%{init: {"handDrawn": false, "layout": "elk"} }%%
+          flowchart TD
+    id1(((This is the text in the circle)))
+      
+
+
+          %%{init: {"look": "handDrawn", "layout": "elk"} }%%
+          flowchart TD
+    id1(((This is the text in the circle)))
+      
+
+ +
+
+
+              flowchart LR
+    id1>This is the text in the box]
+    
+
+
+
+
+          flowchart LR
+    id1>This is the text in the box]
+      
+
+
+          %%{init: {"look": "handDrawn"} }%%
+          flowchart LR
+    id1>This is the text in the box]  
+      
+
+
+          %%{init: {"handDrawn": false, "layout": "elk"} }%%
+          flowchart LR
+    id1>This is the text in the box]  
+      
+
+
+          %%{init: {"look": "handDrawn", "layout": "elk"} }%%
+          flowchart LR
+    id1>This is the text in the box]
+      
+
+ +
+
+
+              flowchart LR
+    id1{This is the text in the box}
+    
+
+
+
+
+          flowchart LR
+    id1{This is the text in the box}
+      
+
+
+          %%{init: {"look": "handDrawn"} }%%
+          flowchart LR
+    id1{This is the text in the box}
+      
+
+
+          %%{init: {"handDrawn": false, "layout": "elk"} }%%
+          flowchart LR
+    id1{This is the text in the box}
+      
+
+
+          %%{init: {"look": "handDrawn", "layout": "elk"} }%%
+          flowchart LR
+    id1{This is the text in the box}
+      
+
+ +
+
+
+              flowchart LR
+    id1{{This is the text in the box}}
+    
+
+
+
+
+          flowchart LR
+    id1{{This is the text in the box}}
+      
+
+
+          %%{init: {"handDrawn": false, "layout": "elk"} }%%
+          flowchart LR
+    id1{{This is the text in the box}}
+      
+
+
+          %%{init: {"look": "handDrawn", "layout": "elk"} }%%
+          flowchart LR
+    id1{{This is the text in the box}}
+      
+
+ +
+
+
+              flowchart TD
+    id1[/This is the text in the box/]
+    
+
+
+
+
+          flowchart TD
+    id1[/This is the text in the box/]
+      
+
+
+          %%{init: {"look": "handDrawn"} }%%
+          flowchart TD
+    id1[/This is the text in the box/]  
+      
+
+
+          %%{init: {"handDrawn": false, "layout": "elk"} }%%
+          flowchart TD
+    id1[/This is the text in the box/] 
+      
+
+
+          %%{init: {"look": "handDrawn", "layout": "elk"} }%%
+          flowchart TD
+    id1[/This is the text in the box/]
+      
+
+ +
+
+
+              flowchart TD
+    id1[\This is the text in the box\]
+    
+
+
+
+
+          flowchart TD
+    id1[\This is the text in the box\]
+      
+
+
+          %%{init: {"look": "handDrawn"} }%%
+          flowchart TD
+    id1[\This is the text in the box\]
+      
+
+
+          %%{init: {"handDrawn": false, "layout": "elk"} }%%
+          flowchart TD
+    id1[\This is the text in the box\]
+      
+
+
+          %%{init: {"look": "handDrawn", "layout": "elk"} }%%
+          flowchart TD
+    id1[\This is the text in the box\]
+
+      
+
+ +
+
+
+              flowchart TD
+    A[/Christmas\]
+    
+
+
+
+
+          flowchart TD
+    A[/Christmas\]
+      
+
+
+          %%{init: {"look": "handDrawn"} }%%
+          flowchart TD
+    A[/Christmas\]
+      
+
+
+          %%{init: {"handDrawn": false, "layout": "elk"} }%%
+          flowchart TD
+    A[/Christmas\]
+      
+
+
+          %%{init: {"look": "handDrawn", "layout": "elk"} }%%
+          flowchart TD
+    A[/Christmas\]
+      
+
+ +
+
+
+              flowchart TD
+    A[\Christmas/]
+    
+
+
+
+
+          flowchart TD
+    A[\Christmas/]
+      
+
+
+          %%{init: {"look": "handDrawn"} }%%
+          flowchart TD
+    A[\Christmas/]
+      
+
+
+          %%{init: {"handDrawn": false, "layout": "elk"} }%%
+          flowchart TD
+    A[\Christmas/]
+      
+
+
+          %%{init: {"look": "handDrawn", "layout": "elk"} }%%
+          flowchart TD
+    A[\Christmas/]  
+      
+
+ +
+
+
+              flowchart LR
+    id1(This is the text in the box)
+    
+
+
+
+
+          flowchart LR
+    id1(This is the text in the box)
+      
+
+
+          %%{init: {"look": "handDrawn"} }%%
+          flowchart LR
+    id1(This is the text in the box)
+      
+
+
+          %%{init: {"handDrawn": false, "layout": "elk"} }%%
+          flowchart LR
+    id1(This is the text in the box)
+      
+
+
+          %%{init: {"look": "handDrawn", "layout": "elk"} }%%
+          flowchart LR
+    id1(This is the text in the box) 
+      
+
+ +
+
+
+              flowchart LR
+    id1[This is the text in the box]
+    
+
+
+
+
+          flowchart LR
+    id1[This is the text in the box]
+      
+
+
+          %%{init: {"look": "handDrawn"} }%%
+          flowchart LR
+    id1[This is the text in the box]
+      
+
+
+          %%{init: {"handDrawn": false, "layout": "elk"} }%%
+          flowchart LR
+    id1[This is the text in the box]
+      
+
+
+          %%{init: {"look": "handDrawn", "layout": "elk"} }%%
+          flowchart LR
+    id1[This is the text in the box]
+      
+
+ + + + diff --git a/cypress/platform/flowchart-state.html b/cypress/platform/flowchart-state.html new file mode 100644 index 000000000..8fb0fde6d --- /dev/null +++ b/cypress/platform/flowchart-state.html @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
State roughFlowchart rough
+ +
+
+
+      flowchart LR
+    id1([This is the text in the box])
+
+  
+
+
+
+
+%%{init: {"look": "handDrawn"} }%%
+stateDiagram-v2
+    stateA
+
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+flowchart LR
+    id1[[This is the text in the box]]
+
+
+      
+
+ + + + diff --git a/cypress/platform/ghsa3.html b/cypress/platform/ghsa3.html index 95436abff..b0ce2415a 100644 --- a/cypress/platform/ghsa3.html +++ b/cypress/platform/ghsa3.html @@ -4,7 +4,7 @@ diff --git a/cypress/platform/gitgraph.html b/cypress/platform/gitgraph.html index 0b9096798..1270f81cd 100644 --- a/cypress/platform/gitgraph.html +++ b/cypress/platform/gitgraph.html @@ -3,7 +3,7 @@ + + + + + + + + + +
+stateDiagram-v2
+    [*] --> Still
+    Still --> [*]
+    Still --> Moving
+    Moving --> Still
+    Moving --> Crash
+    Crash --> [*]    
+
+flowchart RL
+    subgraph "`one`"
+      a1 -- l1 --> a2
+      a1 -- l2 --> a2
+    end
+    
+
+flowchart RL
+    subgraph "`one`"
+      a1 -- l1 --> a2
+      a1 -- l2 --> a2
+    end
+    
+
+flowchart
+id["`A root with a long text that wraps to keep the node size in check. A root with a long text that wraps to keep the node size in check`"]
+
+flowchart LR
+    A[A text that needs to be wrapped wraps to another line]
+    B[A text that needs to be
wrapped wraps to another line] + C["`A text that needs to be wrapped to another line`"]
+
+flowchart LR
+    C["`A text
+        that needs
+        to be wrapped
+        in another
+        way`"]
+  
+
+      classDiagram-v2
+        note "I love this diagram!\nDo you love it?"
+    
+
+    stateDiagram-v2
+    State1: The state with a note with minus - and plus + in it
+    note left of State1
+      Important information! You can write
+      notes with . and  in them.
+    end note    
+
+mindmap
+root
+  Child3(A node with an icon and with a long text that wraps to keep the node size in check)
+
+
+      %%{init: {"theme": "forest"} }%%
+mindmap
+    id1[**Start2**
end] + id2[**Start2**
end] + %% Another comment + id3[**Start2**
end] %% Comment + id4[**Start2**
end
the very end] +
+
+mindmap
+    id1["`**Start2**
+    second line 😎 with long text that is wrapping to the next line`"]
+      id2["`Child **with bold** text`"]
+      id3["`Children of which some
+      is using *italic type of* text`"]
+      id4[Child]
+      id5["`Child
+      Row
+      and another
+      `"]
+    
+
+mindmap
+    id1("`**Root**`"]
+      id2["`A formatted text... with **bold** and *italics*`"]
+      id3[Regular labels works as usual]
+      id4["`Emojis and unicode works too: 🤓
+      ā¤ļā¤žā¤¨āĨā¤¤ā¤ŋ⤃ ØŗŲ„Ø§Ų…  å’Œåšŗ `"]
+
+    
+
+%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
+flowchart TB
+  %% I could not figure out how to use double quotes in labels in Mermaid
+  subgraph ibm[IBM Espresso CPU]
+    core0[IBM PowerPC Broadway Core 0]
+    core1[IBM PowerPC Broadway Core 1]
+    core2[IBM PowerPC Broadway Core 2]
+
+    rom[16 KB ROM]
+
+    core0 --- core2
+
+    rom --> core2
+  end
+
+  subgraph amd["`**AMD** Latte GPU`"]
+    mem[Memory & I/O Bridge]
+    dram[DRAM Controller]
+    edram[32 MB EDRAM MEM1]
+    rom[512 B SEEPROM]
+
+    sata[SATA IF]
+    exi[EXI]
+
+    subgraph gx[GX]
+      sram[3 MB 1T-SRAM]
+    end
+
+    radeon[AMD Radeon R7xx GX2]
+
+    mem --- gx
+    mem --- radeon
+
+    rom --- mem
+
+    mem --- sata
+    mem --- exi
+
+    dram --- sata
+    dram --- exi
+  end
+
+  ddr3[2 GB DDR3 RAM MEM2]
+
+  mem --- ddr3
+  dram --- ddr3
+  edram --- ddr3
+
+  core1 --- mem
+
+  exi --- rtc
+  rtc{{rtc}}
+
+
+%%{init: {"flowchart": {"defaultRenderer": "elk", "htmlLabels": false}} }%%
+flowchart TB
+  %% I could not figure out how to use double quotes in labels in Mermaid
+  subgraph ibm[IBM Espresso CPU]
+    core0[IBM PowerPC Broadway Core 0]
+    core1[IBM PowerPC Broadway Core 1]
+    core2[IBM PowerPC Broadway Core 2]
+
+    rom[16 KB ROM]
+
+    core0 --- core2
+
+    rom --> core2
+  end
+
+  subgraph amd["`**AMD** Latte GPU`"]
+    mem[Memory & I/O Bridge]
+    dram[DRAM Controller]
+    edram[32 MB EDRAM MEM1]
+    rom[512 B SEEPROM]
+
+    sata[SATA IF]
+    exi[EXI]
+
+    subgraph gx[GX]
+      sram[3 MB 1T-SRAM]
+    end
+
+    radeon[AMD Radeon R7xx GX2]
+
+    mem --- gx
+    mem --- radeon
+
+    rom --- mem
+
+    mem --- sata
+    mem --- exi
+
+    dram --- sata
+    dram --- exi
+  end
+
+  ddr3[2 GB DDR3 RAM MEM2]
+
+  mem --- ddr3
+  dram --- ddr3
+  edram --- ddr3
+
+  core1 --- mem
+
+  exi --- rtc
+  rtc{{rtc}}
+
+ +
+
+flowchart TB
+  %% I could not figure out how to use double quotes in labels in Mermaid
+  subgraph ibm[IBM Espresso CPU]
+    core0[IBM PowerPC Broadway Core 0]
+    core1[IBM PowerPC Broadway Core 1]
+    core2[IBM PowerPC Broadway Core 2]
+
+    rom[16 KB ROM]
+
+    core0 --- core2
+
+    rom --> core2
+  end
+
+  subgraph amd[AMD Latte GPU]
+    mem[Memory & I/O Bridge]
+    dram[DRAM Controller]
+    edram[32 MB EDRAM MEM1]
+    rom[512 B SEEPROM]
+
+    sata[SATA IF]
+    exi[EXI]
+
+    subgraph gx[GX]
+      sram[3 MB 1T-SRAM]
+    end
+
+    radeon[AMD Radeon R7xx GX2]
+
+    mem --- gx
+    mem --- radeon
+
+    rom --- mem
+
+    mem --- sata
+    mem --- exi
+
+    dram --- sata
+    dram --- exi
+  end
+
+  ddr3[2 GB DDR3 RAM MEM2]
+
+  mem --- ddr3
+  dram --- ddr3
+  edram --- ddr3
+
+  core1 --- mem
+
+  exi --- rtc
+  rtc{{rtc}}
+
+
+   +
+      flowchart LR
+  B1 --be be--x B2
+  B1 --bo bo--o B3
+  subgraph Ugge
+      B2
+      B3
+      subgraph inner
+          B4
+          B5
+      end
+      subgraph inner2
+        subgraph deeper
+          C4
+          C5
+        end
+        C6
+      end
+
+      B4 --> C4
+
+      B3 -- X --> B4
+      B2 --> inner
+
+      C4 --> C5
+  end
+
+  subgraph outer
+      B6
+  end
+  B6 --> B5
+  
+
+sequenceDiagram
+    Customer->>+Stripe: Makes a payment request
+    Stripe->>+Bank: Forwards the payment request to the bank
+    Bank->>+Customer: Asks for authorization
+    Customer->>+Bank: Provides authorization
+    Bank->>+Stripe: Sends a response with payment details
+    Stripe->>+Merchant: Sends a notification of payment receipt
+    Merchant->>+Stripe: Confirms the payment
+    Stripe->>+Customer: Sends a confirmation of payment
+    Customer->>+Merchant: Receives goods or services
+        
+
+mindmap
+  root((mindmap))
+    Origins
+      Long history
+      ::icon(fa fa-book)
+      Popularisation
+        British popular psychology author Tony Buzan
+    Research
+      On effectiveness
and features + On Automatic creation + Uses + Creative techniques + Strategic planning + Argument mapping + Tools + Pen and paper + Mermaid +
+
+
+  example-diagram
+    
+ + + + + + + + + // import mindmap from '../../packages/mermaid-mindmap/src/detector'; // import example from + '../../packages/mermaid-example-diagram/src/mermaid-example-diagram.core.mjs'; import mermaid + from './mermaid.esm.mjs'; // await mermaid.registerExternalDiagrams([example]); + mermaid.parseError = function (err, hash) { // console.error('Mermaid error: ', err); }; + mermaid.initialize({ // theme: 'forest', startOnLoad: true, logLevel: 0, flowchart: { // + defaultRenderer: 'elk', useMaxWidth: false, // htmlLabels: false, htmlLabels: true, }, // + htmlLabels: false, gantt: { useMaxWidth: false, }, useMaxWidth: false, }); function callback() + { alert('It worked'); } mermaid.parseError = function (err, hash) { console.error('In parse + error:'); console.error(err); }; // mermaid.test1('first_slow', 1200).then((r) => + console.info(r)); // mermaid.test1('second_fast', 200).then((r) => console.info(r)); // + mermaid.test1('third_fast', 200).then((r) => console.info(r)); // mermaid.test1('forth_slow', + 1200).then((r) => console.info(r)); + + + + + diff --git a/cypress/platform/knsv.html b/cypress/platform/knsv.html index e0372f00c..604c38a3b 100644 --- a/cypress/platform/knsv.html +++ b/cypress/platform/knsv.html @@ -4,7 +4,7 @@ + + + + + + + + -
-      block-beta
-  blockArrowId<["Label"]>(right)
-  blockArrowId2<["Label"]>(left)
-  blockArrowId3<["Label"]>(up)
-  blockArrowId4<["Label"]>(down)
-  blockArrowId5<["Label"]>(x)
-  blockArrowId6<["Label"]>(y)
-  blockArrowId6<["Label"]>(x, down)
-    
-
-block-beta
-  block:e:4
-    columns 2
-      f
-      g
-  end
-
-    
-
-block-beta
-  block:e:4
-    columns 2
-      f
-      g
-      h
-  end
-
-    
-
-block-beta
-  columns 4
-  a b c d
-  block:e:4
-    columns 2
-      f
-      g
-      h
-  end
-  i:4
-
-    
-
-flowchart LR
-  X-- "y" -->z
-    
-
-block-beta
-columns 5
-   A space B
-   A --x B
-    
-
-block-beta
-columns 3
-  a["A wide one"] b:2 c:2 d
-    
-
-block-beta
-  block:e
-      f
-  end
-    
-
-block-beta
-  columns 3
-  a:3
-  block:e:3
-      f
-  end
-  g
-    
-
-block-beta
-  columns 3
-  a:3
-  block:e:3
-      f
-      g
-  end
-  h
-  i
-  j
-
-    
-
-block-beta
-columns 3
-  a b:2
-  block:e:3
-      f
-  end
-  g h i
-    
-
-block-beta
-columns 3
-  a b c
-  e:3
-  f g h
-    
-
-block-beta
-columns 1
-  db(("DB"))
-  blockArrowId6<["   "]>(down)
-  block:ID
-    A
-    B["A wide one in the middle"]
-    C
-  end
-  space
-  D
-  ID --> D
-  C --> D
-  style B fill:#f9F,stroke:#333,stroke-width:4px
-    
-
-block-beta
-  columns 5
-  A1:3
-  A2:1
-  A3
-  B1 B2 B3:3
-    
-
-block-beta
-  block
-    D
-    E
-  end
-  db("This is the text in the box")
-    
-
-block-beta
-
-      block
-        D
-      end
-      A["A: I am a wide one"]
-    
-
-block-beta
-    A["square"]
-    B("rounded")
-    C(("circle"))
-    
-
-block-beta
-    A>"rect_left_inv_arrow"]
-    B{"diamond"}
-    C{{"hexagon"}}
-    
-
-block-beta
-    A(["stadium"])
-    
-
-block-beta
-    %% A[["subroutine"]]
-    %% B[("cylinder")]
-    C>"surprise"]
-    
-
-block-beta
-    A[/"lean right"/]
-    B[\"lean left"\]
-    C[/"trapezoid"\]
-    D[\"trapezoid"/]
-    
- -
-flowchart
-      B
-      style B fill:#f9F,stroke:#333,stroke-width:4px
-    
- -
+    
       flowchart LR
-      a1 -- apa --> b1
+        AB["apa@apa@"] --> B(("`apa@apa`"))
     
- -
-flowchart RL
-  subgraph "`one`"
-    id
-  end
+    
+      flowchart
+        D(("for D"))
     
-
-flowchart RL
-    subgraph "`one`"
-      a1 -- l1 --> a2
-      a1 -- l2 --> a2
-    end
-    
-
-flowchart
-id["`A root with a long text that wraps to keep the node size in check. A root with a long text that wraps to keep the node size in check`"]
-
-flowchart LR
-    A[A text that needs to be wrapped wraps to another line]
-    B[A text that needs to be
wrapped wraps to another line] - C["`A text that needs to be wrapped to another line`"]
-
-flowchart LR
-    C["`A text
-        that needs
-        to be wrapped
-        in another
-        way`"]
-  
-
-      classDiagram-v2
-        note "I love this diagram!\nDo you love it?"
-    
-
-    stateDiagram-v2
-    State1: The state with a note with minus - and plus + in it
-    note left of State1
-      Important information! You can write
-      notes with . and  in them.
-    end note    
-
-mindmap
-root
-  Child3(A node with an icon and with a long text that wraps to keep the node size in check)
-
-
-      %%{init: {"theme": "forest"} }%%
-mindmap
-    id1[**Start2**
end] - id2[**Start2**
end] - %% Another comment - id3[**Start2**
end] %% Comment - id4[**Start2**
end
the very end] -
-
-mindmap
-    id1["`**Start2**
-    second line 😎 with long text that is wrapping to the next line`"]
-      id2["`Child **with bold** text`"]
-      id3["`Children of which some
-      is using *italic type of* text`"]
-      id4[Child]
-      id5["`Child
-      Row
-      and another
-      `"]
-    
-
-mindmap
-    id1("`**Root**`"]
-      id2["`A formatted text... with **bold** and *italics*`"]
-      id3[Regular labels works as usual]
-      id4["`Emojis and unicode works too: 🤓
-      ā¤ļā¤žā¤¨āĨā¤¤ā¤ŋ⤃ ØŗŲ„Ø§Ų…  å’Œåšŗ `"]
-
-    
-
-%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
-flowchart TB
-  %% I could not figure out how to use double quotes in labels in Mermaid
-  subgraph ibm[IBM Espresso CPU]
-    core0[IBM PowerPC Broadway Core 0]
-    core1[IBM PowerPC Broadway Core 1]
-    core2[IBM PowerPC Broadway Core 2]
-
-    rom[16 KB ROM]
-
-    core0 --- core2
-
-    rom --> core2
-  end
-
-  subgraph amd["`**AMD** Latte GPU`"]
-    mem[Memory & I/O Bridge]
-    dram[DRAM Controller]
-    edram[32 MB EDRAM MEM1]
-    rom[512 B SEEPROM]
-
-    sata[SATA IF]
-    exi[EXI]
-
-    subgraph gx[GX]
-      sram[3 MB 1T-SRAM]
-    end
-
-    radeon[AMD Radeon R7xx GX2]
-
-    mem --- gx
-    mem --- radeon
-
-    rom --- mem
-
-    mem --- sata
-    mem --- exi
-
-    dram --- sata
-    dram --- exi
-  end
-
-  ddr3[2 GB DDR3 RAM MEM2]
-
-  mem --- ddr3
-  dram --- ddr3
-  edram --- ddr3
-
-  core1 --- mem
-
-  exi --- rtc
-  rtc{{rtc}}
-
-
-%%{init: {"flowchart": {"defaultRenderer": "elk", "htmlLabels": false}} }%%
-flowchart TB
-  %% I could not figure out how to use double quotes in labels in Mermaid
-  subgraph ibm[IBM Espresso CPU]
-    core0[IBM PowerPC Broadway Core 0]
-    core1[IBM PowerPC Broadway Core 1]
-    core2[IBM PowerPC Broadway Core 2]
-
-    rom[16 KB ROM]
-
-    core0 --- core2
-
-    rom --> core2
-  end
-
-  subgraph amd["`**AMD** Latte GPU`"]
-    mem[Memory & I/O Bridge]
-    dram[DRAM Controller]
-    edram[32 MB EDRAM MEM1]
-    rom[512 B SEEPROM]
-
-    sata[SATA IF]
-    exi[EXI]
-
-    subgraph gx[GX]
-      sram[3 MB 1T-SRAM]
-    end
-
-    radeon[AMD Radeon R7xx GX2]
-
-    mem --- gx
-    mem --- radeon
-
-    rom --- mem
-
-    mem --- sata
-    mem --- exi
-
-    dram --- sata
-    dram --- exi
-  end
-
-  ddr3[2 GB DDR3 RAM MEM2]
-
-  mem --- ddr3
-  dram --- ddr3
-  edram --- ddr3
-
-  core1 --- mem
-
-  exi --- rtc
-  rtc{{rtc}}
-
- -
-
-flowchart TB
-  %% I could not figure out how to use double quotes in labels in Mermaid
-  subgraph ibm[IBM Espresso CPU]
-    core0[IBM PowerPC Broadway Core 0]
-    core1[IBM PowerPC Broadway Core 1]
-    core2[IBM PowerPC Broadway Core 2]
-
-    rom[16 KB ROM]
-
-    core0 --- core2
-
-    rom --> core2
-  end
-
-  subgraph amd[AMD Latte GPU]
-    mem[Memory & I/O Bridge]
-    dram[DRAM Controller]
-    edram[32 MB EDRAM MEM1]
-    rom[512 B SEEPROM]
-
-    sata[SATA IF]
-    exi[EXI]
-
-    subgraph gx[GX]
-      sram[3 MB 1T-SRAM]
-    end
-
-    radeon[AMD Radeon R7xx GX2]
-
-    mem --- gx
-    mem --- radeon
-
-    rom --- mem
-
-    mem --- sata
-    mem --- exi
-
-    dram --- sata
-    dram --- exi
-  end
-
-  ddr3[2 GB DDR3 RAM MEM2]
-
-  mem --- ddr3
-  dram --- ddr3
-  edram --- ddr3
-
-  core1 --- mem
-
-  exi --- rtc
-  rtc{{rtc}}
-
-
-   -
+    
       flowchart LR
-  B1 --be be--x B2
-  B1 --bo bo--o B3
-  subgraph Ugge
-      B2
-      B3
-      subgraph inner
-          B4
-          B5
-      end
-      subgraph inner2
-        subgraph deeper
-          C4
-          C5
-        end
-        C6
-      end
-
-      B4 --> C4
-
-      B3 -- X --> B4
-      B2 --> inner
-
-      C4 --> C5
-  end
-
-  subgraph outer
-      B6
-  end
-  B6 --> B5
-  
-
-sequenceDiagram
-    Customer->>+Stripe: Makes a payment request
-    Stripe->>+Bank: Forwards the payment request to the bank
-    Bank->>+Customer: Asks for authorization
-    Customer->>+Bank: Provides authorization
-    Bank->>+Stripe: Sends a response with payment details
-    Stripe->>+Merchant: Sends a notification of payment receipt
-    Merchant->>+Stripe: Confirms the payment
-    Stripe->>+Customer: Sends a confirmation of payment
-    Customer->>+Merchant: Receives goods or services
-        
-
-mindmap
-  root((mindmap))
-    Origins
-      Long history
-      ::icon(fa fa-book)
-      Popularisation
-        British popular psychology author Tony Buzan
-    Research
-      On effectiveness
and features - On Automatic creation - Uses - Creative techniques - Strategic planning - Argument mapping - Tools - Pen and paper - Mermaid + A e1@==> B + e1@{ animate: true}
-
-
-  example-diagram
+    
+flowchart LR
+  A e1@--> B
+  classDef animate stroke-width:2,stroke-dasharray:10\,8,stroke-dashoffset:-180,animation: edge-animation-frame 6s linear infinite, stroke-linecap: round
+  class e1 animate
+    
+

infinite

+
+flowchart LR
+  A e1@--> B
+  classDef animate stroke-dasharray: 9\,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
+  class e1 animate
+    
+

Mermaid - edge-animation-slow

+
+flowchart LR
+  A e1@--> B
+e1@{ animation: fast}
+    
+

Mermaid - edge-animation-fast

+
+flowchart LR
+  A e1@--> B
+  classDef animate stroke-dasharray: 1000,stroke-dashoffset: 1000,animation: dash 10s linear;
+  class e1 edge-animation-fast
     
- - - - - +
 
+info    
+
+---
+config:
+  layout: elk
+---
+      flowchart LR
+      a
+      subgraph s0["APA"]
+      subgraph s8["APA"]
+      subgraph s1["APA"]
+        D{"X"}
+        E[Q]
+      end
+      subgraph s3["BAPA"]
+        F[Q]
+        I
+      end
+            D --> I
+            D --> I
+            D --> I
+
+      I{"X"}
+      end
+      end
+    
+
+---
+config:
+  layout: elk
+---
+      flowchart LR
+      a
+        D{"Use the editor"}
+
+      D -- Mermaid js --> I{"fa:fa-code Text"}
+      D-->I
+      D-->I
+    
+
+---
+config:
+  layout: elk
+---
+flowchart LR
+ subgraph s1["Untitled subgraph"]
+        n1["Evaluate"]
+        n2["Option 1"]
+        n3["Option 2"]
+        n4["fa:fa-car Option 3"]
+  end
+ subgraph s2["Untitled subgraph"]
+        n5["Evaluate"]
+        n6["Option 1"]
+        n7["Option 2"]
+        n8["fa:fa-car Option 3"]
+  end
+    A["Start"] -- Some text --> B("Continue")
+    B --> C{"Evaluate"}
+    C -- One --> D["Option 1"]
+    C -- Two --> E["Option 2"]
+    C -- Three --> F["fa:fa-car Option 3"]
+    n1 -- One --> n2
+    n1 -- Two --> n3
+    n1 -- Three --> n4
+    n5 -- One --> n6
+    n5 -- Two --> n7
+    n5 -- Three --> n8
+    n1@{ shape: diam}
+    n2@{ shape: rect}
+    n3@{ shape: rect}
+    n4@{ shape: rect}
+    n5@{ shape: diam}
+    n6@{ shape: rect}
+    n7@{ shape: rect}
+    n8@{ shape: rect}
+
+    
+
+---
+config:
+  layout: elk
+---
+flowchart LR
+ subgraph s1["Untitled subgraph"]
+        n1["Evaluate"]
+        n2["Option 1"]
+  end
+    n1 -- One --> n2
+
+
+
+
+    
+
+---
+config:
+  layout: elk
+---
+flowchart LR
+    A{A} --> B & C
+
+
+---
+config:
+  layout: elk
+---
+flowchart LR
+    A{A} --> B & C
+    subgraph "subbe"
+      A
+    end
+
+
+---
+config:
+  layout: elk
+---
+flowchart LR
+    n2@{ shape: rect}
+    n3@{ shape: rect}
+    n4@{ shape: rect}
+    A["Start"] -- Some text --> B("Continue")
+    B --> C{"Evaluate"}
+    C -- One --> D["Option 1"]
+    C -- Two --> E["Option 2"]
+    C -- Three --> F["fa:fa-car Option 3"]
+    %% C@{ shape: hexagon}
+
+
+    
+
+---
+config:
+  kanban:
+    ticketBaseUrl: 'https://github.com/your-repo/issues/#TICKET#'
+---
+kanban
+  Backlog
+    task1[📝 Define project requirements]@{ ticket: a101 }
+  To Do
+    task2[🔍 Research technologies]@{ ticket: a102 }
+  Review
+    task4[🔍 Code review for login feature]@{ ticket: a104 }
+  Done
+    task5[✅ Deploy initial version]@{ ticket: a105 }
+  In Progress
+    task3[đŸ’ģ Develop login feature]@{ ticket: 103 }
+
+    
+
+flowchart LR
+nA[Default] --> A@{ icon: 'fa:bell', form: 'rounded' }
+
+    
+
+flowchart LR
+nA[Style] --> A@{ icon: 'fa:bell', form: 'rounded' }
+style A fill:#f9f,stroke:#333,stroke-width:4px
+    
+
+flowchart LR
+nA[Class] --> A@{ icon: 'fa:bell', form: 'rounded' }
+A:::AClass
+classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
+    
+
+flowchart LR
+  nA[Class] --> A@{ icon: 'logos:aws', form: 'rounded' }
+
+    
+
+flowchart LR
+nA[Default] --> A@{ icon: 'fa:bell', form: 'square' }
+
+    
+
+flowchart LR
+nA[Style] --> A@{ icon: 'fa:bell', form: 'square' }
+style A fill:#f9f,stroke:#333,stroke-width:4px
+    
+
+flowchart LR
+nA[Class] --> A@{ icon: 'fa:bell', form: 'square' }
+A:::AClass
+classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
+    
+
+flowchart LR
+  nA[Class] --> A@{ icon: 'logos:aws', form: 'square' }
+
+    
+
+flowchart LR
+nA[Default] --> A@{ icon: 'fa:bell', form: 'circle' }
+
+    
+
+flowchart LR
+nA[Style] --> A@{ icon: 'fa:bell', form: 'circle' }
+style A fill:#f9f,stroke:#333,stroke-width:4px
+    
+
+flowchart LR
+nA[Class] --> A@{ icon: 'fa:bell', form: 'circle' }
+A:::AClass
+classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
+    
+
+flowchart LR
+  nA[Class] --> A@{ icon: 'logos:aws', form: 'circle' }
+  A:::AClass
+  classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
+    
+
+flowchart LR
+  nA[Style] --> A@{ icon: 'logos:aws', form: 'circle' }
+  style A fill:#f9f,stroke:#333,stroke-width:4px
+    
+
+kanban
+  id2[In progress]
+    docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' }
+    
+
+---
+config:
+  kanban:
+    ticketBaseUrl: 'https://mermaidchart.atlassian.net/browse/#TICKET#'
+    # sectionWidth: 300
+---
+kanban
+  Todo
+    [Create Documentation]
+    docs[Create Blog about the new diagram]
+  id7[In progress]
+    id6[Create renderer so that it works in all cases. We also add some extra text here for testing purposes. And some more just for the extra flare.]
+  id9[Ready for deploy]
+    id8[Design grammar]@{ assigned: 'knsv' }
+  id10[Ready for test]
+    id4[Create parsing tests]@{ ticket: MC-2038, assigned: 'K.Sveidqvist', priority: 'High' }
+    id66[last item]@{ priority: 'Very Low', assigned: 'knsv' }
+  id11[Done]
+    id5[define getData]
+    id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char]@{ ticket: MC-2036, priority: 'Very High'}
+    id3[Update DB function]@{ ticket: MC-2037, assigned: knsv, priority: 'High' }
+
+  id12[Can't reproduce]
+    id3[Weird flickering in Firefox]
+    
diff --git a/cypress/platform/knsv3.html b/cypress/platform/knsv3.html index 26368a62a..1d65c2ddf 100644 --- a/cypress/platform/knsv3.html +++ b/cypress/platform/knsv3.html @@ -1,4 +1,4 @@ - + diff --git a/cypress/platform/per.html b/cypress/platform/per.html index e84cea2d0..6d3d198b6 100644 --- a/cypress/platform/per.html +++ b/cypress/platform/per.html @@ -4,7 +4,7 @@ + + + + + + + + + + + + + + + + +
+      flowchart
+          A --> A
+          subgraph B
+            B1 --> B1
+          end
+          subgraph C
+            subgraph C1
+              C2 --> C2
+              subgraph D
+                D1 --> D1
+              end
+              D --> D
+            end
+            C1 --> C1
+          end
+
+    
+ + + diff --git a/cypress/platform/showcase_base.html b/cypress/platform/showcase_base.html index 13e6a9484..6417290bf 100644 --- a/cypress/platform/showcase_base.html +++ b/cypress/platform/showcase_base.html @@ -4,7 +4,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DagreDagre with roughELKELK with rough
+ +
+
+
+      stateId
+  
+
+
+
+
+stateDiagram-v2
+    stateId
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+stateDiagram-v2
+    stateId
+
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+stateDiagram-v2
+    stateId
+
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+stateDiagram-v2
+    stateId
+
+      
+
+ +
+
+
+
+    state "description text" as s2
+  
+
+
+
+
+stateDiagram-v2
+    state "This is a state description" as s2
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+stateDiagram-v2
+    state "This is a state description" as s3
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+stateDiagram-v2
+    state "This is a state description" as s4
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+stateDiagram-v2
+    state "This is a state description" as s5
+      
+
+ +
+
+
+
+    s2 :  description text
+  
+
+
+
+
+stateDiagram-v2
+    s21 : This is a state description
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+stateDiagram-v2
+    s22 : This is a state description
+
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+stateDiagram-v2
+    s23 : This is a state description
+
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+stateDiagram-v2
+    s24 : This is a state description
+
+      
+
+ +
+
+
+
+    s1 --> s2
+
+  
+
+
+
+
+
+    stateDiagram-v2
+    s31 --> s32
+
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+
+   stateDiagram-v2
+    s41 --> s42
+
+
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+stateDiagram-v2
+    s51 --> s52
+
+
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+stateDiagram-v2
+    s61 --> s62
+
+
+      
+
+ +
+
+
+
+    s1 --> s2: A transition
+
+  
+
+
+
+
+
+    stateDiagram-v2
+    a1 --> a2: A transition
+
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+
+   stateDiagram-v2
+    a3 --> a4: A transition
+
+
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+stateDiagram-v2
+    a5 --> a6: A transition
+
+
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+stateDiagram-v2
+   a7 --> a8: A transition
+
+
+      
+
+ +
+
+
+
+      [*] --> test
+    test --> [*]
+
+  
+
+
+
+
+
+    stateDiagram-v2
+       [*] --> test
+    test --> [*]
+
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+
+   stateDiagram-v2
+       [*] --> test
+    test --> [*]
+
+
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+stateDiagram-v2
+       [*] --> test
+    test --> [*]
+
+
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+stateDiagram-v2
+      [*] --> test
+    test --> [*]
+
+
+      
+
+ +
+
+
+
+      [*] --> First
+    state First {
+        [*] --> second
+        second --> [*]
+    }
+
+  
+
+
+
+
+
+    stateDiagram-v2
+       [*] --> First
+    state First {
+        [*] --> second
+        second --> [*]
+    }
+
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+
+   stateDiagram-v2
+       [*] --> First
+    state First {
+        [*] --> second
+        second --> [*]
+    }
+
+
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+stateDiagram-v2
+       [*] --> First
+    state First {
+        [*] --> second
+        second --> [*]
+    }
+
+
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+stateDiagram-v2
+      [*] --> First
+    state First {
+        [*] --> second
+        second --> [*]
+    }
+
+
+      
+
+ +
+
+
+
+
+    [*] --> Level1
+
+    state Level1 {
+        [*] --> Level2
+
+        state Level2 {
+            [*] --> level2
+            level2 --> Level3
+
+            state Level3 {
+                [*] --> level3
+                level3 --> [*]
+            }
+        }
+    }
+
+
+  
+
+
+
+
+
+    stateDiagram-v2
+    [*] --> Level1
+
+    state Level1 {
+        [*] --> Level2
+
+        state Level2 {
+            [*] --> level2
+            level2 --> Level3
+
+            state Level3 {
+                [*] --> level3
+                level3 --> [*]
+            }
+        }
+    }
+
+
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+
+   stateDiagram-v2
+    [*] --> Level1
+
+    state Level1 {
+        [*] --> Level2
+
+        state Level2 {
+            [*] --> level2
+            level2 --> Level3
+
+            state Level3 {
+                [*] --> level3
+                level3 --> [*]
+            }
+        }
+    }
+
+
+
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+ stateDiagram-v2
+    [*] --> Level1
+
+    state Level1 {
+        [*] --> Level2
+
+        state Level2 {
+            [*] --> level2
+            level2 --> Level3
+
+            state Level3 {
+                [*] --> level3
+                level3 --> [*]
+            }
+        }
+    }
+
+
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+ stateDiagram-v2
+    [*] --> Level1
+
+    state Level1 {
+        [*] --> Level2
+
+        state Level2 {
+            [*] --> level2
+            level2 --> Level3
+
+            state Level3 {
+                [*] --> level3
+                level3 --> [*]
+            }
+        }
+    }
+
+      
+
+ +
+
+
+    [*] --> B1
+    B1 --> B2
+    B1 --> B3
+
+    state B1 {
+        [*] --> B11
+        B11 --> [*]
+    }
+    state B2 {
+        [*] --> B22
+        B22 --> [*]
+    }
+    state B3 {
+        [*] --> B33
+        B33 --> [*]
+    }
+
+
+
+  
+
+
+
+
+
+    stateDiagram-v2
+    [*] --> B1
+    B1 --> B2
+    B1 --> B3
+
+    state B1 {
+        [*] --> B11
+        B11 --> [*]
+    }
+    state B2 {
+        [*] --> B22
+        B22 --> [*]
+    }
+    state B3 {
+        [*] --> B33
+        B33 --> [*]
+    }
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+
+   stateDiagram-v2
+   [*] --> B1
+    B1 --> B2
+    B1 --> B3
+
+    state B1 {
+        [*] --> B11
+        B11 --> [*]
+    }
+    state B2 {
+        [*] --> B22
+        B22 --> [*]
+    }
+    state B3 {
+        [*] --> B33
+        B33 --> [*]
+    }
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+ stateDiagram-v2
+  [*] --> B1
+    B1 --> B2
+    B1 --> B3
+
+    state B1 {
+        [*] --> B11
+        B11 --> [*]
+    }
+    state B2 {
+        [*] --> B22
+        B22 --> [*]
+    }
+    state B3 {
+        [*] --> B33
+        B33 --> [*]
+    }
+
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+ stateDiagram-v2
+[*] --> B1
+    B1 --> B2
+    B1 --> B3
+
+    state B1 {
+        [*] --> B11
+        B11 --> [*]
+    }
+    state B2 {
+        [*] --> B22
+        B22 --> [*]
+    }
+    state B3 {
+        [*] --> B33
+        B33 --> [*]
+    }
+      
+
+ +
+
+
+    state if_state <<choice>>
+    [*] --> IsPositive
+    IsPositive --> if_state
+    if_state --> False: if n < 0
+    if_state --> True : if n >= 0
+
+
+
+
+  
+
+
+
+
+
+    stateDiagram-v2
+    state if_state <>
+    [*] --> IsPositive
+    IsPositive --> if_state
+    if_state --> False: if n < 0
+    if_state --> True : if n >= 0
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+
+   stateDiagram-v2
+   state if_state <>
+    [*] --> IsPositive
+    IsPositive --> if_state
+    if_state --> False: if n < 0
+    if_state --> True : if n >= 0
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+ stateDiagram-v2
+   state if_state <>
+    [*] --> IsPositive
+    IsPositive --> if_state
+    if_state --> False: if n < 0
+    if_state --> True : if n >= 0
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+ stateDiagram-v2
+ state if_state <>
+    [*] --> IsPositive
+    IsPositive --> if_state
+    if_state --> False: if n < 0
+    if_state --> True : if n >= 0
+      
+
+ +
+
+
+    state fork_state <<fork>>
+      [*] --> fork_state
+      fork_state --> State2
+      fork_state --> State3
+
+      state join_state <<join>>
+      State2 --> join_state
+      State3 --> join_state
+      join_state --> State4
+      State4 --> [*]
+
+
+
+  
+
+
+
+
+   stateDiagram-v2
+    state fork_state <>
+      [*] --> fork_state
+      fork_state --> State2
+      fork_state --> State3
+
+      state join_state <>
+      State2 --> join_state
+      State3 --> join_state
+      join_state --> State4
+      State4 --> [*]
+
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+   stateDiagram-v2
+    state fork_state <>
+      [*] --> fork_state
+      fork_state --> State2
+      fork_state --> State3
+
+      state join_state <>
+      State2 --> join_state
+      State3 --> join_state
+      join_state --> State4
+      State4 --> [*]
+
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+   stateDiagram-v2
+    state fork_state <>
+      [*] --> fork_state
+      fork_state --> State2
+      fork_state --> State3
+
+      state join_state <>
+      State2 --> join_state
+      State3 --> join_state
+      join_state --> State4
+      State4 --> [*]
+
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+   stateDiagram-v2
+    state fork_state <>
+      [*] --> fork_state
+      fork_state --> State2
+      fork_state --> State3
+
+      state join_state <>
+      State2 --> join_state
+      State3 --> join_state
+      join_state --> State4
+      State4 --> [*]
+
+      
+
+ +
+
+
+
+  TN1: The state with a note
+  note right of TN1
+      note text
+  end note
+  TN1 --> TN2
+  note left of TN2 : note text
+
+  
+
+
+
+
+   stateDiagram-v2
+     TN1: The state with a note
+        note right of TN1
+            Important information! You can write
+            notes.
+        end note
+        TN1 --> TN2
+        note left of TN2 : This is the note to the left.
+
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+   stateDiagram-v2
+     TN3: The state with a note
+        note right of TN3
+            Important information! You can write
+            notes.
+        end note
+        TN3 --> TN4
+        note left of TN4 : This is the note to the left.
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+   stateDiagram-v2
+     TN5: The state with a note
+        note right of TN5
+            Important information! You can write
+            notes.
+        end note
+        TN5 --> TN6
+        note left of TN6 : This is the note to the left.
+
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+   stateDiagram-v2
+     TN7: The state with a note
+        note right of TN7
+            Important information! You can write
+            notes.
+        end note
+        TN7 --> TN8
+        note left of TN8 : This is the note to the left.
+      
+
+ +
+
+
+[*] --> Active
+
+state Active {
+    [*] --> NumLockOff
+    NumLockOff --> NumLockOn : EvNumLockPressed
+    NumLockOn --> NumLockOff : EvNumLockPressed
+    --
+    [*] --> CapsLockOff
+    CapsLockOff --> CapsLockOn : EvCapsLockPressed
+    CapsLockOn --> CapsLockOff : EvCapsLockPressed
+    --
+    [*] --> ScrollLockOff
+    ScrollLockOff --> ScrollLockOn : EvScrollLockPressed
+    ScrollLockOn --> ScrollLockOff : EvScrollLockPressed
+}
+
+
+  
+
+
+
+
+     stateDiagram-v2
+    [*] --> Active
+
+    state Active {
+        [*] --> NumLockOff
+        NumLockOff --> NumLockOn : EvNumLockPressed
+        NumLockOn --> NumLockOff : EvNumLockPressed
+        --
+        [*] --> CapsLockOff
+        CapsLockOff --> CapsLockOn : EvCapsLockPressed
+        CapsLockOn --> CapsLockOff : EvCapsLockPressed
+        --
+        [*] --> ScrollLockOff
+        ScrollLockOff --> ScrollLockOn : EvScrollLockPressed
+        ScrollLockOn --> ScrollLockOff : EvScrollLockPressed
+    }
+
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+     stateDiagram-v2
+    [*] --> Active
+
+    state Active {
+        [*] --> NumLockOff
+        NumLockOff --> NumLockOn : EvNumLockPressed
+        NumLockOn --> NumLockOff : EvNumLockPressed
+        --
+        [*] --> CapsLockOff
+        CapsLockOff --> CapsLockOn : EvCapsLockPressed
+        CapsLockOn --> CapsLockOff : EvCapsLockPressed
+        --
+        [*] --> ScrollLockOff
+        ScrollLockOff --> ScrollLockOn : EvScrollLockPressed
+        ScrollLockOn --> ScrollLockOff : EvScrollLockPressed
+    }
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+     stateDiagram-v2
+    [*] --> Active
+
+    state Active {
+        [*] --> NumLockOff
+        NumLockOff --> NumLockOn : EvNumLockPressed
+        NumLockOn --> NumLockOff : EvNumLockPressed
+        --
+        [*] --> CapsLockOff
+        CapsLockOff --> CapsLockOn : EvCapsLockPressed
+        CapsLockOn --> CapsLockOff : EvCapsLockPressed
+        --
+        [*] --> ScrollLockOff
+        ScrollLockOff --> ScrollLockOn : EvScrollLockPressed
+        ScrollLockOn --> ScrollLockOff : EvScrollLockPressed
+    }
+
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+     stateDiagram-v2
+    [*] --> Active
+
+    state Active {
+        [*] --> NumLockOff
+        NumLockOff --> NumLockOn : EvNumLockPressed
+        NumLockOn --> NumLockOff : EvNumLockPressed
+        --
+        [*] --> CapsLockOff
+        CapsLockOff --> CapsLockOn : EvCapsLockPressed
+        CapsLockOn --> CapsLockOff : EvCapsLockPressed
+        --
+        [*] --> ScrollLockOff
+        ScrollLockOff --> ScrollLockOn : EvScrollLockPressed
+        ScrollLockOn --> ScrollLockOff : EvScrollLockPressed
+    }
+      
+
+ +
+
+
+direction LR
+    [*] --> D1
+    D1 --> D2
+    D2 --> D3
+    state D3 {
+      direction TB
+      D11 --> D22
+    }
+    D2 --> D4
+  
+
+
+
+
+     stateDiagram-v2
+    direction LR
+    [*] --> D1
+    D1 --> D2
+    D2 --> D3
+    state D3 {
+      direction TB
+      D11 --> D22
+    }
+    D2 --> D4
+      
+
+
+%%{init: {"look": "handDrawn"} }%%
+     stateDiagram-v2
+   direction LR
+    [*] --> D1
+    D1 --> D2
+    D2 --> D3
+    state D3 {
+      direction TB
+      D11 --> D22
+    }
+    D2 --> D4
+      
+
+
+%%{init: {"handDrawn": false, "layout": "elk"} }%%
+     stateDiagram-v2
+    direction LR
+    [*] --> D1
+    D1 --> D2
+    D2 --> D3
+    state D3 {
+      direction TB
+      D11 --> D22
+    }
+    D2 --> D4
+      
+
+
+%%{init: {"look": "handDrawn", "layout": "elk"} }%%
+     stateDiagram-v2
+    direction LR
+    [*] --> D1
+    D1 --> D2
+    D2 --> D3
+    state D3 {
+      direction TB
+      D11 --> D22
+    }
+    D2 --> D4
+      
+
Additional ContentNew content 1New content 2New content 3New content 4
+ + + + + + diff --git a/cypress/platform/viewer.js b/cypress/platform/viewer.js index 482a90646..a9d4d2d81 100644 --- a/cypress/platform/viewer.js +++ b/cypress/platform/viewer.js @@ -1,7 +1,7 @@ -import mermaid from './mermaid.esm.mjs'; -import flowchartELK from './mermaid-flowchart-elk.esm.mjs'; import externalExample from './mermaid-example-diagram.esm.mjs'; +import layouts from './mermaid-layout-elk.esm.mjs'; import zenUml from './mermaid-zenuml.esm.mjs'; +import mermaid from './mermaid.esm.mjs'; function b64ToUtf8(str) { return decodeURIComponent(escape(window.atob(str))); @@ -46,8 +46,64 @@ const contentLoaded = async function () { document.getElementsByTagName('body')[0].appendChild(div); } - await mermaid.registerExternalDiagrams([externalExample, zenUml, flowchartELK]); + await mermaid.registerExternalDiagrams([externalExample, zenUml]); + + mermaid.registerLayoutLoaders(layouts); mermaid.initialize(graphObj.mermaid); + const staticBellIconPack = { + prefix: 'fa6-regular', + icons: { + bell: { + body: '', + width: 448, + }, + }, + width: 512, + height: 512, + }; + /* MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE */ + const staticAwsLogoIconPack = { + prefix: 'fluent-emoji', + icons: { + 'tropical-fish': { + width: 32, + height: 32, + body: '', + }, + }, + width: 256, + height: 256, + }; + mermaid.registerIconPacks([ + { + name: 'fa', + loader: () => staticBellIconPack, + }, + { + name: 'fluent-emoji', + loader: () => staticAwsLogoIconPack, + }, + ]); await mermaid.run(); } }; @@ -132,7 +188,7 @@ if (typeof document !== 'undefined') { window.addEventListener( 'load', function () { - if (this.location.href.match('xss.html')) { + if (/xss.html/.exec(this.location.href)) { this.console.log('Using api'); void contentLoadedApi().finally(markRendered); } else { diff --git a/cypress/platform/xss10.html b/cypress/platform/xss10.html index 91b0b94ac..9814fed41 100644 --- a/cypress/platform/xss10.html +++ b/cypress/platform/xss10.html @@ -4,7 +4,7 @@ + + + + + + + + + +
Security check
+
+
+
+
+ + + diff --git a/cypress/platform/xss4.html b/cypress/platform/xss4.html index 614fe09b3..503c660d2 100644 --- a/cypress/platform/xss4.html +++ b/cypress/platform/xss4.html @@ -4,7 +4,7 @@ + +

Class Nodes

+
+
+

Basic Class

+
+          ---
+            config:
+              htmlLabels: false
+          ---
+          classDiagram
+          class _Duck_ {
+            +String beakColor
+            _+_swim_()a_
+            __+quack() test__
+          }
+        
+
+
+

Basic Class

+
+          ---
+          config:
+            htmlLabels: false
+          ---
+          classDiagram
+          class Class10:::exClass2 {
+            int[] id
+            List~int~ ids
+            test(List~int~ ids) List~bool~
+            testArray() bool[]
+          }
+        
+
+
+

Basic Class

+
+          flowchart TD
+            Start --> Stop
+        
+
+
+

Complex Class

+
+                classDiagram
+                class Square~Shape~{
+                  int id
+                  List~int~ position
+                  setPoints(List~int~ points)
+                  getPoints() List~int~
+                }
+
+          Square : -List~string~ messages
+          Square : +setMessages(List~string~ messages)
+          Square : +getMessages() List~string~
+          Square : +getDistanceMatrix() List~List~int~~
+              
+
+
+

No Attributes

+
+          classDiagram
+          class Duck {
+            +swim()
+            +quack()
+          }
+        
+
+
+

No Methods

+
+          classDiagram
+          class Duck {
+            +String beakColor
+          }
+        
+
+
+

Only Class Name

+

Empty line as attribute

+
+          ---
+            config:
+              class:
+                hideEmptyMembersBox: false
+          ---
+          classDiagram
+          class Duck {
+
+          }
+        
+
+
+

Visibility and Types

+

(Further tilde testing)

+
+ classDiagram class Duck { ~interface~~~ +String beakColor #swim() ~quack()~~~ + -test()~~~~~~~ +deposit(amount) bool } +
+
+
+

Additional Classifiers

+

(* Abstract | $ Static)

+
+ classDiagram class Square~Shape~ { int id* List~int~ position* setPoints(List~int~points)* + getPoints()* List~int~ } Square : -List~string~ messages$ Square : + +setMessages(List~string~ messages)* Square : +getMessages()$ List~string~ Square : + +getDistanceMatrix() List~List~int~~$ +
+
+
+

Label

+
+          classDiagram
+          class Animal~test~["Animal with a label"]
+        
+
+
+

Spacing

+

(Fix ensures consistent spacing rules)

+

(No space or single space?)

+
+          classDiagram
+          class ClassName {
+          -attribute:type
+          -            attribute : type
+               test
+
+          + GetAttribute() type
+          +     GetAttribute() type
+          }
+        
+
+
+

Annotation

+
+          classDiagram
+          class Shape
+          <<interface>> Shape
+          Shape : noOfVertices
+          Shape : draw()
+        
+
+
+

Long Class Name Text

+
+          classDiagram
+          class ThisIsATestForALongClassName {
+            <<interface>>
+            noOfLetters
+            delete()
+          }
+        
+
+
+

Long Annotation Text

+
+          classDiagram
+          class Shape
+          <<superlongannotationtext>> Shape
+          Shape : noOfVertices
+          Shape : draw()
+        
+
+
+

Long Member Text

+
+          classDiagram
+          class Shape
+          <<interface>> Shape
+          Shape : noOfVertices
+          Shape : longtexttestkeepgoingandgoing
+          Shape : draw()
+        
+
+
+

Link

+
+          classDiagram
+          class Shape
+          link Shape "https://www.github.com" "This is a tooltip for a link"
+        
+
+
+

Click

+
+          classDiagram
+          class Shape
+          click Shape href "https://www.github.com" "This is a tooltip for a link"
+        
+
+
+

Hand Drawn

+
+          ---
+          config:
+            look: handDrawn
+            htmlLabels: true
+          ---
+          classDiagram
+          class Hand {
+            +String beakColor
+            +swim()
+            +quack()
+          }
+          style Hand fill:#f9f,stroke:#29f,stroke-width:2px
+        
+
+
+

Neutral Theme

+
+          ---
+          config:
+            theme: neutral
+          ---
+          classDiagram
+          class Duck {
+            +String beakColor
+            +swim()
+            +quack()
+          }
+        
+
+
+

Dark Theme

+
+          ---
+          config:
+            theme: dark
+          ---
+          classDiagram
+          class Duck {
+            +String beakColor
+            +swim()
+            +quack()
+          }
+        
+
+
+

Forest Theme

+
+          ---
+          config:
+            theme: forest
+          ---
+          classDiagram
+          class Duck {
+            +String beakColor
+            +swim()
+            +quack()
+          }
+        
+
+
+

Base Theme

+
+          ---
+          config:
+            theme: base
+          ---
+          classDiagram
+          class Duck {
+            +String beakColor
+            +swim()
+            +quack()
+          }
+        
+
+
+

Custom Theme

+
+          %%{
+            init: {
+              'theme': 'base',
+              'themeVariables': {
+                'primaryColor': '#BB2528',
+                'primaryTextColor': '#fff',
+                'primaryBorderColor': '#7C0000',
+                'lineColor': '#F83d29',
+                'secondaryColor': '#006100',
+                'tertiaryColor': '#fff'
+              }
+            }
+          }%%
+          classDiagram
+          class Duck {
+            +String beakColor
+            +swim()
+            +quack()
+          }
+          Duck--Dog
+        
+
+
+

Styling within Diagram

+
+          classDiagram
+          class Duck {
+            +String beakColor
+            +swim()
+            +quack()
+          }
+          style Duck fill:#f9f,stroke:#333,stroke-width:8px
+        
+
+
+

Styling with classDef Statement

+
+          classDiagram
+          class Duck:::bold {
+            +String beakColor
+            +swim()
+            +quack()
+          }
+
+          class Dog {
+            +int numTeeth
+            +bark()
+          }
+
+          cssClass "Duck,Dog" pink
+
+          classDef pink fill:#f9f
+          classDef default color:#f1e
+          classDef bold stroke:#333,stroke-width:6px,color:#fff
+        
+
+
+

Styling with Class in Stylesheet

+
+          classDiagram
+          class Duck {
+            +String beakColor
+            +swim()
+            +quack()
+          }
+          class Duck:::styleClass
+        
+
+
+

Diagram Testing

+
+
+

Class Nodes Only

+
+          ---
+          title: Animal example
+          ---
+          classDiagram
+              Animal : +int age
+              Animal : +String gender
+              Animal: +isMammal()
+              Animal: +mate()
+              class Duck{
+                  +String beakColor
+                  +swim()
+                  +quack()
+              }
+              class Fish{
+                  -int sizeInFeet
+                  -canEat()
+              }
+              class Zebra{
+                  +bool is_wild
+                  +run()
+              }
+        
+
+
+

Class Nodes LR

+
+          ---
+          title: Animal example
+          ---
+          classDiagram
+              direction LR
+              Animal : +int age
+              Animal : +String gender
+              Animal: +isMammal()
+              Animal: +mate()
+              class Duck{
+                  +String beakColor
+                  +swim()
+                  +quack()
+              }
+              class Fish{
+                  -int sizeInFeet
+                  -canEat()
+              }
+              class Zebra{
+                  +bool is_wild
+                  +run()
+              }
+        
+
+
+

Relations

+
+          classDiagram
+            classA <|-- classB
+            classC *-- classD
+            classE o-- classF
+            classG <-- classH
+            classI -- classJ
+            classK <.. classL
+            classM <|.. classN
+            classO .. classP
+        
+
+
+

Two Way Relation

+
+          classDiagram
+          class Animal {
+            int size
+            walk()
+          }
+          class Zebra {
+            int size
+            walk()
+          }
+            Animal o--|> Zebra
+
+        
+
+
+

Relations with Labels

+
+          classDiagram
+            classA <|-- classB : implements
+            classC *-- classD : composition
+            classE o-- classF : aggregation
+        
+
+
+

Cardinality / Multiplicity

+
+          classDiagram
+            Customer "1" --> "*" Ticket
+            Student "1" --> "1..*" Course
+            Galaxy --> "many" Star : Contains
+        
+
+
+

Complex Relations with Theme

+
+          ---
+          config:
+            theme: forest
+            look: handDrawn
+            layout: elk
+          ---
+          classDiagram
+            direction RL
+            class Student {
+              -idCard : IdCard
+            }
+            class IdCard{
+              -id : int
+              -name : string
+            }
+            class Bike{
+              -id : int
+              -name : string
+            }
+            Student "1" o--o "1" IdCard : carries
+            Student "1" o--o "1" Bike : rides
+        
+
+
+

Notes

+
+          classDiagram
+            note "This is a general note"
+            note for MyClass "This is a note for a class"
+            class MyClass
+        
+
+
+

Namespaces

+
+          classDiagram
+            namespace BaseShapes {
+                class Triangle
+                class Rectangle {
+                  double width
+                  double height
+                }
+            }
+        
+
+
+

Namespaces

+
+          ---
+            config:
+              layout: elk
+          ---
+          classDiagram
+          namespace Namespace1 {
+            class C1
+            class C2
+          }
+          C1 --> C2
+          class C3
+          class C4
+        
+
+
+

Full Example

+
+          ---
+          title: Animal example
+          config:
+            layout: dagre
+          ---
+          classDiagram
+              note "From Duck till Zebra"
+              Animal <|--|> Duck
+              note for Duck "can fly
can swim
can dive
can help in debugging" + Animal <|-- Fish + Animal <|--|> Zebra + Animal : +int age + Animal : +String gender + Animal: +isMammal() + Animal: +mate() + class Duck{ + +String beakColor + +swim() + +quack() + } + class Fish{ + -int sizeInFeet + -canEat() + } + class Zebra{ + +bool is_wild + +run() + } + cssClass "Duck" test + classDef test fill:#f71 + %%classDef default fill:#f93 +
+
+
+

Full Example

+
+          ---
+            config:
+              theme: forest
+              look: handDrawn
+          ---
+          classDiagram
+          note for Outside "Note testing"
+          namespace Test {
+              class Outside
+          }
+          namespace BaseShapes {
+              class Triangle
+              class Rectangle {
+                double width
+                double height
+              }
+          }
+          Outside <|--|> Rectangle
+          style Triangle fill:#f9f,stroke:#333,stroke-width:4px
+        
+
+
+
+          ---
+            config:
+              look: handDrawn
+              layout: elk
+          ---
+          classDiagram
+            Class01 "1" <|--|> "*" AveryLongClass : Cool
+            <<interface>> Class01
+            Class03 "1" *-- "*" Class04
+            Class05 "1" o-- "many" Class06
+            Class07 "1" .. "*" Class08
+            Class09 "1" --> "*" C2 : Where am i?
+            Class09 "*" --* "*" C3
+            Class09 "1" --|> "1" Class07
+            NewClass ()--() Class04
+            Class09 <|--|> AveryLongClass
+            Class07  : equals()
+            Class07  : Object[] elementData
+            Class01  : size()
+            Class01  : int chimp
+            Class01  : int gorilla
+            Class08 "1" <--> "*" C2: Cool label
+            class Class10 {
+              <<service>>
+              int id
+              test()
+            }
+            Class10 o--o AveryLongClass
+            Class10 <--> Class07
+        
+
+
+
+          classDiagram
+            test ()--() test2
+        
+
+
+ + + + + diff --git a/cypress/platform/yari2.html b/cypress/platform/yari2.html new file mode 100644 index 000000000..53eefe5ba --- /dev/null +++ b/cypress/platform/yari2.html @@ -0,0 +1,337 @@ + + +

Nodes

+
+
+

Basic ErNode

+
+          ---
+            config:
+              htmlLabels: false
+              look: handDrawn
+              theme: forest
+          ---
+          erDiagram
+            _**hiØ**_[*test*] {
+              *__List~List~int~~sdfds__* __driversLicense__ PK "***The l😀icense #***"
+              *string(99)~T~~~~~~* firstName "Only 99 
characters are a
llowed dsfsdfsdfsdfs" + ~str ing~ lastName + string phone UK + int age + } + style PERSON color:red, stroke:blue,fill:#f9f + classDef test,test2 stroke:red + class PERSON test,test2 +
+
+
+

Basic ErNode

+
+          erDiagram
+            CAR {
+                string registrationNumber
+                string make
+                string model
+            }
+            PERSON {
+                string firstName
+                string lastName
+                int age
+            }
+
+            CAR:::someclass
+            PERSON:::anotherclass,someclass
+
+            classDef someclass fill:#f96
+            classDef anotherclass color:blue
+        
+
+
+

Diagram Testing

+
+
+

Basic Relationship

+
+          ---
+            config:
+              htmlLabels: false
+              layout: elk
+              look: handDrawn
+              theme: forest
+          ---
+          erDiagram
+            "hi" }o..o{ ORDER : places
+            style hi fill:lightblue
+        
+
+
+

Basic Relationship

+
+          ---
+            config:
+              htmlLabels: false
+              look: handDrawn
+              layout: elk
+          ---
+          erDiagram
+            CAR ||--|{ NAMED-DRIVER : allows
+            PERSON ||..o{ NAMED-DRIVER : is
+        
+
+
+

Basic Relationship

+
+          ---
+            config:
+              htmlLabels: true
+              look: handDrawn
+              theme: forest
+          ---
+          erDiagram
+            CAR ||--o{ NAMED-DRIVER : allows
+            CAR {
+                text text PK "comment"
+                string make
+                string model
+                string[] parts
+            }
+            PERSON ||--o{ NAMED-DRIVER : is
+            PERSON ||--o{ CAR : is
+            PERSON {
+                string driversLicense PK "The license #"
+                string(99) firstName "Only 99 characters are allowed"
+                string lastName
+                string phone UK
+                int age
+            }
+            NAMED-DRIVER {
+                string carRegistrationNumber PK, FK
+                string driverLicence PK, FK
+            }
+            MANUFACTURER only one to zero or more CAR : makes
+        
+
+
+

Basic Relationship

+
+          ---
+            title: simple ER diagram
+            config:
+              theme: forest
+          ---
+          erDiagram
+          direction TB
+          p[Pers😀on] {
+              string firstName
+              string lastName
+          }
+          a["Customer Account"] {
+              string email
+          }
+          p ||--o| a : has
+
+        
+
+
+

Basic Relationship

+
+          ---
+            config:
+              layout: elk
+          ---
+          erDiagram
+          CUSTOMER }|..|{ DELIVERY-ADDRESS : has
+          CUSTOMER ||--o{ ORDER : places
+          CUSTOMER ||--o{ INVOICE : "liable for"
+          DELIVERY-ADDRESS ||--o{ ORDER : receives
+          INVOICE ||--|{ ORDER : covers
+          ORDER ||--|{ ORDER-ITEM : includes
+          PRODUCT-CATEGORY ||--|{ PRODUCT : contains
+          PRODUCT ||--o{ ORDER-ITEM : "ordered in"
+        
+
+
+

Basic Relationship

+
+---
+  config:
+    layout: elk
+---
+          erDiagram
+          rental{
+                  ~timestamp with time zone~ rental_date "NN"
+                  ~integer~ inventory_id "NN"
+                  ~integer~ customer_id "NN"
+                  ~timestamp with time zone~ return_date
+                  ~integer~ staff_id "NN"
+                  ~integer~ rental_id "NN"
+                  ~timestamp with time zone~ last_update "NN"
+  }
+          film_actor{
+                  ~integer~ actor_id "NN"
+                  ~integer~ film_id "NN"
+                  ~timestamp with time zone~ last_update "NN"
+  }
+          film{
+                  ~text~ title "NN"
+                  ~text~ description
+                  ~public.year~ release_year
+                  ~integer~ language_id "NN"
+                  ~integer~ original_language_id
+                  ~smallint~ length
+                  ~text[]~ special_features
+                  ~tsvector~ fulltext "NN"
+                  ~integer~ film_id "NN"
+                  ~smallint~ rental_duration "NN"
+                  ~numeric(4,2)~ rental_rate "NN"
+                  ~numeric(5,2)~ replacement_cost "NN"
+                  ~public.mpaa_rating~ rating
+                  ~timestamp with time zone~ last_update "NN"
+  }
+          customer{
+                  ~integer~ store_id "NN"
+                  ~text~ first_name "NN"
+                  ~text~ last_name "NN"
+                  ~text~ email
+                  ~integer~ address_id "NN"
+                  ~integer~ active
+                  ~integer~ customer_id "NN"
+                  ~boolean~ activebool "NN"
+                  ~date~ create_date "NN"
+                  ~timestamp with time zone~ last_update
+  }
+          film_category{
+                  ~integer~ film_id "NN"
+                  ~integer~ category_id "NN"
+                  ~timestamp with time zone~ last_update "NN"
+  }
+          actor{
+                  ~text~ first_name "NN"
+                  ~text~ last_name "NN"
+                  ~integer~ actor_id "NN"
+                  ~timestamp with time zone~ last_update "NN"
+  }
+          store{
+                  ~integer~ manager_staff_id "NN"
+                  ~integer~ address_id "NN"
+                  ~integer~ store_id "NN"
+                  ~timestamp with time zone~ last_update "NN"
+  }
+          city{
+                  ~text~ city "NN"
+                  ~integer~ country_id "NN"
+                  ~integer~ city_id "NN"
+                  ~timestamp with time zone~ last_update "NN"
+  }
+          language{
+                  ~character(20)~ name "NN"
+                  ~integer~ language_id "NN"
+                  ~timestamp with time zone~ last_update "NN"
+  }
+          payment{
+                  ~integer~ customer_id "NN"
+                  ~integer~ staff_id "NN"
+                  ~integer~ rental_id "NN"
+                  ~numeric(5,2)~ amount "NN"
+                  ~timestamp with time zone~ payment_date "NN"
+                  ~integer~ payment_id "NN"
+  }
+          category{
+                  ~text~ name "NN"
+                  ~integer~ category_id "NN"
+                  ~timestamp with time zone~ last_update "NN"
+  }
+          inventory{
+                  ~integer~ film_id "NN"
+                  ~integer~ store_id "NN"
+                  ~integer~ inventory_id "NN"
+                  ~timestamp with time zone~ last_update "NN"
+  }
+          address{
+                  ~text~ address "NN"
+                  ~text~ address2
+                  ~text~ district "NN"
+                  ~integer~ city_id "NN"
+                  ~text~ postal_code
+                  ~text~ phone "NN"
+                  ~integer~ address_id "NN"
+                  ~timestamp with time zone~ last_update "NN"
+  }
+          staff{
+                  ~text~ first_name "NN"
+                  ~text~ last_name "NN"
+                  ~integer~ address_id "NN"
+                  ~text~ email
+                  ~integer~ store_id "NN"
+                  ~text~ username "NN"
+                  ~text~ password
+                  ~bytea~ picture
+                  ~integer~ staff_id "NN"
+                  ~boolean~ active "NN"
+                  ~timestamp with time zone~ last_update "NN"
+  }
+          country{
+                  ~text~ country "NN"
+                  ~integer~ country_id "NN"
+                  ~timestamp with time zone~ last_update "NN"
+  }
+  film_actor }|..|| film : film_actor_film_id_fkey
+  film_actor }|..|| actor : film_actor_actor_id_fkey
+  address }|..|| city : address_city_id_fkey
+  city }|..|| country : city_country_id_fkey
+  customer }|..|| store : customer_store_id_fkey
+  customer }|..|| address : customer_address_id_fkey
+  film }|..|| language : film_original_language_id_fkey
+  film }|..|| language : film_language_id_fkey
+  film_category }|..|| film : film_category_film_id_fkey
+  film_category }|..|| category : film_category_category_id_fkey
+  inventory }|..|| store : inventory_store_id_fkey
+        
+
+
+ + + + + diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js index ef985866e..aa888465b 100644 --- a/cypress/support/e2e.js +++ b/cypress/support/e2e.js @@ -15,6 +15,7 @@ import '@cypress/code-coverage/support'; import '@applitools/eyes-cypress/commands'; +import '@argos-ci/cypress/support'; // Import commands.js using ES2015 syntax: import './commands'; diff --git a/cypress/timings.json b/cypress/timings.json new file mode 100644 index 000000000..66ea9918d --- /dev/null +++ b/cypress/timings.json @@ -0,0 +1,212 @@ +{ + "durations": [ + { + "spec": "cypress/integration/other/configuration.spec.js", + "duration": 5450 + }, + { + "spec": "cypress/integration/other/external-diagrams.spec.js", + "duration": 2004 + }, + { + "spec": "cypress/integration/other/ghsa.spec.js", + "duration": 3183 + }, + { + "spec": "cypress/integration/other/iife.spec.js", + "duration": 1913 + }, + { + "spec": "cypress/integration/other/interaction.spec.js", + "duration": 10944 + }, + { + "spec": "cypress/integration/other/rerender.spec.js", + "duration": 1938 + }, + { + "spec": "cypress/integration/other/xss.spec.js", + "duration": 26753 + }, + { + "spec": "cypress/integration/rendering/appli.spec.js", + "duration": 2571 + }, + { + "spec": "cypress/integration/rendering/architecture.spec.ts", + "duration": 110 + }, + { + "spec": "cypress/integration/rendering/block.spec.js", + "duration": 14697 + }, + { + "spec": "cypress/integration/rendering/c4.spec.js", + "duration": 4705 + }, + { + "spec": "cypress/integration/rendering/classDiagram-elk-v3.spec.js", + "duration": 35841 + }, + { + "spec": "cypress/integration/rendering/classDiagram-handDrawn-v3.spec.js", + "duration": 34279 + }, + { + "spec": "cypress/integration/rendering/classDiagram-v2.spec.js", + "duration": 20641 + }, + { + "spec": "cypress/integration/rendering/classDiagram-v3.spec.js", + "duration": 33020 + }, + { + "spec": "cypress/integration/rendering/classDiagram.spec.js", + "duration": 13546 + }, + { + "spec": "cypress/integration/rendering/conf-and-directives.spec.js", + "duration": 8072 + }, + { + "spec": "cypress/integration/rendering/current.spec.js", + "duration": 2083 + }, + { + "spec": "cypress/integration/rendering/erDiagram-unified.spec.js", + "duration": 78269 + }, + { + "spec": "cypress/integration/rendering/erDiagram.spec.js", + "duration": 12578 + }, + { + "spec": "cypress/integration/rendering/errorDiagram.spec.js", + "duration": 2784 + }, + { + "spec": "cypress/integration/rendering/flowchart-elk.spec.js", + "duration": 36205 + }, + { + "spec": "cypress/integration/rendering/flowchart-handDrawn.spec.js", + "duration": 26627 + }, + { + "spec": "cypress/integration/rendering/flowchart-shape-alias.spec.ts", + "duration": 21332 + }, + { + "spec": "cypress/integration/rendering/flowchart-v2.spec.js", + "duration": 37328 + }, + { + "spec": "cypress/integration/rendering/flowchart.spec.js", + "duration": 25914 + }, + { + "spec": "cypress/integration/rendering/gantt.spec.js", + "duration": 15383 + }, + { + "spec": "cypress/integration/rendering/gitGraph.spec.js", + "duration": 45226 + }, + { + "spec": "cypress/integration/rendering/iconShape.spec.ts", + "duration": 251094 + }, + { + "spec": "cypress/integration/rendering/imageShape.spec.ts", + "duration": 50916 + }, + { + "spec": "cypress/integration/rendering/info.spec.ts", + "duration": 2489 + }, + { + "spec": "cypress/integration/rendering/journey.spec.js", + "duration": 5988 + }, + { + "spec": "cypress/integration/rendering/kanban.spec.ts", + "duration": 6225 + }, + { + "spec": "cypress/integration/rendering/katex.spec.js", + "duration": 3009 + }, + { + "spec": "cypress/integration/rendering/marker_unique_id.spec.js", + "duration": 2426 + }, + { + "spec": "cypress/integration/rendering/mindmap.spec.ts", + "duration": 9306 + }, + { + "spec": "cypress/integration/rendering/newShapes.spec.ts", + "duration": 134419 + }, + { + "spec": "cypress/integration/rendering/oldShapes.spec.ts", + "duration": 102434 + }, + { + "spec": "cypress/integration/rendering/packet.spec.ts", + "duration": 3373 + }, + { + "spec": "cypress/integration/rendering/pie.spec.ts", + "duration": 4898 + }, + { + "spec": "cypress/integration/rendering/quadrantChart.spec.js", + "duration": 7578 + }, + { + "spec": "cypress/integration/rendering/radar.spec.js", + "duration": 4526 + }, + { + "spec": "cypress/integration/rendering/requirement.spec.js", + "duration": 2172 + }, + { + "spec": "cypress/integration/rendering/requirementDiagram-unified.spec.js", + "duration": 47175 + }, + { + "spec": "cypress/integration/rendering/sankey.spec.ts", + "duration": 5717 + }, + { + "spec": "cypress/integration/rendering/sequencediagram.spec.js", + "duration": 32556 + }, + { + "spec": "cypress/integration/rendering/stateDiagram-v2.spec.js", + "duration": 22572 + }, + { + "spec": "cypress/integration/rendering/stateDiagram.spec.js", + "duration": 14064 + }, + { + "spec": "cypress/integration/rendering/theme.spec.js", + "duration": 26565 + }, + { + "spec": "cypress/integration/rendering/timeline.spec.ts", + "duration": 6233 + }, + { + "spec": "cypress/integration/rendering/xyChart.spec.js", + "duration": 17750 + }, + { + "spec": "cypress/integration/rendering/zenuml.spec.js", + "duration": 2696 + } + ] +} diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json index baa9a7217..b01ce9bac 100644 --- a/cypress/tsconfig.json +++ b/cypress/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "target": "es2020", "lib": ["es2020", "dom"], - "types": ["cypress", "node"], + "types": ["cypress", "node", "@argos-ci/cypress/dist/support.d.ts"], "allowImportingTsExtensions": true, "noEmit": true }, diff --git a/demos/architecture.html b/demos/architecture.html new file mode 100644 index 000000000..6d978d952 --- /dev/null +++ b/demos/architecture.html @@ -0,0 +1,256 @@ + + + + + + Architecture Mermaid Quick Test Page + + + + + +

Architecture diagram demo

+

Simple diagram with groups

+
+      architecture-beta
+        group api(cloud)[API]
+
+        service db(database)[Database] in api
+        service disk1(disk)[Storage] in api
+        service disk2(disk)[Storage] in api
+        service server(server)[Server] in api
+        service gateway(internet)[Gateway] 
+
+        db:L -- R:server
+        disk1:T -- B:server
+        disk2:T -- B:db
+        server:T -- B:gateway
+    
+
+ +

Groups within groups

+
+      architecture-beta
+        group api[API]
+        group public[Public API] in api
+        group private[Private API] in api
+
+
+        service serv1(server)[Server] in public
+
+
+        service serv2(server)[Server] in private
+        service db(database)[Database] in private
+
+        service gateway(internet)[Gateway] in api
+
+        serv1:B -- T:serv2
+
+        serv2:L -- R:db
+
+        serv1:L -- R:gateway
+    
+
+ +

Default icon (?) from unknown icon name

+
+      architecture-beta
+        service unknown(iconnamedoesntexist)[Unknown Icon]
+    
+
+ +

Split Direction

+
+      architecture-beta
+        service db(database)[Database]
+        service s3(disk)[Storage]
+        service serv1(server)[Server 1]
+        service serv2(server)[Server 2]
+        service disk(disk)[Disk]
+
+        db:L -- R:s3
+        serv1:L -- T:s3
+        serv2:L -- B:s3
+        serv1:T -- B:disk
+    
+
+ +

Arrow Tests

+
+      architecture-beta
+        service servC(server)[Server 1]
+        service servL(server)[Server 2]
+        service servR(server)[Server 3]
+        service servT(server)[Server 4]
+        service servB(server)[Server 5]
+
+        servC:L <--> R:servL
+        servC:R <--> L:servR
+        servC:T <--> B:servT
+        servC:B <--> T:servB
+
+        servL:T <--> L:servT
+        servL:B <--> L:servB
+        servR:T <--> R:servT
+        servR:B <--> R:servB
+    
+
+      architecture-beta
+        service servC(server)[Server 1]
+        service servL(server)[Server 2]
+        service servR(server)[Server 3]
+        service servT(server)[Server 4]
+        service servB(server)[Server 5]
+
+        servC:L <--> R:servL
+        servC:R <--> L:servR
+        servC:T <--> B:servT
+        servC:B <--> T:servB
+
+        servT:L <--> T:servL
+        servB:L <--> B:servL
+        servT:R <--> T:servR
+        servB:R <--> B:servR
+    
+
+ +

Group Edges

+
+      architecture-beta
+        group left_group(cloud)[Left]
+        group right_group(cloud)[Right]
+        group top_group(cloud)[Top]
+        group bottom_group(cloud)[Bottom]
+        group center_group(cloud)[Center]
+
+        service left_disk(disk)[Disk] in left_group
+        service right_disk(disk)[Disk] in right_group
+        service top_disk(disk)[Disk] in top_group
+        service bottom_disk(disk)[Disk] in bottom_group
+        service center_disk(disk)[Disk] in center_group
+
+        left_disk{group}:R <--> L:center_disk{group}
+        right_disk{group}:L <--> R:center_disk{group}
+        top_disk{group}:B <--> T:center_disk{group}
+        bottom_disk{group}:T <--> B:center_disk{group}
+  
+
+ +

Edge Label Test

+
+      architecture-beta
+        service servC(server)[Server 1]
+        service servL(server)[Server 2]
+        service servR(server)[Server 3]
+        service servT(server)[Server 4]
+        service servB(server)[Server 5]
+
+        servC:L -[Label]- R:servL
+        servC:R -[Label]- L:servR
+        servC:T -[Label]- B:servT
+        servC:B -[Label]- T:servB
+
+        servL:T -[Label]- L:servT
+        servL:B -[Label]- L:servB
+        servR:T -[Label]- R:servT
+        servR:B -[Label]- R:servB
+    
+
+      architecture-beta
+        service servC(server)[Server 1]
+        service servL(server)[Server 2]
+        service servR(server)[Server 3]
+        service servT(server)[Server 4]
+        service servB(server)[Server 5]
+
+        servC:L -[Label that is Long]- R:servL
+        servC:R -[Label that is Long]- L:servR
+        servC:T -[Label that is Long]- B:servT
+        servC:B -[Label that is Long]- T:servB
+
+        servL:T -[Label that is Long]- L:servT
+        servL:B -[Label that is Long]- L:servB
+        servR:T -[Label that is Long]- R:servT
+        servR:B -[Label that is Long]- R:servB
+    
+ +
+

Junction Demo

+
+      architecture-beta
+        service left_disk(disk)[Disk]
+        service top_disk(disk)[Disk]
+        service bottom_disk(disk)[Disk]
+        service top_gateway(internet)[Gateway]
+        service bottom_gateway(internet)[Gateway]
+        junction juncC
+        junction juncR
+
+        left_disk:R -- L:juncC
+        top_disk:B -- T:juncC
+        bottom_disk:T -- B:juncC
+        juncC:R -- L:juncR
+        top_gateway:B -- T:juncR
+        bottom_gateway:T -- B:juncR
+    
+
+ +

Junction Demo Groups

+
+      architecture-beta
+        group left
+        group right
+        service left_disk(disk)[Disk] in left
+        service top_disk(disk)[Disk] in left
+        service bottom_disk(disk)[Disk] in left
+        service top_gateway(internet)[Gateway] in right
+        service bottom_gateway(internet)[Gateway] in right
+        junction juncC in left
+        junction juncR in right
+
+        left_disk:R -- L:juncC
+        top_disk:B -- T:juncC
+        bottom_disk:T -- B:juncC
+
+
+        top_gateway:B <-- T:juncR
+        bottom_gateway:T <-- B:juncR
+
+        juncC{group}:R --> L:juncR{group}
+    
+
+ +

External Icons Demo

+
+    architecture-beta
+      service s3(logos:aws-s3)[Cloud Store]
+      service ec2(logos:aws-ec2)[Server]
+      service api(logos:aws-api-gateway)[Api Gateway]
+      service fa(fa:image)[Font Awesome Icon]
+    
+ + + + diff --git a/demos/c4context.html b/demos/c4context.html index 64ca768e1..d13717c3f 100644 --- a/demos/c4context.html +++ b/demos/c4context.html @@ -110,7 +110,7 @@ title Component diagram for Internet Banking System - API Application Container(spa, "Single Page Application", "javascript and angular", "Provides all the internet banking functionality to customers via their web browser.") - Container(ma, "Mobile App", "Xamarin", "Provides a limited subset ot the internet banking functionality to customers via their mobile mobile device.") + Container(ma, "Mobile App", "Xamarin", "Provides a limited subset ot the internet banking functionality to customers via their mobile device.") ContainerDb(db, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.") System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.") diff --git a/demos/classchart.html b/demos/classchart.html index f04fa5b5f..10d8e6b70 100644 --- a/demos/classchart.html +++ b/demos/classchart.html @@ -148,7 +148,7 @@
     classDiagram
       class Person {
-        +Id : Guid
+        +ID : Guid
         +FirstName : string
         +LastName : string
         -privateProperty : string
@@ -159,30 +159,87 @@
       class People List~List~Person~~
     

-
     classDiagram
-      A1 --> B1
-      namespace A {
-        class A1 {
-          +foo : string
-        }
-        class A2 {
-          +bar : int
+      namespace Company.Project.Module {
+        class GenericClass~T~ {
+          +addItem(item: T)
+          +getItem() T
         }
       }
-      namespace B {
-        class B1 {
-          +foo : bool
-        }
-        class B2 {
-          +bar : float
-        }
-      }
-      A2 --> B2
     

+
+    classDiagram
+      namespace Company.Project.Module.SubModule {
+        class Report {
+          +generatePDF(data: List)
+          +generateCSV(data: List)
+        }
+      }
+      namespace Company.Project.Module {
+        class Admin {
+          +generateReport()
+        }
+      }
+      Admin --> Report : generates
+    
+
+    classDiagram
+      namespace Company.Project.Module {
+        class User {
+          +login(username: String, password: String)
+          +logout()
+        }
+        class Admin {
+          +addUser(user: User)
+          +removeUser(user: User)
+          +generateReport()
+        }
+        class Report {
+          +generatePDF(reportData: List)
+          +generateCSV(reportData: List)
+        }
+      }
+      Admin --> User : manages
+      Admin --> Report : generates
+    
+
+
+    classDiagram
+      namespace Shapes {
+        class Shape {
+          +calculateArea() double
+        }
+        class Circle {
+          +double radius
+        }
+        class Square {
+          +double side
+        }
+      }
 
+      Shape <|-- Circle
+      Shape <|-- Square
+
+      namespace Vehicles {
+        class Vehicle {
+          +String brand
+        }
+        class Car {
+          +int horsepower
+        }
+        class Bike {
+          +boolean hasGears
+        }
+      }
+
+      Vehicle <|-- Car
+      Vehicle <|-- Bike
+      Car --> Circle : "Logo Shape"
+      Bike --> Square : "Logo Shape"
+
+    
+ + + + diff --git a/demos/sequence.html b/demos/sequence.html index abdc84f04..eca935ff5 100644 --- a/demos/sequence.html +++ b/demos/sequence.html @@ -238,6 +238,17 @@ Alice-xJohn: Hello John, how are you? John--xAlice: Great!
+ +
+ +
+    sequenceDiagram
+      participant Alice
+      participant Bob
+      Alice<<->>Bob: Hello!
+      Alice<<->>Bob: Wow, we said that at the same time!
+      Bob<<-->>Alice: Bidirectional Arrows are so cool
+    
@@ -913,7 +1700,7 @@ flowchart LR > **Success** The tooltip functionality and the ability to link to urls are available from version 0.5.2. -?> Due to limitations with how Docsify handles JavaScript callback functions, an alternate working demo for the above code can be viewed at [this jsfiddle](https://jsfiddle.net/Ogglas/2o73vdez/7). +?> Due to limitations with how Docsify handles JavaScript callback functions, an alternate working demo for the above code can be viewed at [this jsfiddle](https://jsfiddle.net/yk4h7qou/2/). Links are opened in the same browser tab/window by default. It is possible to change this by adding a link target to the click definition (`_self`, `_blank`, `_parent` and `_top` are supported): @@ -957,7 +1744,7 @@ Beginner's tip—a full example using interactive links in a html context:
``` -You can also refer the implementation in the live editor [here](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done. +You can also refer the [implementation in the live editor](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done. Not Urgent y-axis Not Important --> "Important ❤" @@ -159,7 +166,14 @@ quadrantChart ``` ```mermaid -%%{init: {"quadrantChart": {"chartWidth": 400, "chartHeight": 400}, "themeVariables": {"quadrant1TextFill": "#ff0000"} }}%% +--- +config: + quadrantChart: + chartWidth: 400 + chartHeight: 400 + themeVariables: + quadrant1TextFill: "ff0000" +--- quadrantChart x-axis Urgent --> Not Urgent y-axis Not Important --> "Important ❤" @@ -178,7 +192,7 @@ Points can either be styled directly or with defined shared classes ```md Point A: [0.9, 0.0] radius: 12 Point B: [0.8, 0.1] color: #ff3300, radius: 10 -Point C: [0.7, 0.2] radius: 25, color: #00ff33, stroke-color: #10f0f0 +Point C: [0.7, 0.2] radius: 25, color: #00ff33, stroke-color: #10f0f0 Point D: [0.6, 0.3] radius: 15, stroke-color: #00ff0f, stroke-width: 5px ,color: #ff33f0 ``` diff --git a/docs/syntax/radar.md b/docs/syntax/radar.md new file mode 100644 index 000000000..bc19d85da --- /dev/null +++ b/docs/syntax/radar.md @@ -0,0 +1,269 @@ +> **Warning** +> +> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. +> +> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/radar.md](../../packages/mermaid/src/docs/syntax/radar.md). + +# Radar Diagram (v11.6.0+) + +## Introduction + +A radar diagram is a simple way to plot low-dimensional data in a circular format. + +It is also known as a **radar chart**, **spider chart**, **star chart**, **cobweb chart**, **polar chart**, or **Kiviat diagram**. + +## Usage + +This diagram type is particularly useful for developers, data scientists, and engineers who require a clear and concise way to represent data in a circular format. + +It is commonly used to graphically summarize and compare the performance of multiple entities across multiple dimensions. + +## Syntax + +```md +radar-beta +axis A, B, C, D, E +curve c1{1,2,3,4,5} +curve c2{5,4,3,2,1} +... More Fields ... +``` + +## Examples + +```mermaid-example +--- +title: "Grades" +--- +radar-beta + axis m["Math"], s["Science"], e["English"] + axis h["History"], g["Geography"], a["Art"] + curve a["Alice"]{85, 90, 80, 70, 75, 90} + curve b["Bob"]{70, 75, 85, 80, 90, 85} + + max 100 + min 0 +``` + +```mermaid +--- +title: "Grades" +--- +radar-beta + axis m["Math"], s["Science"], e["English"] + axis h["History"], g["Geography"], a["Art"] + curve a["Alice"]{85, 90, 80, 70, 75, 90} + curve b["Bob"]{70, 75, 85, 80, 90, 85} + + max 100 + min 0 +``` + +```mermaid-example +radar-beta + title Restaurant Comparison + axis food["Food Quality"], service["Service"], price["Price"] + axis ambiance["Ambiance"], + + curve a["Restaurant A"]{4, 3, 2, 4} + curve b["Restaurant B"]{3, 4, 3, 3} + curve c["Restaurant C"]{2, 3, 4, 2} + curve d["Restaurant D"]{2, 2, 4, 3} + + graticule polygon + max 5 + +``` + +```mermaid +radar-beta + title Restaurant Comparison + axis food["Food Quality"], service["Service"], price["Price"] + axis ambiance["Ambiance"], + + curve a["Restaurant A"]{4, 3, 2, 4} + curve b["Restaurant B"]{3, 4, 3, 3} + curve c["Restaurant C"]{2, 3, 4, 2} + curve d["Restaurant D"]{2, 2, 4, 3} + + graticule polygon + max 5 + +``` + +## Details of Syntax + +### Title + +`title`: The title is an optional field that allows to render a title at the top of the radar diagram. + +``` +radar-beta + title Title of the Radar Diagram + ... +``` + +### Axis + +`axis`: The axis keyword is used to define the axes of the radar diagram. + +Each axis is represented by an ID and an optional label. + +Multiple axes can be defined in a single line. + +``` +radar-beta + axis id1["Label1"] + axis id2["Label2"], id3["Label3"] + ... +``` + +### Curve + +`curve`: The curve keyword is used to define the data points for a curve in the radar diagram. + +Each curve is represented by an ID, an optional label, and a list of values. + +Values can be defined by a list of numbers or a list of key-value pairs. If key-value pairs are used, the key represents the axis ID and the value represents the data point. Else, the data points are assumed to be in the order of the axes defined. + +Multiple curves can be defined in a single line. + +``` +radar-beta + axis axis1, axis2, axis3 + curve id1["Label1"]{1, 2, 3} + curve id2["Label2"]{4, 5, 6}, id3{7, 8, 9} + curve id4{ axis3: 30, axis1: 20, axis2: 10 } + ... +``` + +### Options + +- `showLegend`: The showLegend keyword is used to show or hide the legend in the radar diagram. The legend is shown by default. +- `max`: The maximum value for the radar diagram. This is used to scale the radar diagram. If not provided, the maximum value is calculated from the data points. +- `min`: The minimum value for the radar diagram. This is used to scale the radar diagram. If not provided, the minimum value is `0`. +- `graticule`: The graticule keyword is used to define the type of graticule to be rendered in the radar diagram. The graticule can be `circle` or `polygon`. If not provided, the default graticule is `circle`. +- `ticks`: The ticks keyword is used to define the number of ticks on the graticule. It is the number of concentric circles or polygons drawn to indicate the scale of the radar diagram. If not provided, the default number of ticks is `5`. + +``` +radar-beta + ... + showLegend true + max 100 + min 0 + graticule circle + ticks 5 + ... +``` + +## Configuration + +Please refer to the [configuration](/config/schema-docs/config-defs-radar-diagram-config.html) guide for details. + +| Parameter | Description | Default Value | +| --------------- | ---------------------------------------- | ------------- | +| width | Width of the radar diagram | `600` | +| height | Height of the radar diagram | `600` | +| marginTop | Top margin of the radar diagram | `50` | +| marginBottom | Bottom margin of the radar diagram | `50` | +| marginLeft | Left margin of the radar diagram | `50` | +| marginRight | Right margin of the radar diagram | `50` | +| axisScaleFactor | Scale factor for the axis | `1` | +| axisLabelFactor | Factor to adjust the axis label position | `1.05` | +| curveTension | Tension for the rounded curves | `0.17` | + +## Theme Variables + +### Global Theme Variables + +> **Note** +> The default values for these variables depend on the theme used. To override the default values, set the desired values in the themeVariables section of the configuration: +> +> --- +> +> config: +> themeVariables: +> cScale0: "#FF0000" +> cScale1: "#00FF00" +> +> --- + +Radar charts support the color scales `cScale${i}` where `i` is a number from `0` to the theme's maximum number of colors in its color scale. Usually, the maximum number of colors is `12`. + +| Property | Description | +| ---------- | ------------------------------ | +| fontSize | Font size of the title | +| titleColor | Color of the title | +| cScale${i} | Color scale for the i-th curve | + +### Radar Style Options + +> **Note** +> Specific variables for radar resides inside the `radar` key. To set the radar style options, use this syntax. +> +> --- +> +> config: +> themeVariables: +> radar: +> axisColor: "#FF0000" +> +> --- + +| Property | Description | Default Value | +| -------------------- | ---------------------------- | ------------- | +| axisColor | Color of the axis lines | `black` | +| axisStrokeWidth | Width of the axis lines | `1` | +| axisLabelFontSize | Font size of the axis labels | `12px` | +| curveOpacity | Opacity of the curves | `0.7` | +| curveStrokeWidth | Width of the curves | `2` | +| graticuleColor | Color of the graticule | `black` | +| graticuleOpacity | Opacity of the graticule | `0.5` | +| graticuleStrokeWidth | Width of the graticule | `1` | +| legendBoxSize | Size of the legend box | `10` | +| legendFontSize | Font size of the legend | `14px` | + +## Example on config and theme + +```mermaid-example +--- +config: + radar: + axisScaleFactor: 0.25 + curveTension: 0.1 + theme: base + themeVariables: + cScale0: "#FF0000" + cScale1: "#00FF00" + cScale2: "#0000FF" + radar: + curveOpacity: 0 +--- +radar-beta + axis A, B, C, D, E + curve c1{1,2,3,4,5} + curve c2{5,4,3,2,1} + curve c3{3,3,3,3,3} +``` + +```mermaid +--- +config: + radar: + axisScaleFactor: 0.25 + curveTension: 0.1 + theme: base + themeVariables: + cScale0: "#FF0000" + cScale1: "#00FF00" + cScale2: "#0000FF" + radar: + curveOpacity: 0 +--- +radar-beta + axis A, B, C, D, E + curve c1{1,2,3,4,5} + curve c2{5,4,3,2,1} + curve c3{3,3,3,3,3} +``` + + diff --git a/docs/syntax/requirementDiagram.md b/docs/syntax/requirementDiagram.md index 01fdf1944..36420d9b9 100644 --- a/docs/syntax/requirementDiagram.md +++ b/docs/syntax/requirementDiagram.md @@ -50,7 +50,7 @@ There are three types of components to a requirement diagram: requirement, eleme The grammar for defining each is defined below. Words denoted in angle brackets, such as ``, are enumerated keywords that have options elaborated in a table. `user_defined_...` is use in any place where user input is expected. -An important note on user text: all input can be surrounded in quotes or not. For example, both `Id: "here is an example"` and `Id: here is an example` are both valid. However, users must be careful with unquoted input. The parser will fail if another keyword is detected. +An important note on user text: all input can be surrounded in quotes or not. For example, both `id: "here is an example"` and `id: here is an example` are both valid. However, users must be careful with unquoted input. The parser will fail if another keyword is detected. ### Requirement @@ -84,6 +84,37 @@ element user_defined_name { } ``` +### Markdown Formatting + +In places where user defined text is possible (like names, requirement text, element docref, etc.), you can: + +- Surround the text in quotes: `"example text"` +- Use markdown formatting inside quotes: `"**bold text** and *italics*"` + +Example: + +```mermaid-example +requirementDiagram + +requirement "__test_req__" { + id: 1 + text: "*italicized text* **bold text**" + risk: high + verifymethod: test +} +``` + +```mermaid +requirementDiagram + +requirement "__test_req__" { + id: 1 + text: "*italicized text* **bold text**" + risk: high + verifymethod: test +} +``` + ### Relationship Relationships are comprised of a source node, destination node, and relationship type. @@ -250,4 +281,215 @@ This example uses all features of the diagram. test_req <- copies - test_entity2 ``` +## Direction + +The diagram can be rendered in different directions using the `direction` statement. Valid values are: + +- `TB` - Top to Bottom (default) +- `BT` - Bottom to Top +- `LR` - Left to Right +- `RL` - Right to Left + +Example: + +```mermaid-example +requirementDiagram + +direction LR + +requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test +} + +element test_entity { + type: simulation +} + +test_entity - satisfies -> test_req +``` + +```mermaid +requirementDiagram + +direction LR + +requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test +} + +element test_entity { + type: simulation +} + +test_entity - satisfies -> test_req +``` + +## Styling + +Requirements and elements can be styled using direct styling or classes. As a rule of thumb, when applying styles or classes, it accepts a list of requirement or element names and a list of class names allowing multiple assignments at a time (The only exception is the shorthand syntax `:::` which can assign multiple classes but only to one requirement or element at a time). + +### Direct Styling + +Use the `style` keyword to apply CSS styles directly: + +```mermaid-example +requirementDiagram + +requirement test_req { + id: 1 + text: styling example + risk: low + verifymethod: test +} + +element test_entity { + type: simulation +} + +style test_req fill:#ffa,stroke:#000, color: green +style test_entity fill:#f9f,stroke:#333, color: blue +``` + +```mermaid +requirementDiagram + +requirement test_req { + id: 1 + text: styling example + risk: low + verifymethod: test +} + +element test_entity { + type: simulation +} + +style test_req fill:#ffa,stroke:#000, color: green +style test_entity fill:#f9f,stroke:#333, color: blue +``` + +### Class Definitions + +Define reusable styles using `classDef`: + +```mermaid-example +requirementDiagram + +requirement test_req { + id: 1 + text: "class styling example" + risk: low + verifymethod: test +} + +element test_entity { + type: simulation +} + +classDef important fill:#f96,stroke:#333,stroke-width:4px +classDef test fill:#ffa,stroke:#000 +``` + +```mermaid +requirementDiagram + +requirement test_req { + id: 1 + text: "class styling example" + risk: low + verifymethod: test +} + +element test_entity { + type: simulation +} + +classDef important fill:#f96,stroke:#333,stroke-width:4px +classDef test fill:#ffa,stroke:#000 +``` + +### Default class + +If a class is named default it will be applied to all nodes. Specific styles and classes should be defined afterwards to override the applied default styling. + +``` +classDef default fill:#f9f,stroke:#333,stroke-width:4px; +``` + +### Applying Classes + +Classes can be applied in two ways: + +1. Using the `class` keyword: + +``` +class test_req,test_entity important +``` + +2. Using the shorthand syntax with `:::` either during the definition or afterwards: + +``` +requirement test_req:::important { + id: 1 + text: class styling example + risk: low + verifymethod: test +} +``` + +``` +element test_elem { +} + +test_elem:::myClass +``` + +### Combined Example + +```mermaid-example +requirementDiagram + +requirement test_req:::important { + id: 1 + text: "class styling example" + risk: low + verifymethod: test +} + +element test_entity { + type: simulation +} + +classDef important font-weight:bold + +class test_entity important +style test_entity fill:#f9f,stroke:#333 +``` + +```mermaid +requirementDiagram + +requirement test_req:::important { + id: 1 + text: "class styling example" + risk: low + verifymethod: test +} + +element test_entity { + type: simulation +} + +classDef important font-weight:bold + +class test_entity important +style test_entity fill:#f9f,stroke:#333 +``` + diff --git a/docs/syntax/sequenceDiagram.md b/docs/syntax/sequenceDiagram.md index a8455964e..84240a0cd 100644 --- a/docs/syntax/sequenceDiagram.md +++ b/docs/syntax/sequenceDiagram.md @@ -155,6 +155,9 @@ end box rgb(33,66,99) ... actors ... end +box rgba(33,66,99,0.5) +... actors ... +end ``` > **Note** @@ -206,18 +209,20 @@ Messages can be of two displayed either solid or with a dotted line. [Actor][Arrow][Actor]:Message text ``` -There are six types of arrows currently supported: +There are ten types of arrows currently supported: -| Type | Description | -| ------ | ------------------------------------------------ | -| `->` | Solid line without arrow | -| `-->` | Dotted line without arrow | -| `->>` | Solid line with arrowhead | -| `-->>` | Dotted line with arrowhead | -| `-x` | Solid line with a cross at the end | -| `--x` | Dotted line with a cross at the end. | -| `-)` | Solid line with an open arrow at the end (async) | -| `--)` | Dotted line with a open arrow at the end (async) | +| Type | Description | +| -------- | ---------------------------------------------------- | +| `->` | Solid line without arrow | +| `-->` | Dotted line without arrow | +| `->>` | Solid line with arrowhead | +| `-->>` | Dotted line with arrowhead | +| `<<->>` | Solid line with bidirectional arrowheads (v11.0.0+) | +| `<<-->>` | Dotted line with bidirectional arrowheads (v11.0.0+) | +| `-x` | Solid line with a cross at the end | +| `--x` | Dotted line with a cross at the end | +| `-)` | Solid line with an open arrow at the end (async) | +| `--)` | Dotted line with a open arrow at the end (async) | ## Activations @@ -304,17 +309,35 @@ sequenceDiagram Note over Alice,John: A typical interaction ``` -It is also possible to add a line break (applies to text input in general): +## Line breaks + +Line break can be added to Note and Message: ```mermaid-example sequenceDiagram - Alice->John: Hello John, how are you? + Alice->John: Hello John,
how are you? Note over Alice,John: A typical interaction
But now in two lines ``` ```mermaid sequenceDiagram - Alice->John: Hello John, how are you? + Alice->John: Hello John,
how are you? + Note over Alice,John: A typical interaction
But now in two lines +``` + +Line breaks in Actor names requires aliases: + +```mermaid-example +sequenceDiagram + participant Alice as Alice
Johnson + Alice->John: Hello John,
how are you? + Note over Alice,John: A typical interaction
But now in two lines +``` + +```mermaid +sequenceDiagram + participant Alice as Alice
Johnson + Alice->John: Hello John,
how are you? Note over Alice,John: A typical interaction
But now in two lines ``` @@ -560,6 +583,12 @@ sequenceDiagram It is possible to highlight flows by providing colored background rects. This is done by the notation +``` +rect COLOR +... content ... +end +``` + The colors are defined using rgb and rgba syntax. ``` diff --git a/docs/syntax/stateDiagram.md b/docs/syntax/stateDiagram.md index 7c40a5d2f..c9ca956f2 100644 --- a/docs/syntax/stateDiagram.md +++ b/docs/syntax/stateDiagram.md @@ -160,7 +160,7 @@ In a real world use of state diagrams you often end up with diagrams that are mu have several internal states. These are called composite states in this terminology. In order to define a composite state you need to use the state keyword followed by an id and the body of the composite -state between {}. See the example below: +state between {}. You can name a composite state on a separate line just like a simple state. See the example below: ```mermaid-example stateDiagram-v2 @@ -169,6 +169,14 @@ stateDiagram-v2 [*] --> second second --> [*] } + + [*] --> NamedComposite + NamedComposite: Another Composite + state NamedComposite { + [*] --> namedSimple + namedSimple --> [*] + namedSimple: Another simple + } ``` ```mermaid @@ -178,6 +186,14 @@ stateDiagram-v2 [*] --> second second --> [*] } + + [*] --> NamedComposite + NamedComposite: Another Composite + state NamedComposite { + [*] --> namedSimple + namedSimple --> [*] + namedSimple: Another simple + } ``` You can do this in several layers: @@ -262,7 +278,7 @@ stateDiagram-v2 } ``` -_You can not define transitions between internal states belonging to different composite states_ +_You cannot define transitions between internal states belonging to different composite states_ ## Choice @@ -467,8 +483,8 @@ a _[valid CSS property name](https://www.w3.org/TR/CSS/#properties)_ followed by Here is an example of a classDef with just one property-value pair: -``` - classDef movement font-style:italic; +```txt +classDef movement font-style:italic; ``` where @@ -480,8 +496,8 @@ If you want to have more than one _property-value pair_ then you put a comma (`, Here is an example with three property-value pairs: -``` - classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow +```txt +classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow ``` where @@ -506,7 +522,7 @@ There are two ways to apply a `classDef` style to a state: A `class` statement tells Mermaid to apply the named classDef to one or more classes. The form is: ```txt - class [one or more state names, separated by commas] [name of a style defined with classDef] +class [one or more state names, separated by commas] [name of a style defined with classDef] ``` Here is an example applying the `badBadEvent` style to a state named `Crash`: diff --git a/docs/syntax/timeline.md b/docs/syntax/timeline.md index 3d476c41d..cbebbcd11 100644 --- a/docs/syntax/timeline.md +++ b/docs/syntax/timeline.md @@ -18,7 +18,7 @@ timeline 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter ``` @@ -28,7 +28,7 @@ timeline 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter ``` @@ -67,7 +67,7 @@ timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter ``` @@ -76,7 +76,7 @@ timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter ``` @@ -198,7 +198,7 @@ However, if there is no section defined, then we have two possibilities: title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter ``` @@ -208,7 +208,7 @@ However, if there is no section defined, then we have two possibilities: title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter ``` @@ -234,23 +234,35 @@ mermaid.initialize({ let us look at same example, where we have disabled the multiColor option. ```mermaid-example - %%{init: { 'logLevel': 'debug', 'theme': 'base', 'timeline': {'disableMulticolor': true}}}%% +--- +config: + logLevel: 'debug' + theme: 'base' + timeline: + disableMulticolor: true +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter ``` ```mermaid - %%{init: { 'logLevel': 'debug', 'theme': 'base', 'timeline': {'disableMulticolor': true}}}%% +--- +config: + logLevel: 'debug' + theme: 'base' + timeline: + disableMulticolor: true +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter ``` @@ -269,16 +281,22 @@ Example: Now let's override the default values for the `cScale0` to `cScale2` variables: ```mermaid-example - %%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': { - 'cScale0': '#ff0000', 'cScaleLabel0': '#ffffff', - 'cScale1': '#00ff00', - 'cScale2': '#0000ff', 'cScaleLabel2': '#ffffff' - } } }%% +--- +config: + logLevel: 'debug' + theme: 'default' + themeVariables: + cScale0: '#ff0000' + cScaleLabel0: '#ffffff' + cScale1: '#00ff00' + cScale2: '#0000ff' + cScaleLabel2: '#ffffff' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -287,16 +305,22 @@ Now let's override the default values for the `cScale0` to `cScale2` variables: ``` ```mermaid - %%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': { - 'cScale0': '#ff0000', 'cScaleLabel0': '#ffffff', - 'cScale1': '#00ff00', - 'cScale2': '#0000ff', 'cScaleLabel2': '#ffffff' - } } }%% +--- +config: + logLevel: 'debug' + theme: 'default' + themeVariables: + cScale0: '#ff0000' + cScaleLabel0: '#ffffff' + cScale1: '#00ff00' + cScale2: '#0000ff' + cScaleLabel2: '#ffffff' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -308,7 +332,7 @@ See how the colors are changed to the values specified in the theme variables. ## Themes -Mermaid supports a bunch of pre-defined themes which you can use to find the right one for you. PS: you can actually override an existing theme's variable to get your own custom theme going. Learn more about theming your diagram [here](../config/theming.md). +Mermaid supports a bunch of pre-defined themes which you can use to find the right one for you. PS: you can actually override an existing theme's variable to get your own custom theme going. Learn more about [theming your diagram](../config/theming.md). The following are the different pre-defined theme options: @@ -324,12 +348,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ### Base Theme ```mermaid-example -%%{init: { 'logLevel': 'debug', 'theme': 'base' } }%% +--- +config: + logLevel: 'debug' + theme: 'base' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -337,12 +365,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ``` ```mermaid -%%{init: { 'logLevel': 'debug', 'theme': 'base' } }%% +--- +config: + logLevel: 'debug' + theme: 'base' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -352,12 +384,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ### Forest Theme ```mermaid-example -%%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%% +--- +config: + logLevel: 'debug' + theme: 'forest' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -365,12 +401,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ``` ```mermaid -%%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%% +--- +config: + logLevel: 'debug' + theme: 'forest' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -380,12 +420,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ### Dark Theme ```mermaid-example -%%{init: { 'logLevel': 'debug', 'theme': 'dark' } }%% +--- +config: + logLevel: 'debug' + theme: 'dark' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -393,12 +437,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ``` ```mermaid -%%{init: { 'logLevel': 'debug', 'theme': 'dark' } }%% +--- +config: + logLevel: 'debug' + theme: 'dark' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -408,12 +456,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ### Default Theme ```mermaid-example -%%{init: { 'logLevel': 'debug', 'theme': 'default' } }%% +--- +config: + logLevel: 'debug' + theme: 'default' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -421,12 +473,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ``` ```mermaid -%%{init: { 'logLevel': 'debug', 'theme': 'default' } }%% +--- +config: + logLevel: 'debug' + theme: 'default' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -436,12 +492,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ### Neutral Theme ```mermaid-example -%%{init: { 'logLevel': 'debug', 'theme': 'neutral' } }%% +--- +config: + logLevel: 'debug' + theme: 'neutral' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -449,12 +509,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ``` ```mermaid -%%{init: { 'logLevel': 'debug', 'theme': 'neutral' } }%% +--- +config: + logLevel: 'debug' + theme: 'neutral' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -473,4 +537,4 @@ You can use this method to add mermaid including the timeline diagram to a web p ``` -You can also refer the implementation in the live editor [here](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done. +You can also refer the [implementation in the live editor](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done. diff --git a/docs/syntax/xyChart.md b/docs/syntax/xyChart.md index 7197b984d..dd64f742d 100644 --- a/docs/syntax/xyChart.md +++ b/docs/syntax/xyChart.md @@ -107,17 +107,18 @@ xychart-beta ## Chart Configurations -| Parameter | Description | Default value | -| ------------------------ | ---------------------------------------------- | :-----------: | -| width | Width of the chart | 700 | -| height | Height of the chart | 500 | -| titlePadding | Top and Bottom padding of the title | 10 | -| titleFontSize | Title font size | 20 | -| showTitle | Title to be shown or not | true | -| xAxis | xAxis configuration | AxisConfig | -| yAxis | yAxis configuration | AxisConfig | -| chartOrientation | 'vertical' or 'horizontal' | 'vertical' | -| plotReservedSpacePercent | Minimum space plots will take inside the chart | 50 | +| Parameter | Description | Default value | +| ------------------------ | ------------------------------------------------------------- | :-----------: | +| width | Width of the chart | 700 | +| height | Height of the chart | 500 | +| titlePadding | Top and Bottom padding of the title | 10 | +| titleFontSize | Title font size | 20 | +| showTitle | Title to be shown or not | true | +| xAxis | xAxis configuration | AxisConfig | +| yAxis | yAxis configuration | AxisConfig | +| chartOrientation | 'vertical' or 'horizontal' | 'vertical' | +| plotReservedSpacePercent | Minimum space plots will take inside the chart | 50 | +| showDataLabel | Should show the value corresponding to the bar within the bar | false | ### AxisConfig @@ -137,9 +138,16 @@ xychart-beta ## Chart Theme Variables -> **Note** -> Themes for xychart resides inside xychart attribute so to set the variables use this syntax -> %%{init: { "themeVariables": {"xyChart": {"titleColor": "#ff0000"} } }}%% +Themes for xychart resides inside xychart attribute so to set the variables use this syntax: + +```yaml +--- +config: + themeVariables: + xyChart: + titleColor: '#ff0000' +--- +``` | Parameter | Description | | ---------------- | --------------------------------------------------------- | @@ -163,6 +171,7 @@ config: xyChart: width: 900 height: 600 + showDataLabel: true themeVariables: xyChart: titleColor: "#ff0000" @@ -181,6 +190,7 @@ config: xyChart: width: 900 height: 600 + showDataLabel: true themeVariables: xyChart: titleColor: "#ff0000" diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 000000000..7a144ee00 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,222 @@ +import cspell from '@cspell/eslint-plugin'; +import eslint from '@eslint/js'; +import cypress from 'eslint-plugin-cypress'; +import jsdoc from 'eslint-plugin-jsdoc'; +import json from 'eslint-plugin-json'; +import lodash from 'eslint-plugin-lodash'; +import markdown from 'eslint-plugin-markdown'; +import noOnlyTests from 'eslint-plugin-no-only-tests'; +import tsdoc from 'eslint-plugin-tsdoc'; +import unicorn from 'eslint-plugin-unicorn'; +import globals from 'globals'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config( + eslint.configs.recommended, + ...tseslint.configs.recommendedTypeChecked, + ...tseslint.configs.stylisticTypeChecked, + { + ignores: [ + '**/dist/', + '**/node_modules/', + '.git/', + '**/generated/', + '**/coverage/', + 'packages/mermaid/src/config.type.ts', + 'packages/mermaid/src/docs/.vitepress/components.d.ts', + ], + }, + { + languageOptions: { + parserOptions: { + project: [ + './tsconfig.eslint.json', + './packages/*/tsconfig.json', + './packages/*/tsconfig.eslint.json', + './packages/mermaid/src/docs/tsconfig.json', + ], + tsconfigRootDir: import.meta.dirname, + }, + globals: { + ...globals.browser, + ...globals.node, + ...globals.es2020, + ...globals.jest, + cy: 'readonly', + Cypress: 'readonly', + }, + }, + }, + { + plugins: { + json, + '@cspell': cspell, + 'no-only-tests': noOnlyTests, + lodash, + unicorn, + cypress, + markdown, + tsdoc, + jsdoc, + }, + rules: { + curly: 'error', + 'no-console': 'error', + 'no-prototype-builtins': 'off', + 'no-unused-vars': 'off', + 'cypress/no-async-tests': 'off', + '@typescript-eslint/consistent-type-imports': 'error', + '@typescript-eslint/no-explicit-any': 'warn', + '@typescript-eslint/no-floating-promises': 'error', + '@typescript-eslint/no-misused-promises': 'error', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + args: 'after-used', + argsIgnorePattern: '^_', + caughtErrors: 'all', + caughtErrorsIgnorePattern: '^_', + destructuredArrayIgnorePattern: '^_', + varsIgnorePattern: '^_', + ignoreRestSiblings: true, + }, + ], + '@typescript-eslint/consistent-type-definitions': 'error', + '@typescript-eslint/ban-ts-comment': [ + 'error', + { + 'ts-expect-error': 'allow-with-description', + 'ts-ignore': 'allow-with-description', + 'ts-nocheck': 'allow-with-description', + 'ts-check': 'allow-with-description', + minimumDescriptionLength: 10, + }, + ], + '@typescript-eslint/naming-convention': [ + 'error', + { + selector: 'typeLike', + format: ['PascalCase'], + custom: { + regex: '^I[A-Z]', + match: false, + }, + }, + ], + // START: These rules should be turned on once the codebase is cleaned up + '@typescript-eslint/no-unsafe-argument': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-return': 'off', + '@typescript-eslint/only-throw-error': 'warn', + '@typescript-eslint/prefer-nullish-coalescing': 'warn', + '@typescript-eslint/prefer-promise-reject-errors': 'warn', + // END + 'json/*': ['error', 'allowComments'], + '@cspell/spellchecker': [ + 'error', + { + checkIdentifiers: true, + checkStrings: true, + checkStringTemplates: true, + }, + ], + 'no-empty': [ + 'error', + { + allowEmptyCatch: true, + }, + ], + 'no-only-tests/no-only-tests': 'error', + 'lodash/import-scope': ['error', 'method'], + 'unicorn/better-regex': 'error', + 'unicorn/no-abusive-eslint-disable': 'error', + 'unicorn/no-array-push-push': 'error', + 'unicorn/no-for-loop': 'error', + 'unicorn/no-instanceof-array': 'error', + 'unicorn/no-typeof-undefined': 'error', + 'unicorn/no-unnecessary-await': 'error', + 'unicorn/no-useless-promise-resolve-reject': 'error', + 'unicorn/prefer-array-find': 'error', + 'unicorn/prefer-array-flat-map': 'error', + 'unicorn/prefer-array-index-of': 'error', + 'unicorn/prefer-array-some': 'error', + 'unicorn/prefer-default-parameters': 'error', + 'unicorn/prefer-includes': 'error', + 'unicorn/prefer-negative-index': 'error', + 'unicorn/prefer-object-from-entries': 'error', + 'unicorn/prefer-string-starts-ends-with': 'error', + 'unicorn/prefer-string-trim-start-end': 'error', + 'unicorn/string-content': 'error', + 'unicorn/prefer-spread': 'error', + 'unicorn/no-lonely-if': 'error', + }, + }, + { + files: ['cypress/**', 'demos/**'], + rules: { + 'no-console': 'off', + }, + }, + { + files: ['**/*.{js,jsx,mjs,cjs}'], + rules: { + 'jsdoc/check-indentation': 'off', + 'jsdoc/check-alignment': 'off', + 'jsdoc/check-line-alignment': 'off', + 'jsdoc/multiline-blocks': 'off', + 'jsdoc/newline-after-description': 'off', + 'jsdoc/tag-lines': 'off', + 'jsdoc/require-param-description': 'off', + 'jsdoc/require-param-type': 'off', + 'jsdoc/require-returns': 'off', + 'jsdoc/require-returns-description': 'off', + }, + }, + { + files: ['**/*.{ts,tsx}'], + rules: { + 'no-restricted-syntax': [ + 'error', + { + selector: 'TSEnumDeclaration', + message: + 'Prefer using TypeScript union types over TypeScript enum, since TypeScript enums have a bunch of issues, see https://dev.to/dvddpl/whats-the-problem-with-typescript-enums-2okj', + }, + ], + 'tsdoc/syntax': 'error', + }, + }, + { + files: ['**/*.spec.{ts,js}', 'cypress/**', 'demos/**', '**/docs/**'], + rules: { + 'jsdoc/require-jsdoc': 'off', + '@typescript-eslint/no-unused-vars': 'off', + }, + }, + { + files: ['**/*.spec.{ts,js}', 'tests/**', 'cypress/**/*.js'], + rules: { + '@cspell/spellchecker': [ + 'error', + { + checkIdentifiers: false, + checkStrings: false, + checkStringTemplates: false, + }, + ], + }, + }, + { + files: ['*.html', '*.md', '**/*.md/*'], + rules: { + 'no-var': 'error', + 'no-undef': 'off', + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-floating-promises': 'off', + '@typescript-eslint/no-misused-promises': 'off', + }, + processor: 'markdown/markdown', + } +); diff --git a/package.json b/package.json index f3e0b4e28..0356d23f5 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "10.2.4", "description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.", "type": "module", - "packageManager": "pnpm@8.15.7", + "packageManager": "pnpm@10.4.1+sha512.c753b6c3ad7afa13af388fa6d808035a008e30ea9993f58c6663e2bc5ff21679aa834db094987129aa4d488b86df57f7b634981b2f827cdcacc698cc0cfb88af", "keywords": [ "diagram", "markdown", @@ -19,14 +19,16 @@ "build:esbuild": "pnpm run -r clean && tsx .esbuild/build.ts", "build:mermaid": "pnpm build:esbuild --mermaid", "build:viz": "pnpm build:esbuild --visualize", - "build:types": "tsx .build/types.ts", + "build:types": "pnpm --filter mermaid types:build-config && tsx .build/types.ts", "build:types:watch": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly --watch", "dev": "tsx .esbuild/server.ts", "dev:vite": "tsx .vite/server.ts", "dev:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm dev:vite", - "release": "pnpm build", - "lint": "cross-env NODE_OPTIONS=--max_old_space_size=8192 eslint --cache --cache-strategy content . && pnpm lint:jison && prettier --cache --check .", - "lint:fix": "cross-env NODE_OPTIONS=--max_old_space_size=8192 eslint --cache --cache-strategy content --fix . && prettier --write . && tsx scripts/fixCSpell.ts", + "copy-readme": "cpy './README.*' ./packages/mermaid/ --cwd=.", + "changeset:version": "changeset version && pnpm build && pnpm --filter mermaid run docs:release-version && pnpm --filter mermaid run docs:build && git add --all", + "changeset:publish": "pnpm copy-readme && changeset publish", + "lint": "eslint --quiet --stats --cache --cache-strategy content . && pnpm lint:jison && prettier --cache --check .", + "lint:fix": "eslint --cache --cache-strategy content --fix . && prettier --write . && tsx scripts/fixCSpell.ts", "lint:jison": "tsx ./scripts/jison/lint.mts", "contributors": "tsx scripts/updateContributors.ts", "cypress": "cypress run", @@ -40,8 +42,8 @@ "test": "pnpm lint && vitest run", "test:watch": "vitest --watch", "test:coverage": "vitest --coverage", - "prepublishOnly": "pnpm build && pnpm test", - "prepare": "husky install && pnpm build", + "test:check:tsc": "tsx scripts/tsc-check.ts", + "prepare": "husky && pnpm build", "pre-commit": "lint-staged" }, "repository": { @@ -61,75 +63,84 @@ ] }, "devDependencies": { - "@applitools/eyes-cypress": "^3.42.3", - "@cspell/eslint-plugin": "^8.6.0", - "@cypress/code-coverage": "^3.12.30", - "@rollup/plugin-typescript": "^11.1.6", + "@applitools/eyes-cypress": "^3.44.9", + "@argos-ci/cypress": "^4.0.3", + "@changesets/changelog-github": "^0.5.1", + "@changesets/cli": "^2.27.12", + "@cspell/eslint-plugin": "^8.18.1", + "@cypress/code-coverage": "^3.12.49", + "@eslint/js": "^9.24.0", + "@rollup/plugin-typescript": "^12.1.2", "@types/cors": "^2.8.17", - "@types/eslint": "^8.56.6", - "@types/express": "^4.17.21", + "@types/express": "^5.0.0", "@types/js-yaml": "^4.0.9", - "@types/jsdom": "^21.1.6", - "@types/lodash": "^4.17.0", - "@types/mdast": "^4.0.3", - "@types/node": "^20.11.30", - "@types/rollup-plugin-visualizer": "^4.2.4", - "@typescript-eslint/eslint-plugin": "^7.3.1", - "@typescript-eslint/parser": "^7.3.1", - "@vitest/coverage-v8": "^1.4.0", - "@vitest/spy": "^1.4.0", - "@vitest/ui": "^1.4.0", - "ajv": "^8.12.0", - "chokidar": "^3.6.0", - "concurrently": "^8.2.2", + "@types/jsdom": "^21.1.7", + "@types/lodash": "^4.17.15", + "@types/mdast": "^4.0.4", + "@types/node": "^22.13.5", + "@types/rollup-plugin-visualizer": "^5.0.3", + "@vitest/coverage-v8": "^3.0.6", + "@vitest/spy": "^3.0.6", + "@vitest/ui": "^3.0.6", + "ajv": "^8.17.1", + "chokidar": "^4.0.3", + "concurrently": "^9.1.2", "cors": "^2.8.5", + "cpy-cli": "^5.0.0", "cross-env": "^7.0.3", - "cspell": "^8.6.0", - "cypress": "^13.7.1", + "cspell": "^8.6.1", + "cypress": "^14.0.3", "cypress-image-snapshot": "^4.0.1", - "esbuild": "^0.20.2", - "eslint": "^8.57.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-cypress": "^2.15.1", - "eslint-plugin-html": "^8.0.0", - "eslint-plugin-jest": "^27.9.0", - "eslint-plugin-jsdoc": "^48.2.1", - "eslint-plugin-json": "^3.1.0", - "eslint-plugin-lodash": "^7.4.0", - "eslint-plugin-markdown": "^4.0.1", - "eslint-plugin-no-only-tests": "^3.1.0", - "eslint-plugin-tsdoc": "^0.2.17", - "eslint-plugin-unicorn": "^51.0.1", - "express": "^4.19.1", - "globby": "^14.0.1", - "husky": "^9.0.11", + "cypress-split": "^1.24.14", + "esbuild": "^0.25.0", + "eslint": "^9.24.0", + "eslint-config-prettier": "^10.1.1", + "eslint-plugin-cypress": "^4.2.1", + "eslint-plugin-html": "^8.1.2", + "eslint-plugin-jest": "^28.11.0", + "eslint-plugin-jsdoc": "^50.6.9", + "eslint-plugin-json": "^4.0.1", + "eslint-plugin-lodash": "^8.0.0", + "eslint-plugin-markdown": "^5.1.0", + "eslint-plugin-no-only-tests": "^3.3.0", + "eslint-plugin-tsdoc": "^0.4.0", + "eslint-plugin-unicorn": "^58.0.0", + "express": "^5.1.0", + "globals": "^16.0.0", + "globby": "^14.0.2", + "husky": "^9.1.7", "jest": "^29.7.0", "jison": "^0.4.18", "js-yaml": "^4.1.0", - "jsdom": "^24.0.0", - "langium-cli": "3.0.1", - "lint-staged": "^15.2.2", - "markdown-table": "^3.0.3", - "nyc": "^15.1.0", + "jsdom": "^26.0.0", + "langium-cli": "3.3.0", + "lint-staged": "^15.2.11", + "markdown-table": "^3.0.4", + "nyc": "^17.1.0", "path-browserify": "^1.0.1", - "pnpm": "^8.15.5", - "prettier": "^3.2.5", - "prettier-plugin-jsdoc": "^1.3.0", - "rimraf": "^5.0.5", - "rollup-plugin-visualizer": "^5.12.0", - "start-server-and-test": "^2.0.3", - "tsx": "^4.7.1", - "typescript": "^5.4.3", - "vite": "^5.2.3", - "vite-plugin-istanbul": "^6.0.0", - "vitest": "^1.4.0" + "prettier": "^3.5.2", + "prettier-plugin-jsdoc": "^1.3.2", + "rimraf": "^6.0.1", + "rollup-plugin-visualizer": "^5.14.0", + "start-server-and-test": "^2.0.10", + "tslib": "^2.8.1", + "tsx": "^4.7.3", + "typescript": "~5.7.3", + "typescript-eslint": "^8.29.1", + "vite": "^6.1.1", + "vite-plugin-istanbul": "^7.0.0", + "vitest": "^3.0.6" }, "nyc": { "report-dir": "coverage/cypress" }, "pnpm": { "patchedDependencies": { - "cytoscape@3.28.1": "patches/cytoscape@3.28.1.patch" - } + "roughjs": "patches/roughjs.patch" + }, + "onlyBuiltDependencies": [ + "cypress", + "esbuild" + ] } } diff --git a/packages/mermaid-example-diagram/package.json b/packages/mermaid-example-diagram/package.json index b899e077b..75eaa498e 100644 --- a/packages/mermaid-example-diagram/package.json +++ b/packages/mermaid-example-diagram/package.json @@ -1,6 +1,7 @@ { "name": "@mermaid-js/mermaid-example-diagram", "version": "9.3.0", + "private": true, "description": "Example of external diagram module for MermaidJS.", "module": "dist/mermaid-example-diagram.core.mjs", "types": "dist/detector.d.ts", @@ -18,9 +19,7 @@ "example", "mermaid" ], - "scripts": { - "prepublishOnly": "pnpm -w run build" - }, + "scripts": {}, "repository": { "type": "git", "url": "https://github.com/mermaid-js/mermaid" @@ -38,14 +37,14 @@ ] }, "dependencies": { - "@braintree/sanitize-url": "^7.0.0", + "@braintree/sanitize-url": "^7.0.4", "d3": "^7.9.0", "khroma": "^2.1.0" }, "devDependencies": { - "concurrently": "^8.2.2", + "concurrently": "^9.1.2", "mermaid": "workspace:*", - "rimraf": "^5.0.5" + "rimraf": "^6.0.1" }, "files": [ "dist" diff --git a/packages/mermaid-example-diagram/src/exampleDiagramRenderer.js b/packages/mermaid-example-diagram/src/exampleDiagramRenderer.js index 9b3854aaf..b24a3a237 100644 --- a/packages/mermaid-example-diagram/src/exampleDiagramRenderer.js +++ b/packages/mermaid-example-diagram/src/exampleDiagramRenderer.js @@ -3,7 +3,7 @@ import { select } from 'd3'; import { log, getConfig, setupGraphViewbox } from './mermaidUtils.js'; /** - * Draws a an info picture in the tag with id: id based on the graph definition in text. + * Draws an info picture in the tag with id: id based on the graph definition in text. * * @param {any} text * @param {any} id diff --git a/packages/mermaid-example-diagram/src/mermaidUtils.ts b/packages/mermaid-example-diagram/src/mermaidUtils.ts index eeeca05c5..04d0599c0 100644 --- a/packages/mermaid-example-diagram/src/mermaidUtils.ts +++ b/packages/mermaid-example-diagram/src/mermaidUtils.ts @@ -25,7 +25,7 @@ export const log: Record = { fatal: warning, }; -export let setLogLevel: (level: keyof typeof LEVELS | number | string) => void; +export let setLogLevel: (level: keyof typeof LEVELS | number) => void; export let getConfig: () => object; export let sanitizeText: (str: string) => string; export let commonDb: () => object; diff --git a/packages/mermaid-example-diagram/tsconfig.eslint.json b/packages/mermaid-example-diagram/tsconfig.eslint.json new file mode 100644 index 000000000..5269794ba --- /dev/null +++ b/packages/mermaid-example-diagram/tsconfig.eslint.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": ["./tsconfig.json"], + "compilerOptions": { + "noEmit": true + }, + "include": [ + "./src/**/*.spec.js", + "./src/**/*.spec.ts" // test files + ] +} diff --git a/packages/mermaid-flowchart-elk/package.json b/packages/mermaid-flowchart-elk/package.json deleted file mode 100644 index dc3af195c..000000000 --- a/packages/mermaid-flowchart-elk/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "@mermaid-js/flowchart-elk", - "version": "1.0.0-rc.1", - "description": "Flowchart plugin for mermaid with ELK layout", - "module": "dist/mermaid-flowchart-elk.core.mjs", - "types": "dist/packages/mermaid-flowchart-elk/src/detector.d.ts", - "type": "module", - "exports": { - ".": { - "import": "./dist/mermaid-flowchart-elk.core.mjs", - "types": "./dist/packages/mermaid-flowchart-elk/src/detector.d.ts" - }, - "./*": "./*" - }, - "keywords": [ - "diagram", - "markdown", - "flowchart", - "elk", - "mermaid" - ], - "scripts": { - "prepublishOnly": "pnpm -w run build" - }, - "repository": { - "type": "git", - "url": "https://github.com/mermaid-js/mermaid" - }, - "author": "Knut Sveidqvist", - "license": "MIT", - "dependencies": { - "d3": "^7.9.0", - "dagre-d3-es": "7.0.10", - "elkjs": "^0.9.2", - "khroma": "^2.1.0" - }, - "devDependencies": { - "concurrently": "^8.2.2", - "mermaid": "workspace:^", - "rimraf": "^5.0.5" - }, - "files": [ - "dist" - ] -} diff --git a/packages/mermaid-flowchart-elk/src/detector.spec.ts b/packages/mermaid-flowchart-elk/src/detector.spec.ts deleted file mode 100644 index 6e949c57b..000000000 --- a/packages/mermaid-flowchart-elk/src/detector.spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -import plugin from './detector.js'; -import { describe, it } from 'vitest'; - -const { detector } = plugin; - -describe('flowchart-elk detector', () => { - it('should fail for dagre-d3', () => { - expect( - detector('flowchart', { - flowchart: { - defaultRenderer: 'dagre-d3', - }, - }) - ).toBe(false); - }); - it('should fail for dagre-wrapper', () => { - expect( - detector('flowchart', { - flowchart: { - defaultRenderer: 'dagre-wrapper', - }, - }) - ).toBe(false); - }); - it('should succeed for elk', () => { - expect( - detector('flowchart', { - flowchart: { - defaultRenderer: 'elk', - }, - }) - ).toBe(true); - expect( - detector('graph', { - flowchart: { - defaultRenderer: 'elk', - }, - }) - ).toBe(true); - }); - - it('should detect flowchart-elk', () => { - expect(detector('flowchart-elk')).toBe(true); - }); - - it('should not detect class with defaultRenderer set to elk', () => { - expect( - detector('class', { - flowchart: { - defaultRenderer: 'elk', - }, - }) - ).toBe(false); - }); -}); diff --git a/packages/mermaid-flowchart-elk/src/detector.ts b/packages/mermaid-flowchart-elk/src/detector.ts deleted file mode 100644 index 52fb355a5..000000000 --- a/packages/mermaid-flowchart-elk/src/detector.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { - ExternalDiagramDefinition, - DiagramDetector, - DiagramLoader, -} from '../../mermaid/src/diagram-api/types.js'; - -const id = 'flowchart-elk'; - -const detector: DiagramDetector = (txt, config): boolean => { - if ( - // If diagram explicitly states flowchart-elk - /^\s*flowchart-elk/.test(txt) || - // If a flowchart/graph diagram has their default renderer set to elk - (/^\s*flowchart|graph/.test(txt) && config?.flowchart?.defaultRenderer === 'elk') - ) { - return true; - } - return false; -}; - -const loader: DiagramLoader = async () => { - const { diagram } = await import('./diagram-definition.js'); - return { id, diagram }; -}; - -const plugin: ExternalDiagramDefinition = { - id, - detector, - loader, -}; - -export default plugin; diff --git a/packages/mermaid-flowchart-elk/src/diagram-definition.ts b/packages/mermaid-flowchart-elk/src/diagram-definition.ts deleted file mode 100644 index 4a6b5b076..000000000 --- a/packages/mermaid-flowchart-elk/src/diagram-definition.ts +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-ignore: JISON typing missing -import parser from '../../mermaid/src/diagrams/flowchart/parser/flow.jison'; -import db from '../../mermaid/src/diagrams/flowchart/flowDb.js'; -import styles from '../../mermaid/src/diagrams/flowchart/styles.js'; -import renderer from './flowRenderer-elk.js'; - -export const diagram = { - db, - renderer, - parser, - styles, -}; diff --git a/packages/mermaid-flowchart-elk/src/flowRenderer-elk.js b/packages/mermaid-flowchart-elk/src/flowRenderer-elk.js deleted file mode 100644 index ea6b9af75..000000000 --- a/packages/mermaid-flowchart-elk/src/flowRenderer-elk.js +++ /dev/null @@ -1,903 +0,0 @@ -import { select, line, curveLinear } from 'd3'; -import { insertNode } from '../../mermaid/src/dagre-wrapper/nodes.js'; -import insertMarkers from '../../mermaid/src/dagre-wrapper/markers.js'; -import { insertEdgeLabel } from '../../mermaid/src/dagre-wrapper/edges.js'; -import { findCommonAncestor } from './render-utils.js'; -import { labelHelper } from '../../mermaid/src/dagre-wrapper/shapes/util.js'; -import { getConfig } from '../../mermaid/src/config.js'; -import { log } from '../../mermaid/src/logger.js'; -import utils from '../../mermaid/src/utils.js'; -import { setupGraphViewbox } from '../../mermaid/src/setupGraphViewbox.js'; -import common from '../../mermaid/src/diagrams/common/common.js'; -import { interpolateToCurve, getStylesFromArray } from '../../mermaid/src/utils.js'; -import ELK from 'elkjs/lib/elk.bundled.js'; -import { getLineFunctionsWithOffset } from '../../mermaid/src/utils/lineWithOffset.js'; -import { addEdgeMarkers } from '../../mermaid/src/dagre-wrapper/edgeMarker.js'; - -const elk = new ELK(); - -let portPos = {}; - -const conf = {}; -export const setConf = function (cnf) { - const keys = Object.keys(cnf); - for (const key of keys) { - conf[key] = cnf[key]; - } -}; - -let nodeDb = {}; - -// /** -// * Function that adds the vertices found during parsing to the graph to be rendered. -// * -// * @param vert Object containing the vertices. -// * @param g The graph that is to be drawn. -// * @param svgId -// * @param root -// * @param doc -// * @param diagObj -// */ -export const addVertices = async function (vert, svgId, root, doc, diagObj, parentLookupDb, graph) { - const svg = root.select(`[id="${svgId}"]`); - const nodes = svg.insert('g').attr('class', 'nodes'); - const keys = Object.keys(vert); - - // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition - await Promise.all( - keys.map(async function (id) { - const vertex = vert[id]; - - /** - * Variable for storing the classes for the vertex - * - * @type {string} - */ - let classStr = 'default'; - if (vertex.classes.length > 0) { - classStr = vertex.classes.join(' '); - } - classStr = classStr + ' flowchart-label'; - const styles = getStylesFromArray(vertex.styles); - - // Use vertex id as text in the box if no text is provided by the graph definition - let vertexText = vertex.text !== undefined ? vertex.text : vertex.id; - - // We create a SVG label, either by delegating to addHtmlLabel or manually - let vertexNode; - const labelData = { width: 0, height: 0 }; - - const ports = [ - { - id: vertex.id + '-west', - layoutOptions: { - 'port.side': 'WEST', - }, - }, - { - id: vertex.id + '-east', - layoutOptions: { - 'port.side': 'EAST', - }, - }, - { - id: vertex.id + '-south', - layoutOptions: { - 'port.side': 'SOUTH', - }, - }, - { - id: vertex.id + '-north', - layoutOptions: { - 'port.side': 'NORTH', - }, - }, - ]; - - let radius = 0; - let _shape = ''; - let layoutOptions = {}; - // Set the shape based parameters - switch (vertex.type) { - case 'round': - radius = 5; - _shape = 'rect'; - break; - case 'square': - _shape = 'rect'; - break; - case 'diamond': - _shape = 'question'; - layoutOptions = { - portConstraints: 'FIXED_SIDE', - }; - break; - case 'hexagon': - _shape = 'hexagon'; - break; - case 'odd': - _shape = 'rect_left_inv_arrow'; - break; - case 'lean_right': - _shape = 'lean_right'; - break; - case 'lean_left': - _shape = 'lean_left'; - break; - case 'trapezoid': - _shape = 'trapezoid'; - break; - case 'inv_trapezoid': - _shape = 'inv_trapezoid'; - break; - case 'odd_right': - _shape = 'rect_left_inv_arrow'; - break; - case 'circle': - _shape = 'circle'; - break; - case 'ellipse': - _shape = 'ellipse'; - break; - case 'stadium': - _shape = 'stadium'; - break; - case 'subroutine': - _shape = 'subroutine'; - break; - case 'cylinder': - _shape = 'cylinder'; - break; - case 'group': - _shape = 'rect'; - break; - case 'doublecircle': - _shape = 'doublecircle'; - break; - default: - _shape = 'rect'; - } - - // Add the node - const node = { - labelStyle: styles.labelStyle, - shape: _shape, - labelText: vertexText, - labelType: vertex.labelType, - rx: radius, - ry: radius, - class: classStr, - style: styles.style, - id: vertex.id, - link: vertex.link, - linkTarget: vertex.linkTarget, - tooltip: diagObj.db.getTooltip(vertex.id) || '', - domId: diagObj.db.lookUpDomId(vertex.id), - haveCallback: vertex.haveCallback, - width: vertex.type === 'group' ? 500 : undefined, - dir: vertex.dir, - type: vertex.type, - props: vertex.props, - padding: getConfig().flowchart.padding, - }; - let boundingBox; - let nodeEl; - - // Add the element to the DOM - if (node.type !== 'group') { - nodeEl = await insertNode(nodes, node, vertex.dir); - boundingBox = nodeEl.node().getBBox(); - } else { - const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text'); - // svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:')); - // const rows = vertexText.split(common.lineBreakRegex); - // for (const row of rows) { - // const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan'); - // tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve'); - // tspan.setAttribute('dy', '1em'); - // tspan.setAttribute('x', '1'); - // tspan.textContent = row; - // svgLabel.appendChild(tspan); - // } - // vertexNode = svgLabel; - // const bbox = vertexNode.getBBox(); - const { shapeSvg, bbox } = await labelHelper(nodes, node, undefined, true); - labelData.width = bbox.width; - labelData.wrappingWidth = getConfig().flowchart.wrappingWidth; - labelData.height = bbox.height; - labelData.labelNode = shapeSvg.node(); - node.labelData = labelData; - } - // const { shapeSvg, bbox } = await labelHelper(svg, node, undefined, true); - - const data = { - id: vertex.id, - ports: vertex.type === 'diamond' ? ports : [], - // labelStyle: styles.labelStyle, - // shape: _shape, - layoutOptions, - labelText: vertexText, - labelData, - // labels: [{ text: vertexText }], - // rx: radius, - // ry: radius, - // class: classStr, - // style: styles.style, - // link: vertex.link, - // linkTarget: vertex.linkTarget, - // tooltip: diagObj.db.getTooltip(vertex.id) || '', - domId: diagObj.db.lookUpDomId(vertex.id), - // haveCallback: vertex.haveCallback, - width: boundingBox?.width, - height: boundingBox?.height, - // dir: vertex.dir, - type: vertex.type, - // props: vertex.props, - // padding: getConfig().flowchart.padding, - // boundingBox, - el: nodeEl, - parent: parentLookupDb.parentById[vertex.id], - }; - // if (!Object.keys(parentLookupDb.childrenById).includes(vertex.id)) { - // graph.children.push({ - // ...data, - // }); - // } - nodeDb[node.id] = data; - // log.trace('setNode', { - // labelStyle: styles.labelStyle, - // shape: _shape, - // labelText: vertexText, - // rx: radius, - // ry: radius, - // class: classStr, - // style: styles.style, - // id: vertex.id, - // domId: diagObj.db.lookUpDomId(vertex.id), - // width: vertex.type === 'group' ? 500 : undefined, - // type: vertex.type, - // dir: vertex.dir, - // props: vertex.props, - // padding: getConfig().flowchart.padding, - // parent: parentLookupDb.parentById[vertex.id], - // }); - }) - ); - return graph; -}; - -const getNextPosition = (position, edgeDirection, graphDirection) => { - const portPos = { - TB: { - in: { - north: 'north', - }, - out: { - south: 'west', - west: 'east', - east: 'south', - }, - }, - LR: { - in: { - west: 'west', - }, - out: { - east: 'south', - south: 'north', - north: 'east', - }, - }, - RL: { - in: { - east: 'east', - }, - out: { - west: 'north', - north: 'south', - south: 'west', - }, - }, - BT: { - in: { - south: 'south', - }, - out: { - north: 'east', - east: 'west', - west: 'north', - }, - }, - }; - portPos.TD = portPos.TB; - return portPos[graphDirection][edgeDirection][position]; - // return 'south'; -}; - -const getNextPort = (node, edgeDirection, graphDirection) => { - log.info('getNextPort', { node, edgeDirection, graphDirection }); - if (!portPos[node]) { - switch (graphDirection) { - case 'TB': - case 'TD': - portPos[node] = { - inPosition: 'north', - outPosition: 'south', - }; - break; - case 'BT': - portPos[node] = { - inPosition: 'south', - outPosition: 'north', - }; - break; - case 'RL': - portPos[node] = { - inPosition: 'east', - outPosition: 'west', - }; - break; - case 'LR': - portPos[node] = { - inPosition: 'west', - outPosition: 'east', - }; - break; - } - } - const result = edgeDirection === 'in' ? portPos[node].inPosition : portPos[node].outPosition; - - if (edgeDirection === 'in') { - portPos[node].inPosition = getNextPosition( - portPos[node].inPosition, - edgeDirection, - graphDirection - ); - } else { - portPos[node].outPosition = getNextPosition( - portPos[node].outPosition, - edgeDirection, - graphDirection - ); - } - return result; -}; - -const getEdgeStartEndPoint = (edge, dir) => { - let source = edge.start; - let target = edge.end; - - // Save the original source and target - const sourceId = source; - const targetId = target; - - const startNode = nodeDb[source]; - const endNode = nodeDb[target]; - - if (!startNode || !endNode) { - return { source, target }; - } - - if (startNode.type === 'diamond') { - source = `${source}-${getNextPort(source, 'out', dir)}`; - } - - if (endNode.type === 'diamond') { - target = `${target}-${getNextPort(target, 'in', dir)}`; - } - - // Add the edge to the graph - return { source, target, sourceId, targetId }; -}; - -/** - * Add edges to graph based on parsed graph definition - * - * @param {object} edges The edges to add to the graph - * @param {object} g The graph object - * @param cy - * @param diagObj - * @param graph - * @param svg - */ -export const addEdges = function (edges, diagObj, graph, svg) { - log.info('abc78 edges = ', edges); - const labelsEl = svg.insert('g').attr('class', 'edgeLabels'); - let linkIdCnt = {}; - let dir = diagObj.db.getDirection(); - let defaultStyle; - let defaultLabelStyle; - - if (edges.defaultStyle !== undefined) { - const defaultStyles = getStylesFromArray(edges.defaultStyle); - defaultStyle = defaultStyles.style; - defaultLabelStyle = defaultStyles.labelStyle; - } - - edges.forEach(function (edge) { - // Identify Link - const linkIdBase = 'L-' + edge.start + '-' + edge.end; - // count the links from+to the same node to give unique id - if (linkIdCnt[linkIdBase] === undefined) { - linkIdCnt[linkIdBase] = 0; - log.info('abc78 new entry', linkIdBase, linkIdCnt[linkIdBase]); - } else { - linkIdCnt[linkIdBase]++; - log.info('abc78 new entry', linkIdBase, linkIdCnt[linkIdBase]); - } - let linkId = linkIdBase + '-' + linkIdCnt[linkIdBase]; - log.info('abc78 new link id to be used is', linkIdBase, linkId, linkIdCnt[linkIdBase]); - const linkNameStart = 'LS-' + edge.start; - const linkNameEnd = 'LE-' + edge.end; - - const edgeData = { style: '', labelStyle: '' }; - edgeData.minlen = edge.length || 1; - //edgeData.id = 'id' + cnt; - - // Set link type for rendering - if (edge.type === 'arrow_open') { - edgeData.arrowhead = 'none'; - } else { - edgeData.arrowhead = 'normal'; - } - - // Check of arrow types, placed here in order not to break old rendering - edgeData.arrowTypeStart = 'arrow_open'; - edgeData.arrowTypeEnd = 'arrow_open'; - - /* eslint-disable no-fallthrough */ - switch (edge.type) { - case 'double_arrow_cross': - edgeData.arrowTypeStart = 'arrow_cross'; - case 'arrow_cross': - edgeData.arrowTypeEnd = 'arrow_cross'; - break; - case 'double_arrow_point': - edgeData.arrowTypeStart = 'arrow_point'; - case 'arrow_point': - edgeData.arrowTypeEnd = 'arrow_point'; - break; - case 'double_arrow_circle': - edgeData.arrowTypeStart = 'arrow_circle'; - case 'arrow_circle': - edgeData.arrowTypeEnd = 'arrow_circle'; - break; - } - - let style = ''; - let labelStyle = ''; - - switch (edge.stroke) { - case 'normal': - style = 'fill:none;'; - if (defaultStyle !== undefined) { - style = defaultStyle; - } - if (defaultLabelStyle !== undefined) { - labelStyle = defaultLabelStyle; - } - edgeData.thickness = 'normal'; - edgeData.pattern = 'solid'; - break; - case 'dotted': - edgeData.thickness = 'normal'; - edgeData.pattern = 'dotted'; - edgeData.style = 'fill:none;stroke-width:2px;stroke-dasharray:3;'; - break; - case 'thick': - edgeData.thickness = 'thick'; - edgeData.pattern = 'solid'; - edgeData.style = 'stroke-width: 3.5px;fill:none;'; - break; - } - if (edge.style !== undefined) { - const styles = getStylesFromArray(edge.style); - style = styles.style; - labelStyle = styles.labelStyle; - } - - edgeData.style = edgeData.style += style; - edgeData.labelStyle = edgeData.labelStyle += labelStyle; - - if (edge.interpolate !== undefined) { - edgeData.curve = interpolateToCurve(edge.interpolate, curveLinear); - } else if (edges.defaultInterpolate !== undefined) { - edgeData.curve = interpolateToCurve(edges.defaultInterpolate, curveLinear); - } else { - edgeData.curve = interpolateToCurve(conf.curve, curveLinear); - } - - if (edge.text === undefined) { - if (edge.style !== undefined) { - edgeData.arrowheadStyle = 'fill: #333'; - } - } else { - edgeData.arrowheadStyle = 'fill: #333'; - edgeData.labelpos = 'c'; - } - - edgeData.labelType = edge.labelType; - edgeData.label = edge.text.replace(common.lineBreakRegex, '\n'); - - if (edge.style === undefined) { - edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none;'; - } - - edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:'); - - edgeData.id = linkId; - edgeData.classes = 'flowchart-link ' + linkNameStart + ' ' + linkNameEnd; - - const labelEl = insertEdgeLabel(labelsEl, edgeData); - - // calculate start and end points of the edge, note that the source and target - // can be modified for shapes that have ports - const { source, target, sourceId, targetId } = getEdgeStartEndPoint(edge, dir); - log.debug('abc78 source and target', source, target); - // Add the edge to the graph - graph.edges.push({ - id: 'e' + edge.start + edge.end, - sources: [source], - targets: [target], - sourceId, - targetId, - labelEl: labelEl, - labels: [ - { - width: edgeData.width, - height: edgeData.height, - orgWidth: edgeData.width, - orgHeight: edgeData.height, - text: edgeData.label, - layoutOptions: { - 'edgeLabels.inline': 'true', - 'edgeLabels.placement': 'CENTER', - }, - }, - ], - edgeData, - }); - }); - return graph; -}; - -// TODO: break out and share with dagre wrapper. The current code in dagre wrapper also adds -// adds the line to the graph, but we don't need that here. This is why we can't use the dagre -// wrapper directly for this -/** - * Add the markers to the edge depending on the type of arrow is - * @param svgPath - * @param edgeData - * @param diagramType - * @param arrowMarkerAbsolute - * @param id - */ -const addMarkersToEdge = function (svgPath, edgeData, diagramType, arrowMarkerAbsolute, id) { - let url = ''; - // Check configuration for absolute path - if (arrowMarkerAbsolute) { - url = - window.location.protocol + - '//' + - window.location.host + - window.location.pathname + - window.location.search; - url = url.replace(/\(/g, '\\('); - url = url.replace(/\)/g, '\\)'); - } - - // look in edge data and decide which marker to use - addEdgeMarkers(svgPath, edgeData, url, id, diagramType); -}; - -/** - * Returns the all the styles from classDef statements in the graph definition. - * - * @param text - * @param diagObj - * @returns {Record} ClassDef styles - */ -export const getClasses = function (text, diagObj) { - log.info('Extracting classes'); - return diagObj.db.getClasses(); -}; - -const addSubGraphs = function (db) { - const parentLookupDb = { parentById: {}, childrenById: {} }; - const subgraphs = db.getSubGraphs(); - log.info('Subgraphs - ', subgraphs); - subgraphs.forEach(function (subgraph) { - subgraph.nodes.forEach(function (node) { - parentLookupDb.parentById[node] = subgraph.id; - if (parentLookupDb.childrenById[subgraph.id] === undefined) { - parentLookupDb.childrenById[subgraph.id] = []; - } - parentLookupDb.childrenById[subgraph.id].push(node); - }); - }); - - subgraphs.forEach(function (subgraph) { - const data = { id: subgraph.id }; - if (parentLookupDb.parentById[subgraph.id] !== undefined) { - data.parent = parentLookupDb.parentById[subgraph.id]; - } - }); - return parentLookupDb; -}; - -const calcOffset = function (src, dest, parentLookupDb) { - const ancestor = findCommonAncestor(src, dest, parentLookupDb); - if (ancestor === undefined || ancestor === 'root') { - return { x: 0, y: 0 }; - } - - const ancestorOffset = nodeDb[ancestor].offset; - return { x: ancestorOffset.posX, y: ancestorOffset.posY }; -}; - -const insertEdge = function (edgesEl, edge, edgeData, diagObj, parentLookupDb, id) { - const offset = calcOffset(edge.sourceId, edge.targetId, parentLookupDb); - - const src = edge.sections[0].startPoint; - const dest = edge.sections[0].endPoint; - const segments = edge.sections[0].bendPoints ? edge.sections[0].bendPoints : []; - - const segPoints = segments.map((segment) => [segment.x + offset.x, segment.y + offset.y]); - const points = [ - [src.x + offset.x, src.y + offset.y], - ...segPoints, - [dest.x + offset.x, dest.y + offset.y], - ]; - - const { x, y } = getLineFunctionsWithOffset(edge.edgeData); - const curve = line().x(x).y(y).curve(curveLinear); - const edgePath = edgesEl - .insert('path') - .attr('d', curve(points)) - .attr('class', 'path ' + edgeData.classes) - .attr('fill', 'none'); - Object.entries(edgeData).forEach(([key, value]) => { - if (key !== 'classes') { - edgePath.attr(key, value); - } - }); - const edgeG = edgesEl.insert('g').attr('class', 'edgeLabel'); - const edgeWithLabel = select(edgeG.node().appendChild(edge.labelEl)); - const box = edgeWithLabel.node().firstChild.getBoundingClientRect(); - edgeWithLabel.attr('width', box.width); - edgeWithLabel.attr('height', box.height); - - edgeG.attr( - 'transform', - `translate(${edge.labels[0].x + offset.x}, ${edge.labels[0].y + offset.y})` - ); - addMarkersToEdge(edgePath, edgeData, diagObj.type, diagObj.arrowMarkerAbsolute, id); -}; - -/** - * Recursive function that iterates over an array of nodes and inserts the children of each node. - * It also recursively populates the inserts the children of the children and so on. - * @param {*} graph - * @param nodeArray - * @param parentLookupDb - */ -const insertChildren = (nodeArray, parentLookupDb) => { - nodeArray.forEach((node) => { - // Check if we have reached the end of the tree - if (!node.children) { - node.children = []; - } - // Check if the node has children - const childIds = parentLookupDb.childrenById[node.id]; - // If the node has children, add them to the node - if (childIds) { - childIds.forEach((childId) => { - node.children.push(nodeDb[childId]); - }); - } - // Recursive call - insertChildren(node.children, parentLookupDb); - }); -}; - -/** - * Draws a flowchart in the tag with id: id based on the graph definition in text. - * - * @param text - * @param id - */ - -export const draw = async function (text, id, _version, diagObj) { - const { securityLevel, flowchart: conf } = getConfig(); - nodeDb = {}; - portPos = {}; - const renderEl = select('body').append('div').attr('style', 'height:400px').attr('id', 'cy'); - let graph = { - id: 'root', - layoutOptions: { - 'elk.hierarchyHandling': 'INCLUDE_CHILDREN', - 'elk.layered.spacing.edgeNodeBetweenLayers': conf?.nodeSpacing ? `${conf.nodeSpacing}` : '30', - // 'elk.layered.mergeEdges': 'true', - 'elk.direction': 'DOWN', - // 'elk.ports.sameLayerEdges': true, - // 'nodePlacement.strategy': 'SIMPLE', - }, - children: [], - edges: [], - }; - log.info('Drawing flowchart using v3 renderer', elk); - - // Set the direction, - // Fetch the default direction, use TD if none was found - let dir = diagObj.db.getDirection(); - switch (dir) { - case 'BT': - graph.layoutOptions['elk.direction'] = 'UP'; - break; - case 'TB': - graph.layoutOptions['elk.direction'] = 'DOWN'; - break; - case 'LR': - graph.layoutOptions['elk.direction'] = 'RIGHT'; - break; - case 'RL': - graph.layoutOptions['elk.direction'] = 'LEFT'; - break; - } - - // Find the root dom node to ne used in rendering - // Handle root and document for when rendering in sandbox mode - let sandboxElement; - if (securityLevel === 'sandbox') { - sandboxElement = select('#i' + id); - } - const root = - securityLevel === 'sandbox' - ? select(sandboxElement.nodes()[0].contentDocument.body) - : select('body'); - const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; - - const svg = root.select(`[id="${id}"]`); - // Define the supported markers for the diagram - const markers = ['point', 'circle', 'cross']; - - // Add the marker definitions to the svg as marker tags - insertMarkers(svg, markers, diagObj.type, id); - - // Fetch the vertices/nodes and edges/links from the parsed graph definition - const vert = diagObj.db.getVertices(); - - // Setup nodes from the subgraphs with type group, these will be used - // as nodes with children in the subgraph - let subG; - const subGraphs = diagObj.db.getSubGraphs(); - log.info('Subgraphs - ', subGraphs); - for (let i = subGraphs.length - 1; i >= 0; i--) { - subG = subGraphs[i]; - diagObj.db.addVertex( - subG.id, - { text: subG.title, type: subG.labelType }, - 'group', - undefined, - subG.classes, - subG.dir - ); - } - - // debugger; - // Add an element in the svg to be used to hold the subgraphs container - // elements - const subGraphsEl = svg.insert('g').attr('class', 'subgraphs'); - - // Create the lookup db for the subgraphs and their children to used when creating - // the tree structured graph - const parentLookupDb = addSubGraphs(diagObj.db); - - // Add the nodes to the graph, this will entail creating the actual nodes - // in order to get the size of the node. You can't get the size of a node - // that is not in the dom so we need to add it to the dom, get the size - // we will position the nodes when we get the layout from elkjs - graph = await addVertices(vert, id, root, doc, diagObj, parentLookupDb, graph); - - // Time for the edges, we start with adding an element in the node to hold the edges - const edgesEl = svg.insert('g').attr('class', 'edges edgePath'); - // Fetch the edges form the parsed graph definition - const edges = diagObj.db.getEdges(); - - // Add the edges to the graph, this will entail creating the actual edges - graph = addEdges(edges, diagObj, graph, svg); - - // Iterate through all nodes and add the top level nodes to the graph - const nodes = Object.keys(nodeDb); - nodes.forEach((nodeId) => { - const node = nodeDb[nodeId]; - if (!node.parent) { - graph.children.push(node); - } - // Subgraph - if (parentLookupDb.childrenById[nodeId] !== undefined) { - node.labels = [ - { - text: node.labelText, - layoutOptions: { - 'nodeLabels.placement': '[H_CENTER, V_TOP, INSIDE]', - }, - width: node.labelData.width, - height: node.labelData.height, - // width: 100, - // height: 100, - }, - ]; - delete node.x; - delete node.y; - delete node.width; - delete node.height; - } - }); - - insertChildren(graph.children, parentLookupDb); - log.info('after layout', JSON.stringify(graph, null, 2)); - const g = await elk.layout(graph); - drawNodes(0, 0, g.children, svg, subGraphsEl, diagObj, 0); - utils.insertTitle(svg, 'flowchartTitleText', conf.titleTopMargin, diagObj.db.getDiagramTitle()); - log.info('after layout', g); - g.edges?.map((edge) => { - insertEdge(edgesEl, edge, edge.edgeData, diagObj, parentLookupDb, id); - }); - setupGraphViewbox({}, svg, conf.diagramPadding, conf.useMaxWidth); - // Remove element after layout - renderEl.remove(); -}; - -const drawNodes = (relX, relY, nodeArray, svg, subgraphsEl, diagObj, depth) => { - nodeArray.forEach(function (node) { - if (node) { - nodeDb[node.id].offset = { - posX: node.x + relX, - posY: node.y + relY, - x: relX, - y: relY, - depth, - width: node.width, - height: node.height, - }; - if (node.type === 'group') { - const subgraphEl = subgraphsEl.insert('g').attr('class', 'subgraph'); - subgraphEl - .insert('rect') - .attr('class', 'subgraph subgraph-lvl-' + (depth % 5) + ' node') - .attr('x', node.x + relX) - .attr('y', node.y + relY) - .attr('width', node.width) - .attr('height', node.height); - const label = subgraphEl.insert('g').attr('class', 'label'); - const labelCentering = getConfig().flowchart.htmlLabels ? node.labelData.width / 2 : 0; - label.attr( - 'transform', - `translate(${node.labels[0].x + relX + node.x + labelCentering}, ${ - node.labels[0].y + relY + node.y + 3 - })` - ); - label.node().appendChild(node.labelData.labelNode); - - log.info('Id (UGH)= ', node.type, node.labels); - } else { - log.info('Id (UGH)= ', node.id); - node.el.attr( - 'transform', - `translate(${node.x + relX + node.width / 2}, ${node.y + relY + node.height / 2})` - ); - } - } - }); - nodeArray.forEach(function (node) { - if (node && node.type === 'group') { - drawNodes(relX + node.x, relY + node.y, node.children, svg, subgraphsEl, diagObj, depth + 1); - } - }); -}; - -export default { - getClasses, - draw, -}; diff --git a/packages/mermaid-flowchart-elk/src/render-utils.spec.ts b/packages/mermaid-flowchart-elk/src/render-utils.spec.ts deleted file mode 100644 index 046ed43c1..000000000 --- a/packages/mermaid-flowchart-elk/src/render-utils.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { TreeData } from './render-utils.js'; -import { findCommonAncestor } from './render-utils.js'; -describe('when rendering a flowchart using elk ', () => { - let lookupDb: TreeData; - beforeEach(() => { - lookupDb = { - parentById: { - B4: 'inner', - B5: 'inner', - C4: 'inner2', - C5: 'inner2', - B2: 'Ugge', - B3: 'Ugge', - inner: 'Ugge', - inner2: 'Ugge', - B6: 'outer', - }, - childrenById: { - inner: ['B4', 'B5'], - inner2: ['C4', 'C5'], - Ugge: ['B2', 'B3', 'inner', 'inner2'], - outer: ['B6'], - }, - }; - }); - it('to find parent of siblings in a subgraph', () => { - expect(findCommonAncestor('B4', 'B5', lookupDb)).toBe('inner'); - }); - it('to find an uncle', () => { - expect(findCommonAncestor('B4', 'B2', lookupDb)).toBe('Ugge'); - }); - it('to find a cousin', () => { - expect(findCommonAncestor('B4', 'C4', lookupDb)).toBe('Ugge'); - }); - it('to find a grandparent', () => { - expect(findCommonAncestor('B4', 'B6', lookupDb)).toBe('root'); - }); - it('to find ancestor of siblings in the root', () => { - expect(findCommonAncestor('B1', 'outer', lookupDb)).toBe('root'); - }); -}); diff --git a/packages/mermaid-flowchart-elk/src/styles.ts b/packages/mermaid-flowchart-elk/src/styles.ts deleted file mode 100644 index 60659df45..000000000 --- a/packages/mermaid-flowchart-elk/src/styles.ts +++ /dev/null @@ -1,143 +0,0 @@ -/** Returns the styles given options */ -export interface FlowChartStyleOptions { - arrowheadColor: string; - border2: string; - clusterBkg: string; - clusterBorder: string; - edgeLabelBackground: string; - fontFamily: string; - lineColor: string; - mainBkg: string; - nodeBorder: string; - nodeTextColor: string; - tertiaryColor: string; - textColor: string; - titleColor: string; - [key: string]: string; -} - -const genSections = (options: FlowChartStyleOptions) => { - let sections = ''; - - for (let i = 0; i < 5; i++) { - sections += ` - .subgraph-lvl-${i} { - fill: ${options[`surface${i}`]}; - stroke: ${options[`surfacePeer${i}`]}; - } - `; - } - return sections; -}; - -const getStyles = (options: FlowChartStyleOptions) => - `.label { - font-family: ${options.fontFamily}; - color: ${options.nodeTextColor || options.textColor}; - } - .cluster-label text { - fill: ${options.titleColor}; - } - .cluster-label span { - color: ${options.titleColor}; - } - - .label text,span { - fill: ${options.nodeTextColor || options.textColor}; - color: ${options.nodeTextColor || options.textColor}; - } - - .node rect, - .node circle, - .node ellipse, - .node polygon, - .node path { - fill: ${options.mainBkg}; - stroke: ${options.nodeBorder}; - stroke-width: 1px; - } - - .node .label { - text-align: center; - } - .node.clickable { - cursor: pointer; - } - - .arrowheadPath { - fill: ${options.arrowheadColor}; - } - - .edgePath .path { - stroke: ${options.lineColor}; - stroke-width: 2.0px; - } - - .flowchart-link { - stroke: ${options.lineColor}; - fill: none; - } - - .edgeLabel { - background-color: ${options.edgeLabelBackground}; - rect { - opacity: 0.85; - background-color: ${options.edgeLabelBackground}; - fill: ${options.edgeLabelBackground}; - } - text-align: center; - } - - .cluster rect { - fill: ${options.clusterBkg}; - stroke: ${options.clusterBorder}; - stroke-width: 1px; - } - - .cluster text { - fill: ${options.titleColor}; - } - - .cluster span { - color: ${options.titleColor}; - } - /* .cluster div { - color: ${options.titleColor}; - } */ - - div.mermaidTooltip { - position: absolute; - text-align: center; - max-width: 200px; - padding: 2px; - font-family: ${options.fontFamily}; - font-size: 12px; - background: ${options.tertiaryColor}; - border: 1px solid ${options.border2}; - border-radius: 2px; - pointer-events: none; - z-index: 100; - } - - .flowchartTitleText { - text-anchor: middle; - font-size: 18px; - fill: ${options.textColor}; - } - .subgraph { - stroke-width:2; - rx:3; - } - // .subgraph-lvl-1 { - // fill:#ccc; - // // stroke:black; - // } - - .flowchart-label text { - text-anchor: middle; - } - - ${genSections(options)} -`; - -export default getStyles; diff --git a/packages/mermaid-layout-elk/CHANGELOG.md b/packages/mermaid-layout-elk/CHANGELOG.md new file mode 100644 index 000000000..319d6b828 --- /dev/null +++ b/packages/mermaid-layout-elk/CHANGELOG.md @@ -0,0 +1,55 @@ +# @mermaid-js/layout-elk + +## 0.1.7 + +### Patch Changes + +- [#6090](https://github.com/mermaid-js/mermaid/pull/6090) [`654097c`](https://github.com/mermaid-js/mermaid/commit/654097c43801b2d606bc3d2bef8c6fbc3301e9e4) Thanks [@knsv](https://github.com/knsv)! - fix: Updated offset calculations for diamond shape when handling intersections + +## 0.1.6 + +### Patch Changes + +- [#6081](https://github.com/mermaid-js/mermaid/pull/6081) [`68f41f6`](https://github.com/mermaid-js/mermaid/commit/68f41f685d2afe7d12f63aabf3de0c3461898471) Thanks [@knsv](https://github.com/knsv)! - fix: Elk rendering of Diamond shape intersections + +- Updated dependencies [[`01b5079`](https://github.com/mermaid-js/mermaid/commit/01b5079562ec8d34ce9964910f168873843c68f8), [`1388662`](https://github.com/mermaid-js/mermaid/commit/1388662132cc829f9820c2e9970ae04e2dd90588), [`fe3cffb`](https://github.com/mermaid-js/mermaid/commit/fe3cffbb673a25b81989aacb06e5d0eda35326db)]: + - mermaid@11.4.1 + +## 0.1.5 + +### Patch Changes + +- [#5825](https://github.com/mermaid-js/mermaid/pull/5825) [`233e36c`](https://github.com/mermaid-js/mermaid/commit/233e36c9884fcce141a72ce7c845179781e18632) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - chore: Update render options + +- Updated dependencies [[`6c5b7ce`](https://github.com/mermaid-js/mermaid/commit/6c5b7ce9f41c0fbd59fe03dbefc8418d97697f0a), [`9e3aa70`](https://github.com/mermaid-js/mermaid/commit/9e3aa705ae21fd4898504ab22d775a9e437b898e), [`de2c05c`](https://github.com/mermaid-js/mermaid/commit/de2c05cd5463af68d19dd7b6b3f1303d69ddb2dd)]: + - mermaid@11.3.0 + +## 0.1.4 + +### Patch Changes + +- [#5847](https://github.com/mermaid-js/mermaid/pull/5847) [`dd03043`](https://github.com/mermaid-js/mermaid/commit/dd0304387e85fc57a9ebb666f89ef788c012c2c5) Thanks [@sidharthv96](https://github.com/sidharthv96)! - chore: fix render types + +## 0.1.3 + +### Patch Changes + +- [#5810](https://github.com/mermaid-js/mermaid/pull/5810) [`33a809f`](https://github.com/mermaid-js/mermaid/commit/33a809f09a9aa1f84ba06201ab550bad81c3ff65) Thanks [@knsv](https://github.com/knsv)! - fix: Updates to the default elk configuration + feat: exposing cycleBreakingStrategy to the configuration so that it can be modified suing the configuration. +- Updated dependencies [[`6ecdf7b`](https://github.com/mermaid-js/mermaid/commit/6ecdf7be688efdc53c52fea3ba891327242bc890), [`28bd07f`](https://github.com/mermaid-js/mermaid/commit/28bd07fdeb4fc981107d21317ec6160b31f80116), [`8e640da`](https://github.com/mermaid-js/mermaid/commit/8e640da5436e8ae013b11b1c1821a9afcc15d0d3), [`256a148`](https://github.com/mermaid-js/mermaid/commit/256a148bbf484fc7db6c19f94dd69d5d268ee048), [`16faef4`](https://github.com/mermaid-js/mermaid/commit/16faef4613b91a7d3a98a1563c25b57f9238acc7)]: + - mermaid@11.1.0 + +## 0.1.2 + +### Patch Changes + +- [#5761](https://github.com/mermaid-js/mermaid/pull/5761) [`b34dfe8`](https://github.com/mermaid-js/mermaid/commit/b34dfe8f45eded31da10965ced7ea40fde1ca76c) Thanks [@sidharthv96](https://github.com/sidharthv96)! - Fix type file path + +## 0.1.1 + +### Patch Changes + +- [#5758](https://github.com/mermaid-js/mermaid/pull/5758) [`501a55d`](https://github.com/mermaid-js/mermaid/commit/501a55d8f225901ba345c498dec4298490a0196e) Thanks [@sidharthv96](https://github.com/sidharthv96)! - fix: Types path + +- Updated dependencies [[`5deaef4`](https://github.com/mermaid-js/mermaid/commit/5deaef456e74d796866431c26f69360e4e74dbff)]: + - mermaid@11.0.2 diff --git a/packages/mermaid-layout-elk/README.md b/packages/mermaid-layout-elk/README.md new file mode 100644 index 000000000..c32803292 --- /dev/null +++ b/packages/mermaid-layout-elk/README.md @@ -0,0 +1,72 @@ +# @mermaid-js/layout-elk + +This package provides a layout engine for Mermaid based on the [ELK](https://www.eclipse.org/elk/) layout engine. + +> [!NOTE] +> The ELK Layout engine will not be available in all providers that support mermaid by default. +> The websites will have to install the `@mermaid-js/layout-elk` package to use the ELK layout engine. + +## Usage + +``` +flowchart-elk TD + A --> B + A --> C +``` + +``` +--- +config: + layout: elk +--- + +flowchart TD + A --> B + A --> C +``` + +``` +--- +config: + layout: elk.stress +--- + +flowchart TD + A --> B + A --> C +``` + +### With bundlers + +```sh +npm install @mermaid-js/layout-elk +``` + +```ts +import mermaid from 'mermaid'; +import elkLayouts from '@mermaid-js/layout-elk'; + +mermaid.registerLayoutLoaders(elkLayouts); +``` + +### With CDN + +```html + +``` + +## Supported layouts + +- `elk`: The default layout, which is `elk.layered`. +- `elk.layered`: Layered layout +- `elk.stress`: Stress layout +- `elk.force`: Force layout +- `elk.mrtree`: Multi-root tree layout +- `elk.sporeOverlap`: Spore overlap layout + + diff --git a/packages/mermaid-layout-elk/package.json b/packages/mermaid-layout-elk/package.json new file mode 100644 index 000000000..2ce9bc278 --- /dev/null +++ b/packages/mermaid-layout-elk/package.json @@ -0,0 +1,45 @@ +{ + "name": "@mermaid-js/layout-elk", + "version": "0.1.7", + "description": "ELK layout engine for mermaid", + "module": "dist/mermaid-layout-elk.core.mjs", + "types": "dist/layouts.d.ts", + "type": "module", + "exports": { + ".": { + "import": "./dist/mermaid-layout-elk.core.mjs", + "types": "./dist/layouts.d.ts" + }, + "./*": "./*" + }, + "keywords": [ + "diagram", + "markdown", + "elk", + "mermaid" + ], + "scripts": {}, + "repository": { + "type": "git", + "url": "https://github.com/mermaid-js/mermaid" + }, + "contributors": [ + "Knut Sveidqvist", + "Sidharth Vinod" + ], + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "elkjs": "^0.9.3" + }, + "devDependencies": { + "@types/d3": "^7.4.3", + "mermaid": "workspace:^" + }, + "peerDependencies": { + "mermaid": "^11.0.2" + }, + "files": [ + "dist" + ] +} diff --git a/packages/mermaid-flowchart-elk/src/render-utils.ts b/packages/mermaid-layout-elk/src/find-common-ancestor.ts similarity index 71% rename from packages/mermaid-flowchart-elk/src/render-utils.ts rename to packages/mermaid-layout-elk/src/find-common-ancestor.ts index ebdc01cf7..2d513b66d 100644 --- a/packages/mermaid-flowchart-elk/src/render-utils.ts +++ b/packages/mermaid-layout-elk/src/find-common-ancestor.ts @@ -3,10 +3,15 @@ export interface TreeData { childrenById: Record; } -export const findCommonAncestor = (id1: string, id2: string, treeData: TreeData) => { - const { parentById } = treeData; +export const findCommonAncestor = (id1: string, id2: string, { parentById }: TreeData) => { const visited = new Set(); let currentId = id1; + + // Edge case with self edges + if (id1 === id2) { + return parentById[id1] || 'root'; + } + while (currentId) { visited.add(currentId); if (currentId === id2) { @@ -14,6 +19,7 @@ export const findCommonAncestor = (id1: string, id2: string, treeData: TreeData) } currentId = parentById[currentId]; } + currentId = id2; while (currentId) { if (visited.has(currentId)) { @@ -21,5 +27,6 @@ export const findCommonAncestor = (id1: string, id2: string, treeData: TreeData) } currentId = parentById[currentId]; } + return 'root'; }; diff --git a/packages/mermaid-layout-elk/src/layouts.ts b/packages/mermaid-layout-elk/src/layouts.ts new file mode 100644 index 000000000..dc48ccbfa --- /dev/null +++ b/packages/mermaid-layout-elk/src/layouts.ts @@ -0,0 +1,19 @@ +import type { LayoutLoaderDefinition } from 'mermaid'; + +const loader = async () => await import(`./render.js`); +const algos = ['elk.stress', 'elk.force', 'elk.mrtree', 'elk.sporeOverlap']; + +const layouts: LayoutLoaderDefinition[] = [ + { + name: 'elk', + loader, + algorithm: 'elk.layered', + }, + ...algos.map((algo) => ({ + name: algo, + loader, + algorithm: algo, + })), +]; + +export default layouts; diff --git a/packages/mermaid-layout-elk/src/render.ts b/packages/mermaid-layout-elk/src/render.ts new file mode 100644 index 000000000..4d124c04f --- /dev/null +++ b/packages/mermaid-layout-elk/src/render.ts @@ -0,0 +1,1023 @@ +import { curveLinear } from 'd3'; +import ELK from 'elkjs/lib/elk.bundled.js'; +import type { InternalHelpers, LayoutData, RenderOptions, SVG, SVGGroup } from 'mermaid'; +import { type TreeData, findCommonAncestor } from './find-common-ancestor.js'; + +type Node = LayoutData['nodes'][number]; + +interface LabelData { + width: number; + height: number; + wrappingWidth?: number; + labelNode?: SVGGElement | null; +} + +interface NodeWithVertex extends Omit { + children?: unknown[]; + labelData?: LabelData; + domId?: Node['domId'] | SVGGroup | d3.Selection; +} + +export const render = async ( + data4Layout: LayoutData, + svg: SVG, + { + common, + getConfig, + insertCluster, + insertEdge, + insertEdgeLabel, + insertMarkers, + insertNode, + interpolateToCurve, + labelHelper, + log, + positionEdgeLabel, + }: InternalHelpers, + { algorithm }: RenderOptions +) => { + const nodeDb: Record = {}; + const clusterDb: Record = {}; + + const addVertex = async ( + nodeEl: SVGGroup, + graph: { children: NodeWithVertex[] }, + nodeArr: Node[], + node: Node + ) => { + const labelData: LabelData = { width: 0, height: 0 }; + + const config = getConfig(); + + // Add the element to the DOM + if (!node.isGroup) { + const child: NodeWithVertex = { + ...node, + }; + graph.children.push(child); + nodeDb[node.id] = child; + + const childNodeEl = await insertNode(nodeEl, node, { config, dir: node.dir }); + const boundingBox = childNodeEl.node()!.getBBox(); + child.domId = childNodeEl; + child.width = boundingBox.width; + child.height = boundingBox.height; + } else { + // A subgraph + const child: NodeWithVertex & { children: NodeWithVertex[] } = { + ...node, + children: [], + }; + graph.children.push(child); + nodeDb[node.id] = child; + await addVertices(nodeEl, nodeArr, child, node.id); + + if (node.label) { + // @ts-ignore TODO: fix this + const { shapeSvg, bbox } = await labelHelper(nodeEl, node, undefined, true); + labelData.width = bbox.width; + labelData.wrappingWidth = config.flowchart!.wrappingWidth; + // Give some padding for elk + labelData.height = bbox.height - 2; + labelData.labelNode = shapeSvg.node(); + // We need the label hight to be able to size the subgraph; + shapeSvg.remove(); + } else { + // Subgraph without label + labelData.width = 0; + labelData.height = 0; + } + child.labelData = labelData; + child.domId = nodeEl; + } + }; + + const addVertices = async function ( + nodeEl: SVGGroup, + nodeArr: Node[], + graph: { children: NodeWithVertex[] }, + parentId?: string + ) { + const siblings = nodeArr.filter((node) => node?.parentId === parentId); + log.info('addVertices APA12', siblings, parentId); + // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition + await Promise.all( + siblings.map(async (node) => { + await addVertex(nodeEl, graph, nodeArr, node); + }) + ); + return graph; + }; + + const drawNodes = async ( + relX: number, + relY: number, + nodeArray: any[], + svg: any, + subgraphsEl: SVGGroup, + depth: number + ) => { + await Promise.all( + nodeArray.map(async function (node: { + id: string | number; + x: any; + y: any; + width: number; + labels: { width: any }[]; + height: number; + isGroup: any; + labelData: any; + offset: { posX: number; posY: number }; + shape: any; + domId: { node: () => any; attr: (arg0: string, arg1: string) => void }; + }) { + if (node) { + nodeDb[node.id] = node; + nodeDb[node.id].offset = { + posX: node.x + relX, + posY: node.y + relY, + x: relX, + y: relY, + depth, + width: Math.max(node.width, node.labels ? node.labels[0]?.width || 0 : 0), + height: node.height, + }; + if (node.isGroup) { + log.debug('id abc88 subgraph = ', node.id, node.x, node.y, node.labelData); + const subgraphEl = subgraphsEl.insert('g').attr('class', 'subgraph'); + // TODO use faster way of cloning + const clusterNode = JSON.parse(JSON.stringify(node)); + clusterNode.x = node.offset.posX + node.width / 2; + clusterNode.y = node.offset.posY + node.height / 2; + clusterNode.width = Math.max(clusterNode.width, node.labelData.width); + await insertCluster(subgraphEl, clusterNode); + + log.debug('id (UIO)= ', node.id, node.width, node.shape, node.labels); + } else { + log.info( + 'id NODE = ', + node.id, + node.x, + node.y, + relX, + relY, + node.domId.node(), + `translate(${node.x + relX + node.width / 2}, ${node.y + relY + node.height / 2})` + ); + node.domId.attr( + 'transform', + `translate(${node.x + relX + node.width / 2}, ${node.y + relY + node.height / 2})` + ); + } + } + }) + ); + + await Promise.all( + nodeArray.map(async function (node: { isGroup: any; x: any; y: any; children: any }) { + if (node?.isGroup) { + await drawNodes(relX + node.x, relY + node.y, node.children, svg, subgraphsEl, depth + 1); + } + }) + ); + }; + + const addSubGraphs = (nodeArr: any[]): TreeData => { + const parentLookupDb: TreeData = { parentById: {}, childrenById: {} }; + const subgraphs = nodeArr.filter((node: { isGroup: any }) => node.isGroup); + log.info('Subgraphs - ', subgraphs); + subgraphs.forEach((subgraph: { id: string }) => { + const children = nodeArr.filter((node: { parentId: any }) => node.parentId === subgraph.id); + children.forEach((node: any) => { + parentLookupDb.parentById[node.id] = subgraph.id; + if (parentLookupDb.childrenById[subgraph.id] === undefined) { + parentLookupDb.childrenById[subgraph.id] = []; + } + parentLookupDb.childrenById[subgraph.id].push(node); + }); + }); + + subgraphs.forEach(function (subgraph: { id: string | number }) { + const data: any = { id: subgraph.id }; + if (parentLookupDb.parentById[subgraph.id] !== undefined) { + data.parent = parentLookupDb.parentById[subgraph.id]; + } + }); + return parentLookupDb; + }; + + const getEdgeStartEndPoint = (edge: any) => { + const source: any = edge.start; + const target: any = edge.end; + + // Save the original source and target + const sourceId = source; + const targetId = target; + + const startNode = nodeDb[edge.start.id]; + const endNode = nodeDb[edge.end.id]; + + if (!startNode || !endNode) { + return { source, target }; + } + + // Add the edge to the graph + return { source, target, sourceId, targetId }; + }; + + const calcOffset = function (src: string, dest: string, parentLookupDb: TreeData) { + const ancestor = findCommonAncestor(src, dest, parentLookupDb); + if (ancestor === undefined || ancestor === 'root') { + return { x: 0, y: 0 }; + } + + const ancestorOffset = nodeDb[ancestor].offset; + return { x: ancestorOffset.posX, y: ancestorOffset.posY }; + }; + + /** + * Add edges to graph based on parsed graph definition + */ + const addEdges = async function ( + dataForLayout: { edges: any; direction?: string }, + graph: { + id?: string; + layoutOptions?: { + 'elk.hierarchyHandling': string; + 'elk.algorithm': any; + 'nodePlacement.strategy': any; + 'elk.layered.mergeEdges': any; + 'elk.direction': string; + 'spacing.baseValue': number; + }; + children?: never[]; + edges: any; + }, + svg: SVG + ) { + log.info('abc78 DAGA edges = ', dataForLayout); + const edges = dataForLayout.edges; + const labelsEl = svg.insert('g').attr('class', 'edgeLabels'); + const linkIdCnt: any = {}; + const dir = dataForLayout.direction || 'DOWN'; + let defaultStyle: string | undefined; + let defaultLabelStyle: string | undefined; + + await Promise.all( + edges.map(async function (edge: { + id: string; + start: string; + end: string; + length: number; + text: undefined; + label: any; + type: string; + stroke: any; + interpolate: undefined; + style: undefined; + labelType: any; + startLabelRight?: string; + endLabelLeft?: string; + }) { + // Identify Link + const linkIdBase = edge.id; // 'L-' + edge.start + '-' + edge.end; + // count the links from+to the same node to give unique id + if (linkIdCnt[linkIdBase] === undefined) { + linkIdCnt[linkIdBase] = 0; + log.info('abc78 new entry', linkIdBase, linkIdCnt[linkIdBase]); + } else { + linkIdCnt[linkIdBase]++; + log.info('abc78 new entry', linkIdBase, linkIdCnt[linkIdBase]); + } + const linkId = linkIdBase + '_' + linkIdCnt[linkIdBase]; + edge.id = linkId; + log.info('abc78 new link id to be used is', linkIdBase, linkId, linkIdCnt[linkIdBase]); + const linkNameStart = 'LS_' + edge.start; + const linkNameEnd = 'LE_' + edge.end; + + const edgeData: any = { style: '', labelStyle: '' }; + edgeData.minlen = edge.length || 1; + edge.text = edge.label; + // Set link type for rendering + if (edge.type === 'arrow_open') { + edgeData.arrowhead = 'none'; + } else { + edgeData.arrowhead = 'normal'; + } + + // Check of arrow types, placed here in order not to break old rendering + edgeData.arrowTypeStart = 'arrow_open'; + edgeData.arrowTypeEnd = 'arrow_open'; + + /* eslint-disable no-fallthrough */ + switch (edge.type) { + case 'double_arrow_cross': + edgeData.arrowTypeStart = 'arrow_cross'; + case 'arrow_cross': + edgeData.arrowTypeEnd = 'arrow_cross'; + break; + case 'double_arrow_point': + edgeData.arrowTypeStart = 'arrow_point'; + case 'arrow_point': + edgeData.arrowTypeEnd = 'arrow_point'; + break; + case 'double_arrow_circle': + edgeData.arrowTypeStart = 'arrow_circle'; + case 'arrow_circle': + edgeData.arrowTypeEnd = 'arrow_circle'; + break; + } + + let style = ''; + let labelStyle = ''; + + edgeData.startLabelRight = edge.startLabelRight; + edgeData.endLabelLeft = edge.endLabelLeft; + + switch (edge.stroke) { + case 'normal': + style = 'fill:none;'; + if (defaultStyle !== undefined) { + style = defaultStyle; + } + if (defaultLabelStyle !== undefined) { + labelStyle = defaultLabelStyle; + } + edgeData.thickness = 'normal'; + edgeData.pattern = 'solid'; + break; + case 'dotted': + edgeData.thickness = 'normal'; + edgeData.pattern = 'dotted'; + edgeData.style = 'fill:none;stroke-width:2px;stroke-dasharray:3;'; + break; + case 'thick': + edgeData.thickness = 'thick'; + edgeData.pattern = 'solid'; + edgeData.style = 'stroke-width: 3.5px;fill:none;'; + break; + } + + edgeData.style = edgeData.style += style; + edgeData.labelStyle = edgeData.labelStyle += labelStyle; + + const conf = getConfig(); + if (edge.interpolate !== undefined) { + edgeData.curve = interpolateToCurve(edge.interpolate, curveLinear); + } else if (edges.defaultInterpolate !== undefined) { + edgeData.curve = interpolateToCurve(edges.defaultInterpolate, curveLinear); + } else { + // @ts-ignore TODO: fix this + edgeData.curve = interpolateToCurve(conf.curve, curveLinear); + } + + if (edge.text === undefined) { + if (edge.style !== undefined) { + edgeData.arrowheadStyle = 'fill: #333'; + } + } else { + edgeData.arrowheadStyle = 'fill: #333'; + edgeData.labelpos = 'c'; + } + + edgeData.labelType = edge.labelType; + edgeData.label = (edge?.text || '').replace(common.lineBreakRegex, '\n'); + + if (edge.style === undefined) { + edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none;'; + } + + edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:'); + + edgeData.id = linkId; + edgeData.classes = 'flowchart-link ' + linkNameStart + ' ' + linkNameEnd; + + const labelEl = await insertEdgeLabel(labelsEl, edgeData); + + // calculate start and end points of the edge, note that the source and target + // can be modified for shapes that have ports + // @ts-ignore TODO: fix this + const { source, target, sourceId, targetId } = getEdgeStartEndPoint(edge, dir); + log.debug('abc78 source and target', source, target); + // Add the edge to the graph + graph.edges.push({ + // @ts-ignore TODO: fix this + id: 'e' + edge.start + edge.end, + ...edge, + sources: [source], + targets: [target], + sourceId, + targetId, + labelEl: labelEl, + labels: [ + { + width: edgeData.width, + height: edgeData.height, + orgWidth: edgeData.width, + orgHeight: edgeData.height, + text: edgeData.label, + layoutOptions: { + 'edgeLabels.inline': 'true', + 'edgeLabels.placement': 'CENTER', + }, + }, + ], + edgeData, + }); + }) + ); + return graph; + }; + + function dir2ElkDirection(dir: any) { + switch (dir) { + case 'LR': + return 'RIGHT'; + case 'RL': + return 'LEFT'; + case 'TB': + return 'DOWN'; + case 'BT': + return 'UP'; + default: + return 'DOWN'; + } + } + + function setIncludeChildrenPolicy(nodeId: string, ancestorId: string) { + const node = nodeDb[nodeId]; + + if (!node) { + return; + } + if (node?.layoutOptions === undefined) { + node.layoutOptions = {}; + } + node.layoutOptions['elk.hierarchyHandling'] = 'INCLUDE_CHILDREN'; + if (node.id !== ancestorId) { + setIncludeChildrenPolicy(node.parentId, ancestorId); + } + } + + function intersectLine( + p1: { y: number; x: number }, + p2: { y: number; x: number }, + q1: { x: any; y: any }, + q2: { x: any; y: any } + ) { + log.debug('UIO intersectLine', p1, p2, q1, q2); + // Algorithm from J. Avro, (ed.) Graphics Gems, No 2, Morgan Kaufmann, 1994, + // p7 and p473. + + // let a1, a2, b1, b2, c1, c2; + // let r1, r2, r3, r4; + // let denom, offset, num; + // let x, y; + + // Compute a1, b1, c1, where line joining points 1 and 2 is F(x,y) = a1 x + + // b1 y + c1 = 0. + const a1 = p2.y - p1.y; + const b1 = p1.x - p2.x; + const c1 = p2.x * p1.y - p1.x * p2.y; + + // Compute r3 and r4. + const r3 = a1 * q1.x + b1 * q1.y + c1; + const r4 = a1 * q2.x + b1 * q2.y + c1; + + const epsilon = 1e-6; + + // Check signs of r3 and r4. If both point 3 and point 4 lie on + // same side of line 1, the line segments do not intersect. + if (r3 !== 0 && r4 !== 0 && sameSign(r3, r4)) { + return /*DON'T_INTERSECT*/; + } + + // Compute a2, b2, c2 where line joining points 3 and 4 is G(x,y) = a2 x + b2 y + c2 = 0 + const a2 = q2.y - q1.y; + const b2 = q1.x - q2.x; + const c2 = q2.x * q1.y - q1.x * q2.y; + + // Compute r1 and r2 + const r1 = a2 * p1.x + b2 * p1.y + c2; + const r2 = a2 * p2.x + b2 * p2.y + c2; + + // Check signs of r1 and r2. If both point 1 and point 2 lie + // on same side of second line segment, the line segments do + // not intersect. + if (Math.abs(r1) < epsilon && Math.abs(r2) < epsilon && sameSign(r1, r2)) { + return /*DON'T_INTERSECT*/; + } + + // Line segments intersect: compute intersection point. + const denom = a1 * b2 - a2 * b1; + if (denom === 0) { + return /*COLLINEAR*/; + } + + const offset = Math.abs(denom / 2); + + // The denom/2 is to get rounding instead of truncating. It + // is added or subtracted to the numerator, depending upon the + // sign of the numerator. + let num = b1 * c2 - b2 * c1; + const x = num < 0 ? (num - offset) / denom : (num + offset) / denom; + + num = a2 * c1 - a1 * c2; + const y = num < 0 ? (num - offset) / denom : (num + offset) / denom; + + return { x: x, y: y }; + } + + function sameSign(r1: number, r2: number) { + return r1 * r2 > 0; + } + const diamondIntersection = ( + bounds: { x: any; y: any; width: any; height: any }, + outsidePoint: { x: number; y: number }, + insidePoint: any + ) => { + const x1 = bounds.x; + const y1 = bounds.y; + + const w = bounds.width; //+ bounds.padding; + const h = bounds.height; // + bounds.padding; + + const polyPoints = [ + { x: x1, y: y1 - h / 2 }, + { x: x1 + w / 2, y: y1 }, + { x: x1, y: y1 + h / 2 }, + { x: x1 - w / 2, y: y1 }, + ]; + log.debug( + `APA16 diamondIntersection calc abc89: + outsidePoint: ${JSON.stringify(outsidePoint)} + insidePoint : ${JSON.stringify(insidePoint)} + node-bounds : x:${bounds.x} y:${bounds.y} w:${bounds.width} h:${bounds.height}`, + JSON.stringify(polyPoints) + ); + + const intersections = []; + + let minX = Number.POSITIVE_INFINITY; + let minY = Number.POSITIVE_INFINITY; + + polyPoints.forEach(function (entry) { + minX = Math.min(minX, entry.x); + minY = Math.min(minY, entry.y); + }); + + const left = x1 - w / 2 - minX; + const top = y1 - h / 2 - minY; + + for (let i = 0; i < polyPoints.length; i++) { + const p1 = polyPoints[i]; + const p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0]; + const intersect = intersectLine( + bounds, + outsidePoint, + { x: left + p1.x, y: top + p1.y }, + { x: left + p2.x, y: top + p2.y } + ); + + if (intersect) { + intersections.push(intersect); + } + } + + if (!intersections.length) { + return bounds; + } + + log.debug('UIO intersections', intersections); + + if (intersections.length > 1) { + // More intersections, find the one nearest to edge end point + intersections.sort(function (p, q) { + const pdx = p.x - outsidePoint.x; + const pdy = p.y - outsidePoint.y; + const distp = Math.sqrt(pdx * pdx + pdy * pdy); + + const qdx = q.x - outsidePoint.x; + const qdy = q.y - outsidePoint.y; + const distq = Math.sqrt(qdx * qdx + qdy * qdy); + + return distp < distq ? -1 : distp === distq ? 0 : 1; + }); + } + + return intersections[0]; + }; + + const intersection = ( + node: { x: any; y: any; width: number; height: number }, + outsidePoint: { x: number; y: number }, + insidePoint: { x: number; y: number } + ) => { + log.debug(`intersection calc abc89: + outsidePoint: ${JSON.stringify(outsidePoint)} + insidePoint : ${JSON.stringify(insidePoint)} + node : x:${node.x} y:${node.y} w:${node.width} h:${node.height}`); + const x = node.x; + const y = node.y; + + const dx = Math.abs(x - insidePoint.x); + // const dy = Math.abs(y - insidePoint.y); + const w = node.width / 2; + let r = insidePoint.x < outsidePoint.x ? w - dx : w + dx; + const h = node.height / 2; + + const Q = Math.abs(outsidePoint.y - insidePoint.y); + const R = Math.abs(outsidePoint.x - insidePoint.x); + + if (Math.abs(y - outsidePoint.y) * w > Math.abs(x - outsidePoint.x) * h) { + // Intersection is top or bottom of rect. + const q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y; + r = (R * q) / Q; + const res = { + x: insidePoint.x < outsidePoint.x ? insidePoint.x + r : insidePoint.x - R + r, + y: insidePoint.y < outsidePoint.y ? insidePoint.y + Q - q : insidePoint.y - Q + q, + }; + + if (r === 0) { + res.x = outsidePoint.x; + res.y = outsidePoint.y; + } + if (R === 0) { + res.x = outsidePoint.x; + } + if (Q === 0) { + res.y = outsidePoint.y; + } + + log.debug(`abc89 topp/bott calc, Q ${Q}, q ${q}, R ${R}, r ${r}`, res); // cspell: disable-line + + return res; + } else { + // Intersection on sides of rect + if (insidePoint.x < outsidePoint.x) { + r = outsidePoint.x - w - x; + } else { + // r = outsidePoint.x - w - x; + r = x - w - outsidePoint.x; + } + const q = (Q * r) / R; + // OK let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x + dx - w; + // OK let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : outsidePoint.x + r; + let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x - R + r; + // let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : outsidePoint.x + r; + let _y = insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q; + log.debug(`sides calc abc89, Q ${Q}, q ${q}, R ${R}, r ${r}`, { _x, _y }); + if (r === 0) { + _x = outsidePoint.x; + _y = outsidePoint.y; + } + if (R === 0) { + _x = outsidePoint.x; + } + if (Q === 0) { + _y = outsidePoint.y; + } + + return { x: _x, y: _y }; + } + }; + const outsideNode = ( + node: { x: any; y: any; width: number; height: number }, + point: { x: number; y: number } + ) => { + const x = node.x; + const y = node.y; + const dx = Math.abs(point.x - x); + const dy = Math.abs(point.y - y); + const w = node.width / 2; + const h = node.height / 2; + if (dx >= w || dy >= h) { + return true; + } + return false; + }; + /** + * This function will page a path and node where the last point(s) in the path is inside the node + * and return an update path ending by the border of the node. + */ + const cutPathAtIntersect = ( + _points: any[], + bounds: { x: any; y: any; width: any; height: any; padding: any }, + isDiamond: boolean + ) => { + log.debug('APA18 cutPathAtIntersect Points:', _points, 'node:', bounds, 'isDiamond', isDiamond); + const points: any[] = []; + let lastPointOutside = _points[0]; + let isInside = false; + _points.forEach((point: any) => { + // check if point is inside the boundary rect + if (!outsideNode(bounds, point) && !isInside) { + // First point inside the rect found + // Calc the intersection coord between the point and the last point outside the rect + let inter; + + if (isDiamond) { + const inter2 = diamondIntersection(bounds, lastPointOutside, point); + const distance = Math.sqrt( + (lastPointOutside.x - inter2.x) ** 2 + (lastPointOutside.y - inter2.y) ** 2 + ); + if (distance > 1) { + inter = inter2; + } + } + if (!inter) { + inter = intersection(bounds, lastPointOutside, point); + } + + // Check case where the intersection is the same as the last point + let pointPresent = false; + points.forEach((p) => { + pointPresent = pointPresent || (p.x === inter.x && p.y === inter.y); + }); + // if (!pointPresent) { + if (!points.some((e) => e.x === inter.x && e.y === inter.y)) { + points.push(inter); + } else { + log.debug('abc88 no intersect', inter, points); + } + // points.push(inter); + isInside = true; + } else { + // Outside + log.debug('abc88 outside', point, lastPointOutside, points); + lastPointOutside = point; + // points.push(point); + if (!isInside) { + points.push(point); + } + } + }); + return points; + }; + + // @ts-ignore - ELK is not typed + const elk = new ELK(); + const element = svg.select('g'); + // Add the arrowheads to the svg + insertMarkers(element, data4Layout.markers, data4Layout.type, data4Layout.diagramId); + + // Setup the graph with the layout options and the data for the layout + let elkGraph: any = { + id: 'root', + layoutOptions: { + 'elk.hierarchyHandling': 'INCLUDE_CHILDREN', + 'elk.algorithm': algorithm, + 'nodePlacement.strategy': data4Layout.config.elk?.nodePlacementStrategy, + 'elk.layered.mergeEdges': data4Layout.config.elk?.mergeEdges, + 'elk.direction': 'DOWN', + 'spacing.baseValue': 35, + 'elk.layered.unnecessaryBendpoints': true, + 'elk.layered.cycleBreaking.strategy': data4Layout.config.elk?.cycleBreakingStrategy, + // 'spacing.nodeNode': 20, + // 'spacing.nodeNodeBetweenLayers': 25, + // 'spacing.edgeNode': 20, + // 'spacing.edgeNodeBetweenLayers': 10, + // 'spacing.edgeEdge': 10, + // 'spacing.edgeEdgeBetweenLayers': 20, + // 'spacing.nodeSelfLoop': 20, + + // Tweaking options + // 'elk.layered.nodePlacement.favorStraightEdges': true, + // 'nodePlacement.feedbackEdges': true, + // 'elk.layered.wrapping.multiEdge.improveCuts': true, + // 'elk.layered.wrapping.multiEdge.improveWrappedEdges': true, + // 'elk.layered.wrapping.strategy': 'MULTI_EDGE', + // 'elk.layered.edgeRouting.selfLoopDistribution': 'EQUALLY', + // 'elk.layered.mergeHierarchyEdges': true, + // 'elk.layered.feedbackEdges': true, + // 'elk.layered.crossingMinimization.semiInteractive': true, + // 'elk.layered.edgeRouting.splines.sloppy.layerSpacingFactor': 1, + // 'elk.layered.edgeRouting.polyline.slopedEdgeZoneWidth': 4.0, + // 'elk.layered.wrapping.validify.strategy': 'LOOK_BACK', + // 'elk.insideSelfLoops.activate': true, + // 'elk.alg.layered.options.EdgeStraighteningStrategy': 'NONE', + // 'elk.layered.considerModelOrder.strategy': 'NODES_AND_EDGES', // NODES_AND_EDGES + // 'elk.layered.wrapping.cutting.strategy': 'ARD', // NODES_AND_EDGES + }, + children: [], + edges: [], + }; + + log.info('Drawing flowchart using v4 renderer', elk); + + // Set the direction of the graph based on the parsed information + const dir = data4Layout.direction || 'DOWN'; + elkGraph.layoutOptions['elk.direction'] = dir2ElkDirection(dir); + + // Create the lookup db for the subgraphs and their children to used when creating + // the tree structured graph + const parentLookupDb: any = addSubGraphs(data4Layout.nodes); + + // Add elements in the svg to be used to hold the subgraphs container + // elements and the nodes + const subGraphsEl = svg.insert('g').attr('class', 'subgraphs'); + + const nodeEl = svg.insert('g').attr('class', 'nodes'); + + // Add the nodes to the graph, this will entail creating the actual nodes + // in order to get the size of the node. You can't get the size of a node + // that is not in the dom so we need to add it to the dom, get the size + // we will position the nodes when we get the layout from elkjs + elkGraph = await addVertices(nodeEl, data4Layout.nodes, elkGraph); + // Time for the edges, we start with adding an element in the node to hold the edges + const edgesEl = svg.insert('g').attr('class', 'edges edgePaths'); + + // Add the edges to the elk graph, this will entail creating the actual edges + elkGraph = await addEdges(data4Layout, elkGraph, svg); + + // Iterate through all nodes and add the top level nodes to the graph + const nodes = data4Layout.nodes; + nodes.forEach((n: { id: string | number }) => { + const node = nodeDb[n.id]; + + // Subgraph + if (parentLookupDb.childrenById[node.id] !== undefined) { + node.labels = [ + { + text: node.label, + width: node?.labelData?.width || 50, + height: node?.labelData?.height || 50, + }, + (node.width = node.width + 2 * node.padding), + log.debug('UIO node label', node?.labelData?.width, node.padding), + ]; + node.layoutOptions = { + 'spacing.baseValue': 30, + 'nodeLabels.placement': '[H_CENTER V_TOP, INSIDE]', + }; + if (node.dir) { + node.layoutOptions = { + ...node.layoutOptions, + 'elk.algorithm': algorithm, + 'elk.direction': dir2ElkDirection(node.dir), + 'nodePlacement.strategy': data4Layout.config.elk?.nodePlacementStrategy, + 'elk.layered.mergeEdges': data4Layout.config.elk?.mergeEdges, + 'elk.hierarchyHandling': 'SEPARATE_CHILDREN', + }; + } + delete node.x; + delete node.y; + delete node.width; + delete node.height; + } + }); + elkGraph.edges.forEach((edge: any) => { + const source = edge.sources[0]; + const target = edge.targets[0]; + + if (nodeDb[source].parentId !== nodeDb[target].parentId) { + const ancestorId = findCommonAncestor(source, target, parentLookupDb); + // an edge that breaks a subgraph has been identified, set configuration accordingly + setIncludeChildrenPolicy(source, ancestorId); + setIncludeChildrenPolicy(target, ancestorId); + } + }); + + const g = await elk.layout(elkGraph); + + // debugger; + await drawNodes(0, 0, g.children, svg, subGraphsEl, 0); + g.edges?.map( + (edge: { + sources: (string | number)[]; + targets: (string | number)[]; + start: any; + end: any; + sections: { startPoint: any; endPoint: any; bendPoints: any }[]; + points: any[]; + x: any; + labels: { height: number; width: number; x: number; y: number }[]; + y: any; + }) => { + // (elem, edge, clusterDb, diagramType, graph, id) + const startNode = nodeDb[edge.sources[0]]; + const startCluster = parentLookupDb[edge.sources[0]]; + const endNode = nodeDb[edge.targets[0]]; + const sourceId = edge.start; + const targetId = edge.end; + + const offset = calcOffset(sourceId, targetId, parentLookupDb); + log.debug( + 'APA18 offset', + offset, + sourceId, + ' ==> ', + targetId, + 'edge:', + edge, + 'cluster:', + startCluster, + startNode + ); + if (edge.sections) { + const src = edge.sections[0].startPoint; + const dest = edge.sections[0].endPoint; + const segments = edge.sections[0].bendPoints ? edge.sections[0].bendPoints : []; + + const segPoints = segments.map((segment: { x: any; y: any }) => { + return { x: segment.x + offset.x, y: segment.y + offset.y }; + }); + edge.points = [ + { x: src.x + offset.x, y: src.y + offset.y }, + ...segPoints, + { x: dest.x + offset.x, y: dest.y + offset.y }, + ]; + + let sw = startNode.width; + let ew = endNode.width; + if (startNode.isGroup) { + const bbox = startNode.domId.node().getBBox(); + // sw = Math.max(bbox.width, startNode.width, startNode.labels[0].width); + sw = Math.max(startNode.width, startNode.labels[0].width + startNode.padding); + // sw = startNode.width; + log.debug( + 'UIO width', + startNode.id, + startNode.with, + 'bbox.width=', + bbox.width, + 'lw=', + startNode.labels[0].width, + 'node:', + startNode.width, + 'SW = ', + sw + // 'HTML:', + // startNode.domId.node().innerHTML + ); + } + if (endNode.isGroup) { + const bbox = endNode.domId.node().getBBox(); + ew = Math.max(endNode.width, endNode.labels[0].width + endNode.padding); + + log.debug( + 'UIO width', + startNode.id, + startNode.with, + bbox.width, + 'EW = ', + ew, + 'HTML:', + startNode.innerHTML + ); + } + if (startNode.shape === 'diamond' || startNode.shape === 'diam') { + edge.points.unshift({ + x: startNode.offset.posX + startNode.width / 2, + y: startNode.offset.posY + startNode.height / 2, + }); + } + if (endNode.shape === 'diamond' || endNode.shape === 'diam') { + edge.points.push({ + x: endNode.offset.posX + endNode.width / 2, + y: endNode.offset.posY + endNode.height / 2, + }); + } + + edge.points = cutPathAtIntersect( + edge.points.reverse(), + { + x: startNode.offset.posX + startNode.width / 2, + y: startNode.offset.posY + startNode.height / 2, + width: sw, + height: startNode.height, + padding: startNode.padding, + }, + startNode.shape === 'diamond' || startNode.shape === 'diam' + ).reverse(); + + edge.points = cutPathAtIntersect( + edge.points, + { + x: endNode.offset.posX + endNode.width / 2, + y: endNode.offset.posY + endNode.height / 2, + width: ew, + height: endNode.height, + padding: endNode.padding, + }, + endNode.shape === 'diamond' || endNode.shape === 'diam' + ); + + const paths = insertEdge( + edgesEl, + edge, + clusterDb, + data4Layout.type, + startNode, + endNode, + data4Layout.diagramId + ); + log.info('APA12 edge points after insert', JSON.stringify(edge.points)); + + edge.x = edge.labels[0].x + offset.x + edge.labels[0].width / 2; + edge.y = edge.labels[0].y + offset.y + edge.labels[0].height / 2; + positionEdgeLabel(edge, paths); + } + } + ); +}; diff --git a/packages/mermaid-flowchart-elk/tsconfig.json b/packages/mermaid-layout-elk/tsconfig.json similarity index 89% rename from packages/mermaid-flowchart-elk/tsconfig.json rename to packages/mermaid-layout-elk/tsconfig.json index 5a41d0603..0d701cede 100644 --- a/packages/mermaid-flowchart-elk/tsconfig.json +++ b/packages/mermaid-layout-elk/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "rootDir": "../..", + "rootDir": "./src", "outDir": "./dist", "types": ["vitest/importMeta", "vitest/globals"] }, diff --git a/packages/mermaid-zenuml/package.json b/packages/mermaid-zenuml/package.json index 6be9c89e1..7a419c433 100644 --- a/packages/mermaid-zenuml/package.json +++ b/packages/mermaid-zenuml/package.json @@ -19,8 +19,7 @@ "mermaid" ], "scripts": { - "clean": "rimraf dist", - "prepublishOnly": "pnpm -w run build" + "clean": "rimraf dist" }, "repository": { "type": "git", @@ -34,13 +33,13 @@ ], "license": "MIT", "dependencies": { - "@zenuml/core": "^3.19.2" + "@zenuml/core": "^3.23.28" }, "devDependencies": { "mermaid": "workspace:^" }, "peerDependencies": { - "mermaid": "workspace:>=10.0.0" + "mermaid": "^10 || ^11" }, "files": [ "dist" diff --git a/packages/mermaid-zenuml/src/mermaidUtils.ts b/packages/mermaid-zenuml/src/mermaidUtils.ts index 623685879..413e8d2de 100644 --- a/packages/mermaid-zenuml/src/mermaidUtils.ts +++ b/packages/mermaid-zenuml/src/mermaidUtils.ts @@ -26,7 +26,7 @@ export const log: Record = { fatal: warning, }; -export let setLogLevel: (level: keyof typeof LEVELS | number | string) => void; +export let setLogLevel: (level: keyof typeof LEVELS | number) => void; export let getConfig: () => MermaidConfig; export let sanitizeText: (str: string) => string; // eslint-disable @typescript-eslint/no-explicit-any diff --git a/packages/mermaid-zenuml/src/zenumlRenderer.ts b/packages/mermaid-zenuml/src/zenumlRenderer.ts index a1a807dce..f9dd57996 100644 --- a/packages/mermaid-zenuml/src/zenumlRenderer.ts +++ b/packages/mermaid-zenuml/src/zenumlRenderer.ts @@ -9,7 +9,7 @@ function createTemporaryZenumlContainer(id: string) { container.id = `container-${id}`; container.style.display = 'flex'; container.innerHTML = `
`; - const app = container.querySelector(`#zenUMLApp-${id}`) as HTMLElement; + const app = container.querySelector(`#zenUMLApp-${id}`)!; return { container, app }; } diff --git a/packages/mermaid/CHANGELOG.md b/packages/mermaid/CHANGELOG.md new file mode 100644 index 000000000..b57b83b6a --- /dev/null +++ b/packages/mermaid/CHANGELOG.md @@ -0,0 +1,201 @@ +# mermaid + +## 11.6.0 + +### Minor Changes + +- [#6408](https://github.com/mermaid-js/mermaid/pull/6408) [`ad65313`](https://github.com/mermaid-js/mermaid/commit/ad653138e16765d095613a6e5de86dc5e52ac8f0) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - fix: restore curve type configuration functionality for flowcharts. This fixes the issue where curve type settings were not being applied when configured through any of the following methods: + + - Config + - Init directive (%%{ init: { 'flowchart': { 'curve': '...' } } }%%) + - LinkStyle command (linkStyle default interpolate ...) + +- [#6381](https://github.com/mermaid-js/mermaid/pull/6381) [`95d73bc`](https://github.com/mermaid-js/mermaid/commit/95d73bc3f064dbf261a06483f94a7ef4d0bb52eb) Thanks [@thomascizeron](https://github.com/thomascizeron)! - Add Radar Chart + +### Patch Changes + +- [#2](https://github.com/calvinvette/mermaid/pull/2) [`16d9b63`](https://github.com/mermaid-js/mermaid/commit/16d9b6345749ab5f24d5b8433efc3635d4913863) Thanks [@calvinvette](https://github.com/calvinvette)! - - [#6388](https://github.com/mermaid-js/mermaid/pull/6386) + Thanks [@bollwyvl](https://github.com/bollwyvl) - Fix requirement diagram containment arrow +- Updated dependencies [[`95d73bc`](https://github.com/mermaid-js/mermaid/commit/95d73bc3f064dbf261a06483f94a7ef4d0bb52eb)]: + - @mermaid-js/parser@0.4.0 + +## 11.5.0 + +### Minor Changes + +- [#6187](https://github.com/mermaid-js/mermaid/pull/6187) [`7809b5a`](https://github.com/mermaid-js/mermaid/commit/7809b5a93fae127f45727071f5ff14325222c518) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Flowchart new syntax for node metadata bugs + + - Incorrect label mapping for nodes when using `&` + - Syntax error when `}` with trailing spaces before new line + +- [#6136](https://github.com/mermaid-js/mermaid/pull/6136) [`ec0d9c3`](https://github.com/mermaid-js/mermaid/commit/ec0d9c389aa6018043187654044c1e0b5aa4f600) Thanks [@knsv](https://github.com/knsv)! - Adding support for animation of flowchart edges + +- [#6373](https://github.com/mermaid-js/mermaid/pull/6373) [`05bdf0e`](https://github.com/mermaid-js/mermaid/commit/05bdf0e20e2629fe77513218fbd4e28e65f75882) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - Upgrade Requirement and ER diagram to use the common renderer flow + + - Added support for directions + - Added support for hand drawn look + +- [#6371](https://github.com/mermaid-js/mermaid/pull/6371) [`4d25cab`](https://github.com/mermaid-js/mermaid/commit/4d25caba8e65df078966a283e7e0ae1200bef595) Thanks [@knsv](https://github.com/knsv)! - The arrowhead color should match the color of the edge. Creates a unique clone of the arrow marker with the appropriate color. + +### Patch Changes + +- [#6064](https://github.com/mermaid-js/mermaid/pull/6064) [`2a91849`](https://github.com/mermaid-js/mermaid/commit/2a91849a38641e97ed6b20cb60aa4506d1b63177) Thanks [@NicolasNewman](https://github.com/NicolasNewman)! - fix: architecture diagrams no longer grow to extreme heights due to conflicting alignments + +- [#6198](https://github.com/mermaid-js/mermaid/pull/6198) [`963efa6`](https://github.com/mermaid-js/mermaid/commit/963efa64c794466dcd0f06bad6de6ba554d05a54) Thanks [@ferozmht](https://github.com/ferozmht)! - Fixes for consistent edge id creation & handling edge cases for animate edge feature + +- [#6196](https://github.com/mermaid-js/mermaid/pull/6196) [`127bac1`](https://github.com/mermaid-js/mermaid/commit/127bac1147034d8a8588cc8f7870abe92ebc945e) Thanks [@knsv](https://github.com/knsv)! - Fix for issue #6195 - allowing @ signs inside node labels + +- [#6212](https://github.com/mermaid-js/mermaid/pull/6212) [`90bbf90`](https://github.com/mermaid-js/mermaid/commit/90bbf90a83bf5da53fc8030cf1370bc8238fa4aa) Thanks [@saurabhg772244](https://github.com/saurabhg772244)! - fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each class diagram + +- [#6218](https://github.com/mermaid-js/mermaid/pull/6218) [`232e60c`](https://github.com/mermaid-js/mermaid/commit/232e60c8cbaea804e6d98aa90f90d1ce76730e17) Thanks [@saurabhg772244](https://github.com/saurabhg772244)! - fix: revert state db to resolve getData returning empty nodes and edges + +- [#6250](https://github.com/mermaid-js/mermaid/pull/6250) [`9cad3c7`](https://github.com/mermaid-js/mermaid/commit/9cad3c7aea3bbbc61495b23225ccff76d312783f) Thanks [@saurabhg772244](https://github.com/saurabhg772244)! - `mermaidAPI.getDiagramFromText()` now returns a new db instance on each call for state diagrams + +- [#6293](https://github.com/mermaid-js/mermaid/pull/6293) [`cfd84e5`](https://github.com/mermaid-js/mermaid/commit/cfd84e54d502f4d36a35b50478121558cfbef2c4) Thanks [@saurabhg772244](https://github.com/saurabhg772244)! - Added versioning to StateDB and updated tests and diagrams to use it. + +- [#6161](https://github.com/mermaid-js/mermaid/pull/6161) [`6cc31b7`](https://github.com/mermaid-js/mermaid/commit/6cc31b74530baa6d0f527346ab1395b0896bb3c2) Thanks [@saurabhg772244](https://github.com/saurabhg772244)! - fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each flowchart + +- [#6272](https://github.com/mermaid-js/mermaid/pull/6272) [`ffa7804`](https://github.com/mermaid-js/mermaid/commit/ffa7804af0701b3d044d6794e36bd9132d6c7e8d) Thanks [@saurabhg772244](https://github.com/saurabhg772244)! - fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each sequence diagram. Added unique IDs for messages. + +- [#6205](https://github.com/mermaid-js/mermaid/pull/6205) [`32a68d4`](https://github.com/mermaid-js/mermaid/commit/32a68d489ed83a5b79f516d6b2fb3a7505c5eb24) Thanks [@saurabhg772244](https://github.com/saurabhg772244)! - fix: Gantt, Sankey and User Journey diagram are now able to pick font-family from mermaid config. + +- [#6295](https://github.com/mermaid-js/mermaid/pull/6295) [`da6361f`](https://github.com/mermaid-js/mermaid/commit/da6361f6527918b4b6a9c07cc9558cf2e2c709d2) Thanks [@omkarht](https://github.com/omkarht)! - fix: `getDirection` and `setDirection` in `stateDb` refactored to return and set actual direction + +- [#6185](https://github.com/mermaid-js/mermaid/pull/6185) [`3e32332`](https://github.com/mermaid-js/mermaid/commit/3e32332814c659e7ed1bb73d4a26ed4e61b77d59) Thanks [@saurabhg772244](https://github.com/saurabhg772244)! - `mermaidAPI.getDiagramFromText()` now returns a new different db for each state diagram + +## 11.4.1 + +### Patch Changes + +- [#6059](https://github.com/mermaid-js/mermaid/pull/6059) [`01b5079`](https://github.com/mermaid-js/mermaid/commit/01b5079562ec8d34ce9964910f168873843c68f8) Thanks [@knsv](https://github.com/knsv)! - fix: Kanban diagrams will not render when adding a number as ticket id or assigned for a task + +- [#6038](https://github.com/mermaid-js/mermaid/pull/6038) [`1388662`](https://github.com/mermaid-js/mermaid/commit/1388662132cc829f9820c2e9970ae04e2dd90588) Thanks [@knsv](https://github.com/knsv)! - fix: Intersection calculations for tilted cylinder/DAS when using handdrawn look. Some random seeds could cause the calculations to break. + +- [#6079](https://github.com/mermaid-js/mermaid/pull/6079) [`fe3cffb`](https://github.com/mermaid-js/mermaid/commit/fe3cffbb673a25b81989aacb06e5d0eda35326db) Thanks [@aloisklink](https://github.com/aloisklink)! - Bump dompurify to `^3.2.1`. This removes the need for `@types/dompurify`. + +## 11.4.0 + +### Minor Changes + +- [#5999](https://github.com/mermaid-js/mermaid/pull/5999) [`742ad7c`](https://github.com/mermaid-js/mermaid/commit/742ad7c130964df1fb5544e909d9556081285f68) Thanks [@knsv](https://github.com/knsv)! - Adding Kanban board, a new diagram type + +- [#5880](https://github.com/mermaid-js/mermaid/pull/5880) [`bdf145f`](https://github.com/mermaid-js/mermaid/commit/bdf145ffe362462176d9c1e68d5f3ff5c9d962b0) Thanks [@yari-dewalt](https://github.com/yari-dewalt)! - Class diagram changes: + + - Updates the class diagram to the new unified way of rendering. + - Includes a new "classBox" shape to be used in diagrams + - Other updates such as: + - the option to hide the empty members box in class diagrams, + - support for handDrawn look, + - the introduction of the classDef statement into class diagrams, + - support for styling the default class, + - support lollipop interfaces. + - Includes fixes / additions for #5562 #3139 and #4037 + +### Patch Changes + +- [#5937](https://github.com/mermaid-js/mermaid/pull/5937) [`17b7831`](https://github.com/mermaid-js/mermaid/commit/17b783135f9b2b7748b620dbf81d0f56ab4755f1) Thanks [@saurabhg772244](https://github.com/saurabhg772244)! - fix: Jagged edge fix for icon shape + +- [#5933](https://github.com/mermaid-js/mermaid/pull/5933) [`72d60d2`](https://github.com/mermaid-js/mermaid/commit/72d60d2633584eb59bccdb6cf30b9522db645db2) Thanks [@remcohaszing](https://github.com/remcohaszing)! - Add missing TypeScript dependencies + +- [#5937](https://github.com/mermaid-js/mermaid/pull/5937) [`17b7831`](https://github.com/mermaid-js/mermaid/commit/17b783135f9b2b7748b620dbf81d0f56ab4755f1) Thanks [@saurabhg772244](https://github.com/saurabhg772244)! - fix: Icon color fix for colored icons. + +- [#6002](https://github.com/mermaid-js/mermaid/pull/6002) [`5fabd41`](https://github.com/mermaid-js/mermaid/commit/5fabd414fbee01e43bf6c900907ffc1511ca7440) Thanks [@aloisklink](https://github.com/aloisklink)! - fix: error `mermaid.parse` on an invalid shape, so that it matches the errors thrown by `mermaid.render` + +## 11.3.0 + +### Minor Changes + +- [#5825](https://github.com/mermaid-js/mermaid/pull/5825) [`9e3aa70`](https://github.com/mermaid-js/mermaid/commit/9e3aa705ae21fd4898504ab22d775a9e437b898e) Thanks [@ashishjain0512](https://github.com/ashishjain0512)! - New Flowchart Shapes (with new syntax) + +### Patch Changes + +- [#5849](https://github.com/mermaid-js/mermaid/pull/5849) [`6c5b7ce`](https://github.com/mermaid-js/mermaid/commit/6c5b7ce9f41c0fbd59fe03dbefc8418d97697f0a) Thanks [@ReneLombard](https://github.com/ReneLombard)! - Fixed an issue when the mermaid classdiagram crashes when adding a . to the namespace. + For example + + ```mermaid + + classDiagram + namespace Company.Project.Module { + class GenericClass~T~ { + +addItem(item: T) + +getItem() T + } + } + ``` + +- [#5914](https://github.com/mermaid-js/mermaid/pull/5914) [`de2c05c`](https://github.com/mermaid-js/mermaid/commit/de2c05cd5463af68d19dd7b6b3f1303d69ddb2dd) Thanks [@aloisklink](https://github.com/aloisklink)! - Ban DOMPurify v3.1.7 as a dependency + +## 11.2.1 + +### Patch Changes + +- [#5856](https://github.com/mermaid-js/mermaid/pull/5856) [`bfd8c63`](https://github.com/mermaid-js/mermaid/commit/bfd8c63daaa8420e57da9953922b9f0c94123064) Thanks [@knsv](https://github.com/knsv)! - Fix for issue with calculation of label width when using in firefox + +## 11.2.0 + +### Minor Changes + +- [#5831](https://github.com/mermaid-js/mermaid/pull/5831) [`64abf29`](https://github.com/mermaid-js/mermaid/commit/64abf29ea870eaa47148197f95ce714f85bd7eea) Thanks [@sidharthv96](https://github.com/sidharthv96)! - feat: Return parsed config from mermaid.parse + +### Patch Changes + +- [#5838](https://github.com/mermaid-js/mermaid/pull/5838) [`5e75320`](https://github.com/mermaid-js/mermaid/commit/5e75320d49eab65aca630dcc3c04c8d620a8bbf7) Thanks [@bollwyvl](https://github.com/bollwyvl)! - fix: Replace $root with relative paths + +## 11.1.1 + +### Patch Changes + +- [#5828](https://github.com/mermaid-js/mermaid/pull/5828) [`4c43d21`](https://github.com/mermaid-js/mermaid/commit/4c43d21196f784b6f483ae635fc462329f3d176f) Thanks [@knsv](https://github.com/knsv)! - fix: Fix for issue where self-loops in the root of diagrams break the rendering + +## 11.1.0 + +### Minor Changes + +- [#5793](https://github.com/mermaid-js/mermaid/pull/5793) [`6ecdf7b`](https://github.com/mermaid-js/mermaid/commit/6ecdf7be688efdc53c52fea3ba891327242bc890) Thanks [@sidharthv96](https://github.com/sidharthv96)! - feat: Add support for iconify icons + +- [#5711](https://github.com/mermaid-js/mermaid/pull/5711) [`8e640da`](https://github.com/mermaid-js/mermaid/commit/8e640da5436e8ae013b11b1c1821a9afcc15d0d3) Thanks [@NicolasNewman](https://github.com/NicolasNewman)! - feat(er): allow multi-line relationship labels + +- [#5452](https://github.com/mermaid-js/mermaid/pull/5452) [`256a148`](https://github.com/mermaid-js/mermaid/commit/256a148bbf484fc7db6c19f94dd69d5d268ee048) Thanks [@NicolasNewman](https://github.com/NicolasNewman)! - New Diagram: Architecture + + Adds architecture diagrams which allows users to show relations between services. + +### Patch Changes + +- [#5810](https://github.com/mermaid-js/mermaid/pull/5810) [`28bd07f`](https://github.com/mermaid-js/mermaid/commit/28bd07fdeb4fc981107d21317ec6160b31f80116) Thanks [@knsv](https://github.com/knsv)! - Fix for self loops in cluster + Supporting legacy defaultRenderer directive + +- [#5789](https://github.com/mermaid-js/mermaid/pull/5789) [`16faef4`](https://github.com/mermaid-js/mermaid/commit/16faef4613b91a7d3a98a1563c25b57f9238acc7) Thanks [@sidharthv96](https://github.com/sidharthv96)! - chore: Move icons to architecture, remove full icon sets to reduce bundle size + +- Updated dependencies [[`256a148`](https://github.com/mermaid-js/mermaid/commit/256a148bbf484fc7db6c19f94dd69d5d268ee048), [`7d8143b`](https://github.com/mermaid-js/mermaid/commit/7d8143b917ee3562149a0e0a821ed2d6f29cc05d)]: + - @mermaid-js/parser@0.3.0 + +## 11.0.2 + +### Patch Changes + +- [#5664](https://github.com/mermaid-js/mermaid/pull/5664) [`5deaef4`](https://github.com/mermaid-js/mermaid/commit/5deaef456e74d796866431c26f69360e4e74dbff) Thanks [@Austin-Fulbright](https://github.com/Austin-Fulbright)! - chore: Migrate git graph to langium, use typescript for internals + +- Updated dependencies [[`5deaef4`](https://github.com/mermaid-js/mermaid/commit/5deaef456e74d796866431c26f69360e4e74dbff)]: + - @mermaid-js/parser@0.2.0 + +## 11.0.1 + +### Patch Changes + +- [#2](https://github.com/calvinvette/mermaid/pull/2) [`bf05d87`](https://github.com/mermaid-js/mermaid/commit/bf05d8781edacb580fdb053da167e968b7570117) Thanks [@calvinvette](https://github.com/calvinvette)! - test changeset + +## 11.0.2 + +### Patch Changes + +- Updated dependencies [[`83926c9`](https://github.com/mermaid-js/mermaid/commit/83926c9707b09c34e300888186250191ee8ae30a)]: + - @mermaid-js/parser@0.1.1 + +## 11.0.1 + +### Patch Changes + +- [#5744](https://github.com/mermaid-js/mermaid/pull/5744) [`5013484`](https://github.com/mermaid-js/mermaid/commit/50134849246141ec400e33e08c12c10539b84de9) Thanks [@sidharthv96](https://github.com/sidharthv96)! - Release parser, test changesets + +- Updated dependencies [[`5013484`](https://github.com/mermaid-js/mermaid/commit/50134849246141ec400e33e08c12c10539b84de9)]: + - @mermaid-js/parser@0.1.0 diff --git a/packages/mermaid/package.json b/packages/mermaid/package.json index 9a91a645e..7f8230229 100644 --- a/packages/mermaid/package.json +++ b/packages/mermaid/package.json @@ -1,6 +1,6 @@ { "name": "mermaid", - "version": "11.0.0-alpha.7", + "version": "11.6.0", "description": "Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.", "type": "module", "module": "./dist/mermaid.core.mjs", @@ -34,9 +34,9 @@ "scripts": { "clean": "rimraf dist", "dev": "pnpm -w dev", - "docs:code": "typedoc src/defaultConfig.ts src/config.ts src/mermaidAPI.ts && prettier --write ./src/docs/config/setup", - "docs:build": "rimraf ../../docs && pnpm docs:spellcheck && pnpm docs:code && tsx scripts/docs.cli.mts", - "docs:verify": "pnpm docs:spellcheck && pnpm docs:code && tsx scripts/docs.cli.mts --verify", + "docs:code": "typedoc src/defaultConfig.ts src/config.ts src/mermaid.ts && prettier --write ./src/docs/config/setup", + "docs:build": "rimraf ../../docs && pnpm docs:code && pnpm docs:spellcheck && tsx scripts/docs.cli.mts", + "docs:verify": "pnpm docs:code && pnpm docs:spellcheck && tsx scripts/docs.cli.mts --verify", "docs:pre:vitepress": "pnpm --filter ./src/docs prefetch && rimraf src/vitepress && pnpm docs:code && tsx scripts/docs.cli.mts --vitepress && pnpm --filter ./src/vitepress install --no-frozen-lockfile --ignore-scripts", "docs:build:vitepress": "pnpm docs:pre:vitepress && (cd src/vitepress && pnpm run build) && cpy --flat src/docs/landing/ ./src/vitepress/.vitepress/dist/landing", "docs:dev": "pnpm docs:pre:vitepress && concurrently \"pnpm --filter ./src/vitepress dev\" \"tsx scripts/docs.cli.mts --watch --vitepress\"", @@ -48,8 +48,7 @@ "types:build-config": "tsx scripts/create-types-from-json-schema.mts", "types:verify-config": "tsx scripts/create-types-from-json-schema.mts --verify", "checkCircle": "npx madge --circular ./src", - "release": "pnpm build", - "prepublishOnly": "cpy '../../README.*' ./ --cwd=. && pnpm docs:release-version && pnpm -w run build" + "prepublishOnly": "pnpm docs:verify-version" }, "repository": { "type": "git", @@ -68,75 +67,73 @@ ] }, "dependencies": { - "@braintree/sanitize-url": "^7.0.1", + "@braintree/sanitize-url": "^7.0.4", + "@iconify/utils": "^2.1.33", "@mermaid-js/parser": "workspace:^", - "cytoscape": "^3.28.1", + "@types/d3": "^7.4.3", + "cytoscape": "^3.29.3", "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", - "dagre-d3-es": "7.0.10", - "dayjs": "^1.11.10", - "dompurify": "^3.0.11", - "elkjs": "^0.9.2", + "dagre-d3-es": "7.0.11", + "dayjs": "^1.11.13", + "dompurify": "^3.2.5", "katex": "^0.16.9", "khroma": "^2.1.0", "lodash-es": "^4.17.21", - "mdast-util-from-markdown": "^2.0.0", - "stylis": "^4.3.1", + "marked": "^15.0.7", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", "ts-dedent": "^2.2.0", - "uuid": "^9.0.1" + "uuid": "^11.1.0" }, "devDependencies": { - "@adobe/jsonschema2md": "^8.0.0", - "@types/cytoscape": "^3.19.16", - "@types/d3": "^7.4.3", + "@adobe/jsonschema2md": "^8.0.2", + "@iconify/types": "^2.0.0", + "@types/cytoscape": "^3.21.9", + "@types/cytoscape-fcose": "^2.2.4", "@types/d3-sankey": "^0.12.4", - "@types/d3-scale": "^4.0.8", - "@types/d3-scale-chromatic": "^3.0.3", - "@types/d3-selection": "^3.0.10", - "@types/d3-shape": "^3.1.6", - "@types/dompurify": "^3.0.5", - "@types/jsdom": "^21.1.6", + "@types/d3-scale": "^4.0.9", + "@types/d3-scale-chromatic": "^3.1.0", + "@types/d3-selection": "^3.0.11", + "@types/d3-shape": "^3.1.7", + "@types/jsdom": "^21.1.7", "@types/katex": "^0.16.7", "@types/lodash-es": "^4.17.12", - "@types/micromatch": "^4.0.6", - "@types/prettier": "^3.0.0", - "@types/stylis": "^4.2.5", - "@types/uuid": "^9.0.8", - "@typescript-eslint/eslint-plugin": "^7.3.1", - "@typescript-eslint/parser": "^7.3.1", - "ajv": "^8.12.0", - "chokidar": "^3.6.0", - "concurrently": "^8.2.2", - "cpy-cli": "^5.0.0", - "csstree-validator": "^3.0.0", - "globby": "^14.0.1", + "@types/micromatch": "^4.0.9", + "@types/stylis": "^4.2.7", + "@types/uuid": "^10.0.0", + "ajv": "^8.17.1", + "chokidar": "^4.0.3", + "concurrently": "^9.1.2", + "csstree-validator": "^4.0.1", + "globby": "^14.0.2", "jison": "^0.4.18", "js-base64": "^3.7.7", - "jsdom": "^24.0.0", - "json-schema-to-typescript": "^13.1.2", - "micromatch": "^4.0.5", + "jsdom": "^26.0.0", + "json-schema-to-typescript": "^15.0.4", + "micromatch": "^4.0.8", "path-browserify": "^1.0.1", - "prettier": "^3.2.5", + "prettier": "^3.5.2", "remark": "^15.0.1", "remark-frontmatter": "^5.0.0", - "remark-gfm": "^4.0.0", - "rimraf": "^5.0.5", - "start-server-and-test": "^2.0.3", - "type-fest": "^4.13.1", - "typedoc": "^0.25.12", - "typedoc-plugin-markdown": "^3.17.1", - "typescript": "^5.4.3", + "remark-gfm": "^4.0.1", + "rimraf": "^6.0.1", + "start-server-and-test": "^2.0.10", + "type-fest": "^4.35.0", + "typedoc": "^0.27.8", + "typedoc-plugin-markdown": "^4.4.2", + "typescript": "~5.7.3", "unist-util-flatmap": "^1.0.0", "unist-util-visit": "^5.0.0", - "vitepress": "^1.0.1", + "vitepress": "^1.0.2", "vitepress-plugin-search": "1.0.4-alpha.22" }, "files": [ "dist/", "README.md" ], - "sideEffects": false, "publishConfig": { "access": "public" } diff --git a/packages/mermaid/scripts/create-types-from-json-schema.mts b/packages/mermaid/scripts/create-types-from-json-schema.mts index a300ef00f..4ffc73f4f 100644 --- a/packages/mermaid/scripts/create-types-from-json-schema.mts +++ b/packages/mermaid/scripts/create-types-from-json-schema.mts @@ -10,18 +10,16 @@ /* eslint-disable no-console */ -import { readFile, writeFile } from 'node:fs/promises'; -import { join } from 'node:path'; +import _Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js'; +import { JSON_SCHEMA, load } from 'js-yaml'; +import { compile, type JSONSchema } from 'json-schema-to-typescript'; import assert from 'node:assert'; import { execFile } from 'node:child_process'; +import { readFile, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; import { promisify } from 'node:util'; - -import { load, JSON_SCHEMA } from 'js-yaml'; -import { compile, type JSONSchema } from 'json-schema-to-typescript'; import prettier from 'prettier'; -import _Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js'; - // Workaround for wrong AJV types, see // https://github.com/ajv-validator/ajv/issues/2132#issuecomment-1290409907 const Ajv2019 = _Ajv2019 as unknown as typeof _Ajv2019.default; @@ -34,28 +32,6 @@ const verifyOnly = process.argv.includes('--verify'); /** If `true`, automatically `git add` any changes (i.e. during `pnpm run pre-commit`)*/ const git = process.argv.includes('--git'); -/** - * All of the keys in the mermaid config that have a mermaid diagram config. - */ -const MERMAID_CONFIG_DIAGRAM_KEYS = [ - 'flowchart', - 'sequence', - 'gantt', - 'journey', - 'class', - 'state', - 'er', - 'pie', - 'quadrantChart', - 'xyChart', - 'requirement', - 'mindmap', - 'timeline', - 'gitGraph', - 'c4', - 'sankey', -]; - /** * Loads the MermaidConfig JSON schema YAML file. * @@ -109,7 +85,7 @@ function validateSchema(jsonSchema: unknown): asserts jsonSchema is JSONSchemaTy * * @param mermaidConfigSchema - The input JSON Schema. */ -async function generateTypescript(mermaidConfigSchema: JSONSchemaType) { +async function generateTypeScript(mermaidConfigSchema: JSONSchemaType) { /** * Replace all usages of `allOf` with `extends`. * @@ -121,7 +97,7 @@ async function generateTypescript(mermaidConfigSchema: JSONSchemaType>) { - if (schema['allOf']) { + if (schema.allOf) { const { allOf, ...schemaWithoutAllOf } = schema; return { ...schemaWithoutAllOf, @@ -132,13 +108,13 @@ async function generateTypescript(mermaidConfigSchema: JSONSchemaType`. + * In the future, we should make the input to Mermaid `Partial`. * * @todo TODO: Remove this function when Mermaid releases a new breaking change. * @param schema - The input schema. @@ -148,53 +124,9 @@ async function generateTypescript(mermaidConfigSchema: JSONSchemaType>) { - return { - ...schema, - properties: Object.fromEntries( - Object.entries(schema.properties).map(([key, propertySchema]) => { - if (MERMAID_CONFIG_DIAGRAM_KEYS.includes(key)) { - const { $ref, ...propertySchemaWithoutRef } = propertySchema as JSONSchemaType; - if ($ref === undefined) { - throw Error( - `subSchema ${key} is in MERMAID_CONFIG_DIAGRAM_KEYS but does not have a $ref field` - ); - } - const [ - _root, // eslint-disable-line @typescript-eslint/no-unused-vars - _defs, // eslint-disable-line @typescript-eslint/no-unused-vars - defName, - ] = $ref.split('/'); - return [ - key, - { - ...propertySchemaWithoutRef, - tsType: defName, - }, - ]; - } - return [key, propertySchema]; - }) - ), - }; - } - assert.ok(mermaidConfigSchema.$defs); const modifiedSchema = { - ...unrefSubschemas(removeRequired(mermaidConfigSchema)), + ...removeRequired(mermaidConfigSchema), $defs: Object.fromEntries( Object.entries(mermaidConfigSchema.$defs).map(([key, subSchema]) => { @@ -265,7 +197,7 @@ async function main() { validateSchema(configJsonSchema); // Generate types from JSON Schema - await generateTypescript(configJsonSchema); + await generateTypeScript(configJsonSchema); } main().catch((error) => { diff --git a/packages/mermaid/scripts/docs.mts b/packages/mermaid/scripts/docs.mts index 1bc944ee8..073a3c1a9 100644 --- a/packages/mermaid/scripts/docs.mts +++ b/packages/mermaid/scripts/docs.mts @@ -41,7 +41,8 @@ import { exec } from 'child_process'; import { globby } from 'globby'; import { JSDOM } from 'jsdom'; import { dump, load, JSON_SCHEMA } from 'js-yaml'; -import type { Code, ListItem, Root, Text, YAML } from 'mdast'; +import type { Code, ListItem, PhrasingContent, Root, Text, YAML } from 'mdast'; +import { register } from 'node:module'; import { posix, dirname, relative, join } from 'path'; import prettier from 'prettier'; import { remark } from 'remark'; @@ -53,6 +54,10 @@ import mm from 'micromatch'; import flatmap from 'unist-util-flatmap'; import { visit } from 'unist-util-visit'; +// short-circuit `.schema.yaml` imports, so that we can safely import `shapes.js` +register('./loadHook.mjs', import.meta.url); +const { shapesDefs } = await import('../src/rendering-util/rendering-elements/shapes.js'); + export const MERMAID_RELEASE_VERSION = JSON.parse(readFileSync('../mermaid/package.json', 'utf8')) .version as string; const MERMAID_MAJOR_VERSION = MERMAID_RELEASE_VERSION.split('.')[0]; @@ -88,9 +93,9 @@ const WARN_DOCSDIR_DOESNT_MATCH = `Changed files were transformed in ${SOURCE_DO const prettierConfig = (await prettier.resolveConfig('.')) ?? {}; // From https://github.com/vuejs/vitepress/blob/428eec3750d6b5648a77ac52d88128df0554d4d1/src/node/markdownToVue.ts#L20-L21 const includesRE = //g; -const includedFiles: Set = new Set(); +const includedFiles = new Set(); -const filesTransformed: Set = new Set(); +const filesTransformed = new Set(); const generateHeader = (file: string): string => { // path from file in docs/* to repo root, e.g ../ or ../../ */ @@ -103,6 +108,60 @@ const generateHeader = (file: string): string => { > ## Please edit the corresponding file in [${filePathFromRoot}](${sourcePathRelativeToGenerated}).`; }; +/** + * Builds a markdown list of shapes supported in flowcharts. + */ +export function buildShapeDoc() { + const data = shapesDefs + .sort((a, b) => a.semanticName.localeCompare(b.semanticName)) + .map((shape): PhrasingContent[][] => { + const { name, semanticName, description, shortName, aliases = [] } = shape; + return [ + [{ type: 'text', value: semanticName }], + [{ type: 'text', value: name }], + [{ type: 'inlineCode', value: shortName }], + [{ type: 'text', value: description }], + aliases.sort().flatMap((alias, index) => [ + ...(index !== 0 ? ([{ type: 'text', value: ', ' }] as const) : []), + { + type: 'inlineCode', + value: alias, + }, + ]), + ]; + }); + + // don't prettify this table, since we'd do it later + return remark() + .use(remarkGfm) + .stringify({ + type: 'root', + children: [ + { + type: 'table', + children: [ + ['Semantic Name', 'Shape Name', 'Short Name', 'Description', 'Alias Supported'].map( + (s): PhrasingContent[] => [ + { + type: 'strong', + children: [{ type: 'text', value: s }], + }, + ] + ), + ...data, + ].map((row) => ({ + type: 'tableRow', + children: row.map((cell) => ({ + type: 'tableCell', + children: cell, + })), + })), + }, + ], + }) + .toString(); +} + /** * Given a source file name and path, return the documentation destination full path and file name * Create the destination path if it does not already exist. @@ -181,10 +240,10 @@ export const transformToBlockQuote = ( ) => { if (vitepress) { const vitepressType = type === 'note' ? 'info' : type; - return `::: ${vitepressType} ${customTitle || ''}\n${content}\n:::`; + return `::: ${vitepressType} ${customTitle ?? ''}\n${content}\n:::`; } else { - const icon = blockIcons[type] || ''; - const title = `${icon}${customTitle || capitalize(type)}`; + const icon = blockIcons[type] ?? ''; + const title = `${icon}${customTitle ?? capitalize(type)}`; return `> **${title}** \n> ${content.replace(/\n/g, '\n> ')}`; } }; @@ -192,15 +251,28 @@ export const transformToBlockQuote = ( const injectPlaceholders = (text: string): string => text.replace(//g, MERMAID_MAJOR_VERSION).replace(//g, CDN_URL); +const virtualGenerators: Record string> = { + shapesTable: buildShapeDoc, +}; + const transformIncludeStatements = (file: string, text: string): string => { // resolve includes - src https://github.com/vuejs/vitepress/blob/428eec3750d6b5648a77ac52d88128df0554d4d1/src/node/markdownToVue.ts#L65-L76 - return text.replace(includesRE, (m, m1) => { + return text.replace(includesRE, (m, m1: string) => { try { + if (m1.startsWith('virtual:')) { + const key = m1.replace('virtual:', ''); + const generator = virtualGenerators[key]; + if (!generator) { + throw new Error(`Unknown virtual generator: ${key} in "${file}"`); + } + return generator(); + } const includePath = join(dirname(file), m1).replaceAll('\\', '/'); const content = readSyncedUTF8file(includePath); includedFiles.add(changeToFinalDocDir(includePath)); return content; } catch (error) { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions throw new Error(`Failed to resolve include "${m1}" in "${file}": ${error}`); } }); @@ -241,7 +313,7 @@ export function transformMarkdownAst({ addEditLink, removeYAML, }: TransformMarkdownAstOptions) { - return (tree: Root, _file?: any): Root => { + return (tree: Root): Root => { const astWithTransformedBlocks = flatmap(tree, (node: Code) => { if (node.type !== 'code' || !node.lang) { return [node]; // no transformation if this is not a code block @@ -509,6 +581,7 @@ export const getGlobs = (globs: string[]): string[] => { globs.push( '!**/.vitepress/**', '!**/vite.config.ts', + '!**/tsconfig.json', '!src/docs/index.md', '!**/package.json', '!**/user-avatars/**' diff --git a/packages/mermaid/scripts/docs.spec.ts b/packages/mermaid/scripts/docs.spec.ts index c84bc1bac..68677d4c9 100644 --- a/packages/mermaid/scripts/docs.spec.ts +++ b/packages/mermaid/scripts/docs.spec.ts @@ -1,4 +1,4 @@ -import { transformMarkdownAst, transformToBlockQuote } from './docs.mjs'; +import { buildShapeDoc, transformMarkdownAst, transformToBlockQuote } from './docs.mjs'; import { remark } from 'remark'; // import it this way so we can mock it import remarkFrontmatter from 'remark-frontmatter'; @@ -165,4 +165,59 @@ This Markdown should be kept. }); }); }); + + describe('buildShapeDoc', () => { + it('should build shapesTable based on the shapeDefs', () => { + expect(buildShapeDoc()).toMatchInlineSnapshot(` + "| **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** | + | --------------------------------- | ---------------------- | -------------- | ------------------------------ | ---------------------------------------------------------------- | + | Card | Notched Rectangle | \`notch-rect\` | Represents a card | \`card\`, \`notched-rectangle\` | + | Collate | Hourglass | \`hourglass\` | Represents a collate operation | \`collate\`, \`hourglass\` | + | Com Link | Lightning Bolt | \`bolt\` | Communication link | \`com-link\`, \`lightning-bolt\` | + | Comment | Curly Brace | \`brace\` | Adds a comment | \`brace-l\`, \`comment\` | + | Comment Right | Curly Brace | \`brace-r\` | Adds a comment | | + | Comment with braces on both sides | Curly Braces | \`braces\` | Adds a comment | | + | Data Input/Output | Lean Right | \`lean-r\` | Represents input or output | \`in-out\`, \`lean-right\` | + | Data Input/Output | Lean Left | \`lean-l\` | Represents output or input | \`lean-left\`, \`out-in\` | + | Database | Cylinder | \`cyl\` | Database storage | \`cylinder\`, \`database\`, \`db\` | + | Decision | Diamond | \`diam\` | Decision-making step | \`decision\`, \`diamond\`, \`question\` | + | Delay | Half-Rounded Rectangle | \`delay\` | Represents a delay | \`half-rounded-rectangle\` | + | Direct Access Storage | Horizontal Cylinder | \`h-cyl\` | Direct access storage | \`das\`, \`horizontal-cylinder\` | + | Disk Storage | Lined Cylinder | \`lin-cyl\` | Disk storage | \`disk\`, \`lined-cylinder\` | + | Display | Curved Trapezoid | \`curv-trap\` | Represents a display | \`curved-trapezoid\`, \`display\` | + | Divided Process | Divided Rectangle | \`div-rect\` | Divided process shape | \`div-proc\`, \`divided-process\`, \`divided-rectangle\` | + | Document | Document | \`doc\` | Represents a document | \`doc\`, \`document\` | + | Event | Rounded Rectangle | \`rounded\` | Represents an event | \`event\` | + | Extract | Triangle | \`tri\` | Extraction process | \`extract\`, \`triangle\` | + | Fork/Join | Filled Rectangle | \`fork\` | Fork or join in process flow | \`join\` | + | Internal Storage | Window Pane | \`win-pane\` | Internal storage | \`internal-storage\`, \`window-pane\` | + | Junction | Filled Circle | \`f-circ\` | Junction point | \`filled-circle\`, \`junction\` | + | Lined Document | Lined Document | \`lin-doc\` | Lined document | \`lined-document\` | + | Lined/Shaded Process | Lined Rectangle | \`lin-rect\` | Lined process shape | \`lin-proc\`, \`lined-process\`, \`lined-rectangle\`, \`shaded-process\` | + | Loop Limit | Trapezoidal Pentagon | \`notch-pent\` | Loop limit step | \`loop-limit\`, \`notched-pentagon\` | + | Manual File | Flipped Triangle | \`flip-tri\` | Manual file operation | \`flipped-triangle\`, \`manual-file\` | + | Manual Input | Sloped Rectangle | \`sl-rect\` | Manual input step | \`manual-input\`, \`sloped-rectangle\` | + | Manual Operation | Trapezoid Base Top | \`trap-t\` | Represents a manual task | \`inv-trapezoid\`, \`manual\`, \`trapezoid-top\` | + | Multi-Document | Stacked Document | \`docs\` | Multiple documents | \`documents\`, \`st-doc\`, \`stacked-document\` | + | Multi-Process | Stacked Rectangle | \`st-rect\` | Multiple processes | \`processes\`, \`procs\`, \`stacked-rectangle\` | + | Odd | Odd | \`odd\` | Odd shape | | + | Paper Tape | Flag | \`flag\` | Paper tape | \`paper-tape\` | + | Prepare Conditional | Hexagon | \`hex\` | Preparation or condition step | \`hexagon\`, \`prepare\` | + | Priority Action | Trapezoid Base Bottom | \`trap-b\` | Priority action | \`priority\`, \`trapezoid\`, \`trapezoid-bottom\` | + | Process | Rectangle | \`rect\` | Standard process shape | \`proc\`, \`process\`, \`rectangle\` | + | Start | Circle | \`circle\` | Starting point | \`circ\` | + | Start | Small Circle | \`sm-circ\` | Small starting point | \`small-circle\`, \`start\` | + | Stop | Double Circle | \`dbl-circ\` | Represents a stop point | \`double-circle\` | + | Stop | Framed Circle | \`fr-circ\` | Stop point | \`framed-circle\`, \`stop\` | + | Stored Data | Bow Tie Rectangle | \`bow-rect\` | Stored data | \`bow-tie-rectangle\`, \`stored-data\` | + | Subprocess | Framed Rectangle | \`fr-rect\` | Subprocess | \`framed-rectangle\`, \`subproc\`, \`subprocess\`, \`subroutine\` | + | Summary | Crossed Circle | \`cross-circ\` | Summary | \`crossed-circle\`, \`summary\` | + | Tagged Document | Tagged Document | \`tag-doc\` | Tagged document | \`tag-doc\`, \`tagged-document\` | + | Tagged Process | Tagged Rectangle | \`tag-rect\` | Tagged process | \`tag-proc\`, \`tagged-process\`, \`tagged-rectangle\` | + | Terminal Point | Stadium | \`stadium\` | Terminal point | \`pill\`, \`terminal\` | + | Text Block | Text Block | \`text\` | Text block | | + " + `); + }); + }); }); diff --git a/packages/mermaid/scripts/loadHook.mjs b/packages/mermaid/scripts/loadHook.mjs new file mode 100644 index 000000000..50129861b --- /dev/null +++ b/packages/mermaid/scripts/loadHook.mjs @@ -0,0 +1,22 @@ +import { fileURLToPath } from 'node:url'; +/** @import import { LoadHook } from "node:module"; */ +/** + * @type {LoadHook} + * + * Load hook that short circuits the loading of `.schema.yaml` files with `export default {}`. + * These would normally be loaded using ESBuild, but that doesn't work for these local scripts. + * + * @see https://nodejs.org/api/module.html#loadurl-context-nextload + */ +export const load = async (url, context, nextLoad) => { + const filePath = url.startsWith('file://') ? fileURLToPath(url) : url; + if (filePath.endsWith('.schema.yaml')) { + return { + format: 'module', + shortCircuit: true, + source: `export default {}`, + }; + } else { + return await nextLoad(url, context); + } +}; diff --git a/packages/mermaid/scripts/update-release-version.mts b/packages/mermaid/scripts/update-release-version.mts index a5943b37b..0459d3444 100644 --- a/packages/mermaid/scripts/update-release-version.mts +++ b/packages/mermaid/scripts/update-release-version.mts @@ -5,23 +5,34 @@ * So contributors adding new features will only have to add the placeholder and not worry about updating the version number. * */ +import { readFile, writeFile } from 'fs/promises'; import { posix } from 'path'; import { - getGlobs, getFilesFromGlobs, - SOURCE_DOCS_DIR, - readSyncedUTF8file, + getGlobs, MERMAID_RELEASE_VERSION, + readSyncedUTF8file, + SOURCE_DOCS_DIR, } from './docs.mjs'; -import { writeFile } from 'fs/promises'; const verifyOnly: boolean = process.argv.includes('--verify'); const versionPlaceholder = ''; +const verifyDocumentation = async () => { + const fileContent = await readFile('./src/docs/community/contributing.md', 'utf-8'); + if (!fileContent.includes(versionPlaceholder)) { + console.error( + `The placeholder ${versionPlaceholder} is not present in the contributing.md file.` + ); + process.exit(1); + } +}; + const main = async () => { + await verifyDocumentation(); const sourceDirGlob = posix.join('.', SOURCE_DOCS_DIR, '**'); const mdFileGlobs = getGlobs([posix.join(sourceDirGlob, '*.md')]); - mdFileGlobs.push('!**/community/development.md', '!**/community/code.md'); + mdFileGlobs.push('!**/community/contributing.md'); const mdFiles = await getFilesFromGlobs(mdFileGlobs); mdFiles.sort(); const mdFilesWithPlaceholder: string[] = []; diff --git a/packages/mermaid/src/Diagram.ts b/packages/mermaid/src/Diagram.ts index 86e7bf159..fb423b9b0 100644 --- a/packages/mermaid/src/Diagram.ts +++ b/packages/mermaid/src/Diagram.ts @@ -6,6 +6,7 @@ import { encodeEntities } from './utils.js'; import type { DetailedError } from './utils.js'; import type { DiagramDefinition, DiagramMetadata } from './diagram-api/types.js'; +// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?: any) => void; /** @@ -19,7 +20,7 @@ export class Diagram { text = encodeEntities(text) + '\n'; try { getDiagram(type); - } catch (e) { + } catch { const loader = getDiagramLoader(type); if (!loader) { throw new UnknownDiagramError(`Diagram ${type} not found.`); diff --git a/packages/mermaid/src/accessibility.spec.ts b/packages/mermaid/src/accessibility.spec.ts index 7745e02ef..f5998c475 100644 --- a/packages/mermaid/src/accessibility.spec.ts +++ b/packages/mermaid/src/accessibility.spec.ts @@ -1,6 +1,6 @@ import { MockedD3 } from './tests/MockedD3.js'; import { setA11yDiagramInfo, addSVGa11yTitleDescription } from './accessibility.js'; -import type { D3Element } from './mermaidAPI.js'; +import type { D3Element } from './types.js'; describe('accessibility', () => { const fauxSvgNode: MockedD3 = new MockedD3(); @@ -109,7 +109,7 @@ describe('accessibility', () => { describe('with a11y description', () => { const a11yDesc = 'a11y description'; - it('shold set aria-labelledby to the title id inserted as a child', () => { + it('should set aria-labelledby to the title id inserted as a child', () => { expectAriaLabelledByItTitleId(fauxSvgNode, a11yTitle, a11yDesc, givenId); }); diff --git a/packages/mermaid/src/accessibility.ts b/packages/mermaid/src/accessibility.ts index 69e22b301..a094755ff 100644 --- a/packages/mermaid/src/accessibility.ts +++ b/packages/mermaid/src/accessibility.ts @@ -5,7 +5,7 @@ * @see https://www.w3.org/TR/wai-aria-1.1/ * @see https://www.w3.org/TR/svg-aam-1.0/ */ -import type { D3Element } from './mermaidAPI.js'; +import type { D3Element } from './types.js'; /** * SVG element role: diff --git a/packages/mermaid/src/config.spec.ts b/packages/mermaid/src/config.spec.ts index 8dd4ff33c..000be1282 100644 --- a/packages/mermaid/src/config.spec.ts +++ b/packages/mermaid/src/config.spec.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ import * as configApi from './config.js'; import type { MermaidConfig } from './config.type.js'; diff --git a/packages/mermaid/src/config.ts b/packages/mermaid/src/config.ts index 4168c24c4..9468a3e46 100644 --- a/packages/mermaid/src/config.ts +++ b/packages/mermaid/src/config.ts @@ -21,7 +21,7 @@ export const updateCurrentConfig = (siteCfg: MermaidConfig, _directives: Mermaid let sumOfDirectives: MermaidConfig = {}; for (const d of _directives) { sanitize(d); - // Apply the data from the directive where the the overrides the themeVariables + // Apply the data from the directive where the overrides the themeVariables sumOfDirectives = assignWithDepth(sumOfDirectives, d); } @@ -189,8 +189,11 @@ export const addDirective = (directive: MermaidConfig) => { sanitizeDirective(directive); // If the directive has a fontFamily, but no themeVariables, add the fontFamily to the themeVariables - if (directive.fontFamily && (!directive.themeVariables || !directive.themeVariables.fontFamily)) { - directive.themeVariables = { fontFamily: directive.fontFamily }; + if (directive.fontFamily && !directive.themeVariables?.fontFamily) { + directive.themeVariables = { + ...directive.themeVariables, + fontFamily: directive.fontFamily, + }; } directives.push(directive); @@ -227,7 +230,7 @@ const ConfigWarning = { } as const; type ConfigWarningStrings = keyof typeof ConfigWarning; -const issuedWarnings: { [key in ConfigWarningStrings]?: boolean } = {}; +const issuedWarnings: Partial> = {}; const issueWarning = (warning: ConfigWarningStrings) => { if (issuedWarnings[warning]) { return; diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 79f424315..cc2bdc432 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -5,10 +5,6 @@ * and run json-schema-to-typescript to regenerate this file. */ -/** - * Configuration options to pass to the `dompurify` library. - */ -export type DOMPurifyConfiguration = import('dompurify').Config; /** * JavaScript function that returns a `FontConfig`. * @@ -50,6 +46,10 @@ export type SankeyLinkColor = 'source' | 'target' | 'gradient'; * via the `definition` "SankeyNodeAlignment". */ export type SankeyNodeAlignment = 'left' | 'right' | 'center' | 'justify'; +/** + * Configuration options to pass to the `dompurify` library. + */ +export type DOMPurifyConfiguration = import('dompurify').Config; /** * The font size to use */ @@ -61,9 +61,24 @@ export interface MermaidConfig { * You may also use `themeCSS` to override this value. * */ - theme?: 'default' | 'forest' | 'dark' | 'neutral' | 'null'; + theme?: 'default' | 'base' | 'dark' | 'forest' | 'neutral' | 'null'; themeVariables?: any; themeCSS?: string; + /** + * Defines which main look to use for the diagram. + * + */ + look?: 'classic' | 'handDrawn'; + /** + * Defines the seed to be used when using handDrawn look. This is important for the automated tests as they will always find differences without the seed. The default value is 0 which gives a random seed. + * + */ + handDrawnSeed?: number; + /** + * Defines which layout algorithm to use for rendering the diagram. + * + */ + layout?: string; /** * The maximum allowed size of the users text diagram */ @@ -73,6 +88,28 @@ export interface MermaidConfig { * */ maxEdges?: number; + elk?: { + /** + * Elk specific option that allows edges to share path where it convenient. It can make for pretty diagrams but can also make it harder to read the diagram. + * + */ + mergeEdges?: boolean; + /** + * Elk specific option affecting how nodes are placed. + * + */ + nodePlacementStrategy?: 'SIMPLE' | 'NETWORK_SIMPLEX' | 'LINEAR_SEGMENTS' | 'BRANDES_KOEPF'; + /** + * This strategy decides how to find cycles in the graph and deciding which edges need adjustment to break loops. + * + */ + cycleBreakingStrategy?: + | 'GREEDY' + | 'DEPTH_FIRST' + | 'INTERACTIVE' + | 'MODEL_ORDER' + | 'GREEDY_MODEL_ORDER'; + }; darkMode?: boolean; htmlLabels?: boolean; /** @@ -104,10 +141,7 @@ export interface MermaidConfig { arrowMarkerAbsolute?: boolean; /** * This option controls which `currentConfig` keys are considered secure and - * can only be changed via call to `mermaidAPI.initialize`. - * Calls to `mermaidAPI.reinitialize` cannot make changes to the secure keys - * in the current `currentConfig`. - * + * can only be changed via call to `mermaid.initialize`. * This prevents malicious graph directives from overriding a site's default security. * */ @@ -120,6 +154,13 @@ export interface MermaidConfig { * */ legacyMathML?: boolean; + /** + * This option forces Mermaid to rely on KaTeX's own stylesheet for rendering MathML. Due to differences between OS + * fonts and browser's MathML implementation, this option is recommended if consistent rendering is important. + * If set to true, ignores legacyMathML. + * + */ + forceLegacyMathML?: boolean; /** * This option controls if the generated ids of nodes in the SVG are * generated randomly or based on a seed. @@ -150,12 +191,15 @@ export interface MermaidConfig { quadrantChart?: QuadrantChartConfig; xyChart?: XYChartConfig; requirement?: RequirementDiagramConfig; + architecture?: ArchitectureDiagramConfig; mindmap?: MindmapDiagramConfig; + kanban?: KanbanDiagramConfig; gitGraph?: GitGraphDiagramConfig; c4?: C4DiagramConfig; sankey?: SankeyDiagramConfig; packet?: PacketDiagramConfig; block?: BlockDiagramConfig; + radar?: RadarDiagramConfig; dompurifyConfig?: DOMPurifyConfiguration; wrap?: boolean; fontSize?: number; @@ -168,36 +212,89 @@ export interface MermaidConfig { suppressErrorRendering?: boolean; } /** - * The object containing configurations specific for packet diagrams. + * The object containing configurations specific for flowcharts * * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "PacketDiagramConfig". + * via the `definition` "FlowchartDiagramConfig". */ -export interface PacketDiagramConfig extends BaseDiagramConfig { +export interface FlowchartDiagramConfig extends BaseDiagramConfig { /** - * The height of each row in the packet diagram. + * Margin top for the text over the diagram */ - rowHeight?: number; + titleTopMargin?: number; /** - * The width of each bit in the packet diagram. + * Defines a top/bottom margin for subgraph titles + * */ - bitWidth?: number; + subGraphTitleMargin?: { + top?: number; + bottom?: number; + }; + arrowMarkerAbsolute?: boolean; /** - * The number of bits to display per row. + * The amount of padding around the diagram as a whole so that embedded + * diagrams have margins, expressed in pixels. + * */ - bitsPerRow?: number; + diagramPadding?: number; /** - * Toggle to display or hide bit numbers. + * Flag for setting whether or not a html tag should be used for rendering labels on the edges. + * */ - showBits?: boolean; + htmlLabels?: boolean; /** - * The horizontal padding between the blocks in a row. + * Defines the spacing between nodes on the same level + * + * Pertains to horizontal spacing for TB (top to bottom) or BT (bottom to top) graphs, + * and the vertical spacing for LR as well as RL graphs. + * */ - paddingX?: number; + nodeSpacing?: number; /** - * The vertical padding between the rows. + * Defines the spacing between nodes on different levels + * + * Pertains to horizontal spacing for TB (top to bottom) or BT (bottom to top) graphs, + * and the vertical spacing for LR as well as RL graphs. + * */ - paddingY?: number; + rankSpacing?: number; + /** + * Defines how mermaid renders curves for flowcharts. + * + */ + curve?: + | 'basis' + | 'bumpX' + | 'bumpY' + | 'cardinal' + | 'catmullRom' + | 'linear' + | 'monotoneX' + | 'monotoneY' + | 'natural' + | 'step' + | 'stepAfter' + | 'stepBefore'; + /** + * Represents the padding between the labels and the shape + * + * **Only used in new experimental rendering.** + * + */ + padding?: number; + /** + * Decides which rendering engine that is to be used for the rendering. + * + */ + defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk'; + /** + * Width of nodes where text is wrapped. + * + * When using markdown strings the text is wrapped automatically, this + * value sets the max width of a text before it continues on a new line. + * + */ + wrappingWidth?: number; } /** * This interface was referenced by `MermaidConfig`'s JSON-Schema @@ -214,13 +311,799 @@ export interface BaseDiagramConfig { useMaxWidth?: boolean; } /** - * The object containing configurations specific for block diagrams. + * The object containing configurations specific for sequence diagrams * * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "BlockDiagramConfig". + * via the `definition` "SequenceDiagramConfig". */ -export interface BlockDiagramConfig extends BaseDiagramConfig { +export interface SequenceDiagramConfig extends BaseDiagramConfig { + arrowMarkerAbsolute?: boolean; + hideUnusedParticipants?: boolean; + /** + * Width of the activation rect + */ + activationWidth?: number; + /** + * Margin to the right and left of the sequence diagram + */ + diagramMarginX?: number; + /** + * Margin to the over and under the sequence diagram + */ + diagramMarginY?: number; + /** + * Margin between actors + */ + actorMargin?: number; + /** + * Width of actor boxes + */ + width?: number; + /** + * Height of actor boxes + */ + height?: number; + /** + * Margin around loop boxes + */ + boxMargin?: number; + /** + * Margin around the text in loop/alt/opt boxes + */ + boxTextMargin?: number; + /** + * Margin around notes + */ + noteMargin?: number; + /** + * Space between messages. + */ + messageMargin?: number; + /** + * Multiline message alignment + */ + messageAlign?: 'left' | 'center' | 'right'; + /** + * Mirror actors under diagram + * + */ + mirrorActors?: boolean; + /** + * forces actor popup menus to always be visible (to support E2E testing). + * + */ + forceMenus?: boolean; + /** + * Prolongs the edge of the diagram downwards. + * + * Depending on css styling this might need adjustment. + * + */ + bottomMarginAdj?: number; + /** + * Curved Arrows become Right Angles + * + * This will display arrows that start and begin at the same node as + * right angles, rather than as curves. + * + */ + rightAngles?: boolean; + /** + * This will show the node numbers + */ + showSequenceNumbers?: boolean; + /** + * This sets the font size of the actor's description + */ + actorFontSize?: string | number; + /** + * This sets the font family of the actor's description + */ + actorFontFamily?: string; + /** + * This sets the font weight of the actor's description + */ + actorFontWeight?: string | number; + /** + * This sets the font size of actor-attached notes + */ + noteFontSize?: string | number; + /** + * This sets the font family of actor-attached notes + */ + noteFontFamily?: string; + /** + * This sets the font weight of actor-attached notes + */ + noteFontWeight?: string | number; + /** + * This sets the text alignment of actor-attached notes + */ + noteAlign?: 'left' | 'center' | 'right'; + /** + * This sets the font size of actor messages + */ + messageFontSize?: string | number; + /** + * This sets the font family of actor messages + */ + messageFontFamily?: string; + /** + * This sets the font weight of actor messages + */ + messageFontWeight?: string | number; + /** + * This sets the auto-wrap state for the diagram + */ + wrap?: boolean; + /** + * This sets the auto-wrap padding for the diagram (sides only) + */ + wrapPadding?: number; + /** + * This sets the width of the loop-box (loop, alt, opt, par) + */ + labelBoxWidth?: number; + /** + * This sets the height of the loop-box (loop, alt, opt, par) + */ + labelBoxHeight?: number; + messageFont?: FontCalculator; + noteFont?: FontCalculator; + actorFont?: FontCalculator; +} +/** + * The object containing configurations specific for gantt diagrams + * + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "GanttDiagramConfig". + */ +export interface GanttDiagramConfig extends BaseDiagramConfig { + /** + * Margin top for the text over the diagram + */ + titleTopMargin?: number; + /** + * The height of the bars in the graph + */ + barHeight?: number; + /** + * The margin between the different activities in the gantt diagram + */ + barGap?: number; + /** + * Margin between title and gantt diagram and between axis and gantt diagram. + * + */ + topPadding?: number; + /** + * The space allocated for the section name to the right of the activities + * + */ + rightPadding?: number; + /** + * The space allocated for the section name to the left of the activities + * + */ + leftPadding?: number; + /** + * Vertical starting position of the grid lines + */ + gridLineStartPadding?: number; + /** + * Font size + */ + fontSize?: number; + /** + * Font size for sections + */ + sectionFontSize?: string | number; + /** + * The number of alternating section styles + */ + numberSectionStyles?: number; + /** + * Date/time format of the axis + * + * This might need adjustment to match your locale and preferences. + * + */ + axisFormat?: string; + /** + * axis ticks + * + * Pattern is: + * + * ```javascript + * /^([1-9][0-9]*)(millisecond|second|minute|hour|day|week|month)$/ + * ``` + * + */ + tickInterval?: string; + /** + * When this flag is set, date labels will be added to the top of the chart + * + */ + topAxis?: boolean; + /** + * Controls the display mode. + * + */ + displayMode?: '' | 'compact'; + /** + * On which day a week-based interval should start + * + */ + weekday?: 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday'; +} +/** + * The object containing configurations specific for journey diagrams + * + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "JourneyDiagramConfig". + */ +export interface JourneyDiagramConfig extends BaseDiagramConfig { + /** + * Margin to the right and left of the c4 diagram, must be a positive value. + * + */ + diagramMarginX?: number; + /** + * Margin to the over and under the c4 diagram, must be a positive value. + * + */ + diagramMarginY?: number; + /** + * Margin between actors + */ + leftMargin?: number; + /** + * Maximum width of actor labels + */ + maxLabelWidth?: number; + /** + * Width of actor boxes + */ + width?: number; + /** + * Height of actor boxes + */ + height?: number; + /** + * Margin around loop boxes + */ + boxMargin?: number; + /** + * Margin around the text in loop/alt/opt boxes + */ + boxTextMargin?: number; + /** + * Margin around notes + */ + noteMargin?: number; + /** + * Space between messages. + */ + messageMargin?: number; + /** + * Multiline message alignment + */ + messageAlign?: 'left' | 'center' | 'right'; + /** + * Prolongs the edge of the diagram downwards. + * + * Depending on css styling this might need adjustment. + * + */ + bottomMarginAdj?: number; + /** + * Curved Arrows become Right Angles + * + * This will display arrows that start and begin at the same node as + * right angles, rather than as curves. + * + */ + rightAngles?: boolean; + taskFontSize?: string | number; + taskFontFamily?: string; + taskMargin?: number; + /** + * Width of activation box + */ + activationWidth?: number; + /** + * text placement as: tspan | fo | old only text as before + * + */ + textPlacement?: string; + actorColours?: string[]; + sectionFills?: string[]; + sectionColours?: string[]; + /** + * Color of the title text in Journey Diagrams + */ + titleColor?: string; + /** + * Font family to be used for the title text in Journey Diagrams + */ + titleFontFamily?: string; + /** + * Font size to be used for the title text in Journey Diagrams + */ + titleFontSize?: string; +} +/** + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "TimelineDiagramConfig". + */ +export interface TimelineDiagramConfig extends BaseDiagramConfig { + /** + * Margin to the right and left of the c4 diagram, must be a positive value. + * + */ + diagramMarginX?: number; + /** + * Margin to the over and under the c4 diagram, must be a positive value. + * + */ + diagramMarginY?: number; + /** + * Margin between actors + */ + leftMargin?: number; + /** + * Width of actor boxes + */ + width?: number; + /** + * Height of actor boxes + */ + height?: number; padding?: number; + /** + * Margin around loop boxes + */ + boxMargin?: number; + /** + * Margin around the text in loop/alt/opt boxes + */ + boxTextMargin?: number; + /** + * Margin around notes + */ + noteMargin?: number; + /** + * Space between messages. + */ + messageMargin?: number; + /** + * Multiline message alignment + */ + messageAlign?: 'left' | 'center' | 'right'; + /** + * Prolongs the edge of the diagram downwards. + * + * Depending on css styling this might need adjustment. + * + */ + bottomMarginAdj?: number; + /** + * Curved Arrows become Right Angles + * + * This will display arrows that start and begin at the same node as + * right angles, rather than as curves. + * + */ + rightAngles?: boolean; + taskFontSize?: string | number; + taskFontFamily?: string; + taskMargin?: number; + /** + * Width of activation box + */ + activationWidth?: number; + /** + * text placement as: tspan | fo | old only text as before + * + */ + textPlacement?: string; + actorColours?: string[]; + sectionFills?: string[]; + sectionColours?: string[]; + disableMulticolor?: boolean; +} +/** + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "ClassDiagramConfig". + */ +export interface ClassDiagramConfig extends BaseDiagramConfig { + /** + * Margin top for the text over the diagram + */ + titleTopMargin?: number; + /** + * Controls whether or arrow markers in html code are absolute paths or anchors. + * This matters if you are using base tag settings. + * + */ + arrowMarkerAbsolute?: boolean; + dividerMargin?: number; + padding?: number; + textHeight?: number; + /** + * Decides which rendering engine that is to be used for the rendering. + * + */ + defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk'; + nodeSpacing?: number; + rankSpacing?: number; + /** + * The amount of padding around the diagram as a whole so that embedded + * diagrams have margins, expressed in pixels. + * + */ + diagramPadding?: number; + htmlLabels?: boolean; + hideEmptyMembersBox?: boolean; +} +/** + * The object containing configurations specific for entity relationship diagrams + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "StateDiagramConfig". + */ +export interface StateDiagramConfig extends BaseDiagramConfig { + /** + * Margin top for the text over the diagram + */ + titleTopMargin?: number; + arrowMarkerAbsolute?: boolean; + dividerMargin?: number; + sizeUnit?: number; + padding?: number; + textHeight?: number; + titleShift?: number; + noteMargin?: number; + nodeSpacing?: number; + rankSpacing?: number; + forkWidth?: number; + forkHeight?: number; + miniPadding?: number; + /** + * Font size factor, this is used to guess the width of the edges labels + * before rendering by dagre layout. + * This might need updating if/when switching font + * + */ + fontSizeFactor?: number; + fontSize?: number; + labelHeight?: number; + edgeLengthFactor?: string; + compositTitleSize?: number; + radius?: number; + /** + * Decides which rendering engine that is to be used for the rendering. + * + */ + defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk'; +} +/** + * The object containing configurations specific for entity relationship diagrams + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "ErDiagramConfig". + */ +export interface ErDiagramConfig extends BaseDiagramConfig { + /** + * Margin top for the text over the diagram + */ + titleTopMargin?: number; + /** + * The amount of padding around the diagram as a whole so that embedded + * diagrams have margins, expressed in pixels. + * + */ + diagramPadding?: number; + /** + * Directional bias for layout of entities + */ + layoutDirection?: 'TB' | 'BT' | 'LR' | 'RL'; + /** + * The minimum width of an entity box. Expressed in pixels. + */ + minEntityWidth?: number; + /** + * The minimum height of an entity box. Expressed in pixels. + */ + minEntityHeight?: number; + /** + * The minimum internal padding between text in an entity box and the enclosing box borders. + * Expressed in pixels. + * + */ + entityPadding?: number; + nodeSpacing?: number; + rankSpacing?: number; + /** + * Stroke color of box edges and lines. + */ + stroke?: string; + /** + * Fill color of entity boxes + */ + fill?: string; + /** + * Font size (expressed as an integer representing a number of pixels) + */ + fontSize?: number; +} +/** + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "PieDiagramConfig". + */ +export interface PieDiagramConfig extends BaseDiagramConfig { + /** + * Axial position of slice's label from zero at the center to 1 at the outside edges. + * + */ + textPosition?: number; +} +/** + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "QuadrantChartConfig". + */ +export interface QuadrantChartConfig extends BaseDiagramConfig { + /** + * Width of the chart + */ + chartWidth?: number; + /** + * Height of the chart + */ + chartHeight?: number; + /** + * Chart title top and bottom padding + */ + titleFontSize?: number; + /** + * Padding around the quadrant square + */ + titlePadding?: number; + /** + * quadrant title padding from top if the quadrant is rendered on top + */ + quadrantPadding?: number; + /** + * Padding around x-axis labels + */ + xAxisLabelPadding?: number; + /** + * Padding around y-axis labels + */ + yAxisLabelPadding?: number; + /** + * x-axis label font size + */ + xAxisLabelFontSize?: number; + /** + * y-axis label font size + */ + yAxisLabelFontSize?: number; + /** + * quadrant title font size + */ + quadrantLabelFontSize?: number; + /** + * quadrant title padding from top if the quadrant is rendered on top + */ + quadrantTextTopPadding?: number; + /** + * padding between point and point label + */ + pointTextPadding?: number; + /** + * point title font size + */ + pointLabelFontSize?: number; + /** + * radius of the point to be drawn + */ + pointRadius?: number; + /** + * position of x-axis labels + */ + xAxisPosition?: 'top' | 'bottom'; + /** + * position of y-axis labels + */ + yAxisPosition?: 'left' | 'right'; + /** + * stroke width of edges of the box that are inside the quadrant + */ + quadrantInternalBorderStrokeWidth?: number; + /** + * stroke width of edges of the box that are outside the quadrant + */ + quadrantExternalBorderStrokeWidth?: number; +} +/** + * This object contains configuration specific to XYCharts + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "XYChartConfig". + */ +export interface XYChartConfig extends BaseDiagramConfig { + /** + * width of the chart + */ + width?: number; + /** + * height of the chart + */ + height?: number; + /** + * Font size of the chart title + */ + titleFontSize?: number; + /** + * Top and bottom space from the chart title + */ + titlePadding?: number; + /** + * Should show the value corresponding to the bar within the bar + */ + showDataLabel?: boolean; + /** + * Should show the chart title + */ + showTitle?: boolean; + xAxis?: XYChartAxisConfig; + yAxis?: XYChartAxisConfig; + /** + * How to plot will be drawn horizontal or vertical + */ + chartOrientation?: 'vertical' | 'horizontal'; + /** + * Minimum percent of space plots of the chart will take + */ + plotReservedSpacePercent?: number; +} +/** + * This object contains configuration for XYChart axis config + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "XYChartAxisConfig". + */ +export interface XYChartAxisConfig { + /** + * Should show the axis labels (tick text) + */ + showLabel?: boolean; + /** + * font size of the axis labels (tick text) + */ + labelFontSize?: number; + /** + * top and bottom space from axis label (tick text) + */ + labelPadding?: number; + /** + * Should show the axis title + */ + showTitle?: boolean; + /** + * font size of the axis title + */ + titleFontSize?: number; + /** + * top and bottom space from axis title + */ + titlePadding?: number; + /** + * Should show the axis tick lines + */ + showTick?: boolean; + /** + * length of the axis tick lines + */ + tickLength?: number; + /** + * width of the axis tick lines + */ + tickWidth?: number; + /** + * Show line across the axis + */ + showAxisLine?: boolean; + /** + * Width of the axis line + */ + axisLineWidth?: number; +} +/** + * The object containing configurations specific for req diagrams + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "RequirementDiagramConfig". + */ +export interface RequirementDiagramConfig extends BaseDiagramConfig { + rect_fill?: string; + text_color?: string; + rect_border_size?: string; + rect_border_color?: string; + rect_min_width?: number; + rect_min_height?: number; + fontSize?: number; + rect_padding?: number; + line_height?: number; +} +/** + * The object containing configurations specific for architecture diagrams + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "ArchitectureDiagramConfig". + */ +export interface ArchitectureDiagramConfig extends BaseDiagramConfig { + padding?: number; + iconSize?: number; + fontSize?: number; +} +/** + * The object containing configurations specific for mindmap diagrams + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "MindmapDiagramConfig". + */ +export interface MindmapDiagramConfig extends BaseDiagramConfig { + padding?: number; + maxNodeWidth?: number; +} +/** + * The object containing configurations specific for kanban diagrams + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "KanbanDiagramConfig". + */ +export interface KanbanDiagramConfig extends BaseDiagramConfig { + padding?: number; + sectionWidth?: number; + ticketBaseUrl?: string; +} +/** + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "GitGraphDiagramConfig". + */ +export interface GitGraphDiagramConfig extends BaseDiagramConfig { + /** + * Margin top for the text over the diagram + */ + titleTopMargin?: number; + diagramPadding?: number; + nodeLabel?: NodeLabel; + mainBranchName?: string; + mainBranchOrder?: number; + showCommitLabel?: boolean; + showBranches?: boolean; + rotateCommitLabel?: boolean; + parallelCommits?: boolean; + /** + * Controls whether or arrow markers in html code are absolute paths or anchors. + * This matters if you are using base tag settings. + * + */ + arrowMarkerAbsolute?: boolean; +} +/** + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "NodeLabel". + */ +export interface NodeLabel { + width?: number; + height?: number; + x?: number; + y?: number; } /** * The object containing configurations specific for c4 diagrams @@ -603,827 +1486,6 @@ export interface C4DiagramConfig extends BaseDiagramConfig { boundaryFont?: FontCalculator; messageFont?: FontCalculator; } -/** - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "GitGraphDiagramConfig". - */ -export interface GitGraphDiagramConfig extends BaseDiagramConfig { - /** - * Margin top for the text over the diagram - */ - titleTopMargin?: number; - diagramPadding?: number; - nodeLabel?: NodeLabel; - mainBranchName?: string; - mainBranchOrder?: number; - showCommitLabel?: boolean; - showBranches?: boolean; - rotateCommitLabel?: boolean; - parallelCommits?: boolean; - /** - * Controls whether or arrow markers in html code are absolute paths or anchors. - * This matters if you are using base tag settings. - * - */ - arrowMarkerAbsolute?: boolean; -} -/** - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "NodeLabel". - */ -export interface NodeLabel { - width?: number; - height?: number; - x?: number; - y?: number; -} -/** - * The object containing configurations specific for req diagrams - * - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "RequirementDiagramConfig". - */ -export interface RequirementDiagramConfig extends BaseDiagramConfig { - rect_fill?: string; - text_color?: string; - rect_border_size?: string; - rect_border_color?: string; - rect_min_width?: number; - rect_min_height?: number; - fontSize?: number; - rect_padding?: number; - line_height?: number; -} -/** - * The object containing configurations specific for mindmap diagrams - * - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "MindmapDiagramConfig". - */ -export interface MindmapDiagramConfig extends BaseDiagramConfig { - padding?: number; - maxNodeWidth?: number; -} -/** - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "PieDiagramConfig". - */ -export interface PieDiagramConfig extends BaseDiagramConfig { - /** - * Axial position of slice's label from zero at the center to 1 at the outside edges. - * - */ - textPosition?: number; -} -/** - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "QuadrantChartConfig". - */ -export interface QuadrantChartConfig extends BaseDiagramConfig { - /** - * Width of the chart - */ - chartWidth?: number; - /** - * Height of the chart - */ - chartHeight?: number; - /** - * Chart title top and bottom padding - */ - titleFontSize?: number; - /** - * Padding around the quadrant square - */ - titlePadding?: number; - /** - * quadrant title padding from top if the quadrant is rendered on top - */ - quadrantPadding?: number; - /** - * Padding around x-axis labels - */ - xAxisLabelPadding?: number; - /** - * Padding around y-axis labels - */ - yAxisLabelPadding?: number; - /** - * x-axis label font size - */ - xAxisLabelFontSize?: number; - /** - * y-axis label font size - */ - yAxisLabelFontSize?: number; - /** - * quadrant title font size - */ - quadrantLabelFontSize?: number; - /** - * quadrant title padding from top if the quadrant is rendered on top - */ - quadrantTextTopPadding?: number; - /** - * padding between point and point label - */ - pointTextPadding?: number; - /** - * point title font size - */ - pointLabelFontSize?: number; - /** - * radius of the point to be drawn - */ - pointRadius?: number; - /** - * position of x-axis labels - */ - xAxisPosition?: 'top' | 'bottom'; - /** - * position of y-axis labels - */ - yAxisPosition?: 'left' | 'right'; - /** - * stroke width of edges of the box that are inside the quadrant - */ - quadrantInternalBorderStrokeWidth?: number; - /** - * stroke width of edges of the box that are outside the quadrant - */ - quadrantExternalBorderStrokeWidth?: number; -} -/** - * This object contains configuration for XYChart axis config - * - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "XYChartAxisConfig". - */ -export interface XYChartAxisConfig { - /** - * Should show the axis labels (tick text) - */ - showLabel?: boolean; - /** - * font size of the axis labels (tick text) - */ - labelFontSize?: number; - /** - * top and bottom space from axis label (tick text) - */ - labelPadding?: number; - /** - * Should show the axis title - */ - showTitle?: boolean; - /** - * font size of the axis title - */ - titleFontSize?: number; - /** - * top and bottom space from axis title - */ - titlePadding?: number; - /** - * Should show the axis tick lines - */ - showTick?: boolean; - /** - * length of the axis tick lines - */ - tickLength?: number; - /** - * width of the axis tick lines - */ - tickWidth?: number; - /** - * Show line across the axis - */ - showAxisLine?: boolean; - /** - * Width of the axis line - */ - axisLineWidth?: number; -} -/** - * This object contains configuration specific to XYCharts - * - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "XYChartConfig". - */ -export interface XYChartConfig extends BaseDiagramConfig { - /** - * width of the chart - */ - width?: number; - /** - * height of the chart - */ - height?: number; - /** - * Font size of the chart title - */ - titleFontSize?: number; - /** - * Top and bottom space from the chart title - */ - titlePadding?: number; - /** - * Should show the chart title - */ - showTitle?: boolean; - xAxis?: XYChartAxisConfig; - yAxis?: XYChartAxisConfig; - /** - * How to plot will be drawn horizontal or vertical - */ - chartOrientation?: 'vertical' | 'horizontal'; - /** - * Minimum percent of space plots of the chart will take - */ - plotReservedSpacePercent?: number; -} -/** - * The object containing configurations specific for entity relationship diagrams - * - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "ErDiagramConfig". - */ -export interface ErDiagramConfig extends BaseDiagramConfig { - /** - * Margin top for the text over the diagram - */ - titleTopMargin?: number; - /** - * The amount of padding around the diagram as a whole so that embedded - * diagrams have margins, expressed in pixels. - * - */ - diagramPadding?: number; - /** - * Directional bias for layout of entities - */ - layoutDirection?: 'TB' | 'BT' | 'LR' | 'RL'; - /** - * The minimum width of an entity box. Expressed in pixels. - */ - minEntityWidth?: number; - /** - * The minimum height of an entity box. Expressed in pixels. - */ - minEntityHeight?: number; - /** - * The minimum internal padding between text in an entity box and the enclosing box borders. - * Expressed in pixels. - * - */ - entityPadding?: number; - /** - * Stroke color of box edges and lines. - */ - stroke?: string; - /** - * Fill color of entity boxes - */ - fill?: string; - /** - * Font size (expressed as an integer representing a number of pixels) - */ - fontSize?: number; -} -/** - * The object containing configurations specific for entity relationship diagrams - * - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "StateDiagramConfig". - */ -export interface StateDiagramConfig extends BaseDiagramConfig { - /** - * Margin top for the text over the diagram - */ - titleTopMargin?: number; - arrowMarkerAbsolute?: boolean; - dividerMargin?: number; - sizeUnit?: number; - padding?: number; - textHeight?: number; - titleShift?: number; - noteMargin?: number; - forkWidth?: number; - forkHeight?: number; - miniPadding?: number; - /** - * Font size factor, this is used to guess the width of the edges labels - * before rendering by dagre layout. - * This might need updating if/when switching font - * - */ - fontSizeFactor?: number; - fontSize?: number; - labelHeight?: number; - edgeLengthFactor?: string; - compositTitleSize?: number; - radius?: number; - /** - * Decides which rendering engine that is to be used for the rendering. - * - */ - defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk'; -} -/** - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "ClassDiagramConfig". - */ -export interface ClassDiagramConfig extends BaseDiagramConfig { - /** - * Margin top for the text over the diagram - */ - titleTopMargin?: number; - /** - * Controls whether or arrow markers in html code are absolute paths or anchors. - * This matters if you are using base tag settings. - * - */ - arrowMarkerAbsolute?: boolean; - dividerMargin?: number; - padding?: number; - textHeight?: number; - /** - * Decides which rendering engine that is to be used for the rendering. - * - */ - defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk'; - nodeSpacing?: number; - rankSpacing?: number; - /** - * The amount of padding around the diagram as a whole so that embedded - * diagrams have margins, expressed in pixels. - * - */ - diagramPadding?: number; - htmlLabels?: boolean; -} -/** - * The object containing configurations specific for journey diagrams - * - * - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "JourneyDiagramConfig". - */ -export interface JourneyDiagramConfig extends BaseDiagramConfig { - /** - * Margin to the right and left of the c4 diagram, must be a positive value. - * - */ - diagramMarginX?: number; - /** - * Margin to the over and under the c4 diagram, must be a positive value. - * - */ - diagramMarginY?: number; - /** - * Margin between actors - */ - leftMargin?: number; - /** - * Width of actor boxes - */ - width?: number; - /** - * Height of actor boxes - */ - height?: number; - /** - * Margin around loop boxes - */ - boxMargin?: number; - /** - * Margin around the text in loop/alt/opt boxes - */ - boxTextMargin?: number; - /** - * Margin around notes - */ - noteMargin?: number; - /** - * Space between messages. - */ - messageMargin?: number; - /** - * Multiline message alignment - */ - messageAlign?: 'left' | 'center' | 'right'; - /** - * Prolongs the edge of the diagram downwards. - * - * Depending on css styling this might need adjustment. - * - */ - bottomMarginAdj?: number; - /** - * Curved Arrows become Right Angles - * - * This will display arrows that start and begin at the same node as - * right angles, rather than as curves. - * - */ - rightAngles?: boolean; - taskFontSize?: string | number; - taskFontFamily?: string; - taskMargin?: number; - /** - * Width of activation box - */ - activationWidth?: number; - /** - * text placement as: tspan | fo | old only text as before - * - */ - textPlacement?: string; - actorColours?: string[]; - sectionFills?: string[]; - sectionColours?: string[]; -} -/** - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "TimelineDiagramConfig". - */ -export interface TimelineDiagramConfig extends BaseDiagramConfig { - /** - * Margin to the right and left of the c4 diagram, must be a positive value. - * - */ - diagramMarginX?: number; - /** - * Margin to the over and under the c4 diagram, must be a positive value. - * - */ - diagramMarginY?: number; - /** - * Margin between actors - */ - leftMargin?: number; - /** - * Width of actor boxes - */ - width?: number; - /** - * Height of actor boxes - */ - height?: number; - padding?: number; - /** - * Margin around loop boxes - */ - boxMargin?: number; - /** - * Margin around the text in loop/alt/opt boxes - */ - boxTextMargin?: number; - /** - * Margin around notes - */ - noteMargin?: number; - /** - * Space between messages. - */ - messageMargin?: number; - /** - * Multiline message alignment - */ - messageAlign?: 'left' | 'center' | 'right'; - /** - * Prolongs the edge of the diagram downwards. - * - * Depending on css styling this might need adjustment. - * - */ - bottomMarginAdj?: number; - /** - * Curved Arrows become Right Angles - * - * This will display arrows that start and begin at the same node as - * right angles, rather than as curves. - * - */ - rightAngles?: boolean; - taskFontSize?: string | number; - taskFontFamily?: string; - taskMargin?: number; - /** - * Width of activation box - */ - activationWidth?: number; - /** - * text placement as: tspan | fo | old only text as before - * - */ - textPlacement?: string; - actorColours?: string[]; - sectionFills?: string[]; - sectionColours?: string[]; - disableMulticolor?: boolean; -} -/** - * The object containing configurations specific for gantt diagrams - * - * - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "GanttDiagramConfig". - */ -export interface GanttDiagramConfig extends BaseDiagramConfig { - /** - * Margin top for the text over the diagram - */ - titleTopMargin?: number; - /** - * The height of the bars in the graph - */ - barHeight?: number; - /** - * The margin between the different activities in the gantt diagram - */ - barGap?: number; - /** - * Margin between title and gantt diagram and between axis and gantt diagram. - * - */ - topPadding?: number; - /** - * The space allocated for the section name to the right of the activities - * - */ - rightPadding?: number; - /** - * The space allocated for the section name to the left of the activities - * - */ - leftPadding?: number; - /** - * Vertical starting position of the grid lines - */ - gridLineStartPadding?: number; - /** - * Font size - */ - fontSize?: number; - /** - * Font size for sections - */ - sectionFontSize?: string | number; - /** - * The number of alternating section styles - */ - numberSectionStyles?: number; - /** - * Date/time format of the axis - * - * This might need adjustment to match your locale and preferences. - * - */ - axisFormat?: string; - /** - * axis ticks - * - * Pattern is: - * - * ```javascript - * /^([1-9][0-9]*)(millisecond|second|minute|hour|day|week|month)$/ - * ``` - * - */ - tickInterval?: string; - /** - * When this flag is set, date labels will be added to the top of the chart - * - */ - topAxis?: boolean; - /** - * Controls the display mode. - * - */ - displayMode?: '' | 'compact'; - /** - * On which day a week-based interval should start - * - */ - weekday?: 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday'; -} -/** - * The object containing configurations specific for sequence diagrams - * - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "SequenceDiagramConfig". - */ -export interface SequenceDiagramConfig extends BaseDiagramConfig { - arrowMarkerAbsolute?: boolean; - hideUnusedParticipants?: boolean; - /** - * Width of the activation rect - */ - activationWidth?: number; - /** - * Margin to the right and left of the sequence diagram - */ - diagramMarginX?: number; - /** - * Margin to the over and under the sequence diagram - */ - diagramMarginY?: number; - /** - * Margin between actors - */ - actorMargin?: number; - /** - * Width of actor boxes - */ - width?: number; - /** - * Height of actor boxes - */ - height?: number; - /** - * Margin around loop boxes - */ - boxMargin?: number; - /** - * Margin around the text in loop/alt/opt boxes - */ - boxTextMargin?: number; - /** - * Margin around notes - */ - noteMargin?: number; - /** - * Space between messages. - */ - messageMargin?: number; - /** - * Multiline message alignment - */ - messageAlign?: 'left' | 'center' | 'right'; - /** - * Mirror actors under diagram - * - */ - mirrorActors?: boolean; - /** - * forces actor popup menus to always be visible (to support E2E testing). - * - */ - forceMenus?: boolean; - /** - * Prolongs the edge of the diagram downwards. - * - * Depending on css styling this might need adjustment. - * - */ - bottomMarginAdj?: number; - /** - * Curved Arrows become Right Angles - * - * This will display arrows that start and begin at the same node as - * right angles, rather than as curves. - * - */ - rightAngles?: boolean; - /** - * This will show the node numbers - */ - showSequenceNumbers?: boolean; - /** - * This sets the font size of the actor's description - */ - actorFontSize?: string | number; - /** - * This sets the font family of the actor's description - */ - actorFontFamily?: string; - /** - * This sets the font weight of the actor's description - */ - actorFontWeight?: string | number; - /** - * This sets the font size of actor-attached notes - */ - noteFontSize?: string | number; - /** - * This sets the font family of actor-attached notes - */ - noteFontFamily?: string; - /** - * This sets the font weight of actor-attached notes - */ - noteFontWeight?: string | number; - /** - * This sets the text alignment of actor-attached notes - */ - noteAlign?: 'left' | 'center' | 'right'; - /** - * This sets the font size of actor messages - */ - messageFontSize?: string | number; - /** - * This sets the font family of actor messages - */ - messageFontFamily?: string; - /** - * This sets the font weight of actor messages - */ - messageFontWeight?: string | number; - /** - * This sets the auto-wrap state for the diagram - */ - wrap?: boolean; - /** - * This sets the auto-wrap padding for the diagram (sides only) - */ - wrapPadding?: number; - /** - * This sets the width of the loop-box (loop, alt, opt, par) - */ - labelBoxWidth?: number; - /** - * This sets the height of the loop-box (loop, alt, opt, par) - */ - labelBoxHeight?: number; - messageFont?: FontCalculator; - noteFont?: FontCalculator; - actorFont?: FontCalculator; -} -/** - * The object containing configurations specific for flowcharts - * - * This interface was referenced by `MermaidConfig`'s JSON-Schema - * via the `definition` "FlowchartDiagramConfig". - */ -export interface FlowchartDiagramConfig extends BaseDiagramConfig { - /** - * Margin top for the text over the diagram - */ - titleTopMargin?: number; - /** - * Defines a top/bottom margin for subgraph titles - * - */ - subGraphTitleMargin?: { - top?: number; - bottom?: number; - }; - arrowMarkerAbsolute?: boolean; - /** - * The amount of padding around the diagram as a whole so that embedded - * diagrams have margins, expressed in pixels. - * - */ - diagramPadding?: number; - /** - * Flag for setting whether or not a html tag should be used for rendering labels on the edges. - * - */ - htmlLabels?: boolean; - /** - * Defines the spacing between nodes on the same level - * - * Pertains to horizontal spacing for TB (top to bottom) or BT (bottom to top) graphs, - * and the vertical spacing for LR as well as RL graphs. - * - */ - nodeSpacing?: number; - /** - * Defines the spacing between nodes on different levels - * - * Pertains to horizontal spacing for TB (top to bottom) or BT (bottom to top) graphs, - * and the vertical spacing for LR as well as RL graphs. - * - */ - rankSpacing?: number; - /** - * Defines how mermaid renders curves for flowcharts. - * - */ - curve?: 'basis' | 'linear' | 'cardinal'; - /** - * Represents the padding between the labels and the shape - * - * **Only used in new experimental rendering.** - * - */ - padding?: number; - /** - * Decides which rendering engine that is to be used for the rendering. - * - */ - defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk'; - /** - * Width of nodes where text is wrapped. - * - * When using markdown strings the text ius wrapped automatically, this - * value sets the max width of a text before it continues on a new line. - * - */ - wrappingWidth?: number; -} /** * The object containing configurations specific for sankey diagrams. * @@ -1456,6 +1518,91 @@ export interface SankeyDiagramConfig extends BaseDiagramConfig { */ suffix?: string; } +/** + * The object containing configurations specific for packet diagrams. + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "PacketDiagramConfig". + */ +export interface PacketDiagramConfig extends BaseDiagramConfig { + /** + * The height of each row in the packet diagram. + */ + rowHeight?: number; + /** + * The width of each bit in the packet diagram. + */ + bitWidth?: number; + /** + * The number of bits to display per row. + */ + bitsPerRow?: number; + /** + * Toggle to display or hide bit numbers. + */ + showBits?: boolean; + /** + * The horizontal padding between the blocks in a row. + */ + paddingX?: number; + /** + * The vertical padding between the rows. + */ + paddingY?: number; +} +/** + * The object containing configurations specific for block diagrams. + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "BlockDiagramConfig". + */ +export interface BlockDiagramConfig extends BaseDiagramConfig { + padding?: number; +} +/** + * The object containing configurations specific for radar diagrams. + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "RadarDiagramConfig". + */ +export interface RadarDiagramConfig extends BaseDiagramConfig { + /** + * The size of the radar diagram. + */ + width?: number; + /** + * The size of the radar diagram. + */ + height?: number; + /** + * The margin from the top of the radar diagram. + */ + marginTop?: number; + /** + * The margin from the right of the radar diagram. + */ + marginRight?: number; + /** + * The margin from the bottom of the radar diagram. + */ + marginBottom?: number; + /** + * The margin from the left of the radar diagram. + */ + marginLeft?: number; + /** + * The scale factor of the axis. + */ + axisScaleFactor?: number; + /** + * The scale factor of the axis label. + */ + axisLabelFactor?: number; + /** + * The tension factor for the Catmull-Rom spline conversion to cubic BÊzier curves. + */ + curveTension?: number; +} /** * This interface was referenced by `MermaidConfig`'s JSON-Schema * via the `definition` "FontConfig". diff --git a/packages/mermaid/src/dagre-wrapper/GraphObjects.md b/packages/mermaid/src/dagre-wrapper/GraphObjects.md index 730b42e3f..b90ce6931 100644 --- a/packages/mermaid/src/dagre-wrapper/GraphObjects.md +++ b/packages/mermaid/src/dagre-wrapper/GraphObjects.md @@ -22,7 +22,7 @@ flowchart C1 --> C2 ``` -The new nodes C1 and C2 are a special type of nodes, clusterNodes. ClusterNodes have have the nodes in the cluster including the cluster attached in a graph object. +The new nodes C1 and C2 are a special type of nodes, clusterNodes. ClusterNodes have the nodes in the cluster including the cluster attached in a graph object. When rendering this diagram it is being rendered recursively. The diagram is rendered by the dagre-mermaid:render function which in turn will be used to render the node C1 and the node C2. The result of those renderings will be inserted as nodes in the "root" diagram. With this recursive approach it would be possible to have different layout direction for each cluster. @@ -32,7 +32,7 @@ When rendering this diagram it is being rendered recursively. The diagram is ren _Data for a clusterNode_ -When a cluster has edges to or from some of its nodes leading outside the cluster the approach of recursive rendering can not be used as the layout of the graph needs to take responsibility for nodes outside of the cluster. +When a cluster has edges to or from some of its nodes leading outside the cluster the approach of recursive rendering cannot be used as the layout of the graph needs to take responsibility for nodes outside of the cluster. ```mermaid flowchart @@ -45,7 +45,7 @@ flowchart a --> C2 ``` -To handle this case a special type of edge is inserted. The edge to/from the cluster is replaced with an edge to/from a node in the cluster which is tagged with toCluster/fromCluster. When rendering this edge the intersection between the edge and the border of the cluster is calculated making the edge start/stop there. In practice this renders like an an edge to/from the cluster. +To handle this case a special type of edge is inserted. The edge to/from the cluster is replaced with an edge to/from a node in the cluster which is tagged with toCluster/fromCluster. When rendering this edge the intersection between the edge and the border of the cluster is calculated making the edge start/stop there. In practice this renders like an edge to/from the cluster. In the diagram above the root diagram would be rendered with C1 whereas C2 would be rendered recursively. @@ -53,7 +53,7 @@ Of these two approaches the top one renders better and is used when possible. Wh # Graph objects and their properties -Explains the representation of various objects used to render the flow charts and what the properties mean. This ofc from the perspective of the dagre-wrapper. +Explains the representation of various objects used to render the flow charts and what the properties mean. This is from the perspective of the dagre-wrapper. ## node @@ -100,13 +100,13 @@ double_arrow_point arrow_circle double_arrow_circle -Lets try to make these types semantic free so that diagram type semantics does not find its way in to this more generic layer. +Lets try to make these types semantic free so that diagram type semantics does not find its way into this more generic layer. Required edgeData for proper rendering: | property | description | | ---------- | -------------------------------------------------------------------- | -| id | Id of the edge | +| id | ID of the edge | | arrowHead | overlap between arrowHead and arrowType? | | arrowType | overlap between arrowHead and arrowType? | | style | | diff --git a/packages/mermaid/src/dagre-wrapper/blockArrowHelper.ts b/packages/mermaid/src/dagre-wrapper/blockArrowHelper.ts index 3c5000a49..848dc9fcc 100644 --- a/packages/mermaid/src/dagre-wrapper/blockArrowHelper.ts +++ b/packages/mermaid/src/dagre-wrapper/blockArrowHelper.ts @@ -42,9 +42,6 @@ export const getArrowPoints = ( // Padding to use, half of the node padding. const padding = node.padding / 2; - // Initialize an empty array to store points for the arrow. - const points = []; - if ( directions.has('right') && directions.has('left') && diff --git a/packages/mermaid/src/dagre-wrapper/createLabel.js b/packages/mermaid/src/dagre-wrapper/createLabel.js index f49d65f25..d2b59b5a9 100644 --- a/packages/mermaid/src/dagre-wrapper/createLabel.js +++ b/packages/mermaid/src/dagre-wrapper/createLabel.js @@ -25,15 +25,10 @@ function addHtmlLabel(node) { const label = node.label; const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel'; - div.html( - '' + - label + - '' - ); + const span = div.append('span'); + span.html(label); + applyStyle(span, node.labelStyle); + span.attr('class', labelClass); applyStyle(div, node.labelStyle); div.style('display', 'inline-block'); diff --git a/packages/mermaid/src/dagre-wrapper/edgeMarker.spec.ts b/packages/mermaid/src/dagre-wrapper/edgeMarker.spec.ts index 6cfb59fab..6fb439552 100644 --- a/packages/mermaid/src/dagre-wrapper/edgeMarker.spec.ts +++ b/packages/mermaid/src/dagre-wrapper/edgeMarker.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/unbound-method */ import type { Mocked } from 'vitest'; import type { SVG } from '../diagram-api/types.js'; import { addEdgeMarkers } from './edgeMarker.js'; diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js index 1a72328e8..8404e54d7 100644 --- a/packages/mermaid/src/dagre-wrapper/edges.js +++ b/packages/mermaid/src/dagre-wrapper/edges.js @@ -279,7 +279,7 @@ export const intersection = (node, outsidePoint, insidePoint) => { return res; } else { - // Intersection onn sides of rect + // Intersection on sides of rect if (insidePoint.x < outsidePoint.x) { r = outsidePoint.x - w - x; } else { @@ -324,7 +324,7 @@ const cutPathAtIntersect = (_points, boundaryNode) => { // check if point is inside the boundary rect if (!outsideNode(boundaryNode, point) && !isInside) { // First point inside the rect found - // Calc the intersection coord between the point anf the last point outside the rect + // Calc the intersection coord between the point and the last point outside the rect const inter = intersection(boundaryNode, lastPointOutside, point); // // Check case where the intersection is the same as the last point diff --git a/packages/mermaid/src/dagre-wrapper/edges.spec.js b/packages/mermaid/src/dagre-wrapper/edges.spec.js index 9b2772ecd..dfe4c7901 100644 --- a/packages/mermaid/src/dagre-wrapper/edges.spec.js +++ b/packages/mermaid/src/dagre-wrapper/edges.spec.js @@ -30,7 +30,7 @@ describe('Graphlib decorations', () => { expect(int.x).toBeCloseTo(192.4609375); expect(int.y).toBeCloseTo(145.15711441743503); }); - it('case 3 - intersection on top of box outside point greater then inside point', function () { + it('case 3 - intersection on top of box outside point greater than inside point', function () { const o = { x: 157, y: 39 }; const i = { x: 104, y: 105 }; const node2 = { @@ -44,7 +44,7 @@ describe('Graphlib decorations', () => { expect(int.y).toBeCloseTo(76); // expect(int.y).toBeCloseTo(67.833) }); - it('case 4 - intersection on top of box inside point greater then inside point', function () { + it('case 4 - intersection on top of box inside point greater than inside point', function () { const o = { x: 144, y: 38 }; const i = { x: 198, y: 105 }; const node2 = { diff --git a/packages/mermaid/src/dagre-wrapper/index.js b/packages/mermaid/src/dagre-wrapper/index.js index 70f1a862c..86ae7e284 100644 --- a/packages/mermaid/src/dagre-wrapper/index.js +++ b/packages/mermaid/src/dagre-wrapper/index.js @@ -51,7 +51,7 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit } } log.info('(Insert) Node XXX' + v + ': ' + JSON.stringify(graph.node(v))); - if (node && node.clusterNode) { + if (node?.clusterNode) { // const children = graph.children(v); log.info('Cluster identified', v, node.width, graph.node(v)); // `node.graph.setGraph` applies the graph configurations such as nodeSpacing to subgraphs as without this the default values would be used @@ -87,7 +87,7 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit // insertCluster(clusters, graph.node(v)); } else { log.info('Node - the non recursive path', v, node.id, node); - await insertNode(nodes, graph.node(v), dir); + await insertNode(nodes, graph.node(v), { config: siteConfig, dir }); } } }) @@ -97,25 +97,26 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit // Also figure out which edges point to/from clusters and adjust them accordingly // Edges from/to clusters really points to the first child in the cluster. // TODO: pick optimal child in the cluster to us as link anchor - graph.edges().forEach(function (e) { + graph.edges().forEach(async function (e) { const edge = graph.edge(e.v, e.w, e.name); log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e)); log.info('Edge ' + e.v + ' -> ' + e.w + ': ', e, ' ', JSON.stringify(graph.edge(e))); // Check if link is either from or to a cluster log.info('Fix', clusterDb, 'ids:', e.v, e.w, 'Translating: ', clusterDb[e.v], clusterDb[e.w]); - insertEdgeLabel(edgeLabels, edge); + await insertEdgeLabel(edgeLabels, edge); }); graph.edges().forEach(function (e) { log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e)); }); + log.info('Graph before layout:', JSON.stringify(graphlibJson.write(graph))); log.info('#############################################'); log.info('### Layout ###'); log.info('#############################################'); log.info(graph); dagreLayout(graph); - log.info('Graph after layout:', graphlibJson.write(graph)); + log.info('Graph after layout:', JSON.stringify(graphlibJson.write(graph))); // Move the nodes to the correct place let diff = 0; const { subGraphTitleTotalMargin } = getSubGraphTitleMargins(siteConfig); @@ -130,7 +131,7 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit ' height: ', node.height ); - if (node && node.clusterNode) { + if (node?.clusterNode) { // clusterDb[node.id].node = node; node.y += subGraphTitleTotalMargin; positionNode(node); diff --git a/packages/mermaid/src/dagre-wrapper/intersect.js b/packages/mermaid/src/dagre-wrapper/intersect.js deleted file mode 100644 index 41bcb5a53..000000000 --- a/packages/mermaid/src/dagre-wrapper/intersect.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - node: require('./intersect-node'), - circle: require('./intersect-circle'), - ellipse: require('./intersect-ellipse'), - polygon: require('./intersect-polygon'), - rect: require('./intersect-rect'), -}; diff --git a/packages/mermaid/src/dagre-wrapper/intersect/index.js b/packages/mermaid/src/dagre-wrapper/intersect/index.js index e33b6dd51..47f71747d 100644 --- a/packages/mermaid/src/dagre-wrapper/intersect/index.js +++ b/packages/mermaid/src/dagre-wrapper/intersect/index.js @@ -1,5 +1,5 @@ /* - * Borrowed with love from from dagre-d3. Many thanks to cpettitt! + * Borrowed with love from dagre-d3. Many thanks to cpettitt! */ import node from './intersect-node.js'; diff --git a/packages/mermaid/src/dagre-wrapper/mermaid-graphlib.js b/packages/mermaid/src/dagre-wrapper/mermaid-graphlib.js index 04ee9d16b..3873f8f81 100644 --- a/packages/mermaid/src/dagre-wrapper/mermaid-graphlib.js +++ b/packages/mermaid/src/dagre-wrapper/mermaid-graphlib.js @@ -351,7 +351,7 @@ export const extractor = (graph, depth) => { return; } // For clusters without incoming and/or outgoing edges, create a new cluster-node - // containing the nodes and edges in the custer in a new graph + // containing the nodes and edges in the cluster in a new graph // for (let i = 0;) let nodes = graph.nodes(); let hasChildren = false; @@ -399,7 +399,7 @@ export const extractor = (graph, depth) => { const graphSettings = graph.graph(); let dir = graphSettings.rankdir === 'TB' ? 'LR' : 'TB'; - if (clusterDb[node] && clusterDb[node].clusterData && clusterDb[node].clusterData.dir) { + if (clusterDb[node]?.clusterData?.dir) { dir = clusterDb[node].clusterData.dir; log.warn('Fixing dir', clusterDb[node].clusterData.dir, dir); } diff --git a/packages/mermaid/src/dagre-wrapper/nodes.js b/packages/mermaid/src/dagre-wrapper/nodes.js index 8abcfe5bd..2677fd785 100644 --- a/packages/mermaid/src/dagre-wrapper/nodes.js +++ b/packages/mermaid/src/dagre-wrapper/nodes.js @@ -1,12 +1,12 @@ import { select } from 'd3'; -import { log } from '../logger.js'; -import { labelHelper, updateNodeBounds, insertPolygonShape } from './shapes/util.js'; import { getConfig } from '../diagram-api/diagramAPI.js'; -import intersect from './intersect/index.js'; -import createLabel from './createLabel.js'; -import note from './shapes/note.js'; import { evaluate } from '../diagrams/common/common.js'; +import { log } from '../logger.js'; import { getArrowPoints } from './blockArrowHelper.js'; +import createLabel from './createLabel.js'; +import intersect from './intersect/index.js'; +import note from './shapes/note.js'; +import { insertPolygonShape, labelHelper, updateNodeBounds } from './shapes/util.js'; const formatClass = (str) => { if (str) { @@ -395,6 +395,7 @@ const rect = async (parent, node) => { // add the rect const rect = shapeSvg.insert('rect', ':first-child'); + // console.log('Rect node:', node, 'bbox:', bbox, 'halfPadding:', halfPadding, 'node.padding:', node.padding); // const totalWidth = bbox.width + node.padding * 2; // const totalHeight = bbox.height + node.padding * 2; const totalWidth = node.positioned ? node.width : bbox.width + node.padding; @@ -901,7 +902,7 @@ const class_box = (parent, node) => { const labelContainer = shapeSvg.insert('g').attr('class', 'label'); let verticalPos = 0; - const hasInterface = node.classData.annotations && node.classData.annotations[0]; + const hasInterface = node.classData.annotations?.[0]; // 1. Create the labels const interfaceLabelText = node.classData.annotations[0] @@ -1130,7 +1131,7 @@ const shapes = { let nodeElems = {}; -export const insertNode = async (elem, node, dir) => { +export const insertNode = async (elem, node, renderOptions) => { let newEl; let el; @@ -1143,9 +1144,9 @@ export const insertNode = async (elem, node, dir) => { target = node.linkTarget || '_blank'; } newEl = elem.insert('svg:a').attr('xlink:href', node.link).attr('target', target); - el = await shapes[node.shape](newEl, node, dir); + el = await shapes[node.shape](newEl, node, renderOptions); } else { - el = await shapes[node.shape](elem, node, dir); + el = await shapes[node.shape](elem, node, renderOptions); newEl = el; } if (node.tooltip) { @@ -1154,9 +1155,6 @@ export const insertNode = async (elem, node, dir) => { if (node.class) { el.attr('class', 'node default ' + node.class); } - // MC Special - newEl.attr('data-node', 'true'); - newEl.attr('data-id', node.id); nodeElems[node.id] = newEl; diff --git a/packages/mermaid/src/dagre-wrapper/patterns.js b/packages/mermaid/src/dagre-wrapper/patterns.js deleted file mode 100644 index 3025f8ef9..000000000 --- a/packages/mermaid/src/dagre-wrapper/patterns.js +++ /dev/null @@ -1,52 +0,0 @@ -/** Setup arrow head and define the marker. The result is appended to the svg. */ - -// import { log } from '../logger.js'; - -// Only add the number of markers that the diagram needs -const insertPatterns = (elem, patternArray, type, id) => { - patternArray.forEach((patternName) => { - patterns[patternName](elem, type, id); - }); -}; - -{ - /* - {' '} - - {' '} - - {' '} - - {' '} - {' '} - {' '} - {' '} -; */ -} - -const dots = (elem, type) => { - elem - .append('defs') - .append('marker') - .attr('id', type + '-barbEnd') - .attr('refX', 19) - .attr('refY', 7) - .attr('markerWidth', 20) - .attr('markerHeight', 14) - .attr('markerUnits', 0) - .attr('orient', 'auto') - .append('path') - .attr('d', 'M 19,7 L9,13 L14,7 L9,1 Z'); -}; - -// TODO rename the class diagram markers to something shape descriptive and semantic free -const patterns = { - dots, -}; -export default insertPatterns; diff --git a/packages/mermaid/src/defaultConfig.ts b/packages/mermaid/src/defaultConfig.ts index 76a8152b7..2e4e20f50 100644 --- a/packages/mermaid/src/defaultConfig.ts +++ b/packages/mermaid/src/defaultConfig.ts @@ -20,10 +20,15 @@ const config: RequiredDeep = { // Set, even though they're `undefined` so that `configKeys` finds these keys // TODO: Should we replace these with `null` so that they can go in the JSON Schema? deterministicIDSeed: undefined, + elk: { + // mergeEdges is needed here to be considered + mergeEdges: false, + nodePlacementStrategy: 'BRANDES_KOEPF', + }, themeCSS: undefined, // add non-JSON default config values - themeVariables: theme['default'].getThemeVariables(), + themeVariables: theme.default.getThemeVariables(), sequence: { ...defaultConfigJson.sequence, messageFont: function () { @@ -48,6 +53,9 @@ const config: RequiredDeep = { }; }, }, + class: { + hideEmptyMembersBox: false, + }, gantt: { ...defaultConfigJson.gantt, tickInterval: undefined, @@ -244,24 +252,15 @@ const config: RequiredDeep = { ...defaultConfigJson.requirement, useWidth: undefined, }, - gitGraph: { - ...defaultConfigJson.gitGraph, - // TODO: This is a temporary override for `gitGraph`, since every other - // diagram does have `useMaxWidth`, but instead sets it to `true`. - // Should we set this to `true` instead? - useMaxWidth: false, - }, - sankey: { - ...defaultConfigJson.sankey, - // this is false, unlike every other diagram (other than gitGraph) - // TODO: can we make this default to `true` instead? - useMaxWidth: false, - }, packet: { ...defaultConfigJson.packet, }, + radar: { + ...defaultConfigJson.radar, + }, }; +// eslint-disable-next-line @typescript-eslint/no-explicit-any const keyify = (obj: any, prefix = ''): string[] => Object.keys(obj).reduce((res: string[], el): string[] => { if (Array.isArray(obj[el])) { @@ -272,5 +271,5 @@ const keyify = (obj: any, prefix = ''): string[] => return [...res, prefix + el]; }, []); -export const configKeys: Set = new Set(keyify(config, '')); +export const configKeys = new Set(keyify(config, '')); export default config; diff --git a/packages/mermaid/src/diagram-api/diagram-orchestration.spec.ts b/packages/mermaid/src/diagram-api/diagram-orchestration.spec.ts index 4517ff622..3ec2d861f 100644 --- a/packages/mermaid/src/diagram-api/diagram-orchestration.spec.ts +++ b/packages/mermaid/src/diagram-api/diagram-orchestration.spec.ts @@ -9,7 +9,7 @@ describe('diagram-orchestration', () => { expect(detectType('graph TD; A-->B')).toBe('flowchart'); }); - describe('proper diagram types should be detetced', () => { + describe('proper diagram types should be detected', () => { beforeAll(() => { addDiagrams(); }); diff --git a/packages/mermaid/src/diagram-api/diagram-orchestration.ts b/packages/mermaid/src/diagram-api/diagram-orchestration.ts index 63fe19cdd..f3c9197be 100644 --- a/packages/mermaid/src/diagram-api/diagram-orchestration.ts +++ b/packages/mermaid/src/diagram-api/diagram-orchestration.ts @@ -19,9 +19,12 @@ import errorDiagram from '../diagrams/error/errorDiagram.js'; import flowchartElk from '../diagrams/flowchart/elk/detector.js'; import timeline from '../diagrams/timeline/detector.js'; import mindmap from '../diagrams/mindmap/detector.js'; +import kanban from '../diagrams/kanban/detector.js'; import sankey from '../diagrams/sankey/sankeyDetector.js'; import { packet } from '../diagrams/packet/detector.js'; +import { radar } from '../diagrams/radar/detector.js'; import block from '../diagrams/block/blockDetector.js'; +import architecture from '../diagrams/architecture/architectureDetector.js'; import { registerLazyLoadedDiagrams } from './detectType.js'; import { registerDiagram } from './diagramAPI.js'; import '../type.d.ts'; @@ -75,6 +78,7 @@ export const addDiagrams = () => { // Ordering of detectors is important. The first one to return true will be used. registerLazyLoadedDiagrams( c4, + kanban, classDiagramV2, classDiagram, er, @@ -94,6 +98,8 @@ export const addDiagrams = () => { sankey, packet, xychart, - block + block, + architecture, + radar ); }; diff --git a/packages/mermaid/src/diagram-api/diagramAPI.spec.ts b/packages/mermaid/src/diagram-api/diagramAPI.spec.ts index 9fe6541d6..68991cffb 100644 --- a/packages/mermaid/src/diagram-api/diagramAPI.spec.ts +++ b/packages/mermaid/src/diagram-api/diagramAPI.spec.ts @@ -29,7 +29,7 @@ describe('DiagramAPI', () => { `[UnknownDiagramError: No diagram type detected matching given configuration for text: loki diagram]` ); const detector: DiagramDetector = (str: string) => { - return str.match('loki') !== null; + return /loki/.exec(str) !== null; }; registerDiagram( 'loki', diff --git a/packages/mermaid/src/diagram-api/diagramAPI.ts b/packages/mermaid/src/diagram-api/diagramAPI.ts index 5ea3825ef..df4514adf 100644 --- a/packages/mermaid/src/diagram-api/diagramAPI.ts +++ b/packages/mermaid/src/diagram-api/diagramAPI.ts @@ -30,9 +30,7 @@ export const getCommonDb = () => { }; const diagrams: Record = {}; -export interface Detectors { - [key: string]: DiagramDetector; -} +export type Detectors = Record; /** * Registers the given diagram with Mermaid. diff --git a/packages/mermaid/src/diagram-api/loadDiagram.ts b/packages/mermaid/src/diagram-api/loadDiagram.ts index c1b445bf6..1ec01ec06 100644 --- a/packages/mermaid/src/diagram-api/loadDiagram.ts +++ b/packages/mermaid/src/diagram-api/loadDiagram.ts @@ -10,7 +10,7 @@ export const loadRegisteredDiagrams = async () => { if (loader) { try { getDiagram(key); - } catch (error) { + } catch { try { // Register diagram if it is not already registered const { diagram, id } = await loader(); diff --git a/packages/mermaid/src/diagram-api/types.ts b/packages/mermaid/src/diagram-api/types.ts index 6ab82bd0d..fdb175e52 100644 --- a/packages/mermaid/src/diagram-api/types.ts +++ b/packages/mermaid/src/diagram-api/types.ts @@ -70,7 +70,7 @@ export interface DiagramRenderer { getClasses?: ( text: string, diagram: Pick - ) => Record; + ) => Map; } export interface DiagramDefinition { @@ -129,6 +129,6 @@ export type HTML = d3.Selection; -export type Group = d3.Selection; +export type SVGGroup = d3.Selection; export type DiagramStylesProvider = (options?: any) => string; diff --git a/packages/mermaid/src/diagram.spec.ts b/packages/mermaid/src/diagram.spec.ts index 4b9c907b3..8e7759d6d 100644 --- a/packages/mermaid/src/diagram.spec.ts +++ b/packages/mermaid/src/diagram.spec.ts @@ -30,12 +30,12 @@ const getDummyDiagram = (id: string, title?: string): Awaited { test('should detect inbuilt diagrams', async () => { - const graph = (await Diagram.fromText('graph TD; A-->B')) as Diagram; + const graph = await Diagram.fromText('graph TD; A-->B'); expect(graph).toBeInstanceOf(Diagram); expect(graph.type).toBe('flowchart-v2'); - const sequence = (await Diagram.fromText( + const sequence = await Diagram.fromText( 'sequenceDiagram; Alice->>+John: Hello John, how are you?' - )) as Diagram; + ); expect(sequence).toBeInstanceOf(Diagram); expect(sequence.type).toBe('sequence'); }); @@ -85,7 +85,7 @@ describe('diagram detection', () => { ); }); - test('should consider entity codes when present in diagram defination', async () => { + test('should consider entity codes when present in diagram definition', async () => { const diagram = await Diagram.fromText(`sequenceDiagram A->>B: I #9829; you! B->>A: I #9829; you #infin; times more!`); diff --git a/packages/mermaid/src/diagrams/architecture/architecture.spec.ts b/packages/mermaid/src/diagrams/architecture/architecture.spec.ts new file mode 100644 index 000000000..d0405d025 --- /dev/null +++ b/packages/mermaid/src/diagrams/architecture/architecture.spec.ts @@ -0,0 +1,70 @@ +import { it, describe, expect } from 'vitest'; +import { db } from './architectureDb.js'; +import { parser } from './architectureParser.js'; + +const { + clear, + getDiagramTitle, + getAccTitle, + getAccDescription, + getServices, + getGroups, + getEdges, + getJunctions, +} = db; + +describe('architecture diagrams', () => { + beforeEach(() => { + clear(); + }); + + describe('architecture diagram definitions', () => { + it('should handle the architecture keyword', async () => { + const str = `architecture-beta`; + await expect(parser.parse(str)).resolves.not.toThrow(); + }); + + it('should handle a simple radar definition', async () => { + const str = `architecture-beta + service db + `; + await expect(parser.parse(str)).resolves.not.toThrow(); + }); + }); + + describe('should handle TitleAndAccessibilities', () => { + it('should handle title on the first line', async () => { + const str = `architecture-beta title Simple Architecture Diagram`; + await expect(parser.parse(str)).resolves.not.toThrow(); + expect(getDiagramTitle()).toBe('Simple Architecture Diagram'); + }); + + it('should handle title on another line', async () => { + const str = `architecture-beta + title Simple Architecture Diagram + `; + await expect(parser.parse(str)).resolves.not.toThrow(); + expect(getDiagramTitle()).toBe('Simple Architecture Diagram'); + }); + + it('should handle accessibility title and description', async () => { + const str = `architecture-beta + accTitle: Accessibility Title + accDescr: Accessibility Description + `; + await expect(parser.parse(str)).resolves.not.toThrow(); + expect(getAccTitle()).toBe('Accessibility Title'); + expect(getAccDescription()).toBe('Accessibility Description'); + }); + + it('should handle multiline accessibility description', async () => { + const str = `architecture-beta + accDescr { + Accessibility Description + } + `; + await expect(parser.parse(str)).resolves.not.toThrow(); + expect(getAccDescription()).toBe('Accessibility Description'); + }); + }); +}); diff --git a/packages/mermaid/src/diagrams/architecture/architectureDb.ts b/packages/mermaid/src/diagrams/architecture/architectureDb.ts new file mode 100644 index 000000000..c7bd64e21 --- /dev/null +++ b/packages/mermaid/src/diagrams/architecture/architectureDb.ts @@ -0,0 +1,362 @@ +import type { ArchitectureDiagramConfig } from '../../config.type.js'; +import DEFAULT_CONFIG from '../../defaultConfig.js'; +import { getConfig as commonGetConfig } from '../../config.js'; +import type { D3Element } from '../../types.js'; +import { ImperativeState } from '../../utils/imperativeState.js'; +import { + clear as commonClear, + getAccDescription, + getAccTitle, + getDiagramTitle, + setAccDescription, + setAccTitle, + setDiagramTitle, +} from '../common/commonDb.js'; +import type { + ArchitectureAlignment, + ArchitectureDB, + ArchitectureDirectionPair, + ArchitectureDirectionPairMap, + ArchitectureEdge, + ArchitectureGroup, + ArchitectureJunction, + ArchitectureNode, + ArchitectureService, + ArchitectureSpatialMap, + ArchitectureState, +} from './architectureTypes.js'; +import { + getArchitectureDirectionAlignment, + getArchitectureDirectionPair, + isArchitectureDirection, + isArchitectureJunction, + isArchitectureService, + shiftPositionByArchitectureDirectionPair, +} from './architectureTypes.js'; +import { cleanAndMerge } from '../../utils.js'; + +const DEFAULT_ARCHITECTURE_CONFIG: Required = + DEFAULT_CONFIG.architecture; + +const state = new ImperativeState(() => ({ + nodes: {}, + groups: {}, + edges: [], + registeredIds: {}, + config: DEFAULT_ARCHITECTURE_CONFIG, + dataStructures: undefined, + elements: {}, +})); + +const clear = (): void => { + state.reset(); + commonClear(); +}; + +const addService = function ({ + id, + icon, + in: parent, + title, + iconText, +}: Omit) { + if (state.records.registeredIds[id] !== undefined) { + throw new Error( + `The service id [${id}] is already in use by another ${state.records.registeredIds[id]}` + ); + } + if (parent !== undefined) { + if (id === parent) { + throw new Error(`The service [${id}] cannot be placed within itself`); + } + if (state.records.registeredIds[parent] === undefined) { + throw new Error( + `The service [${id}]'s parent does not exist. Please make sure the parent is created before this service` + ); + } + if (state.records.registeredIds[parent] === 'node') { + throw new Error(`The service [${id}]'s parent is not a group`); + } + } + + state.records.registeredIds[id] = 'node'; + + state.records.nodes[id] = { + id, + type: 'service', + icon, + iconText, + title, + edges: [], + in: parent, + }; +}; + +const getServices = (): ArchitectureService[] => + Object.values(state.records.nodes).filter(isArchitectureService); + +const addJunction = function ({ id, in: parent }: Omit) { + state.records.registeredIds[id] = 'node'; + + state.records.nodes[id] = { + id, + type: 'junction', + edges: [], + in: parent, + }; +}; + +const getJunctions = (): ArchitectureJunction[] => + Object.values(state.records.nodes).filter(isArchitectureJunction); + +const getNodes = (): ArchitectureNode[] => Object.values(state.records.nodes); + +const getNode = (id: string): ArchitectureNode | null => state.records.nodes[id]; + +const addGroup = function ({ id, icon, in: parent, title }: ArchitectureGroup) { + if (state.records.registeredIds[id] !== undefined) { + throw new Error( + `The group id [${id}] is already in use by another ${state.records.registeredIds[id]}` + ); + } + if (parent !== undefined) { + if (id === parent) { + throw new Error(`The group [${id}] cannot be placed within itself`); + } + if (state.records.registeredIds[parent] === undefined) { + throw new Error( + `The group [${id}]'s parent does not exist. Please make sure the parent is created before this group` + ); + } + if (state.records.registeredIds[parent] === 'node') { + throw new Error(`The group [${id}]'s parent is not a group`); + } + } + + state.records.registeredIds[id] = 'group'; + + state.records.groups[id] = { + id, + icon, + title, + in: parent, + }; +}; +const getGroups = (): ArchitectureGroup[] => { + return Object.values(state.records.groups); +}; + +const addEdge = function ({ + lhsId, + rhsId, + lhsDir, + rhsDir, + lhsInto, + rhsInto, + lhsGroup, + rhsGroup, + title, +}: ArchitectureEdge) { + if (!isArchitectureDirection(lhsDir)) { + throw new Error( + `Invalid direction given for left hand side of edge ${lhsId}--${rhsId}. Expected (L,R,T,B) got ${lhsDir}` + ); + } + if (!isArchitectureDirection(rhsDir)) { + throw new Error( + `Invalid direction given for right hand side of edge ${lhsId}--${rhsId}. Expected (L,R,T,B) got ${rhsDir}` + ); + } + + if (state.records.nodes[lhsId] === undefined && state.records.groups[lhsId] === undefined) { + throw new Error( + `The left-hand id [${lhsId}] does not yet exist. Please create the service/group before declaring an edge to it.` + ); + } + if (state.records.nodes[rhsId] === undefined && state.records.groups[lhsId] === undefined) { + throw new Error( + `The right-hand id [${rhsId}] does not yet exist. Please create the service/group before declaring an edge to it.` + ); + } + + const lhsGroupId = state.records.nodes[lhsId].in; + const rhsGroupId = state.records.nodes[rhsId].in; + if (lhsGroup && lhsGroupId && rhsGroupId && lhsGroupId == rhsGroupId) { + throw new Error( + `The left-hand id [${lhsId}] is modified to traverse the group boundary, but the edge does not pass through two groups.` + ); + } + if (rhsGroup && lhsGroupId && rhsGroupId && lhsGroupId == rhsGroupId) { + throw new Error( + `The right-hand id [${rhsId}] is modified to traverse the group boundary, but the edge does not pass through two groups.` + ); + } + + const edge = { + lhsId, + lhsDir, + lhsInto, + lhsGroup, + rhsId, + rhsDir, + rhsInto, + rhsGroup, + title, + }; + + state.records.edges.push(edge); + if (state.records.nodes[lhsId] && state.records.nodes[rhsId]) { + state.records.nodes[lhsId].edges.push(state.records.edges[state.records.edges.length - 1]); + state.records.nodes[rhsId].edges.push(state.records.edges[state.records.edges.length - 1]); + } +}; + +const getEdges = (): ArchitectureEdge[] => state.records.edges; + +/** + * Returns the current diagram's adjacency list, spatial map, & group alignments. + * If they have not been created, run the algorithms to generate them. + * @returns + */ +const getDataStructures = () => { + if (state.records.dataStructures === undefined) { + // Tracks how groups are aligned with one another. Generated while creating the adj list + const groupAlignments: Record< + string, + Record> + > = {}; + + // Create an adjacency list of the diagram to perform BFS on + // Outer reduce applied on all services + // Inner reduce applied on the edges for a service + const adjList = Object.entries(state.records.nodes).reduce< + Record + >((prevOuter, [id, service]) => { + prevOuter[id] = service.edges.reduce((prevInner, edge) => { + // track the direction groups connect to one another + const lhsGroupId = getNode(edge.lhsId)?.in; + const rhsGroupId = getNode(edge.rhsId)?.in; + if (lhsGroupId && rhsGroupId && lhsGroupId !== rhsGroupId) { + const alignment = getArchitectureDirectionAlignment(edge.lhsDir, edge.rhsDir); + if (alignment !== 'bend') { + groupAlignments[lhsGroupId] ??= {}; + groupAlignments[lhsGroupId][rhsGroupId] = alignment; + groupAlignments[rhsGroupId] ??= {}; + groupAlignments[rhsGroupId][lhsGroupId] = alignment; + } + } + + if (edge.lhsId === id) { + // source is LHS + const pair = getArchitectureDirectionPair(edge.lhsDir, edge.rhsDir); + if (pair) { + prevInner[pair] = edge.rhsId; + } + } else { + // source is RHS + const pair = getArchitectureDirectionPair(edge.rhsDir, edge.lhsDir); + if (pair) { + prevInner[pair] = edge.lhsId; + } + } + return prevInner; + }, {}); + return prevOuter; + }, {}); + + // Configuration for the initial pass of BFS + const firstId = Object.keys(adjList)[0]; + const visited = { [firstId]: 1 }; + // If a key is present in this object, it has not been visited + const notVisited = Object.keys(adjList).reduce( + (prev, id) => (id === firstId ? prev : { ...prev, [id]: 1 }), + {} as Record + ); + + // Perform BFS on the adjacency list + const BFS = (startingId: string): ArchitectureSpatialMap => { + const spatialMap = { [startingId]: [0, 0] }; + const queue = [startingId]; + while (queue.length > 0) { + const id = queue.shift(); + if (id) { + visited[id] = 1; + delete notVisited[id]; + const adj = adjList[id]; + const [posX, posY] = spatialMap[id]; + Object.entries(adj).forEach(([dir, rhsId]) => { + if (!visited[rhsId]) { + spatialMap[rhsId] = shiftPositionByArchitectureDirectionPair( + [posX, posY], + dir as ArchitectureDirectionPair + ); + queue.push(rhsId); + } + }); + } + } + return spatialMap; + }; + const spatialMaps = [BFS(firstId)]; + + // If our diagram is disconnected, keep adding additional spatial maps until all disconnected graphs have been found + while (Object.keys(notVisited).length > 0) { + spatialMaps.push(BFS(Object.keys(notVisited)[0])); + } + state.records.dataStructures = { + adjList, + spatialMaps, + groupAlignments, + }; + } + return state.records.dataStructures; +}; + +const setElementForId = (id: string, element: D3Element) => { + state.records.elements[id] = element; +}; +const getElementById = (id: string) => state.records.elements[id]; + +const getConfig = (): Required => { + const config = cleanAndMerge({ + ...DEFAULT_ARCHITECTURE_CONFIG, + ...commonGetConfig().architecture, + }); + return config; +}; + +export const db: ArchitectureDB = { + clear, + setDiagramTitle, + getDiagramTitle, + setAccTitle, + getAccTitle, + setAccDescription, + getAccDescription, + getConfig, + + addService, + getServices, + addJunction, + getJunctions, + getNodes, + getNode, + addGroup, + getGroups, + addEdge, + getEdges, + setElementForId, + getElementById, + getDataStructures, +}; + +/** + * Typed wrapper for resolving an architecture diagram's config fields. Returns the default value if undefined + * @param field - the config field to access + * @returns + */ +export function getConfigField( + field: T +): Required[T] { + return getConfig()[field]; +} diff --git a/packages/mermaid/src/diagrams/architecture/architectureDetector.ts b/packages/mermaid/src/diagrams/architecture/architectureDetector.ts new file mode 100644 index 000000000..c15b474ab --- /dev/null +++ b/packages/mermaid/src/diagrams/architecture/architectureDetector.ts @@ -0,0 +1,24 @@ +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; + +const id = 'architecture'; + +const detector: DiagramDetector = (txt) => { + return /^\s*architecture/.test(txt); +}; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./architectureDiagram.js'); + return { id, diagram }; +}; + +const architecture: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default architecture; diff --git a/packages/mermaid/src/diagrams/architecture/architectureDiagram.ts b/packages/mermaid/src/diagrams/architecture/architectureDiagram.ts new file mode 100644 index 000000000..82dacd3e1 --- /dev/null +++ b/packages/mermaid/src/diagrams/architecture/architectureDiagram.ts @@ -0,0 +1,12 @@ +import type { DiagramDefinition } from '../../diagram-api/types.js'; +import { parser } from './architectureParser.js'; +import { db } from './architectureDb.js'; +import styles from './architectureStyles.js'; +import { renderer } from './architectureRenderer.js'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, +}; diff --git a/packages/mermaid/src/diagrams/architecture/architectureIcons.ts b/packages/mermaid/src/diagrams/architecture/architectureIcons.ts new file mode 100644 index 000000000..fac4a7b12 --- /dev/null +++ b/packages/mermaid/src/diagrams/architecture/architectureIcons.ts @@ -0,0 +1,43 @@ +import { unknownIcon } from '../../rendering-util/icons.js'; +import type { IconifyJSON } from '@iconify/types'; + +const wrapIcon = (icon: string) => { + return `${icon}`; +}; + +export const architectureIcons: IconifyJSON = { + prefix: 'mermaid-architecture', + height: 80, + width: 80, + icons: { + database: { + body: wrapIcon( + '' + ), + }, + server: { + body: wrapIcon( + '' + ), + }, + disk: { + body: wrapIcon( + '' + ), + }, + internet: { + body: wrapIcon( + '' + ), + }, + cloud: { + body: wrapIcon( + '' + ), + }, + unknown: unknownIcon, + blank: { + body: wrapIcon(''), + }, + }, +}; diff --git a/packages/mermaid/src/diagrams/architecture/architectureParser.ts b/packages/mermaid/src/diagrams/architecture/architectureParser.ts new file mode 100644 index 000000000..a7159d907 --- /dev/null +++ b/packages/mermaid/src/diagrams/architecture/architectureParser.ts @@ -0,0 +1,24 @@ +import type { Architecture } from '@mermaid-js/parser'; +import { parse } from '@mermaid-js/parser'; +import { log } from '../../logger.js'; +import type { ParserDefinition } from '../../diagram-api/types.js'; +import { populateCommonDb } from '../common/populateCommonDb.js'; +import type { ArchitectureDB } from './architectureTypes.js'; +import { db } from './architectureDb.js'; + +const populateDb = (ast: Architecture, db: ArchitectureDB) => { + populateCommonDb(ast, db); + ast.groups.map(db.addGroup); + ast.services.map((service) => db.addService({ ...service, type: 'service' })); + ast.junctions.map((service) => db.addJunction({ ...service, type: 'junction' })); + // @ts-ignore TODO our parser guarantees the type is L/R/T/B and not string. How to change to union type? + ast.edges.map(db.addEdge); +}; + +export const parser: ParserDefinition = { + parse: async (input: string): Promise => { + const ast: Architecture = await parse('architecture', input); + log.debug(ast); + populateDb(ast, db); + }, +}; diff --git a/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts b/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts new file mode 100644 index 000000000..9479e5108 --- /dev/null +++ b/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts @@ -0,0 +1,536 @@ +import { registerIconPacks } from '../../rendering-util/icons.js'; +import type { Position } from 'cytoscape'; +import cytoscape from 'cytoscape'; +import type { FcoseLayoutOptions } from 'cytoscape-fcose'; +import fcose from 'cytoscape-fcose'; +import { select } from 'd3'; +import type { DrawDefinition, SVG } from '../../diagram-api/types.js'; +import type { Diagram } from '../../Diagram.js'; +import { log } from '../../logger.js'; +import { selectSvgElement } from '../../rendering-util/selectSvgElement.js'; +import { setupGraphViewbox } from '../../setupGraphViewbox.js'; +import { getConfigField } from './architectureDb.js'; +import { architectureIcons } from './architectureIcons.js'; +import type { + ArchitectureAlignment, + ArchitectureDataStructures, + ArchitectureGroupAlignments, + ArchitectureJunction, + ArchitectureSpatialMap, + EdgeSingular, + EdgeSingularData, + NodeSingularData, +} from './architectureTypes.js'; +import { + type ArchitectureDB, + type ArchitectureDirection, + type ArchitectureEdge, + type ArchitectureGroup, + type ArchitectureService, + ArchitectureDirectionName, + edgeData, + getOppositeArchitectureDirection, + isArchitectureDirectionXY, + isArchitectureDirectionY, + nodeData, +} from './architectureTypes.js'; +import { drawEdges, drawGroups, drawJunctions, drawServices } from './svgDraw.js'; + +registerIconPacks([ + { + name: architectureIcons.prefix, + icons: architectureIcons, + }, +]); +cytoscape.use(fcose); + +function addServices(services: ArchitectureService[], cy: cytoscape.Core) { + services.forEach((service) => { + cy.add({ + group: 'nodes', + data: { + type: 'service', + id: service.id, + icon: service.icon, + label: service.title, + parent: service.in, + width: getConfigField('iconSize'), + height: getConfigField('iconSize'), + } as NodeSingularData, + classes: 'node-service', + }); + }); +} + +function addJunctions(junctions: ArchitectureJunction[], cy: cytoscape.Core) { + junctions.forEach((junction) => { + cy.add({ + group: 'nodes', + data: { + type: 'junction', + id: junction.id, + parent: junction.in, + width: getConfigField('iconSize'), + height: getConfigField('iconSize'), + } as NodeSingularData, + classes: 'node-junction', + }); + }); +} + +function positionNodes(db: ArchitectureDB, cy: cytoscape.Core) { + cy.nodes().map((node) => { + const data = nodeData(node); + if (data.type === 'group') { + return; + } + data.x = node.position().x; + data.y = node.position().y; + + const nodeElem = db.getElementById(data.id); + nodeElem.attr('transform', 'translate(' + (data.x || 0) + ',' + (data.y || 0) + ')'); + }); +} + +function addGroups(groups: ArchitectureGroup[], cy: cytoscape.Core) { + groups.forEach((group) => { + cy.add({ + group: 'nodes', + data: { + type: 'group', + id: group.id, + icon: group.icon, + label: group.title, + parent: group.in, + } as NodeSingularData, + classes: 'node-group', + }); + }); +} + +function addEdges(edges: ArchitectureEdge[], cy: cytoscape.Core) { + edges.forEach((parsedEdge) => { + const { lhsId, rhsId, lhsInto, lhsGroup, rhsInto, lhsDir, rhsDir, rhsGroup, title } = + parsedEdge; + const edgeType = isArchitectureDirectionXY(parsedEdge.lhsDir, parsedEdge.rhsDir) + ? 'segments' + : 'straight'; + const edge: EdgeSingularData = { + id: `${lhsId}-${rhsId}`, + label: title, + source: lhsId, + sourceDir: lhsDir, + sourceArrow: lhsInto, + sourceGroup: lhsGroup, + sourceEndpoint: + lhsDir === 'L' + ? '0 50%' + : lhsDir === 'R' + ? '100% 50%' + : lhsDir === 'T' + ? '50% 0' + : '50% 100%', + target: rhsId, + targetDir: rhsDir, + targetArrow: rhsInto, + targetGroup: rhsGroup, + targetEndpoint: + rhsDir === 'L' + ? '0 50%' + : rhsDir === 'R' + ? '100% 50%' + : rhsDir === 'T' + ? '50% 0' + : '50% 100%', + }; + cy.add({ + group: 'edges', + data: edge, + classes: edgeType, + }); + }); +} + +function getAlignments( + db: ArchitectureDB, + spatialMaps: ArchitectureSpatialMap[], + groupAlignments: ArchitectureGroupAlignments +): fcose.FcoseAlignmentConstraint { + /** + * Flattens the alignment object so nodes in different groups will be in the same alignment array IFF their groups don't connect in a conflicting alignment + * + * i.e., two groups which connect horizontally should not have nodes with vertical alignments to one another + * + * See: #5952 + * + * @param alignmentObj - alignment object with the outer key being the row/col # and the inner key being the group name mapped to the nodes on that axis in the group + * @param alignmentDir - alignment direction + * @returns flattened alignment object with an arbitrary key mapping to nodes in the same row/col + */ + const flattenAlignments = ( + alignmentObj: Record>, + alignmentDir: ArchitectureAlignment + ): Record => { + return Object.entries(alignmentObj).reduce( + (prev, [dir, alignments]) => { + // prev is the mapping of x/y coordinate to an array of the nodes in that row/column + let cnt = 0; + const arr = Object.entries(alignments); // [group name, array of nodes within the group on axis dir] + if (arr.length === 1) { + // If only one group exists in the row/column, we don't need to do anything else + prev[dir] = arr[0][1]; + return prev; + } + for (let i = 0; i < arr.length - 1; i++) { + for (let j = i + 1; j < arr.length; j++) { + const [aGroupId, aNodeIds] = arr[i]; + const [bGroupId, bNodeIds] = arr[j]; + const alignment = groupAlignments[aGroupId]?.[bGroupId]; // Get how the two groups are intended to align (undefined if they aren't) + + if (alignment === alignmentDir) { + // If the intended alignment between the two groups is the same as the alignment we are parsing + prev[dir] ??= []; + prev[dir] = [...prev[dir], ...aNodeIds, ...bNodeIds]; // add the node ids of both groups to the axis array in prev + } else if (aGroupId === 'default' || bGroupId === 'default') { + // If either of the groups are in the default space (not in a group), use the same behavior as above + prev[dir] ??= []; + prev[dir] = [...prev[dir], ...aNodeIds, ...bNodeIds]; + } else { + // Otherwise, the nodes in the two groups are not intended to align + const keyA = `${dir}-${cnt++}`; + prev[keyA] = aNodeIds; + const keyB = `${dir}-${cnt++}`; + prev[keyB] = bNodeIds; + } + } + } + + return prev; + }, + {} as Record + ); + }; + + const alignments = spatialMaps.map((spatialMap) => { + const horizontalAlignments: Record> = {}; + const verticalAlignments: Record> = {}; + + // Group service ids in an object with their x and y coordinate as the key + Object.entries(spatialMap).forEach(([id, [x, y]]) => { + const nodeGroup = db.getNode(id)?.in ?? 'default'; + + horizontalAlignments[y] ??= {}; + horizontalAlignments[y][nodeGroup] ??= []; + horizontalAlignments[y][nodeGroup].push(id); + + verticalAlignments[x] ??= {}; + verticalAlignments[x][nodeGroup] ??= []; + verticalAlignments[x][nodeGroup].push(id); + }); + + // Merge the values of each object into a list if the inner list has at least 2 elements + return { + horiz: Object.values(flattenAlignments(horizontalAlignments, 'horizontal')).filter( + (arr) => arr.length > 1 + ), + vert: Object.values(flattenAlignments(verticalAlignments, 'vertical')).filter( + (arr) => arr.length > 1 + ), + }; + }); + + // Merge the alignment lists for each spatial map into one 2d array per axis + const [horizontal, vertical] = alignments.reduce( + ([prevHoriz, prevVert], { horiz, vert }) => { + return [ + [...prevHoriz, ...horiz], + [...prevVert, ...vert], + ]; + }, + [[] as string[][], [] as string[][]] + ); + + return { + horizontal, + vertical, + }; +} + +function getRelativeConstraints( + spatialMaps: ArchitectureSpatialMap[] +): fcose.FcoseRelativePlacementConstraint[] { + const relativeConstraints: fcose.FcoseRelativePlacementConstraint[] = []; + const posToStr = (pos: number[]) => `${pos[0]},${pos[1]}`; + const strToPos = (pos: string) => pos.split(',').map((p) => parseInt(p)); + + spatialMaps.forEach((spatialMap) => { + const invSpatialMap = Object.fromEntries( + Object.entries(spatialMap).map(([id, pos]) => [posToStr(pos), id]) + ); + + // perform BFS + const queue = [posToStr([0, 0])]; + const visited: Record = {}; + const directions: Record = { + L: [-1, 0], + R: [1, 0], + T: [0, 1], + B: [0, -1], + }; + while (queue.length > 0) { + const curr = queue.shift(); + if (curr) { + visited[curr] = 1; + const currId = invSpatialMap[curr]; + if (currId) { + const currPos = strToPos(curr); + Object.entries(directions).forEach(([dir, shift]) => { + const newPos = posToStr([currPos[0] + shift[0], currPos[1] + shift[1]]); + const newId = invSpatialMap[newPos]; + // If there is an adjacent service to the current one and it has not yet been visited + if (newId && !visited[newPos]) { + queue.push(newPos); + // @ts-ignore cannot determine if left/right or top/bottom are paired together + relativeConstraints.push({ + [ArchitectureDirectionName[dir as ArchitectureDirection]]: newId, + [ArchitectureDirectionName[ + getOppositeArchitectureDirection(dir as ArchitectureDirection) + ]]: currId, + gap: 1.5 * getConfigField('iconSize'), + }); + } + }); + } + } + } + }); + return relativeConstraints; +} + +function layoutArchitecture( + services: ArchitectureService[], + junctions: ArchitectureJunction[], + groups: ArchitectureGroup[], + edges: ArchitectureEdge[], + db: ArchitectureDB, + { spatialMaps, groupAlignments }: ArchitectureDataStructures +): Promise { + return new Promise((resolve) => { + const renderEl = select('body').append('div').attr('id', 'cy').attr('style', 'display:none'); + const cy = cytoscape({ + container: document.getElementById('cy'), + style: [ + { + selector: 'edge', + style: { + 'curve-style': 'straight', + label: 'data(label)', + 'source-endpoint': 'data(sourceEndpoint)', + 'target-endpoint': 'data(targetEndpoint)', + }, + }, + { + selector: 'edge.segments', + style: { + 'curve-style': 'segments', + 'segment-weights': '0', + 'segment-distances': [0.5], + // @ts-ignore Incorrect library types + 'edge-distances': 'endpoints', + 'source-endpoint': 'data(sourceEndpoint)', + 'target-endpoint': 'data(targetEndpoint)', + }, + }, + { + selector: 'node', + style: { + // @ts-ignore Incorrect library types + 'compound-sizing-wrt-labels': 'include', + }, + }, + { + selector: 'node[label]', + style: { + 'text-valign': 'bottom', + 'text-halign': 'center', + 'font-size': `${getConfigField('fontSize')}px`, + }, + }, + { + selector: '.node-service', + style: { + label: 'data(label)', + width: 'data(width)', + height: 'data(height)', + }, + }, + { + selector: '.node-junction', + style: { + width: 'data(width)', + height: 'data(height)', + }, + }, + { + selector: '.node-group', + style: { + // @ts-ignore Incorrect library types + padding: `${getConfigField('padding')}px`, + }, + }, + ], + }); + // Remove element after layout + renderEl.remove(); + + addGroups(groups, cy); + addServices(services, cy); + addJunctions(junctions, cy); + addEdges(edges, cy); + // Use the spatial map to create alignment arrays for fcose + const alignmentConstraint = getAlignments(db, spatialMaps, groupAlignments); + + // Create the relative constraints for fcose by using an inverse of the spatial map and performing BFS on it + const relativePlacementConstraint = getRelativeConstraints(spatialMaps); + + const layout = cy.layout({ + name: 'fcose', + quality: 'proof', + styleEnabled: false, + animate: false, + nodeDimensionsIncludeLabels: false, + // Adjust the edge parameters if it passes through the border of a group + // Hacky fix for: https://github.com/iVis-at-Bilkent/cytoscape.js-fcose/issues/67 + idealEdgeLength(edge: EdgeSingular) { + const [nodeA, nodeB] = edge.connectedNodes(); + const { parent: parentA } = nodeData(nodeA); + const { parent: parentB } = nodeData(nodeB); + const elasticity = + parentA === parentB ? 1.5 * getConfigField('iconSize') : 0.5 * getConfigField('iconSize'); + return elasticity; + }, + edgeElasticity(edge: EdgeSingular) { + const [nodeA, nodeB] = edge.connectedNodes(); + const { parent: parentA } = nodeData(nodeA); + const { parent: parentB } = nodeData(nodeB); + const elasticity = parentA === parentB ? 0.45 : 0.001; + return elasticity; + }, + alignmentConstraint, + relativePlacementConstraint, + } as FcoseLayoutOptions); + + // Once the diagram has been generated and the service's position cords are set, adjust the XY edges to have a 90deg bend + layout.one('layoutstop', () => { + function getSegmentWeights( + source: Position, + target: Position, + pointX: number, + pointY: number + ) { + let W, D; + const { x: sX, y: sY } = source; + const { x: tX, y: tY } = target; + + D = + (pointY - sY + ((sX - pointX) * (sY - tY)) / (sX - tX)) / + Math.sqrt(1 + Math.pow((sY - tY) / (sX - tX), 2)); + W = Math.sqrt(Math.pow(pointY - sY, 2) + Math.pow(pointX - sX, 2) - Math.pow(D, 2)); + + const distAB = Math.sqrt(Math.pow(tX - sX, 2) + Math.pow(tY - sY, 2)); + W = W / distAB; + + //check whether the point (pointX, pointY) is on right or left of the line src to tgt. for instance : a point C(X, Y) and line (AB). d=(xB-xA)(yC-yA)-(yB-yA)(xC-xA). if d>0, then C is on left of the line. if d<0, it is on right. if d=0, it is on the line. + let delta1 = (tX - sX) * (pointY - sY) - (tY - sY) * (pointX - sX); + switch (true) { + case delta1 >= 0: + delta1 = 1; + break; + case delta1 < 0: + delta1 = -1; + break; + } + //check whether the point (pointX, pointY) is "behind" the line src to tgt + let delta2 = (tX - sX) * (pointX - sX) + (tY - sY) * (pointY - sY); + switch (true) { + case delta2 >= 0: + delta2 = 1; + break; + case delta2 < 0: + delta2 = -1; + break; + } + + D = Math.abs(D) * delta1; //ensure that sign of D is same as sign of delta1. Hence we need to take absolute value of D and multiply by delta1 + W = W * delta2; + + return { + distances: D, + weights: W, + }; + } + cy.startBatch(); + for (const edge of Object.values(cy.edges())) { + if (edge.data?.()) { + const { x: sX, y: sY } = edge.source().position(); + const { x: tX, y: tY } = edge.target().position(); + if (sX !== tX && sY !== tY) { + const sEP = edge.sourceEndpoint(); + const tEP = edge.targetEndpoint(); + const { sourceDir } = edgeData(edge); + const [pointX, pointY] = isArchitectureDirectionY(sourceDir) + ? [sEP.x, tEP.y] + : [tEP.x, sEP.y]; + const { weights, distances } = getSegmentWeights(sEP, tEP, pointX, pointY); + edge.style('segment-distances', distances); + edge.style('segment-weights', weights); + } + } + } + cy.endBatch(); + layout.run(); + }); + layout.run(); + + cy.ready((e) => { + log.info('Ready', e); + resolve(cy); + }); + }); +} + +export const draw: DrawDefinition = async (text, id, _version, diagObj: Diagram) => { + // TODO: Add title support for architecture diagrams + + const db = diagObj.db as ArchitectureDB; + + const services = db.getServices(); + const junctions = db.getJunctions(); + const groups = db.getGroups(); + const edges = db.getEdges(); + const ds = db.getDataStructures(); + + const svg: SVG = selectSvgElement(id); + + const edgesElem = svg.append('g'); + edgesElem.attr('class', 'architecture-edges'); + + const servicesElem = svg.append('g'); + servicesElem.attr('class', 'architecture-services'); + + const groupElem = svg.append('g'); + groupElem.attr('class', 'architecture-groups'); + + await drawServices(db, servicesElem, services); + drawJunctions(db, servicesElem, junctions); + + const cy = await layoutArchitecture(services, junctions, groups, edges, db, ds); + + await drawEdges(edgesElem, cy); + await drawGroups(groupElem, cy); + positionNodes(db, cy); + + setupGraphViewbox(undefined, svg, getConfigField('padding'), getConfigField('useMaxWidth')); +}; + +export const renderer = { draw }; diff --git a/packages/mermaid/src/diagrams/architecture/architectureStyles.ts b/packages/mermaid/src/diagrams/architecture/architectureStyles.ts new file mode 100644 index 000000000..7f494ecd1 --- /dev/null +++ b/packages/mermaid/src/diagrams/architecture/architectureStyles.ts @@ -0,0 +1,38 @@ +import type { DiagramStylesProvider } from '../../diagram-api/types.js'; +import type { ArchitectureStyleOptions } from './architectureTypes.js'; + +const getStyles: DiagramStylesProvider = (options: ArchitectureStyleOptions) => + ` + .edge { + stroke-width: ${options.archEdgeWidth}; + stroke: ${options.archEdgeColor}; + fill: none; + } + + .arrow { + fill: ${options.archEdgeArrowColor}; + } + + .node-bkg { + fill: none; + stroke: ${options.archGroupBorderColor}; + stroke-width: ${options.archGroupBorderWidth}; + stroke-dasharray: 8; + } + .node-icon-text { + display: flex; + align-items: center; + } + + .node-icon-text > div { + color: #fff; + margin: 1px; + height: fit-content; + text-align: center; + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + } +`; + +export default getStyles; diff --git a/packages/mermaid/src/diagrams/architecture/architectureTypes.ts b/packages/mermaid/src/diagrams/architecture/architectureTypes.ts new file mode 100644 index 000000000..c61df11ff --- /dev/null +++ b/packages/mermaid/src/diagrams/architecture/architectureTypes.ts @@ -0,0 +1,381 @@ +import type { DiagramDBBase } from '../../diagram-api/types.js'; +import type { ArchitectureDiagramConfig } from '../../config.type.js'; +import type { D3Element } from '../../types.js'; +import type cytoscape from 'cytoscape'; + +/*=======================================*\ +| Architecture Diagram Types | +\*=======================================*/ + +export type ArchitectureAlignment = 'vertical' | 'horizontal' | 'bend'; + +export type ArchitectureDirection = 'L' | 'R' | 'T' | 'B'; +export type ArchitectureDirectionX = Extract; +export type ArchitectureDirectionY = Extract; + +/** + * Contains LL, RR, TT, BB which are impossible connections + */ +export type InvalidArchitectureDirectionPair = `${ArchitectureDirection}${ArchitectureDirection}`; +export type ArchitectureDirectionPair = Exclude< + InvalidArchitectureDirectionPair, + 'LL' | 'RR' | 'TT' | 'BB' +>; +export type ArchitectureDirectionPairXY = Exclude< + InvalidArchitectureDirectionPair, + 'LL' | 'RR' | 'TT' | 'BB' | 'LR' | 'RL' | 'TB' | 'BT' +>; + +export const ArchitectureDirectionName = { + L: 'left', + R: 'right', + T: 'top', + B: 'bottom', +} as const; + +export const ArchitectureDirectionArrow = { + L: (scale: number) => `${scale},${scale / 2} 0,${scale} 0,0`, + R: (scale: number) => `0,${scale / 2} ${scale},0 ${scale},${scale}`, + T: (scale: number) => `0,0 ${scale},0 ${scale / 2},${scale}`, + B: (scale: number) => `${scale / 2},0 ${scale},${scale} 0,${scale}`, +} as const; + +export const ArchitectureDirectionArrowShift = { + L: (orig: number, arrowSize: number) => orig - arrowSize + 2, + R: (orig: number, _arrowSize: number) => orig - 2, + T: (orig: number, arrowSize: number) => orig - arrowSize + 2, + B: (orig: number, _arrowSize: number) => orig - 2, +} as const; + +export const getOppositeArchitectureDirection = function ( + x: ArchitectureDirection +): ArchitectureDirection { + if (isArchitectureDirectionX(x)) { + return x === 'L' ? 'R' : 'L'; + } else { + return x === 'T' ? 'B' : 'T'; + } +}; + +export const isArchitectureDirection = function (x: unknown): x is ArchitectureDirection { + const temp = x as ArchitectureDirection; + return temp === 'L' || temp === 'R' || temp === 'T' || temp === 'B'; +}; + +export const isArchitectureDirectionX = function ( + x: ArchitectureDirection +): x is ArchitectureDirectionX { + const temp = x as ArchitectureDirectionX; + return temp === 'L' || temp === 'R'; +}; + +export const isArchitectureDirectionY = function ( + x: ArchitectureDirection +): x is ArchitectureDirectionY { + const temp = x as ArchitectureDirectionY; + return temp === 'T' || temp === 'B'; +}; + +export const isArchitectureDirectionXY = function ( + a: ArchitectureDirection, + b: ArchitectureDirection +) { + const aX_bY = isArchitectureDirectionX(a) && isArchitectureDirectionY(b); + const aY_bX = isArchitectureDirectionY(a) && isArchitectureDirectionX(b); + return aX_bY || aY_bX; +}; + +export const isArchitecturePairXY = function ( + pair: ArchitectureDirectionPair +): pair is ArchitectureDirectionPairXY { + const lhs = pair[0] as ArchitectureDirection; + const rhs = pair[1] as ArchitectureDirection; + const aX_bY = isArchitectureDirectionX(lhs) && isArchitectureDirectionY(rhs); + const aY_bX = isArchitectureDirectionY(lhs) && isArchitectureDirectionX(rhs); + return aX_bY || aY_bX; +}; + +/** + * Verifies that the architecture direction pair does not contain an invalid match (LL, RR, TT, BB) + * @param x - architecture direction pair which could potentially be invalid + * @returns true if the pair is not LL, RR, TT, or BB + */ +export const isValidArchitectureDirectionPair = function ( + x: InvalidArchitectureDirectionPair +): x is ArchitectureDirectionPair { + return x !== 'LL' && x !== 'RR' && x !== 'TT' && x !== 'BB'; +}; + +export type ArchitectureDirectionPairMap = Partial>; + +/** + * Creates a pair of the directions of each side of an edge. This function should be used instead of manually creating it to ensure that the source is always the first character. + * + * Note: Undefined is returned when sourceDir and targetDir are the same. In theory this should never happen since the diagram parser throws an error if a user defines it as such. + * @param sourceDir - source direction + * @param targetDir - target direction + * @returns + */ +export const getArchitectureDirectionPair = function ( + sourceDir: ArchitectureDirection, + targetDir: ArchitectureDirection +): ArchitectureDirectionPair | undefined { + const pair: `${ArchitectureDirection}${ArchitectureDirection}` = `${sourceDir}${targetDir}`; + return isValidArchitectureDirectionPair(pair) ? pair : undefined; +}; + +/** + * Given an x,y position for an arrow and the direction of the edge it belongs to, return a factor for slightly shifting the edge + * @param param0 - [x, y] coordinate pair + * @param pair - architecture direction pair + * @returns a new [x, y] coordinate pair + */ +export const shiftPositionByArchitectureDirectionPair = function ( + [x, y]: number[], + pair: ArchitectureDirectionPair +): number[] { + const lhs = pair[0] as ArchitectureDirection; + const rhs = pair[1] as ArchitectureDirection; + if (isArchitectureDirectionX(lhs)) { + if (isArchitectureDirectionY(rhs)) { + return [x + (lhs === 'L' ? -1 : 1), y + (rhs === 'T' ? 1 : -1)]; + } else { + return [x + (lhs === 'L' ? -1 : 1), y]; + } + } else { + if (isArchitectureDirectionX(rhs)) { + return [x + (rhs === 'L' ? 1 : -1), y + (lhs === 'T' ? 1 : -1)]; + } else { + return [x, y + (lhs === 'T' ? 1 : -1)]; + } + } +}; + +/** + * Given the directional pair of an XY edge, get the scale factors necessary to shift the coordinates inwards towards the edge + * @param pair - XY pair of an edge + * @returns - number[] containing [+/- 1, +/- 1] + */ +export const getArchitectureDirectionXYFactors = function ( + pair: ArchitectureDirectionPairXY +): number[] { + if (pair === 'LT' || pair === 'TL') { + return [1, 1]; + } else if (pair === 'BL' || pair === 'LB') { + return [1, -1]; + } else if (pair === 'BR' || pair === 'RB') { + return [-1, -1]; + } else { + return [-1, 1]; + } +}; + +export const getArchitectureDirectionAlignment = function ( + a: ArchitectureDirection, + b: ArchitectureDirection +): ArchitectureAlignment { + if (isArchitectureDirectionXY(a, b)) { + return 'bend'; + } else if (isArchitectureDirectionX(a)) { + return 'horizontal'; + } + return 'vertical'; +}; + +export interface ArchitectureStyleOptions { + archEdgeColor: string; + archEdgeArrowColor: string; + archEdgeWidth: string; + archGroupBorderColor: string; + archGroupBorderWidth: string; +} + +export interface ArchitectureService { + id: string; + type: 'service'; + edges: ArchitectureEdge[]; + icon?: string; + iconText?: string; + title?: string; + in?: string; + width?: number; + height?: number; +} + +export interface ArchitectureJunction { + id: string; + type: 'junction'; + edges: ArchitectureEdge[]; + in?: string; + width?: number; + height?: number; +} + +export type ArchitectureNode = ArchitectureService | ArchitectureJunction; + +export const isArchitectureService = function (x: ArchitectureNode): x is ArchitectureService { + const temp = x as ArchitectureService; + return temp.type === 'service'; +}; + +export const isArchitectureJunction = function (x: ArchitectureNode): x is ArchitectureJunction { + const temp = x as ArchitectureJunction; + return temp.type === 'junction'; +}; + +export interface ArchitectureGroup { + id: string; + icon?: string; + title?: string; + in?: string; +} + +export interface ArchitectureEdge
{ + lhsId: string; + lhsDir: DT; + lhsInto?: boolean; + lhsGroup?: boolean; + rhsId: string; + rhsDir: DT; + rhsInto?: boolean; + rhsGroup?: boolean; + title?: string; +} + +export interface ArchitectureDB extends DiagramDBBase { + clear: () => void; + addService: (service: Omit) => void; + getServices: () => ArchitectureService[]; + addJunction: (service: Omit) => void; + getJunctions: () => ArchitectureJunction[]; + getNodes: () => ArchitectureNode[]; + getNode: (id: string) => ArchitectureNode | null; + addGroup: (group: ArchitectureGroup) => void; + getGroups: () => ArchitectureGroup[]; + addEdge: (edge: ArchitectureEdge) => void; + getEdges: () => ArchitectureEdge[]; + setElementForId: (id: string, element: D3Element) => void; + getElementById: (id: string) => D3Element; + getDataStructures: () => ArchitectureDataStructures; +} + +export type ArchitectureAdjacencyList = Record; +export type ArchitectureSpatialMap = Record; + +/** + * Maps the direction that groups connect from. + * + * **Outer key**: ID of group A + * + * **Inner key**: ID of group B + * + * **Value**: 'vertical' or 'horizontal' + * + * Note: tmp[groupA][groupB] == tmp[groupB][groupA] + */ +export type ArchitectureGroupAlignments = Record< + string, + Record> +>; + +export interface ArchitectureDataStructures { + adjList: ArchitectureAdjacencyList; + spatialMaps: ArchitectureSpatialMap[]; + groupAlignments: ArchitectureGroupAlignments; +} + +export interface ArchitectureState extends Record { + nodes: Record; + groups: Record; + edges: ArchitectureEdge[]; + registeredIds: Record; + dataStructures?: ArchitectureDataStructures; + elements: Record; + config: ArchitectureDiagramConfig; +} + +/*=======================================*\ +| Cytoscape Override Types | +\*=======================================*/ + +export interface EdgeSingularData { + id: string; + label?: string; + source: string; + sourceDir: ArchitectureDirection; + sourceArrow?: boolean; + sourceGroup?: boolean; + target: string; + targetDir: ArchitectureDirection; + targetArrow?: boolean; + targetGroup?: boolean; + [key: string]: any; +} + +export const edgeData = (edge: cytoscape.EdgeSingular) => { + return edge.data() as EdgeSingularData; +}; + +export interface EdgeSingular extends cytoscape.EdgeSingular { + _private: { + bodyBounds: unknown; + rscratch: { + startX: number; + startY: number; + midX: number; + midY: number; + endX: number; + endY: number; + }; + }; + data(): EdgeSingularData; + data(key: T): EdgeSingularData[T]; +} + +export type NodeSingularData = + | { + type: 'service'; + id: string; + icon?: string; + label?: string; + parent?: string; + width: number; + height: number; + [key: string]: any; + } + | { + type: 'junction'; + id: string; + parent?: string; + width: number; + height: number; + [key: string]: any; + } + | { + type: 'group'; + id: string; + icon?: string; + label?: string; + parent?: string; + [key: string]: any; + }; + +export const nodeData = (node: cytoscape.NodeSingular) => { + return node.data() as NodeSingularData; +}; + +export interface NodeSingular extends cytoscape.NodeSingular { + _private: { + bodyBounds: { + h: number; + w: number; + x1: number; + x2: number; + y1: number; + y2: number; + }; + children: cytoscape.NodeSingular[]; + }; + data(): NodeSingularData; + data(key: T): NodeSingularData[T]; +} diff --git a/packages/mermaid/src/diagrams/architecture/svgDraw.ts b/packages/mermaid/src/diagrams/architecture/svgDraw.ts new file mode 100644 index 000000000..b10a451fe --- /dev/null +++ b/packages/mermaid/src/diagrams/architecture/svgDraw.ts @@ -0,0 +1,370 @@ +import { getIconSVG } from '../../rendering-util/icons.js'; +import type cytoscape from 'cytoscape'; +import { getConfig } from '../../diagram-api/diagramAPI.js'; +import { createText } from '../../rendering-util/createText.js'; +import type { D3Element } from '../../types.js'; +import { db, getConfigField } from './architectureDb.js'; +import { architectureIcons } from './architectureIcons.js'; +import { + ArchitectureDirectionArrow, + ArchitectureDirectionArrowShift, + edgeData, + getArchitectureDirectionPair, + getArchitectureDirectionXYFactors, + isArchitectureDirectionX, + isArchitectureDirectionXY, + isArchitectureDirectionY, + isArchitecturePairXY, + nodeData, + type ArchitectureDB, + type ArchitectureJunction, + type ArchitectureService, +} from './architectureTypes.js'; + +export const drawEdges = async function (edgesEl: D3Element, cy: cytoscape.Core) { + const padding = getConfigField('padding'); + const iconSize = getConfigField('iconSize'); + const halfIconSize = iconSize / 2; + const arrowSize = iconSize / 6; + const halfArrowSize = arrowSize / 2; + + await Promise.all( + cy.edges().map(async (edge) => { + const { + source, + sourceDir, + sourceArrow, + sourceGroup, + target, + targetDir, + targetArrow, + targetGroup, + label, + } = edgeData(edge); + let { x: startX, y: startY } = edge[0].sourceEndpoint(); + const { x: midX, y: midY } = edge[0].midpoint(); + let { x: endX, y: endY } = edge[0].targetEndpoint(); + + // Adjust the edge distance if it has the {group} modifier + const groupEdgeShift = padding + 4; + // +18 comes from the service label height that extends the padding on the bottom side of each group + if (sourceGroup) { + if (isArchitectureDirectionX(sourceDir)) { + startX += sourceDir === 'L' ? -groupEdgeShift : groupEdgeShift; + } else { + startY += sourceDir === 'T' ? -groupEdgeShift : groupEdgeShift + 18; + } + } + + if (targetGroup) { + if (isArchitectureDirectionX(targetDir)) { + endX += targetDir === 'L' ? -groupEdgeShift : groupEdgeShift; + } else { + endY += targetDir === 'T' ? -groupEdgeShift : groupEdgeShift + 18; + } + } + + // Adjust the edge distance if it doesn't have the {group} modifier and the endpoint is a junction node + if (!sourceGroup && db.getNode(source)?.type === 'junction') { + if (isArchitectureDirectionX(sourceDir)) { + startX += sourceDir === 'L' ? halfIconSize : -halfIconSize; + } else { + startY += sourceDir === 'T' ? halfIconSize : -halfIconSize; + } + } + if (!targetGroup && db.getNode(target)?.type === 'junction') { + if (isArchitectureDirectionX(targetDir)) { + endX += targetDir === 'L' ? halfIconSize : -halfIconSize; + } else { + endY += targetDir === 'T' ? halfIconSize : -halfIconSize; + } + } + + if (edge[0]._private.rscratch) { + // const bounds = edge[0]._private.rscratch; + + const g = edgesEl.insert('g'); + + g.insert('path') + .attr('d', `M ${startX},${startY} L ${midX},${midY} L${endX},${endY} `) + .attr('class', 'edge'); + + if (sourceArrow) { + const xShift = isArchitectureDirectionX(sourceDir) + ? ArchitectureDirectionArrowShift[sourceDir](startX, arrowSize) + : startX - halfArrowSize; + const yShift = isArchitectureDirectionY(sourceDir) + ? ArchitectureDirectionArrowShift[sourceDir](startY, arrowSize) + : startY - halfArrowSize; + + g.insert('polygon') + .attr('points', ArchitectureDirectionArrow[sourceDir](arrowSize)) + .attr('transform', `translate(${xShift},${yShift})`) + .attr('class', 'arrow'); + } + if (targetArrow) { + const xShift = isArchitectureDirectionX(targetDir) + ? ArchitectureDirectionArrowShift[targetDir](endX, arrowSize) + : endX - halfArrowSize; + const yShift = isArchitectureDirectionY(targetDir) + ? ArchitectureDirectionArrowShift[targetDir](endY, arrowSize) + : endY - halfArrowSize; + + g.insert('polygon') + .attr('points', ArchitectureDirectionArrow[targetDir](arrowSize)) + .attr('transform', `translate(${xShift},${yShift})`) + .attr('class', 'arrow'); + } + + if (label) { + const axis = !isArchitectureDirectionXY(sourceDir, targetDir) + ? isArchitectureDirectionX(sourceDir) + ? 'X' + : 'Y' + : 'XY'; + + let width = 0; + if (axis === 'X') { + width = Math.abs(startX - endX); + } else if (axis === 'Y') { + // Reduce width by a factor of 1.5 to avoid overlapping service labels + width = Math.abs(startY - endY) / 1.5; + } else { + width = Math.abs(startX - endX) / 2; + } + + const textElem = g.append('g'); + await createText( + textElem, + label, + { + useHtmlLabels: false, + width, + classes: 'architecture-service-label', + }, + getConfig() + ); + + textElem + .attr('dy', '1em') + .attr('alignment-baseline', 'middle') + .attr('dominant-baseline', 'middle') + .attr('text-anchor', 'middle'); + + if (axis === 'X') { + textElem.attr('transform', 'translate(' + midX + ', ' + midY + ')'); + } else if (axis === 'Y') { + textElem.attr('transform', 'translate(' + midX + ', ' + midY + ') rotate(-90)'); + } else if (axis === 'XY') { + const pair = getArchitectureDirectionPair(sourceDir, targetDir); + if (pair && isArchitecturePairXY(pair)) { + const bboxOrig = textElem.node().getBoundingClientRect(); + const [x, y] = getArchitectureDirectionXYFactors(pair); + + textElem + .attr('dominant-baseline', 'auto') + .attr('transform', `rotate(${-1 * x * y * 45})`); + + // Calculate the new width/height with the rotation applied, and transform to the proper position + const bboxNew = textElem.node().getBoundingClientRect(); + textElem.attr( + 'transform', + ` + translate(${midX}, ${midY - bboxOrig.height / 2}) + translate(${(x * bboxNew.width) / 2}, ${(y * bboxNew.height) / 2}) + rotate(${-1 * x * y * 45}, 0, ${bboxOrig.height / 2}) + ` + ); + } + } + } + } + }) + ); +}; + +export const drawGroups = async function (groupsEl: D3Element, cy: cytoscape.Core) { + const padding = getConfigField('padding'); + const groupIconSize = padding * 0.75; + + const fontSize = getConfigField('fontSize'); + + const iconSize = getConfigField('iconSize'); + const halfIconSize = iconSize / 2; + + await Promise.all( + cy.nodes().map(async (node) => { + const data = nodeData(node); + if (data.type === 'group') { + const { h, w, x1, y1 } = node.boundingBox(); + + groupsEl + .append('rect') + .attr('x', x1 + halfIconSize) + .attr('y', y1 + halfIconSize) + .attr('width', w) + .attr('height', h) + .attr('class', 'node-bkg'); + + const groupLabelContainer = groupsEl.append('g'); + let shiftedX1 = x1; + let shiftedY1 = y1; + if (data.icon) { + const bkgElem = groupLabelContainer.append('g'); + bkgElem.html( + `${await getIconSVG(data.icon, { height: groupIconSize, width: groupIconSize, fallbackPrefix: architectureIcons.prefix })}` + ); + bkgElem.attr( + 'transform', + 'translate(' + + (shiftedX1 + halfIconSize + 1) + + ', ' + + (shiftedY1 + halfIconSize + 1) + + ')' + ); + shiftedX1 += groupIconSize; + // TODO: test with more values + // - 1 - 2 comes from the Y axis transform of the icon and label + shiftedY1 += fontSize / 2 - 1 - 2; + } + if (data.label) { + const textElem = groupLabelContainer.append('g'); + await createText( + textElem, + data.label, + { + useHtmlLabels: false, + width: w, + classes: 'architecture-service-label', + }, + getConfig() + ); + textElem + .attr('dy', '1em') + .attr('alignment-baseline', 'middle') + .attr('dominant-baseline', 'start') + .attr('text-anchor', 'start'); + + textElem.attr( + 'transform', + 'translate(' + + (shiftedX1 + halfIconSize + 4) + + ', ' + + (shiftedY1 + halfIconSize + 2) + + ')' + ); + } + } + }) + ); +}; + +export const drawServices = async function ( + db: ArchitectureDB, + elem: D3Element, + services: ArchitectureService[] +): Promise { + for (const service of services) { + const serviceElem = elem.append('g'); + const iconSize = getConfigField('iconSize'); + + if (service.title) { + const textElem = serviceElem.append('g'); + await createText( + textElem, + service.title, + { + useHtmlLabels: false, + width: iconSize * 1.5, + classes: 'architecture-service-label', + }, + getConfig() + ); + + textElem + .attr('dy', '1em') + .attr('alignment-baseline', 'middle') + .attr('dominant-baseline', 'middle') + .attr('text-anchor', 'middle'); + + textElem.attr('transform', 'translate(' + iconSize / 2 + ', ' + iconSize + ')'); + } + + const bkgElem = serviceElem.append('g'); + if (service.icon) { + // TODO: should a warning be given to end-users saying which icon names are available? + // if (!isIconNameInUse(service.icon)) { + // throw new Error(`Invalid SVG Icon name: "${service.icon}"`); + // } + bkgElem.html( + `${await getIconSVG(service.icon, { height: iconSize, width: iconSize, fallbackPrefix: architectureIcons.prefix })}` + ); + } else if (service.iconText) { + bkgElem.html( + `${await getIconSVG('blank', { height: iconSize, width: iconSize, fallbackPrefix: architectureIcons.prefix })}` + ); + const textElemContainer = bkgElem.append('g'); + const fo = textElemContainer + .append('foreignObject') + .attr('width', iconSize) + .attr('height', iconSize); + const divElem = fo + .append('div') + .attr('class', 'node-icon-text') + .attr('style', `height: ${iconSize}px;`) + .append('div') + .html(service.iconText); + const fontSize = + parseInt( + window + .getComputedStyle(divElem.node(), null) + .getPropertyValue('font-size') + .replace(/\D/g, '') + ) ?? 16; + divElem.attr('style', `-webkit-line-clamp: ${Math.floor((iconSize - 2) / fontSize)};`); + } else { + bkgElem + .append('path') + .attr('class', 'node-bkg') + .attr('id', 'node-' + service.id) + .attr( + 'd', + `M0 ${iconSize} v${-iconSize} q0,-5 5,-5 h${iconSize} q5,0 5,5 v${iconSize} H0 Z` + ); + } + + serviceElem.attr('class', 'architecture-service'); + + const { width, height } = serviceElem._groups[0][0].getBBox(); + service.width = width; + service.height = height; + db.setElementForId(service.id, serviceElem); + } + return 0; +}; + +export const drawJunctions = function ( + db: ArchitectureDB, + elem: D3Element, + junctions: ArchitectureJunction[] +) { + junctions.forEach((junction) => { + const junctionElem = elem.append('g'); + const iconSize = getConfigField('iconSize'); + + const bkgElem = junctionElem.append('g'); + bkgElem + .append('rect') + .attr('id', 'node-' + junction.id) + .attr('fill-opacity', '0') + .attr('width', iconSize) + .attr('height', iconSize); + + junctionElem.attr('class', 'architecture-junction'); + + const { width, height } = junctionElem._groups[0][0].getBBox(); + junctionElem.width = width; + junctionElem.height = height; + db.setElementForId(junction.id, junctionElem); + }); +}; diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts index e4c863c1d..d6e35ed15 100644 --- a/packages/mermaid/src/diagrams/block/blockDB.ts +++ b/packages/mermaid/src/diagrams/block/blockDB.ts @@ -1,21 +1,26 @@ import clone from 'lodash-es/clone.js'; import * as configApi from '../../config.js'; +import { getConfig } from '../../diagram-api/diagramAPI.js'; import type { DiagramDB } from '../../diagram-api/types.js'; import { log } from '../../logger.js'; +import common from '../common/common.js'; import { clear as commonClear } from '../common/commonDb.js'; import type { Block, ClassDef } from './blockTypes.js'; // Initialize the node database for simple lookups -let blockDatabase: Record = {}; +let blockDatabase = new Map(); let edgeList: Block[] = []; -let edgeCount: Record = {}; +let edgeCount = new Map(); const COLOR_KEYWORD = 'color'; const FILL_KEYWORD = 'fill'; const BG_FILL = 'bgFill'; const STYLECLASS_SEP = ','; +const config = getConfig(); -let classes = {} as Record; +let classes = new Map(); + +const sanitizeText = (txt: string) => common.sanitizeText(txt, config); /** * Called when the parser comes across a (style) class definition @@ -26,17 +31,18 @@ let classes = {} as Record; */ export const addStyleClass = function (id: string, styleAttributes = '') { // create a new style class object with this id - if (classes[id] === undefined) { - classes[id] = { id: id, styles: [], textStyles: [] }; // This is a classDef + let foundClass = classes.get(id); + if (!foundClass) { + foundClass = { id: id, styles: [], textStyles: [] }; + classes.set(id, foundClass); // This is a classDef } - const foundClass = classes[id]; if (styleAttributes !== undefined && styleAttributes !== null) { styleAttributes.split(STYLECLASS_SEP).forEach((attrib) => { // remove any trailing ; const fixedAttrib = attrib.replace(/([^;]*);/, '$1').trim(); // replace some style keywords - if (attrib.match(COLOR_KEYWORD)) { + if (RegExp(COLOR_KEYWORD).exec(attrib)) { const newStyle1 = fixedAttrib.replace(FILL_KEYWORD, BG_FILL); const newStyle2 = newStyle1.replace(COLOR_KEYWORD, FILL_KEYWORD); foundClass.textStyles.push(newStyle2); @@ -54,7 +60,7 @@ export const addStyleClass = function (id: string, styleAttributes = '') { * @param styles - the string with 1 or more style attributes (each separated by a comma) */ export const addStyle2Node = function (id: string, styles = '') { - const foundBlock = blockDatabase[id]; + const foundBlock = blockDatabase.get(id)!; if (styles !== undefined && styles !== null) { foundBlock.styles = styles.split(STYLECLASS_SEP); } @@ -70,11 +76,11 @@ export const addStyle2Node = function (id: string, styles = '') { */ export const setCssClass = function (itemIds: string, cssClassName: string) { itemIds.split(',').forEach(function (id: string) { - let foundBlock = blockDatabase[id]; + let foundBlock = blockDatabase.get(id); if (foundBlock === undefined) { const trimmedId = id.trim(); - blockDatabase[trimmedId] = { id: trimmedId, type: 'na', children: [] } as Block; - foundBlock = blockDatabase[trimmedId]; + foundBlock = { id: trimmedId, type: 'na', children: [] } as Block; + blockDatabase.set(trimmedId, foundBlock); } if (!foundBlock.classes) { foundBlock.classes = []; @@ -83,16 +89,19 @@ export const setCssClass = function (itemIds: string, cssClassName: string) { }); }; -const populateBlockDatabase = (_blockList: Block[] | Block[][], parent: Block): void => { +const populateBlockDatabase = (_blockList: Block[], parent: Block): void => { const blockList = _blockList.flat(); const children = []; for (const block of blockList) { + if (block.label) { + block.label = sanitizeText(block.label); + } if (block.type === 'classDef') { addStyleClass(block.id, block.css); continue; } if (block.type === 'applyClass') { - setCssClass(block.id, block?.styleClass || ''); + setCssClass(block.id, block?.styleClass ?? ''); continue; } if (block.type === 'applyStyles') { @@ -102,14 +111,11 @@ const populateBlockDatabase = (_blockList: Block[] | Block[][], parent: Block): continue; } if (block.type === 'column-setting') { - parent.columns = block.columns || -1; + parent.columns = block.columns ?? -1; } else if (block.type === 'edge') { - if (edgeCount[block.id]) { - edgeCount[block.id]++; - } else { - edgeCount[block.id] = 1; - } - block.id = edgeCount[block.id] + '-' + block.id; + const count = (edgeCount.get(block.id) ?? 0) + 1; + edgeCount.set(block.id, count); + block.id = count + '-' + block.id; edgeList.push(block); } else { if (!block.label) { @@ -120,16 +126,17 @@ const populateBlockDatabase = (_blockList: Block[] | Block[][], parent: Block): block.label = block.id; } } - const newBlock = !blockDatabase[block.id]; - if (newBlock) { - blockDatabase[block.id] = block; + const existingBlock = blockDatabase.get(block.id); + + if (existingBlock === undefined) { + blockDatabase.set(block.id, block); } else { // Add newer relevant data to aggregated node if (block.type !== 'na') { - blockDatabase[block.id].type = block.type; + existingBlock.type = block.type; } if (block.label !== block.id) { - blockDatabase[block.id].label = block.label; + existingBlock.label = block.label; } } @@ -138,14 +145,14 @@ const populateBlockDatabase = (_blockList: Block[] | Block[][], parent: Block): } if (block.type === 'space') { // log.debug('abc95 space', block); - const w = block.width || 1; + const w = block.width ?? 1; for (let j = 0; j < w; j++) { const newBlock = clone(block); newBlock.id = newBlock.id + '-' + j; - blockDatabase[newBlock.id] = newBlock; + blockDatabase.set(newBlock.id, newBlock); children.push(newBlock); } - } else if (newBlock) { + } else if (existingBlock === undefined) { children.push(block); } } @@ -160,12 +167,12 @@ const clear = (): void => { log.debug('Clear called'); commonClear(); rootBlock = { id: 'root', type: 'composite', children: [], columns: -1 } as Block; - blockDatabase = { root: rootBlock }; - blocks = [] as Block[]; - classes = {} as Record; + blockDatabase = new Map([['root', rootBlock]]); + blocks = []; + classes = new Map(); edgeList = []; - edgeCount = {}; + edgeCount = new Map(); }; export function typeStr2Type(typeStr: string) { @@ -241,7 +248,7 @@ const setHierarchy = (block: Block[]): void => { }; const getColumns = (blockId: string): number => { - const block = blockDatabase[blockId]; + const block = blockDatabase.get(blockId); if (!block) { return -1; } @@ -259,10 +266,10 @@ const getColumns = (blockId: string): number => { * @returns */ const getBlocksFlat = () => { - return [...Object.values(blockDatabase)]; + return [...blockDatabase.values()]; }; /** - * Returns the the hierarchy of blocks + * Returns the hierarchy of blocks * @returns */ const getBlocks = () => { @@ -273,11 +280,11 @@ const getEdges = () => { return edgeList; }; const getBlock = (id: string) => { - return blockDatabase[id]; + return blockDatabase.get(id); }; const setBlock = (block: Block) => { - blockDatabase[block.id] = block; + blockDatabase.set(block.id, block); }; const getLogger = () => console; diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts index e6289ad82..509b5b715 100644 --- a/packages/mermaid/src/diagrams/block/blockRenderer.ts +++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts @@ -1,11 +1,6 @@ -import { - scaleOrdinal as d3scaleOrdinal, - schemeTableau10 as d3schemeTableau10, - select as d3select, -} from 'd3'; +import { select as d3select } from 'd3'; import type { Diagram } from '../../Diagram.js'; import * as configApi from '../../config.js'; -import type { MermaidConfig } from '../../config.type.js'; import insertMarkers from '../../dagre-wrapper/markers.js'; import { log } from '../../logger.js'; import { configureSvgSize } from '../../setupGraphViewbox.js'; @@ -13,13 +8,6 @@ import type { BlockDB } from './blockDB.js'; import { layout } from './layout.js'; import { calculateBlockSizes, insertBlocks, insertEdges } from './renderHelpers.js'; -/** - * Returns the all the styles from classDef statements in the graph definition. - * - * @param text - The text with the classes - * @param diagObj - The diagram object - * @returns ClassDef - The styles - */ export const getClasses = function (text: any, diagObj: any) { return diagObj.db.getClasses(); }; @@ -50,8 +38,6 @@ export const draw = async function ( const markers = ['point', 'circle', 'cross']; // Add the marker definitions to the svg as marker tags - // insertMarkers(svg, markers, diagObj.type, diagObj.arrowMarkerAbsolute); - // insertMarkers(svg, markers, diagObj.type, true); insertMarkers(svg, markers, diagObj.type, id); const bl = db.getBlocks(); @@ -64,18 +50,14 @@ export const draw = async function ( await insertBlocks(nodes, bl, db); await insertEdges(nodes, edges, blArr, db, id); - // log.debug('Here', bl); - // Establish svg dimensions and get width and height - // - // const bounds2 = nodes.node().getBoundingClientRect(); // Why, oh why ???? if (bounds) { const bounds2 = bounds; const magicFactor = Math.max(1, Math.round(0.125 * (bounds2.width / bounds2.height))); const height = bounds2.height + magicFactor + 10; const width = bounds2.width + 10; - const { useMaxWidth } = conf as Exclude; + const { useMaxWidth } = conf!; configureSvgSize(svg, height, width, !!useMaxWidth); log.debug('Here Bounds', bounds, bounds2); svg.attr( @@ -83,9 +65,6 @@ export const draw = async function ( `${bounds2.x - 5} ${bounds2.y - 5} ${bounds2.width + 10} ${bounds2.height + 10}` ); } - - // Get color scheme for the graph - const colorScheme = d3scaleOrdinal(d3schemeTableau10); }; export default { diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts index c16d4e497..a00e935ac 100644 --- a/packages/mermaid/src/diagrams/block/layout.ts +++ b/packages/mermaid/src/diagrams/block/layout.ts @@ -2,7 +2,8 @@ import type { BlockDB } from './blockDB.js'; import type { Block } from './blockTypes.js'; import { log } from '../../logger.js'; import { getConfig } from '../../diagram-api/diagramAPI.js'; -const padding = getConfig()?.block?.padding || 8; +// TODO: This means the number we provide in diagram's config will never be used. Should fix. +const padding = getConfig()?.block?.padding ?? 8; interface BlockPosition { px: number; @@ -42,7 +43,7 @@ const getMaxChildSize = (block: Block) => { // find max width of children // log.debug('getMaxChildSize abc95 (start) parent:', block.id); for (const child of block.children) { - const { width, height, x, y } = child.size || { width: 0, height: 0, x: 0, y: 0 }; + const { width, height, x, y } = child.size ?? { width: 0, height: 0, x: 0, y: 0 }; log.debug( 'getMaxChildSize abc95 child:', child.id, @@ -60,7 +61,7 @@ const getMaxChildSize = (block: Block) => { continue; } if (width > maxWidth) { - maxWidth = width / (block.widthInColumns || 1); + maxWidth = width / (block.widthInColumns ?? 1); } if (height > maxHeight) { maxHeight = height; @@ -76,7 +77,7 @@ function setBlockSizes(block: Block, db: BlockDB, siblingWidth = 0, siblingHeigh block?.size?.x, 'block width =', block?.size, - 'sieblingWidth', + 'siblingWidth', siblingWidth ); if (!block?.size?.width) { @@ -104,10 +105,10 @@ function setBlockSizes(block: Block, db: BlockDB, siblingWidth = 0, siblingHeigh for (const child of block.children) { if (child.size) { log.debug( - `abc95 Setting size of children of ${block.id} id=${child.id} ${maxWidth} ${maxHeight} ${child.size}` + `abc95 Setting size of children of ${block.id} id=${child.id} ${maxWidth} ${maxHeight} ${JSON.stringify(child.size)}` ); child.size.width = - maxWidth * (child.widthInColumns || 1) + padding * ((child.widthInColumns || 1) - 1); + maxWidth * (child.widthInColumns ?? 1) + padding * ((child.widthInColumns ?? 1) - 1); child.size.height = maxHeight; child.size.x = 0; child.size.y = 0; @@ -121,10 +122,10 @@ function setBlockSizes(block: Block, db: BlockDB, siblingWidth = 0, siblingHeigh setBlockSizes(child, db, maxWidth, maxHeight); } - const columns = block.columns || -1; + const columns = block.columns ?? -1; let numItems = 0; for (const child of block.children) { - numItems += child.widthInColumns || 1; + numItems += child.widthInColumns ?? 1; } // The width and height in number blocks @@ -133,8 +134,6 @@ function setBlockSizes(block: Block, db: BlockDB, siblingWidth = 0, siblingHeigh xSize = columns; } - const w = block.widthInColumns || 1; - const ySize = Math.ceil(numItems / xSize); let width = xSize * (maxWidth + padding) + padding; @@ -142,7 +141,7 @@ function setBlockSizes(block: Block, db: BlockDB, siblingWidth = 0, siblingHeigh // If maxWidth if (width < siblingWidth) { log.debug( - `Detected to small siebling: abc95 ${block.id} sieblingWidth ${siblingWidth} sieblingHeight ${siblingHeight} width ${width}` + `Detected to small sibling: abc95 ${block.id} siblingWidth ${siblingWidth} siblingHeight ${siblingHeight} width ${width}` ); width = siblingWidth; height = siblingHeight; @@ -206,13 +205,13 @@ function layoutBlocks(block: Block, db: BlockDB) { log.debug( `abc85 layout blocks (=>layoutBlocks) ${block.id} x: ${block?.size?.x} y: ${block?.size?.y} width: ${block?.size?.width}` ); - const columns = block.columns || -1; + const columns = block.columns ?? -1; log.debug('layoutBlocks columns abc95', block.id, '=>', columns, block); if ( block.children && // find max width of children block.children.length > 0 ) { - const width = block?.children[0]?.size?.width || 0; + const width = block?.children[0]?.size?.width ?? 0; const widthOfChildren = block.children.length * width + (block.children.length - 1) * padding; log.debug('widthOfChildren 88', widthOfChildren, 'posX'); @@ -251,7 +250,7 @@ function layoutBlocks(block: Block, db: BlockDB) { } ${halfWidth} padding=${padding} width=${width} halfWidth=${halfWidth} => x:${ child.size.x } y:${child.size.y} ${child.widthInColumns} (width * (child?.w || 1)) / 2 ${ - (width * (child?.widthInColumns || 1)) / 2 + (width * (child?.widthInColumns ?? 1)) / 2 }` ); @@ -265,15 +264,13 @@ function layoutBlocks(block: Block, db: BlockDB) { child.id }startingPosX${startingPosX}${padding}${halfWidth}=>x:${child.size.x}y:${child.size.y}${ child.widthInColumns - }(width * (child?.w || 1)) / 2${(width * (child?.widthInColumns || 1)) / 2}` + }(width * (child?.w || 1)) / 2${(width * (child?.widthInColumns ?? 1)) / 2}` ); } - - // posY += height + padding; if (child.children) { layoutBlocks(child, db); } - columnPos += child?.widthInColumns || 1; + columnPos += child?.widthInColumns ?? 1; log.debug('abc88 columnsPos', child, columnPos); } } diff --git a/packages/mermaid/src/diagrams/block/parser/block.spec.ts b/packages/mermaid/src/diagrams/block/parser/block.spec.ts index 65338375a..4bf3290d8 100644 --- a/packages/mermaid/src/diagrams/block/parser/block.spec.ts +++ b/packages/mermaid/src/diagrams/block/parser/block.spec.ts @@ -1,19 +1,16 @@ // @ts-ignore: jison doesn't export types import block from './block.jison'; import db from '../blockDB.js'; -import { cleanupComments } from '../../../diagram-api/comments.js'; -import { prepareTextForParsing } from '../blockUtils.js'; -import { setConfig } from '../../../config.js'; describe('Block diagram', function () { - describe('when parsing an block diagram graph it should handle > ', function () { + describe('when parsing a block diagram graph it should handle > ', function () { beforeEach(function () { block.parser.yy = db; block.parser.yy.clear(); block.parser.yy.getLogger = () => console; }); - it('a diagram with a node', async () => { + it('a diagram with a node', () => { const str = `block-beta id `; @@ -24,7 +21,7 @@ describe('Block diagram', function () { expect(blocks[0].id).toBe('id'); expect(blocks[0].label).toBe('id'); }); - it('a node with a square shape and a label', async () => { + it('a node with a square shape and a label', () => { const str = `block-beta id["A label"] `; @@ -36,7 +33,7 @@ describe('Block diagram', function () { expect(blocks[0].label).toBe('A label'); expect(blocks[0].type).toBe('square'); }); - it('a diagram with multiple nodes', async () => { + it('a diagram with multiple nodes', () => { const str = `block-beta id1 id2 @@ -52,7 +49,7 @@ describe('Block diagram', function () { expect(blocks[1].label).toBe('id2'); expect(blocks[1].type).toBe('na'); }); - it('a diagram with multiple nodes', async () => { + it('a diagram with multiple nodes', () => { const str = `block-beta id1 id2 @@ -73,7 +70,7 @@ describe('Block diagram', function () { expect(blocks[2].type).toBe('na'); }); - it('a node with a square shape and a label', async () => { + it('a node with a square shape and a label', () => { const str = `block-beta id["A label"] id2`; @@ -88,7 +85,7 @@ describe('Block diagram', function () { expect(blocks[1].label).toBe('id2'); expect(blocks[1].type).toBe('na'); }); - it('a diagram with multiple nodes with edges abc123', async () => { + it('a diagram with multiple nodes with edges abc123', () => { const str = `block-beta id1["first"] --> id2["second"] `; @@ -102,7 +99,7 @@ describe('Block diagram', function () { expect(edges[0].end).toBe('id2'); expect(edges[0].arrowTypeEnd).toBe('arrow_point'); }); - it('a diagram with multiple nodes with edges abc123', async () => { + it('a diagram with multiple nodes with edges abc123', () => { const str = `block-beta id1["first"] -- "a label" --> id2["second"] `; @@ -117,7 +114,7 @@ describe('Block diagram', function () { expect(edges[0].arrowTypeEnd).toBe('arrow_point'); expect(edges[0].label).toBe('a label'); }); - it('a diagram with column statements', async () => { + it('a diagram with column statements', () => { const str = `block-beta columns 2 block1["Block 1"] @@ -128,7 +125,7 @@ describe('Block diagram', function () { const blocks = db.getBlocks(); expect(blocks.length).toBe(1); }); - it('a diagram withput column statements', async () => { + it('a diagram without column statements', () => { const str = `block-beta block1["Block 1"] `; @@ -138,7 +135,7 @@ describe('Block diagram', function () { const blocks = db.getBlocks(); expect(blocks.length).toBe(1); }); - it('a diagram with auto column statements', async () => { + it('a diagram with auto column statements', () => { const str = `block-beta columns auto block1["Block 1"] @@ -150,7 +147,7 @@ describe('Block diagram', function () { expect(blocks.length).toBe(1); }); - it('blocks next to each other', async () => { + it('blocks next to each other', () => { const str = `block-beta columns 2 block1["Block 1"] @@ -164,7 +161,7 @@ describe('Block diagram', function () { expect(blocks.length).toBe(2); }); - it('blocks on top of each other', async () => { + it('blocks on top of each other', () => { const str = `block-beta columns 1 block1["Block 1"] @@ -178,7 +175,7 @@ describe('Block diagram', function () { expect(blocks.length).toBe(2); }); - it('compound blocks 2', async () => { + it('compound blocks 2', () => { const str = `block-beta block aBlock["ABlock"] @@ -206,7 +203,7 @@ describe('Block diagram', function () { expect(bBlock.label).toBe('BBlock'); expect(bBlock.type).toBe('square'); }); - it('compound blocks of compound blocks', async () => { + it('compound blocks of compound blocks', () => { const str = `block-beta block aBlock["ABlock"] @@ -241,7 +238,7 @@ describe('Block diagram', function () { expect(bBlock.label).toBe('BBlock'); expect(bBlock.type).toBe('square'); }); - it('compound blocks with title', async () => { + it('compound blocks with title', () => { const str = `block-beta block:compoundBlock["Compound block"] columns 1 @@ -266,7 +263,7 @@ describe('Block diagram', function () { expect(block2.label).toBe('Block 2'); expect(block2.type).toBe('square'); }); - it('blocks mixed with compound blocks', async () => { + it('blocks mixed with compound blocks', () => { const str = `block-beta columns 1 block1["Block 1"] @@ -293,7 +290,7 @@ describe('Block diagram', function () { expect(block2.type).toBe('square'); }); - it('Arrow blocks', async () => { + it('Arrow blocks', () => { const str = `block-beta columns 3 block1["Block 1"] @@ -317,7 +314,7 @@ describe('Block diagram', function () { expect(blockArrow.type).toBe('block_arrow'); expect(blockArrow.directions).toContain('right'); }); - it('Arrow blocks with multiple points', async () => { + it('Arrow blocks with multiple points', () => { const str = `block-beta columns 1 A @@ -340,7 +337,7 @@ describe('Block diagram', function () { expect(blockArrow.directions).toContain('down'); expect(blockArrow.directions).not.toContain('right'); }); - it('blocks with different widths', async () => { + it('blocks with different widths', () => { const str = `block-beta columns 3 one["One Slot"] @@ -355,7 +352,7 @@ describe('Block diagram', function () { const two = blocks[1]; expect(two.widthInColumns).toBe(2); }); - it('empty blocks', async () => { + it('empty blocks', () => { const str = `block-beta columns 3 space @@ -374,7 +371,7 @@ describe('Block diagram', function () { expect(sp2.type).toBe('space'); expect(middle.label).toBe('In the middle'); }); - it('classDef statements applied to a block', async () => { + it('classDef statements applied to a block', () => { const str = `block-beta classDef black color:#ffffff, fill:#000000; @@ -388,11 +385,11 @@ describe('Block diagram', function () { const mc = blocks[0]; expect(mc.classes).toContain('black'); const classes = db.getClasses(); - const black = classes.black; + const black = classes.get('black')!; expect(black.id).toBe('black'); expect(black.styles[0]).toEqual('color:#ffffff'); }); - it('style statements applied to a block', async () => { + it('style statements applied to a block', () => { const str = `block-beta columns 1 B["A wide one in the middle"] @@ -406,4 +403,21 @@ columns 1 expect(B.styles).toContain('fill:#f9F'); }); }); + + describe('prototype properties', function () { + function validateProperty(prop: string) { + expect(() => block.parse(`block-beta\n${prop}`)).not.toThrow(); + expect(() => + block.parse(`block-beta\nA; classDef ${prop} color:#ffffff,fill:#000000; class A ${prop}`) + ).not.toThrow(); + } + + it('should work with a __proto__ property', function () { + validateProperty('__proto__'); + }); + + it('should work with a constructor property', function () { + validateProperty('constructor'); + }); + }); }); diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts index c509ae198..8957b4d8f 100644 --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts @@ -11,14 +11,13 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) { let classStr = 'default'; if ((vertex?.classes?.length || 0) > 0) { - classStr = (vertex?.classes || []).join(' '); + classStr = (vertex?.classes ?? []).join(' '); } classStr = classStr + ' flowchart-label'; // We create a SVG label, either by delegating to addHtmlLabel or manually let radius = 0; let shape = ''; - let layoutOptions = {}; let padding; // Set the shape based parameters switch (vertex.type) { @@ -36,9 +35,6 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) { break; case 'diamond': shape = 'question'; - layoutOptions = { - portConstraints: 'FIXED_SIDE', - }; break; case 'hexagon': shape = 'hexagon'; @@ -89,12 +85,12 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) { shape = 'rect'; } - const styles = getStylesFromArray(vertex?.styles || []); + const styles = getStylesFromArray(vertex?.styles ?? []); // Use vertex id as text in the box if no text is provided by the graph definition const vertexText = vertex.label; - const bounds = vertex.size || { width: 0, height: 0, x: 0, y: 0 }; + const bounds = vertex.size ?? { width: 0, height: 0, x: 0, y: 0 }; // Add the node const node = { labelStyle: styles.labelStyle, @@ -113,7 +109,7 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) { positioned, intersect: undefined, type: vertex.type, - padding: padding ?? (getConfig()?.block?.padding || 0), + padding: padding ?? getConfig()?.block?.padding ?? 0, }; return node; } @@ -128,7 +124,8 @@ async function calculateBlockSize( } // Add the element to the DOM to size it - const nodeEl = await insertNode(elem, node); + const config = getConfig(); + const nodeEl = await insertNode(elem, node, { config }); const boundingBox = nodeEl.node().getBBox(); const obj = db.getBlock(node.id); obj.size = { width: boundingBox.width, height: boundingBox.height, x: 0, y: 0, node: nodeEl }; @@ -142,7 +139,8 @@ export async function insertBlockPositioned(elem: any, block: Block, db: any) { // Add the element to the DOM to size it const obj = db.getBlock(node.id); if (obj.type !== 'space') { - const nodeEl = await insertNode(elem, node); + const config = getConfig(); + await insertNode(elem, node, { config }); block.intersect = node?.intersect; positionNode(node); } @@ -218,7 +216,7 @@ export async function insertEdges( { x: end.x, y: end.y }, ]; // edge.points = points; - await insertEdge( + insertEdge( elem, { v: edge.start, w: edge.end, name: edge.id }, { @@ -243,7 +241,7 @@ export async function insertEdges( points, classes: 'edge-thickness-normal edge-pattern-solid flowchart-link LS-a1 LE-b1', }); - await positionEdgeLabel( + positionEdgeLabel( { ...edge, x: points[1].x, y: points[1].y }, { originalPath: points, diff --git a/packages/mermaid/src/diagrams/c4/c4Db.js b/packages/mermaid/src/diagrams/c4/c4Db.js index 70248fcc4..db17da9ff 100644 --- a/packages/mermaid/src/diagrams/c4/c4Db.js +++ b/packages/mermaid/src/diagrams/c4/c4Db.js @@ -705,6 +705,7 @@ export const getBoundaries = function (parentBoundary) { } }; +// cspell:ignore getBoundarys /** * @deprecated Use {@link getBoundaries} instead */ diff --git a/packages/mermaid/src/diagrams/c4/c4Renderer.js b/packages/mermaid/src/diagrams/c4/c4Renderer.js index 959eba295..87211b24f 100644 --- a/packages/mermaid/src/diagrams/c4/c4Renderer.js +++ b/packages/mermaid/src/diagrams/c4/c4Renderer.js @@ -258,21 +258,21 @@ export const drawC4ShapeArray = function (currentBounds, diagram, c4ShapeArray, c4ShapeLabelConf.fontSize = c4ShapeLabelConf.fontSize + 2; c4ShapeLabelConf.fontWeight = 'bold'; calcC4ShapeTextWH('label', c4Shape, c4ShapeTextWrap, c4ShapeLabelConf, textLimitWidth); - c4Shape['label'].Y = Y + 8; - Y = c4Shape['label'].Y + c4Shape['label'].height; + c4Shape.label.Y = Y + 8; + Y = c4Shape.label.Y + c4Shape.label.height; if (c4Shape.type && c4Shape.type.text !== '') { c4Shape.type.text = '[' + c4Shape.type.text + ']'; let c4ShapeTypeConf = c4ShapeFont(conf, c4Shape.typeC4Shape.text); calcC4ShapeTextWH('type', c4Shape, c4ShapeTextWrap, c4ShapeTypeConf, textLimitWidth); - c4Shape['type'].Y = Y + 5; - Y = c4Shape['type'].Y + c4Shape['type'].height; + c4Shape.type.Y = Y + 5; + Y = c4Shape.type.Y + c4Shape.type.height; } else if (c4Shape.techn && c4Shape.techn.text !== '') { c4Shape.techn.text = '[' + c4Shape.techn.text + ']'; let c4ShapeTechnConf = c4ShapeFont(conf, c4Shape.techn.text); calcC4ShapeTextWH('techn', c4Shape, c4ShapeTextWrap, c4ShapeTechnConf, textLimitWidth); - c4Shape['techn'].Y = Y + 5; - Y = c4Shape['techn'].Y + c4Shape['techn'].height; + c4Shape.techn.Y = Y + 5; + Y = c4Shape.techn.Y + c4Shape.techn.height; } let rectHeight = Y; @@ -281,11 +281,11 @@ export const drawC4ShapeArray = function (currentBounds, diagram, c4ShapeArray, if (c4Shape.descr && c4Shape.descr.text !== '') { let c4ShapeDescrConf = c4ShapeFont(conf, c4Shape.typeC4Shape.text); calcC4ShapeTextWH('descr', c4Shape, c4ShapeTextWrap, c4ShapeDescrConf, textLimitWidth); - c4Shape['descr'].Y = Y + 20; - Y = c4Shape['descr'].Y + c4Shape['descr'].height; + c4Shape.descr.Y = Y + 20; + Y = c4Shape.descr.Y + c4Shape.descr.height; rectWidth = Math.max(c4Shape.label.width, c4Shape.descr.width); - rectHeight = Y - c4Shape['descr'].textLines * 5; + rectHeight = Y - c4Shape.descr.textLines * 5; } rectWidth = rectWidth + conf.c4ShapePadding; @@ -482,8 +482,8 @@ function drawInsideBoundary( currentBoundaryLabelConf, currentBounds.data.widthLimit ); - currentBoundary['label'].Y = Y + 8; - Y = currentBoundary['label'].Y + currentBoundary['label'].height; + currentBoundary.label.Y = Y + 8; + Y = currentBoundary.label.Y + currentBoundary.label.height; if (currentBoundary.type && currentBoundary.type.text !== '') { currentBoundary.type.text = '[' + currentBoundary.type.text + ']'; @@ -495,8 +495,8 @@ function drawInsideBoundary( currentBoundaryTypeConf, currentBounds.data.widthLimit ); - currentBoundary['type'].Y = Y + 5; - Y = currentBoundary['type'].Y + currentBoundary['type'].height; + currentBoundary.type.Y = Y + 5; + Y = currentBoundary.type.Y + currentBoundary.type.height; } if (currentBoundary.descr && currentBoundary.descr.text !== '') { @@ -509,8 +509,8 @@ function drawInsideBoundary( currentBoundaryDescrConf, currentBounds.data.widthLimit ); - currentBoundary['descr'].Y = Y + 20; - Y = currentBoundary['descr'].Y + currentBoundary['descr'].height; + currentBoundary.descr.Y = Y + 20; + Y = currentBoundary.descr.Y + currentBoundary.descr.height; } if (i == 0 || i % c4BoundaryInRow === 0) { @@ -542,7 +542,7 @@ function drawInsideBoundary( ); } parentBoundaryAlias = currentBoundary.alias; - let nextCurrentBoundaries = diagObj.db.getBoundarys(parentBoundaryAlias); + let nextCurrentBoundaries = diagObj.db.getBoundaries(parentBoundaryAlias); if (nextCurrentBoundaries.length > 0) { // draw boundary inside currentBoundary @@ -622,7 +622,7 @@ export const draw = function (_text, id, _version, diagObj) { globalBoundaryMaxY = conf.diagramMarginY; const title = diagObj.db.getTitle(); - let currentBoundaries = diagObj.db.getBoundarys(''); + let currentBoundaries = diagObj.db.getBoundaries(''); // switch (c4type) { // case 'C4Context': drawInsideBoundary(diagram, '', screenBounds, currentBoundaries, diagObj); diff --git a/packages/mermaid/src/diagrams/c4/parser/c4Boundary.spec.js b/packages/mermaid/src/diagrams/c4/parser/c4Boundary.spec.js index f43f00748..20735eeb0 100644 --- a/packages/mermaid/src/diagrams/c4/parser/c4Boundary.spec.js +++ b/packages/mermaid/src/diagrams/c4/parser/c4Boundary.spec.js @@ -21,7 +21,7 @@ System(SystemAA, "Internet Banking System") const yy = c4.parser.yy; - const boundaries = yy.getBoundarys(); + const boundaries = yy.getBoundaries(); expect(boundaries.length).toBe(2); const boundary = boundaries[1]; @@ -49,7 +49,7 @@ ${macroName}(b1, "BankBoundary") { System(SystemAA, "Internet Banking System") }`); - expect(c4.parser.yy.getBoundarys()[1]).toMatchObject({ + expect(c4.parser.yy.getBoundaries()[1]).toMatchObject({ alias: 'b1', }); }); @@ -60,7 +60,7 @@ ${macroName}(b1, "BankBoundary") { System(SystemAA, "Internet Banking System") }`); - expect(c4.parser.yy.getBoundarys()[1]).toMatchObject({ + expect(c4.parser.yy.getBoundaries()[1]).toMatchObject({ label: { text: 'BankBoundary', }, @@ -73,7 +73,7 @@ ${macroName}(b1, "", "company") { System(SystemAA, "Internet Banking System") }`); - expect(c4.parser.yy.getBoundarys()[1]).toMatchObject({ + expect(c4.parser.yy.getBoundaries()[1]).toMatchObject({ type: { text: 'company' }, }); }); @@ -84,7 +84,7 @@ ${macroName}(b1, $link="https://github.com/mermaidjs") { System(SystemAA, "Internet Banking System") }`); - expect(c4.parser.yy.getBoundarys()[1]).toMatchObject({ + expect(c4.parser.yy.getBoundaries()[1]).toMatchObject({ label: { text: { link: 'https://github.com/mermaidjs', @@ -99,7 +99,7 @@ ${macroName}(b1, $tags="tag1,tag2") { System(SystemAA, "Internet Banking System") }`); - expect(c4.parser.yy.getBoundarys()[1]).toMatchObject({ + expect(c4.parser.yy.getBoundaries()[1]).toMatchObject({ label: { text: { tags: 'tag1,tag2', diff --git a/packages/mermaid/src/diagrams/c4/parser/c4Diagram.jison b/packages/mermaid/src/diagrams/c4/parser/c4Diagram.jison index a6bd8a6ec..63856f044 100644 --- a/packages/mermaid/src/diagrams/c4/parser/c4Diagram.jison +++ b/packages/mermaid/src/diagrams/c4/parser/c4Diagram.jison @@ -256,7 +256,7 @@ boundaryStartStatement boundaryStart : ENTERPRISE_BOUNDARY attributes {$2.splice(2, 0, 'ENTERPRISE'); yy.addPersonOrSystemBoundary(...$2); $$=$2;} - | SYSTEM_BOUNDARY attributes {$2.splice(2, 0, 'ENTERPRISE'); yy.addPersonOrSystemBoundary(...$2); $$=$2;} + | SYSTEM_BOUNDARY attributes {$2.splice(2, 0, 'SYSTEM'); yy.addPersonOrSystemBoundary(...$2); $$=$2;} | BOUNDARY attributes {yy.addPersonOrSystemBoundary(...$2); $$=$2;} | CONTAINER_BOUNDARY attributes {$2.splice(2, 0, 'CONTAINER'); yy.addContainerBoundary(...$2); $$=$2;} | NODE attributes {yy.addDeploymentNode('node', ...$2); $$=$2;} diff --git a/packages/mermaid/src/diagrams/c4/svgDraw.js b/packages/mermaid/src/diagrams/c4/svgDraw.js index 6bff267f6..5cd8998ae 100644 --- a/packages/mermaid/src/diagrams/c4/svgDraw.js +++ b/packages/mermaid/src/diagrams/c4/svgDraw.js @@ -111,7 +111,7 @@ export const drawRels = (elem, rels, conf) => { }; /** - * Draws an boundary in the diagram + * Draws a boundary in the diagram * * @param {any} elem - The diagram we'll draw to. * @param {any} boundary - The boundary to draw. diff --git a/packages/mermaid/src/diagrams/class/classDb.ts b/packages/mermaid/src/diagrams/class/classDb.ts index 0e18d1e0f..82ddcf09b 100644 --- a/packages/mermaid/src/diagrams/class/classDb.ts +++ b/packages/mermaid/src/diagrams/class/classDb.ts @@ -1,9 +1,8 @@ -import type { Selection } from 'd3'; -import { select } from 'd3'; +import { select, type Selection } from 'd3'; import { log } from '../../logger.js'; import { getConfig } from '../../diagram-api/diagramAPI.js'; import common from '../common/common.js'; -import utils from '../../utils.js'; +import utils, { getEdgeId } from '../../utils.js'; import { setAccTitle, getAccTitle, @@ -21,491 +20,720 @@ import type { ClassMap, NamespaceMap, NamespaceNode, + StyleClass, + Interface, } from './classTypes.js'; +import type { Node, Edge } from '../../rendering-util/types.js'; +import type { DiagramDB } from '../../diagram-api/types.js'; const MERMAID_DOM_ID_PREFIX = 'classId-'; - -let relations: ClassRelation[] = []; -let classes: ClassMap = {}; -let notes: ClassNote[] = []; let classCounter = 0; -let namespaces: NamespaceMap = {}; -let namespaceCounter = 0; - -let functions: any[] = []; const sanitizeText = (txt: string) => common.sanitizeText(txt, getConfig()); -const splitClassNameAndType = function (_id: string) { - const id = common.sanitizeText(_id, getConfig()); - let genericType = ''; - let className = id; +export class ClassDB implements DiagramDB { + private relations: ClassRelation[] = []; + private classes = new Map(); + private readonly styleClasses = new Map(); + private notes: ClassNote[] = []; + private interfaces: Interface[] = []; + // private static classCounter = 0; + private namespaces = new Map(); + private namespaceCounter = 0; - if (id.indexOf('~') > 0) { - const split = id.split('~'); - className = sanitizeText(split[0]); - genericType = sanitizeText(split[1]); + private functions: any[] = []; + + constructor() { + this.functions.push(this.setupToolTips.bind(this)); + this.clear(); + + // Needed for JISON since it only supports direct properties + this.addRelation = this.addRelation.bind(this); + this.addClassesToNamespace = this.addClassesToNamespace.bind(this); + this.addNamespace = this.addNamespace.bind(this); + this.setCssClass = this.setCssClass.bind(this); + this.addMembers = this.addMembers.bind(this); + this.addClass = this.addClass.bind(this); + this.setClassLabel = this.setClassLabel.bind(this); + this.addAnnotation = this.addAnnotation.bind(this); + this.addMember = this.addMember.bind(this); + this.cleanupLabel = this.cleanupLabel.bind(this); + this.addNote = this.addNote.bind(this); + this.defineClass = this.defineClass.bind(this); + this.setDirection = this.setDirection.bind(this); + this.setLink = this.setLink.bind(this); + this.bindFunctions = this.bindFunctions.bind(this); + this.clear = this.clear.bind(this); + + this.setTooltip = this.setTooltip.bind(this); + this.setClickEvent = this.setClickEvent.bind(this); + this.setCssStyle = this.setCssStyle.bind(this); } - return { className: className, type: genericType }; -}; + private splitClassNameAndType(_id: string) { + const id = common.sanitizeText(_id, getConfig()); + let genericType = ''; + let className = id; -export const setClassLabel = function (_id: string, label: string) { - const id = common.sanitizeText(_id, getConfig()); - if (label) { - label = sanitizeText(label); - } - - const { className } = splitClassNameAndType(id); - classes[className].label = label; -}; - -/** - * Function called by parser when a node definition has been found. - * - * @param id - Id of the class to add - * @public - */ -export const addClass = function (_id: string) { - const id = common.sanitizeText(_id, getConfig()); - const { className, type } = splitClassNameAndType(id); - // Only add class if not exists - if (Object.hasOwn(classes, className)) { - return; - } - // alert('Adding class: ' + className); - const name = common.sanitizeText(className, getConfig()); - // alert('Adding class after: ' + name); - classes[name] = { - id: name, - type: type, - label: name, - cssClasses: [], - methods: [], - members: [], - annotations: [], - styles: [], - domId: MERMAID_DOM_ID_PREFIX + name + '-' + classCounter, - } as ClassNode; - - classCounter++; -}; - -/** - * Function to lookup domId from id in the graph definition. - * - * @param id - class ID to lookup - * @public - */ -export const lookUpDomId = function (_id: string): string { - const id = common.sanitizeText(_id, getConfig()); - if (id in classes) { - return classes[id].domId; - } - throw new Error('Class not found: ' + id); -}; - -export const clear = function () { - relations = []; - classes = {}; - notes = []; - functions = []; - functions.push(setupToolTips); - namespaces = {}; - namespaceCounter = 0; - commonClear(); -}; - -export const getClass = function (id: string): ClassNode { - return classes[id]; -}; - -export const getClasses = function (): ClassMap { - return classes; -}; - -export const getRelations = function (): ClassRelation[] { - return relations; -}; - -export const getNotes = function () { - return notes; -}; - -export const addRelation = function (relation: ClassRelation) { - log.debug('Adding relation: ' + JSON.stringify(relation)); - addClass(relation.id1); - addClass(relation.id2); - - relation.id1 = splitClassNameAndType(relation.id1).className; - relation.id2 = splitClassNameAndType(relation.id2).className; - - relation.relationTitle1 = common.sanitizeText(relation.relationTitle1.trim(), getConfig()); - - relation.relationTitle2 = common.sanitizeText(relation.relationTitle2.trim(), getConfig()); - - relations.push(relation); -}; - -/** - * Adds an annotation to the specified class Annotations mark special properties of the given type - * (like 'interface' or 'service') - * - * @param className - The class name - * @param annotation - The name of the annotation without any brackets - * @public - */ -export const addAnnotation = function (className: string, annotation: string) { - const validatedClassName = splitClassNameAndType(className).className; - classes[validatedClassName].annotations.push(annotation); -}; - -/** - * Adds a member to the specified class - * - * @param className - The class name - * @param member - The full name of the member. If the member is enclosed in `<>` it is - * treated as an annotation If the member is ending with a closing bracket ) it is treated as a - * method Otherwise the member will be treated as a normal property - * @public - */ -export const addMember = function (className: string, member: string) { - addClass(className); - - const validatedClassName = splitClassNameAndType(className).className; - const theClass = classes[validatedClassName]; - - if (typeof member === 'string') { - // Member can contain white spaces, we trim them out - const memberString = member.trim(); - - if (memberString.startsWith('<<') && memberString.endsWith('>>')) { - // its an annotation - theClass.annotations.push(sanitizeText(memberString.substring(2, memberString.length - 2))); - } else if (memberString.indexOf(')') > 0) { - //its a method - theClass.methods.push(new ClassMember(memberString, 'method')); - } else if (memberString) { - theClass.members.push(new ClassMember(memberString, 'attribute')); - } - } -}; - -export const addMembers = function (className: string, members: string[]) { - if (Array.isArray(members)) { - members.reverse(); - members.forEach((member) => addMember(className, member)); - } -}; - -export const addNote = function (text: string, className: string) { - const note = { - id: `note${notes.length}`, - class: className, - text: text, - }; - notes.push(note); -}; - -export const cleanupLabel = function (label: string) { - if (label.startsWith(':')) { - label = label.substring(1); - } - return sanitizeText(label.trim()); -}; - -/** - * Called by parser when assigning cssClass to a class - * - * @param ids - Comma separated list of ids - * @param className - Class to add - */ -export const setCssClass = function (ids: string, className: string) { - ids.split(',').forEach(function (_id) { - let id = _id; - if (_id[0].match(/\d/)) { - id = MERMAID_DOM_ID_PREFIX + id; - } - if (classes[id] !== undefined) { - classes[id].cssClasses.push(className); - } - }); -}; - -/** - * Called by parser when a tooltip is found, e.g. a clickable element. - * - * @param ids - Comma separated list of ids - * @param tooltip - Tooltip to add - */ -const setTooltip = function (ids: string, tooltip?: string) { - ids.split(',').forEach(function (id) { - if (tooltip !== undefined) { - classes[id].tooltip = sanitizeText(tooltip); - } - }); -}; - -export const getTooltip = function (id: string, namespace?: string) { - if (namespace) { - return namespaces[namespace].classes[id].tooltip; - } - - return classes[id].tooltip; -}; - -/** - * Called by parser when a link is found. Adds the URL to the vertex data. - * - * @param ids - Comma separated list of ids - * @param linkStr - URL to create a link for - * @param target - Target of the link, _blank by default as originally defined in the svgDraw.js file - */ -export const setLink = function (ids: string, linkStr: string, target: string) { - const config = getConfig(); - ids.split(',').forEach(function (_id) { - let id = _id; - if (_id[0].match(/\d/)) { - id = MERMAID_DOM_ID_PREFIX + id; - } - if (classes[id] !== undefined) { - classes[id].link = utils.formatUrl(linkStr, config); - if (config.securityLevel === 'sandbox') { - classes[id].linkTarget = '_top'; - } else if (typeof target === 'string') { - classes[id].linkTarget = sanitizeText(target); - } else { - classes[id].linkTarget = '_blank'; - } - } - }); - setCssClass(ids, 'clickable'); -}; - -/** - * Called by parser when a click definition is found. Registers an event handler. - * - * @param ids - Comma separated list of ids - * @param functionName - Function to be called on click - * @param functionArgs - Function args the function should be called with - */ -export const setClickEvent = function (ids: string, functionName: string, functionArgs: string) { - ids.split(',').forEach(function (id) { - setClickFunc(id, functionName, functionArgs); - classes[id].haveCallback = true; - }); - setCssClass(ids, 'clickable'); -}; - -const setClickFunc = function (_domId: string, functionName: string, functionArgs: string) { - const domId = common.sanitizeText(_domId, getConfig()); - const config = getConfig(); - if (config.securityLevel !== 'loose') { - return; - } - if (functionName === undefined) { - return; - } - - const id = domId; - if (classes[id] !== undefined) { - const elemId = lookUpDomId(id); - let argList: string[] = []; - if (typeof functionArgs === 'string') { - /* Splits functionArgs by ',', ignoring all ',' in double quoted strings */ - argList = functionArgs.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/); - for (let i = 0; i < argList.length; i++) { - let item = argList[i].trim(); - /* Removes all double quotes at the start and end of an argument */ - /* This preserves all starting and ending whitespace inside */ - if (item.charAt(0) === '"' && item.charAt(item.length - 1) === '"') { - item = item.substr(1, item.length - 2); - } - argList[i] = item; - } + if (id.indexOf('~') > 0) { + const split = id.split('~'); + className = sanitizeText(split[0]); + genericType = sanitizeText(split[1]); } - /* if no arguments passed into callback, default to passing in id */ - if (argList.length === 0) { - argList.push(elemId); + return { className: className, type: genericType }; + } + + public setClassLabel(_id: string, label: string) { + const id = common.sanitizeText(_id, getConfig()); + if (label) { + label = sanitizeText(label); } - functions.push(function () { - const elem = document.querySelector(`[id="${elemId}"]`); - if (elem !== null) { - elem.addEventListener( - 'click', - function () { - utils.runFunc(functionName, ...argList); - }, - false - ); - } - }); - } -}; - -export const bindFunctions = function (element: Element) { - functions.forEach(function (fun) { - fun(element); - }); -}; - -export const lineType = { - LINE: 0, - DOTTED_LINE: 1, -}; - -export const relationType = { - AGGREGATION: 0, - EXTENSION: 1, - COMPOSITION: 2, - DEPENDENCY: 3, - LOLLIPOP: 4, -}; - -const setupToolTips = function (element: Element) { - let tooltipElem: Selection = - select('.mermaidTooltip'); - // @ts-expect-error - Incorrect types - if ((tooltipElem._groups || tooltipElem)[0][0] === null) { - tooltipElem = select('body').append('div').attr('class', 'mermaidTooltip').style('opacity', 0); + const { className } = this.splitClassNameAndType(id); + this.classes.get(className)!.label = label; + this.classes.get(className)!.text = + `${label}${this.classes.get(className)!.type ? `<${this.classes.get(className)!.type}>` : ''}`; } - const svg = select(element).select('svg'); + /** + * Function called by parser when a node definition has been found. + * + * @param id - ID of the class to add + * @public + */ + public addClass(_id: string) { + const id = common.sanitizeText(_id, getConfig()); + const { className, type } = this.splitClassNameAndType(id); + // Only add class if not exists + if (this.classes.has(className)) { + return; + } + // alert('Adding class: ' + className); + const name = common.sanitizeText(className, getConfig()); + // alert('Adding class after: ' + name); + this.classes.set(name, { + id: name, + type: type, + label: name, + text: `${name}${type ? `<${type}>` : ''}`, + shape: 'classBox', + cssClasses: 'default', + methods: [], + members: [], + annotations: [], + styles: [], + domId: MERMAID_DOM_ID_PREFIX + name + '-' + classCounter, + } as ClassNode); - const nodes = svg.selectAll('g.node'); - nodes - .on('mouseover', function () { - const el = select(this); - const title = el.attr('title'); - // Don't try to draw a tooltip if no data is provided - if (title === null) { - return; - } - // @ts-ignore - getBoundingClientRect is not part of the d3 type definition - const rect = this.getBoundingClientRect(); - - // @ts-expect-error - Incorrect types - tooltipElem.transition().duration(200).style('opacity', '.9'); - tooltipElem - .text(el.attr('title')) - .style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px') - .style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px'); - tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '
')); - el.classed('hover', true); - }) - .on('mouseout', function () { - // @ts-expect-error - Incorrect types - tooltipElem.transition().duration(500).style('opacity', 0); - const el = select(this); - el.classed('hover', false); - }); -}; -functions.push(setupToolTips); - -let direction = 'TB'; -const getDirection = () => direction; -const setDirection = (dir: string) => { - direction = dir; -}; - -/** - * Function called by parser when a namespace definition has been found. - * - * @param id - Id of the namespace to add - * @public - */ -export const addNamespace = function (id: string) { - if (namespaces[id] !== undefined) { - return; + classCounter++; } - namespaces[id] = { - id: id, - classes: {}, - children: {}, - domId: MERMAID_DOM_ID_PREFIX + id + '-' + namespaceCounter, - } as NamespaceNode; + private addInterface(label: string, classId: string) { + const classInterface: Interface = { + id: `interface${this.interfaces.length}`, + label, + classId, + }; - namespaceCounter++; -}; - -const getNamespace = function (name: string): NamespaceNode { - return namespaces[name]; -}; - -const getNamespaces = function (): NamespaceMap { - return namespaces; -}; - -/** - * Function called by parser when a namespace definition has been found. - * - * @param id - Id of the namespace to add - * @param classNames - Ids of the class to add - * @public - */ -export const addClassesToNamespace = function (id: string, classNames: string[]) { - if (namespaces[id] === undefined) { - return; + this.interfaces.push(classInterface); } - for (const name of classNames) { - const { className } = splitClassNameAndType(name); - classes[className].parent = id; - namespaces[id].classes[className] = classes[className]; - } -}; -export const setCssStyle = function (id: string, styles: string[]) { - const thisClass = classes[id]; - if (!styles || !thisClass) { - return; + /** + * Function to lookup domId from id in the graph definition. + * + * @param id - class ID to lookup + * @public + */ + public lookUpDomId(_id: string): string { + const id = common.sanitizeText(_id, getConfig()); + if (this.classes.has(id)) { + return this.classes.get(id)!.domId; + } + throw new Error('Class not found: ' + id); } - for (const s of styles) { - if (s.includes(',')) { - thisClass.styles.push(...s.split(',')); + + public clear() { + this.relations = []; + this.classes = new Map(); + this.notes = []; + this.interfaces = []; + this.functions = []; + this.functions.push(this.setupToolTips.bind(this)); + this.namespaces = new Map(); + this.namespaceCounter = 0; + this.direction = 'TB'; + commonClear(); + } + + public getClass(id: string): ClassNode { + return this.classes.get(id)!; + } + + public getClasses(): ClassMap { + return this.classes; + } + + public getRelations(): ClassRelation[] { + return this.relations; + } + + public getNotes() { + return this.notes; + } + + public addRelation(classRelation: ClassRelation) { + log.debug('Adding relation: ' + JSON.stringify(classRelation)); + // Due to relationType cannot just check if it is equal to 'none' or it complains, can fix this later + const invalidTypes = [ + this.relationType.LOLLIPOP, + this.relationType.AGGREGATION, + this.relationType.COMPOSITION, + this.relationType.DEPENDENCY, + this.relationType.EXTENSION, + ]; + + if ( + classRelation.relation.type1 === this.relationType.LOLLIPOP && + !invalidTypes.includes(classRelation.relation.type2) + ) { + this.addClass(classRelation.id2); + this.addInterface(classRelation.id1, classRelation.id2); + classRelation.id1 = `interface${this.interfaces.length - 1}`; + } else if ( + classRelation.relation.type2 === this.relationType.LOLLIPOP && + !invalidTypes.includes(classRelation.relation.type1) + ) { + this.addClass(classRelation.id1); + this.addInterface(classRelation.id2, classRelation.id1); + classRelation.id2 = `interface${this.interfaces.length - 1}`; } else { - thisClass.styles.push(s); + this.addClass(classRelation.id1); + this.addClass(classRelation.id2); + } + + classRelation.id1 = this.splitClassNameAndType(classRelation.id1).className; + classRelation.id2 = this.splitClassNameAndType(classRelation.id2).className; + + classRelation.relationTitle1 = common.sanitizeText( + classRelation.relationTitle1.trim(), + getConfig() + ); + + classRelation.relationTitle2 = common.sanitizeText( + classRelation.relationTitle2.trim(), + getConfig() + ); + + this.relations.push(classRelation); + } + + /** + * Adds an annotation to the specified class Annotations mark special properties of the given type + * (like 'interface' or 'service') + * + * @param className - The class name + * @param annotation - The name of the annotation without any brackets + * @public + */ + public addAnnotation(className: string, annotation: string) { + const validatedClassName = this.splitClassNameAndType(className).className; + this.classes.get(validatedClassName)!.annotations.push(annotation); + } + + /** + * Adds a member to the specified class + * + * @param className - The class name + * @param member - The full name of the member. If the member is enclosed in `<>` it is + * treated as an annotation If the member is ending with a closing bracket ) it is treated as a + * method Otherwise the member will be treated as a normal property + * @public + */ + public addMember(className: string, member: string) { + this.addClass(className); + + const validatedClassName = this.splitClassNameAndType(className).className; + const theClass = this.classes.get(validatedClassName)!; + + if (typeof member === 'string') { + // Member can contain white spaces, we trim them out + const memberString = member.trim(); + + if (memberString.startsWith('<<') && memberString.endsWith('>>')) { + // its an annotation + theClass.annotations.push(sanitizeText(memberString.substring(2, memberString.length - 2))); + } else if (memberString.indexOf(')') > 0) { + //its a method + theClass.methods.push(new ClassMember(memberString, 'method')); + } else if (memberString) { + theClass.members.push(new ClassMember(memberString, 'attribute')); + } } } -}; -export default { - setAccTitle, - getAccTitle, - getAccDescription, - setAccDescription, - getConfig: () => getConfig().class, - addClass, - bindFunctions, - clear, - getClass, - getClasses, - getNotes, - addAnnotation, - addNote, - getRelations, - addRelation, - getDirection, - setDirection, - addMember, - addMembers, - cleanupLabel, - lineType, - relationType, - setClickEvent, - setCssClass, - setLink, - getTooltip, - setTooltip, - lookUpDomId, - setDiagramTitle, - getDiagramTitle, - setClassLabel, - addNamespace, - addClassesToNamespace, - getNamespace, - getNamespaces, - setCssStyle, -}; + public addMembers(className: string, members: string[]) { + if (Array.isArray(members)) { + members.reverse(); + members.forEach((member) => this.addMember(className, member)); + } + } + + public addNote(text: string, className: string) { + const note = { + id: `note${this.notes.length}`, + class: className, + text: text, + }; + this.notes.push(note); + } + + public cleanupLabel(label: string) { + if (label.startsWith(':')) { + label = label.substring(1); + } + return sanitizeText(label.trim()); + } + + /** + * Called by parser when assigning cssClass to a class + * + * @param ids - Comma separated list of ids + * @param className - Class to add + */ + public setCssClass(ids: string, className: string) { + ids.split(',').forEach((_id) => { + let id = _id; + if (/\d/.exec(_id[0])) { + id = MERMAID_DOM_ID_PREFIX + id; + } + const classNode = this.classes.get(id); + if (classNode) { + classNode.cssClasses += ' ' + className; + } + }); + } + + public defineClass(ids: string[], style: string[]) { + for (const id of ids) { + let styleClass = this.styleClasses.get(id); + if (styleClass === undefined) { + styleClass = { id, styles: [], textStyles: [] }; + this.styleClasses.set(id, styleClass); + } + + if (style) { + style.forEach((s) => { + if (/color/.exec(s)) { + const newStyle = s.replace('fill', 'bgFill'); // .replace('color', 'fill'); + styleClass.textStyles.push(newStyle); + } + styleClass.styles.push(s); + }); + } + + this.classes.forEach((value) => { + if (value.cssClasses.includes(id)) { + value.styles.push(...style.flatMap((s) => s.split(','))); + } + }); + } + } + + /** + * Called by parser when a tooltip is found, e.g. a clickable element. + * + * @param ids - Comma separated list of ids + * @param tooltip - Tooltip to add + */ + public setTooltip(ids: string, tooltip?: string) { + ids.split(',').forEach((id) => { + if (tooltip !== undefined) { + this.classes.get(id)!.tooltip = sanitizeText(tooltip); + } + }); + } + + public getTooltip(id: string, namespace?: string) { + if (namespace && this.namespaces.has(namespace)) { + return this.namespaces.get(namespace)!.classes.get(id)!.tooltip; + } + + return this.classes.get(id)!.tooltip; + } + + /** + * Called by parser when a link is found. Adds the URL to the vertex data. + * + * @param ids - Comma separated list of ids + * @param linkStr - URL to create a link for + * @param target - Target of the link, _blank by default as originally defined in the svgDraw.js file + */ + public setLink(ids: string, linkStr: string, target: string) { + const config = getConfig(); + ids.split(',').forEach((_id) => { + let id = _id; + if (/\d/.exec(_id[0])) { + id = MERMAID_DOM_ID_PREFIX + id; + } + const theClass = this.classes.get(id); + if (theClass) { + theClass.link = utils.formatUrl(linkStr, config); + if (config.securityLevel === 'sandbox') { + theClass.linkTarget = '_top'; + } else if (typeof target === 'string') { + theClass.linkTarget = sanitizeText(target); + } else { + theClass.linkTarget = '_blank'; + } + } + }); + this.setCssClass(ids, 'clickable'); + } + + /** + * Called by parser when a click definition is found. Registers an event handler. + * + * @param ids - Comma separated list of ids + * @param functionName - Function to be called on click + * @param functionArgs - Function args the function should be called with + */ + public setClickEvent(ids: string, functionName: string, functionArgs: string) { + ids.split(',').forEach((id) => { + this.setClickFunc(id, functionName, functionArgs); + this.classes.get(id)!.haveCallback = true; + }); + this.setCssClass(ids, 'clickable'); + } + + private setClickFunc(_domId: string, functionName: string, functionArgs: string) { + const domId = common.sanitizeText(_domId, getConfig()); + const config = getConfig(); + if (config.securityLevel !== 'loose') { + return; + } + if (functionName === undefined) { + return; + } + + const id = domId; + if (this.classes.has(id)) { + const elemId = this.lookUpDomId(id); + let argList: string[] = []; + if (typeof functionArgs === 'string') { + /* Splits functionArgs by ',', ignoring all ',' in double quoted strings */ + argList = functionArgs.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/); + for (let i = 0; i < argList.length; i++) { + let item = argList[i].trim(); + /* Removes all double quotes at the start and end of an argument */ + /* This preserves all starting and ending whitespace inside */ + if (item.startsWith('"') && item.endsWith('"')) { + item = item.substr(1, item.length - 2); + } + argList[i] = item; + } + } + + /* if no arguments passed into callback, default to passing in id */ + if (argList.length === 0) { + argList.push(elemId); + } + + this.functions.push(() => { + const elem = document.querySelector(`[id="${elemId}"]`); + if (elem !== null) { + elem.addEventListener( + 'click', + () => { + utils.runFunc(functionName, ...argList); + }, + false + ); + } + }); + } + } + + public bindFunctions(element: Element) { + this.functions.forEach((fun) => { + fun(element); + }); + } + + public readonly lineType = { + LINE: 0, + DOTTED_LINE: 1, + }; + + public readonly relationType = { + AGGREGATION: 0, + EXTENSION: 1, + COMPOSITION: 2, + DEPENDENCY: 3, + LOLLIPOP: 4, + }; + + private readonly setupToolTips = (element: Element) => { + let tooltipElem: Selection = + select('.mermaidTooltip'); + // @ts-expect-error - Incorrect types + if ((tooltipElem._groups || tooltipElem)[0][0] === null) { + tooltipElem = select('body') + .append('div') + .attr('class', 'mermaidTooltip') + .style('opacity', 0); + } + + const svg = select(element).select('svg'); + + const nodes = svg.selectAll('g.node'); + nodes + .on('mouseover', (event: MouseEvent) => { + const el = select(event.currentTarget as HTMLElement); + const title = el.attr('title'); + // Don't try to draw a tooltip if no data is provided + if (title === null) { + return; + } + // @ts-ignore - getBoundingClientRect is not part of the d3 type definition + const rect = this.getBoundingClientRect(); + + tooltipElem.transition().duration(200).style('opacity', '.9'); + tooltipElem + .text(el.attr('title')) + .style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px') + .style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px'); + tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '
')); + el.classed('hover', true); + }) + .on('mouseout', (event: MouseEvent) => { + tooltipElem.transition().duration(500).style('opacity', 0); + const el = select(event.currentTarget as HTMLElement); + el.classed('hover', false); + }); + }; + + private direction = 'TB'; + public getDirection() { + return this.direction; + } + public setDirection(dir: string) { + this.direction = dir; + } + + /** + * Function called by parser when a namespace definition has been found. + * + * @param id - ID of the namespace to add + * @public + */ + public addNamespace(id: string) { + if (this.namespaces.has(id)) { + return; + } + + this.namespaces.set(id, { + id: id, + classes: new Map(), + children: {}, + domId: MERMAID_DOM_ID_PREFIX + id + '-' + this.namespaceCounter, + } as NamespaceNode); + + this.namespaceCounter++; + } + + public getNamespace(name: string): NamespaceNode { + return this.namespaces.get(name)!; + } + + public getNamespaces(): NamespaceMap { + return this.namespaces; + } + + /** + * Function called by parser when a namespace definition has been found. + * + * @param id - ID of the namespace to add + * @param classNames - IDs of the class to add + * @public + */ + public addClassesToNamespace(id: string, classNames: string[]) { + if (!this.namespaces.has(id)) { + return; + } + for (const name of classNames) { + const { className } = this.splitClassNameAndType(name); + this.classes.get(className)!.parent = id; + this.namespaces.get(id)!.classes.set(className, this.classes.get(className)!); + } + } + + public setCssStyle(id: string, styles: string[]) { + const thisClass = this.classes.get(id); + if (!styles || !thisClass) { + return; + } + for (const s of styles) { + if (s.includes(',')) { + thisClass.styles.push(...s.split(',')); + } else { + thisClass.styles.push(s); + } + } + } + + /** + * Gets the arrow marker for a type index + * + * @param type - The type to look for + * @returns The arrow marker + */ + private getArrowMarker(type: number) { + let marker; + switch (type) { + case 0: + marker = 'aggregation'; + break; + case 1: + marker = 'extension'; + break; + case 2: + marker = 'composition'; + break; + case 3: + marker = 'dependency'; + break; + case 4: + marker = 'lollipop'; + break; + default: + marker = 'none'; + } + return marker; + } + + public getData() { + const nodes: Node[] = []; + const edges: Edge[] = []; + const config = getConfig(); + + for (const namespaceKey of this.namespaces.keys()) { + const namespace = this.namespaces.get(namespaceKey); + if (namespace) { + const node: Node = { + id: namespace.id, + label: namespace.id, + isGroup: true, + padding: config.class!.padding ?? 16, + // parent node must be one of [rect, roundedWithTitle, noteGroup, divider] + shape: 'rect', + cssStyles: ['fill: none', 'stroke: black'], + look: config.look, + }; + nodes.push(node); + } + } + + for (const classKey of this.classes.keys()) { + const classNode = this.classes.get(classKey); + if (classNode) { + const node = classNode as unknown as Node; + node.parentId = classNode.parent; + node.look = config.look; + nodes.push(node); + } + } + + let cnt = 0; + for (const note of this.notes) { + cnt++; + const noteNode: Node = { + id: note.id, + label: note.text, + isGroup: false, + shape: 'note', + padding: config.class!.padding ?? 6, + cssStyles: [ + 'text-align: left', + 'white-space: nowrap', + `fill: ${config.themeVariables.noteBkgColor}`, + `stroke: ${config.themeVariables.noteBorderColor}`, + ], + look: config.look, + }; + nodes.push(noteNode); + + const noteClassId = this.classes.get(note.class)?.id ?? ''; + + if (noteClassId) { + const edge: Edge = { + id: `edgeNote${cnt}`, + start: note.id, + end: noteClassId, + type: 'normal', + thickness: 'normal', + classes: 'relation', + arrowTypeStart: 'none', + arrowTypeEnd: 'none', + arrowheadStyle: '', + labelStyle: [''], + style: ['fill: none'], + pattern: 'dotted', + look: config.look, + }; + edges.push(edge); + } + } + + for (const _interface of this.interfaces) { + const interfaceNode: Node = { + id: _interface.id, + label: _interface.label, + isGroup: false, + shape: 'rect', + cssStyles: ['opacity: 0;'], + look: config.look, + }; + nodes.push(interfaceNode); + } + + cnt = 0; + for (const classRelation of this.relations) { + cnt++; + const edge: Edge = { + id: getEdgeId(classRelation.id1, classRelation.id2, { + prefix: 'id', + counter: cnt, + }), + start: classRelation.id1, + end: classRelation.id2, + type: 'normal', + label: classRelation.title, + labelpos: 'c', + thickness: 'normal', + classes: 'relation', + arrowTypeStart: this.getArrowMarker(classRelation.relation.type1), + arrowTypeEnd: this.getArrowMarker(classRelation.relation.type2), + startLabelRight: + classRelation.relationTitle1 === 'none' ? '' : classRelation.relationTitle1, + endLabelLeft: classRelation.relationTitle2 === 'none' ? '' : classRelation.relationTitle2, + arrowheadStyle: '', + labelStyle: ['display: inline-block'], + style: classRelation.style || '', + pattern: classRelation.relation.lineType == 1 ? 'dashed' : 'solid', + look: config.look, + }; + edges.push(edge); + } + + return { nodes, edges, other: {}, config, direction: this.getDirection() }; + } + + public setAccTitle = setAccTitle; + public getAccTitle = getAccTitle; + public setAccDescription = setAccDescription; + public getAccDescription = getAccDescription; + public setDiagramTitle = setDiagramTitle; + public getDiagramTitle = getDiagramTitle; + public getConfig = () => getConfig().class; +} diff --git a/packages/mermaid/src/diagrams/class/classDiagram-styles.spec.js b/packages/mermaid/src/diagrams/class/classDiagram-styles.spec.js index 957188401..71f322478 100644 --- a/packages/mermaid/src/diagrams/class/classDiagram-styles.spec.js +++ b/packages/mermaid/src/diagrams/class/classDiagram-styles.spec.js @@ -1,9 +1,11 @@ import { parser } from './parser/classDiagram.jison'; -import classDb from './classDb.js'; +import { ClassDB } from './classDb.js'; describe('class diagram, ', function () { describe('when parsing data from a classDiagram it', function () { + let classDb; beforeEach(function () { + classDb = new ClassDB(); parser.yy = classDb; parser.yy.clear(); }); @@ -13,7 +15,7 @@ describe('class diagram, ', function () { parser.parse(str); - expect(parser.yy.getClass('Class01').cssClasses[0]).toBe('exClass'); + expect(parser.yy.getClass('Class01').cssClasses).toBe('default exClass'); }); it('should be possible to apply a css class to a class directly with struct', function () { @@ -28,7 +30,7 @@ describe('class diagram, ', function () { parser.parse(str); const testClass = parser.yy.getClass('Class1'); - expect(testClass.cssClasses[0]).toBe('exClass'); + expect(testClass.cssClasses).toBe('default exClass'); }); it('should be possible to apply a css class to a class with relations', function () { @@ -36,7 +38,7 @@ describe('class diagram, ', function () { parser.parse(str); - expect(parser.yy.getClass('Class01').cssClasses[0]).toBe('exClass'); + expect(parser.yy.getClass('Class01').cssClasses).toBe('default exClass'); }); it('should be possible to apply a cssClass to a class', function () { @@ -44,7 +46,7 @@ describe('class diagram, ', function () { parser.parse(str); - expect(parser.yy.getClass('Class01').cssClasses[0]).toBe('exClass'); + expect(parser.yy.getClass('Class01').cssClasses).toBe('default exClass'); }); it('should be possible to apply a cssClass to a comma separated list of classes', function () { @@ -53,8 +55,8 @@ describe('class diagram, ', function () { parser.parse(str); - expect(parser.yy.getClass('Class01').cssClasses[0]).toBe('exClass'); - expect(parser.yy.getClass('Class02').cssClasses[0]).toBe('exClass'); + expect(parser.yy.getClass('Class01').cssClasses).toBe('default exClass'); + expect(parser.yy.getClass('Class02').cssClasses).toBe('default exClass'); }); it('should be possible to apply a style to an individual node', function () { const str = @@ -69,5 +71,47 @@ describe('class diagram, ', function () { expect(styleElements[1]).toBe('stroke:#333'); expect(styleElements[2]).toBe('stroke-width:4px'); }); + it('should be possible to define and assign a class inside the diagram', function () { + const str = + 'classDiagram\n' + 'class Class01\n cssClass "Class01" pink\n classDef pink fill:#f9f'; + + parser.parse(str); + + expect(parser.yy.getClass('Class01').cssClasses).toBe('default pink'); + }); + it('should be possible to define and assign a class using shorthand inside the diagram', function () { + const str = 'classDiagram\n' + 'class Class01:::pink\n classDef pink fill:#f9f'; + + parser.parse(str); + + expect(parser.yy.getClass('Class01').cssClasses).toBe('default pink'); + }); + it('should properly assign styles from a class defined inside the diagram', function () { + const str = + 'classDiagram\n' + + 'class Class01:::pink\n classDef pink fill:#f9f,stroke:#333,stroke-width:6px'; + + parser.parse(str); + + expect(parser.yy.getClass('Class01').styles).toStrictEqual([ + 'fill:#f9f', + 'stroke:#333', + 'stroke-width:6px', + ]); + }); + it('should properly assign multiple classes and styles from classes defined inside the diagram', function () { + const str = + 'classDiagram\n' + + 'class Class01:::pink\n cssClass "Class01" bold\n classDef pink fill:#f9f\n classDef bold stroke:#333,stroke-width:6px'; + + parser.parse(str); + + expect(parser.yy.getClass('Class01').styles).toStrictEqual([ + 'fill:#f9f', + 'stroke:#333', + 'stroke-width:6px', + ]); + expect(parser.yy.getClass('Class01').cssClasses).toBe('default pink bold'); + }); }); }); diff --git a/packages/mermaid/src/diagrams/class/classDiagram-v2.ts b/packages/mermaid/src/diagrams/class/classDiagram-v2.ts index ec5398d29..9111fe658 100644 --- a/packages/mermaid/src/diagrams/class/classDiagram-v2.ts +++ b/packages/mermaid/src/diagrams/class/classDiagram-v2.ts @@ -1,13 +1,15 @@ import type { DiagramDefinition } from '../../diagram-api/types.js'; // @ts-ignore: JISON doesn't support types import parser from './parser/classDiagram.jison'; -import db from './classDb.js'; +import { ClassDB } from './classDb.js'; import styles from './styles.js'; -import renderer from './classRenderer-v2.js'; +import renderer from './classRenderer-v3-unified.js'; export const diagram: DiagramDefinition = { parser, - db, + get db() { + return new ClassDB(); + }, renderer, styles, init: (cnf) => { @@ -15,6 +17,5 @@ export const diagram: DiagramDefinition = { cnf.class = {}; } cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - db.clear(); }, }; diff --git a/packages/mermaid/src/diagrams/class/classDiagram.spec.ts b/packages/mermaid/src/diagrams/class/classDiagram.spec.ts index e3dbb17f1..7c88f2e41 100644 --- a/packages/mermaid/src/diagrams/class/classDiagram.spec.ts +++ b/packages/mermaid/src/diagrams/class/classDiagram.spec.ts @@ -1,7 +1,9 @@ +/* eslint-disable @typescript-eslint/unbound-method -- Broken for Vitest mocks, see https://github.com/vitest-dev/eslint-plugin-vitest/pull/286 */ // @ts-expect-error Jison doesn't export types import { parser } from './parser/classDiagram.jison'; -import classDb from './classDb.js'; +import { ClassDB } from './classDb.js'; import { vi, describe, it, expect } from 'vitest'; +import type { ClassMap, NamespaceNode } from './classTypes.js'; const spyOn = vi.spyOn; const staticCssStyle = 'text-decoration:underline;'; @@ -9,10 +11,83 @@ const abstractCssStyle = 'font-style:italic;'; describe('given a basic class diagram, ', function () { describe('when parsing class definition', function () { + let classDb: ClassDB; beforeEach(function () { - classDb.clear(); + classDb = new ClassDB(); parser.yy = classDb; }); + it('should handle classes within namespaces', () => { + const str = `classDiagram + namespace Company.Project { + class User { + +login(username: String, password: String) + +logout() + } + } + namespace Company.Project.Module { + class Admin { + +addUser(user: User) + +removeUser(user: User) + } + }`; + + parser.parse(str); + + const user = classDb.getClass('User'); + const admin = classDb.getClass('Admin'); + + // Check if the classes are correctly registered under their respective namespaces + expect(user.parent).toBe('Company.Project'); + expect(admin.parent).toBe('Company.Project.Module'); + expect(user.methods.length).toBe(2); + expect(admin.methods.length).toBe(2); + }); + + it('should handle generic classes within namespaces', () => { + const str = `classDiagram + namespace Company.Project.Module { + class GenericClass~T~ { + +addItem(item: T) + +getItem() T + } + }`; + + parser.parse(str); + + const genericClass = classDb.getClass('GenericClass'); + expect(genericClass.type).toBe('T'); + expect(genericClass.methods[0].getDisplayDetails().displayText).toBe('+addItem(item: T)'); + expect(genericClass.methods[1].getDisplayDetails().displayText).toBe('+getItem() : T'); + }); + + it('should handle nested namespaces and relationships', () => { + const str = ` classDiagram + namespace Company.Project.Module.SubModule { + class Report { + +generatePDF(data: List) + +generateCSV(data: List) + } + } + namespace Company.Project.Module { + class Admin { + +generateReport() + } + } + Admin --> Report : generates`; + + parser.parse(str); + + const report = classDb.getClass('Report'); + const admin = classDb.getClass('Admin'); + const relations = classDb.getRelations(); + + expect(report.parent).toBe('Company.Project.Module.SubModule'); + expect(admin.parent).toBe('Company.Project.Module'); + expect(relations[0].id1).toBe('Admin'); + expect(relations[0].id2).toBe('Report'); + expect(relations[0].title).toBe('generates'); + }); + it('should handle accTitle and accDescr', function () { const str = `classDiagram accTitle: My Title @@ -47,7 +122,23 @@ describe('given a basic class diagram, ', function () { } }); - it('should handle backquoted class names', function () { + it('should handle fully qualified class names in relationships', () => { + const str = `classDiagram + namespace Company.Project.Module { + class User + class Admin + } + Admin --> User : manages`; + + parser.parse(str); + + const relations = classDb.getRelations(); + expect(relations[0].id1).toBe('Admin'); + expect(relations[0].id2).toBe('User'); + expect(relations[0].title).toBe('manages'); + }); + + it('should handle backticked class names', function () { const str = 'classDiagram\n' + 'class `Car`'; parser.parse(str); @@ -157,7 +248,7 @@ describe('given a basic class diagram, ', function () { const c1 = classDb.getClass('C1'); expect(c1.label).toBe('Class 1 with text label'); - expect(c1.cssClasses[0]).toBe('styleClass'); + expect(c1.cssClasses).toBe('default styleClass'); }); it('should parse a class with text label and css class', () => { @@ -172,7 +263,7 @@ describe('given a basic class diagram, ', function () { const c1 = classDb.getClass('C1'); expect(c1.label).toBe('Class 1 with text label'); expect(c1.members[0].getDisplayDetails().displayText).toBe('int member1'); - expect(c1.cssClasses[0]).toBe('styleClass'); + expect(c1.cssClasses).toBe('default styleClass'); }); it('should parse two classes with text labels and css classes', () => { @@ -187,11 +278,11 @@ describe('given a basic class diagram, ', function () { const c1 = classDb.getClass('C1'); expect(c1.label).toBe('Class 1 with text label'); - expect(c1.cssClasses[0]).toBe('styleClass'); + expect(c1.cssClasses).toBe('default styleClass'); const c2 = classDb.getClass('C2'); expect(c2.label).toBe('Long long long long long long long long long long label'); - expect(c2.cssClasses[0]).toBe('styleClass'); + expect(c2.cssClasses).toBe('default styleClass'); }); it('should parse two classes with text labels and css class shorthands', () => { @@ -204,11 +295,11 @@ describe('given a basic class diagram, ', function () { const c1 = classDb.getClass('C1'); expect(c1.label).toBe('Class 1 with text label'); - expect(c1.cssClasses[0]).toBe('styleClass1'); + expect(c1.cssClasses).toBe('default styleClass1'); const c2 = classDb.getClass('C2'); expect(c2.label).toBe('Class 2 !@#$%^&*() label'); - expect(c2.cssClasses[0]).toBe('styleClass2'); + expect(c2.cssClasses).toBe('default styleClass2'); }); it('should parse multiple classes with same text labels', () => { @@ -392,12 +483,27 @@ class C13["With Città foreign language"] Student "1" --o "1" IdCard : carries Student "1" --o "1" Bike : rides`); - expect(Object.keys(classDb.getClasses()).length).toBe(3); - expect(classDb.getClasses().Student).toMatchInlineSnapshot(` + const studentClass = classDb.getClasses().get('Student'); + // Check that the important properties match, but ignore the domId + expect(studentClass).toMatchObject({ + id: 'Student', + label: 'Student', + members: [ + expect.objectContaining({ + id: 'idCard : IdCard', + visibility: '-', + }), + ], + methods: [], + annotations: [], + cssClasses: 'default', + }); + + expect(classDb.getClasses().get('Student')).toMatchInlineSnapshot(` { "annotations": [], - "cssClasses": [], - "domId": "classId-Student-134", + "cssClasses": "default", + "domId": "classId-Student-141", "id": "Student", "label": "Student", "members": [ @@ -405,11 +511,14 @@ class C13["With Città foreign language"] "classifier": "", "id": "idCard : IdCard", "memberType": "attribute", + "text": "\\-idCard : IdCard", "visibility": "-", }, ], "methods": [], + "shape": "classBox", "styles": [], + "text": "Student", "type": "", } `); @@ -443,11 +552,23 @@ class C13["With Città foreign language"] ] `); }); + + it('should revert direction to default once direction is removed', () => { + parser.parse(`classDiagram + direction RL + class A`); + expect(classDb.getDirection()).toBe('RL'); + classDb.clear(); + parser.parse(`classDiagram + class B`); + expect(classDb.getDirection()).toBe('TB'); + }); }); describe('when parsing class defined in brackets', function () { + let classDb: ClassDB; beforeEach(function () { - classDb.clear(); + classDb = new ClassDB(); parser.yy = classDb; }); @@ -538,8 +659,9 @@ class C13["With Città foreign language"] }); describe('when parsing comments', function () { + let classDb: ClassDB; beforeEach(function () { - classDb.clear(); + classDb = new ClassDB(); parser.yy = classDb; }); @@ -628,8 +750,9 @@ foo() }); describe('when parsing click statements', function () { + let classDb: ClassDB; beforeEach(function () { - classDb.clear(); + classDb = new ClassDB(); parser.yy = classDb; }); it('should handle href link', function () { @@ -642,7 +765,7 @@ foo() const actual = parser.yy.getClass('Class1'); expect(actual.link).toBe('google.com'); - expect(actual.cssClasses[0]).toBe('clickable'); + expect(actual.cssClasses).toBe('default clickable'); }); it('should handle href link with tooltip', function () { @@ -658,7 +781,7 @@ foo() const actual = parser.yy.getClass('Class1'); expect(actual.link).toBe('google.com'); expect(actual.tooltip).toBe('A Tooltip'); - expect(actual.cssClasses[0]).toBe('clickable'); + expect(actual.cssClasses).toBe('default clickable'); }); it('should handle href link with tooltip and target', function () { @@ -677,7 +800,7 @@ foo() const actual = parser.yy.getClass('Class1'); expect(actual.link).toBe('google.com'); expect(actual.tooltip).toBe('A tooltip'); - expect(actual.cssClasses[0]).toBe('clickable'); + expect(actual.cssClasses).toBe('default clickable'); }); it('should handle function call', function () { @@ -739,8 +862,9 @@ foo() }); describe('when parsing annotations', function () { + let classDb: ClassDB; beforeEach(function () { - classDb.clear(); + classDb = new ClassDB(); parser.yy = classDb; }); @@ -803,8 +927,9 @@ foo() describe('given a class diagram with members and methods ', function () { describe('when parsing members', function () { + let classDb: ClassDB; beforeEach(function () { - classDb.clear(); + classDb = new ClassDB(); parser.yy = classDb; }); @@ -862,8 +987,9 @@ describe('given a class diagram with members and methods ', function () { }); describe('when parsing method definition', function () { + let classDb: ClassDB; beforeEach(function () { - classDb.clear(); + classDb = new ClassDB(); parser.yy = classDb; }); @@ -949,8 +1075,9 @@ describe('given a class diagram with members and methods ', function () { describe('given a class diagram with generics, ', function () { describe('when parsing valid generic classes', function () { + let classDb: ClassDB; beforeEach(function () { - classDb.clear(); + classDb = new ClassDB(); parser.yy = classDb; }); @@ -1062,8 +1189,9 @@ namespace space { describe('given a class diagram with relationships, ', function () { describe('when parsing basic relationships', function () { + let classDb: ClassDB; beforeEach(function () { - classDb.clear(); + classDb = new ClassDB(); parser.yy = classDb; }); @@ -1079,7 +1207,7 @@ describe('given a class diagram with relationships, ', function () { parser.parse(str); }); - it('should handle backquoted class name', function () { + it('should handle backticked class name', function () { const str = 'classDiagram\n' + '`Class1` <|-- Class02\n' + @@ -1372,8 +1500,7 @@ describe('given a class diagram with relationships, ', function () { const testClass = parser.yy.getClass('Class1'); expect(testClass.link).toBe('google.com'); - expect(testClass.cssClasses.length).toBe(1); - expect(testClass.cssClasses[0]).toBe('clickable'); + expect(testClass.cssClasses).toBe('default clickable'); }); it('should associate click and href link and css appropriately', function () { @@ -1386,8 +1513,7 @@ describe('given a class diagram with relationships, ', function () { const testClass = parser.yy.getClass('Class1'); expect(testClass.link).toBe('google.com'); - expect(testClass.cssClasses.length).toBe(1); - expect(testClass.cssClasses[0]).toBe('clickable'); + expect(testClass.cssClasses).toBe('default clickable'); }); it('should associate link with tooltip', function () { @@ -1401,8 +1527,7 @@ describe('given a class diagram with relationships, ', function () { const testClass = parser.yy.getClass('Class1'); expect(testClass.link).toBe('google.com'); expect(testClass.tooltip).toBe('A tooltip'); - expect(testClass.cssClasses.length).toBe(1); - expect(testClass.cssClasses[0]).toBe('clickable'); + expect(testClass.cssClasses).toBe('default clickable'); }); it('should associate click and href link with tooltip', function () { @@ -1416,8 +1541,7 @@ describe('given a class diagram with relationships, ', function () { const testClass = parser.yy.getClass('Class1'); expect(testClass.link).toBe('google.com'); expect(testClass.tooltip).toBe('A tooltip'); - expect(testClass.cssClasses.length).toBe(1); - expect(testClass.cssClasses[0]).toBe('clickable'); + expect(testClass.cssClasses).toBe('default clickable'); }); it('should associate click and href link with tooltip and target appropriately', function () { @@ -1539,12 +1663,12 @@ class Class2 }`; parser.parse(str); - const testNamespace = parser.yy.getNamespace('Namespace1'); - const testClasses = parser.yy.getClasses(); - expect(Object.keys(testNamespace.classes).length).toBe(2); + const testNamespace: NamespaceNode = parser.yy.getNamespace('Namespace1'); + const testClasses: ClassMap = parser.yy.getClasses(); + expect(testNamespace.classes.size).toBe(2); expect(Object.keys(testNamespace.children).length).toBe(0); - expect(testNamespace.classes['Class1'].id).toBe('Class1'); - expect(Object.keys(testClasses).length).toBe(2); + expect(testNamespace.classes.get('Class1')?.id).toBe('Class1'); + expect(testClasses.size).toBe(2); }); it('should add relations between classes of different namespaces', function () { @@ -1573,25 +1697,25 @@ class Class2 const testNamespaceB = parser.yy.getNamespace('B'); const testClasses = parser.yy.getClasses(); const testRelations = parser.yy.getRelations(); - expect(Object.keys(testNamespaceA.classes).length).toBe(2); - expect(testNamespaceA.classes['A1'].members[0].getDisplayDetails().displayText).toBe( + expect(testNamespaceA.classes.size).toBe(2); + expect(testNamespaceA.classes.get('A1').members[0].getDisplayDetails().displayText).toBe( '+foo : string' ); - expect(testNamespaceA.classes['A2'].members[0].getDisplayDetails().displayText).toBe( + expect(testNamespaceA.classes.get('A2').members[0].getDisplayDetails().displayText).toBe( '+bar : int' ); - expect(Object.keys(testNamespaceB.classes).length).toBe(2); - expect(testNamespaceB.classes['B1'].members[0].getDisplayDetails().displayText).toBe( + expect(testNamespaceB.classes.size).toBe(2); + expect(testNamespaceB.classes.get('B1').members[0].getDisplayDetails().displayText).toBe( '+foo : bool' ); - expect(testNamespaceB.classes['B2'].members[0].getDisplayDetails().displayText).toBe( + expect(testNamespaceB.classes.get('B2').members[0].getDisplayDetails().displayText).toBe( '+bar : float' ); - expect(Object.keys(testClasses).length).toBe(4); - expect(testClasses['A1'].parent).toBe('A'); - expect(testClasses['A2'].parent).toBe('A'); - expect(testClasses['B1'].parent).toBe('B'); - expect(testClasses['B2'].parent).toBe('B'); + expect(testClasses.size).toBe(4); + expect(testClasses.get('A1').parent).toBe('A'); + expect(testClasses.get('A2').parent).toBe('A'); + expect(testClasses.get('B1').parent).toBe('B'); + expect(testClasses.get('B2').parent).toBe('B'); expect(testRelations[0].id1).toBe('A1'); expect(testRelations[0].id2).toBe('B1'); expect(testRelations[1].id1).toBe('A2'); @@ -1600,7 +1724,9 @@ class Class2 }); describe('when parsing classDiagram with text labels', () => { + let classDb: ClassDB; beforeEach(function () { + classDb = new ClassDB(); parser.yy = classDb; parser.yy.clear(); }); @@ -1674,8 +1800,7 @@ C1 --> C2 const c1 = classDb.getClass('C1'); expect(c1.label).toBe('Class 1 with text label'); - expect(c1.cssClasses.length).toBe(1); - expect(c1.cssClasses[0]).toBe('styleClass'); + expect(c1.cssClasses).toBe('default styleClass'); const member = c1.members[0]; expect(member.getDisplayDetails().displayText).toBe('+member1'); }); @@ -1691,8 +1816,7 @@ cssClass "C1" styleClass const c1 = classDb.getClass('C1'); expect(c1.label).toBe('Class 1 with text label'); - expect(c1.cssClasses.length).toBe(1); - expect(c1.cssClasses[0]).toBe('styleClass'); + expect(c1.cssClasses).toBe('default styleClass'); const member = c1.members[0]; expect(member.getDisplayDetails().displayText).toBe('+member1'); }); @@ -1709,13 +1833,11 @@ cssClass "C1,C2" styleClass const c1 = classDb.getClass('C1'); expect(c1.label).toBe('Class 1 with text label'); - expect(c1.cssClasses.length).toBe(1); - expect(c1.cssClasses[0]).toBe('styleClass'); + expect(c1.cssClasses).toBe('default styleClass'); const c2 = classDb.getClass('C2'); expect(c2.label).toBe('Long long long long long long long long long long label'); - expect(c2.cssClasses.length).toBe(1); - expect(c2.cssClasses[0]).toBe('styleClass'); + expect(c2.cssClasses).toBe('default styleClass'); }); it('should parse two classes with text labels and css class shorthands', () => { @@ -1729,13 +1851,11 @@ C1 --> C2 const c1 = classDb.getClass('C1'); expect(c1.label).toBe('Class 1 with text label'); - expect(c1.cssClasses.length).toBe(1); - expect(c1.cssClasses[0]).toBe('styleClass1'); + expect(c1.cssClasses).toBe('default styleClass1'); const c2 = classDb.getClass('C2'); expect(c2.label).toBe('Class 2 !@#$%^&*() label'); - expect(c2.cssClasses.length).toBe(1); - expect(c2.cssClasses[0]).toBe('styleClass2'); + expect(c2.cssClasses).toBe('default styleClass2'); }); it('should parse multiple classes with same text labels', () => { @@ -1789,3 +1909,40 @@ class C13["With Città foreign language"] }); }); }); + +describe('class db class', () => { + let classDb: ClassDB; + beforeEach(() => { + classDb = new ClassDB(); + }); + // This is to ensure that functions used in class JISON are exposed as function from ClassDB + it('should have functions used in class JISON as own property', () => { + const functionsUsedInParser = [ + 'addRelation', + 'cleanupLabel', + 'setAccTitle', + 'setAccDescription', + 'addClassesToNamespace', + 'addNamespace', + 'setCssClass', + 'addMembers', + 'addClass', + 'setClassLabel', + 'addAnnotation', + 'addMember', + 'addNote', + 'defineClass', + 'setDirection', + 'relationType', + 'lineType', + 'setClickEvent', + 'setTooltip', + 'setLink', + 'setCssStyle', + ] as const satisfies (keyof ClassDB)[]; + + for (const fun of functionsUsedInParser) { + expect(Object.hasOwn(classDb, fun)).toBe(true); + } + }); +}); diff --git a/packages/mermaid/src/diagrams/class/classDiagram.ts b/packages/mermaid/src/diagrams/class/classDiagram.ts index 7f027c186..9111fe658 100644 --- a/packages/mermaid/src/diagrams/class/classDiagram.ts +++ b/packages/mermaid/src/diagrams/class/classDiagram.ts @@ -1,13 +1,15 @@ import type { DiagramDefinition } from '../../diagram-api/types.js'; // @ts-ignore: JISON doesn't support types import parser from './parser/classDiagram.jison'; -import db from './classDb.js'; +import { ClassDB } from './classDb.js'; import styles from './styles.js'; -import renderer from './classRenderer.js'; +import renderer from './classRenderer-v3-unified.js'; export const diagram: DiagramDefinition = { parser, - db, + get db() { + return new ClassDB(); + }, renderer, styles, init: (cnf) => { @@ -15,6 +17,5 @@ export const diagram: DiagramDefinition = { cnf.class = {}; } cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - db.clear(); }, }; diff --git a/packages/mermaid/src/diagrams/class/classRenderer-v2.ts b/packages/mermaid/src/diagrams/class/classRenderer-v2.ts index a01b1427b..0f02efa0d 100644 --- a/packages/mermaid/src/diagrams/class/classRenderer-v2.ts +++ b/packages/mermaid/src/diagrams/class/classRenderer-v2.ts @@ -4,7 +4,7 @@ import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; import { log } from '../../logger.js'; import { getConfig } from '../../diagram-api/diagramAPI.js'; import { render } from '../../dagre-wrapper/index.js'; -import utils from '../../utils.js'; +import utils, { getEdgeId } from '../../utils.js'; import { interpolateToCurve, getStylesFromArray } from '../../utils.js'; import { setupGraphViewbox } from '../../setupGraphViewbox.js'; import common from '../common/common.js'; @@ -44,14 +44,11 @@ export const addNamespaces = function ( _id: string, diagObj: any ) { - const keys = Object.keys(namespaces); - log.info('keys:', keys); + log.info('keys:', [...namespaces.keys()]); log.info(namespaces); // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition - keys.forEach(function (id) { - const vertex = namespaces[id]; - + namespaces.forEach(function (vertex) { // parent node must be one of [rect, roundedWithTitle, noteGroup, divider] const shape = 'rect'; @@ -89,16 +86,13 @@ export const addClasses = function ( diagObj: any, parent?: string ) { - const keys = Object.keys(classes); - log.info('keys:', keys); + log.info('keys:', [...classes.keys()]); log.info(classes); // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition - keys - .filter((id) => classes[id].parent == parent) - .forEach(function (id) { - const vertex = classes[id]; - + [...classes.values()] + .filter((vertex) => vertex.parent === parent) + .forEach(function (vertex) { /** * Variable for storing the classes for the vertex */ @@ -187,7 +181,7 @@ export const addNotes = function ( g.setNode(vertex.id, node); log.info('setNode', node); - if (!vertex.class || !(vertex.class in classes)) { + if (!vertex.class || !classes.has(vertex.class)) { return; } const edgeId = startEdgeId + i; @@ -231,7 +225,10 @@ export const addRelations = function (relations: ClassRelation[], g: graphlib.Gr //Set relationship style and line type classes: 'relation', pattern: edge.relation.lineType == 1 ? 'dashed' : 'solid', - id: `id_${edge.id1}_${edge.id2}_${cnt}`, + id: getEdgeId(edge.id1, edge.id2, { + prefix: 'id', + counter: cnt, + }), // Set link type for rendering arrowhead: edge.type === 'arrow_open' ? 'none' : 'normal', //Set edge extra labels @@ -346,7 +343,7 @@ export const draw = async function (text: string, id: string, _version: string, } const root = securityLevel === 'sandbox' - ? select(sandboxElement.nodes()[0].contentDocument.body) + ? select(sandboxElement.nodes()[0]!.contentDocument.body) : select('body'); const svg = root.select(`[id="${id}"]`); @@ -366,7 +363,7 @@ export const draw = async function (text: string, id: string, _version: string, // Add label rects for non html labels if (!conf?.htmlLabels) { - const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0]!.contentDocument : document; const labels = doc.querySelectorAll('[id="' + id + '"] .edgeLabel .label'); for (const label of labels) { // Get dimensions of label diff --git a/packages/mermaid/src/diagrams/class/classRenderer-v3-unified.ts b/packages/mermaid/src/diagrams/class/classRenderer-v3-unified.ts new file mode 100644 index 000000000..670f93f16 --- /dev/null +++ b/packages/mermaid/src/diagrams/class/classRenderer-v3-unified.ts @@ -0,0 +1,79 @@ +import { getConfig } from '../../diagram-api/diagramAPI.js'; +import type { DiagramStyleClassDef } from '../../diagram-api/types.js'; +import { log } from '../../logger.js'; +import { getDiagramElement } from '../../rendering-util/insertElementsForSize.js'; +import { getRegisteredLayoutAlgorithm, render } from '../../rendering-util/render.js'; +import { setupViewPortForSVG } from '../../rendering-util/setupViewPortForSVG.js'; +import type { LayoutData } from '../../rendering-util/types.js'; +import utils from '../../utils.js'; + +/** + * Get the direction from the statement items. + * Look through all of the documents (docs) in the parsedItems + * Because is a _document_ direction, the default direction is not necessarily the same as the overall default _diagram_ direction. + * @param parsedItem - the parsed statement item to look through + * @param defaultDir - the direction to use if none is found + * @returns The direction to use + */ +export const getDir = (parsedItem: any, defaultDir = 'TB') => { + if (!parsedItem.doc) { + return defaultDir; + } + + let dir = defaultDir; + + for (const parsedItemDoc of parsedItem.doc) { + if (parsedItemDoc.stmt === 'dir') { + dir = parsedItemDoc.value; + } + } + + return dir; +}; + +export const getClasses = function ( + text: string, + diagramObj: any +): Map { + return diagramObj.db.getClasses(); +}; + +export const draw = async function (text: string, id: string, _version: string, diag: any) { + log.info('REF0:'); + log.info('Drawing class diagram (v3)', id); + const { securityLevel, state: conf, layout } = getConfig(); + // Extracting the data from the parsed structure into a more usable form + // Not related to the refactoring, but this is the first step in the rendering process + // diag.db.extract(diag.db.getRootDocV2()); + + // The getData method provided in all supported diagrams is used to extract the data from the parsed structure + // into the Layout data format + const data4Layout = diag.db.getData() as LayoutData; + + // Create the root SVG - the element is the div containing the SVG element + const svg = getDiagramElement(id, securityLevel); + + data4Layout.type = diag.type; + data4Layout.layoutAlgorithm = getRegisteredLayoutAlgorithm(layout); + + data4Layout.nodeSpacing = conf?.nodeSpacing || 50; + data4Layout.rankSpacing = conf?.rankSpacing || 50; + data4Layout.markers = ['aggregation', 'extension', 'composition', 'dependency', 'lollipop']; + data4Layout.diagramId = id; + await render(data4Layout, svg); + const padding = 8; + utils.insertTitle( + svg, + 'classDiagramTitleText', + conf?.titleTopMargin ?? 25, + diag.db.getDiagramTitle() + ); + + setupViewPortForSVG(svg, padding, 'classDiagram', conf?.useMaxWidth ?? true); +}; + +export default { + getClasses, + draw, + getDir, +}; diff --git a/packages/mermaid/src/diagrams/class/classRenderer.js b/packages/mermaid/src/diagrams/class/classRenderer.js index be098b027..27e525537 100644 --- a/packages/mermaid/src/diagrams/class/classRenderer.js +++ b/packages/mermaid/src/diagrams/class/classRenderer.js @@ -175,10 +175,10 @@ export const draw = function (text, id, _version, diagObj) { }); const classes = diagObj.db.getClasses(); - const keys = Object.keys(classes); + const keys = [...classes.keys()]; for (const key of keys) { - const classDef = classes[key]; + const classDef = classes.get(key); const node = svgDraw.drawClass(diagram, classDef, conf, diagObj); idCache[node.id] = node; @@ -216,7 +216,7 @@ export const draw = function (text, id, _version, diagObj) { // metadata about the node. In this case we're going to add labels to each of // our nodes. g.setNode(node.id, node); - if (note.class && note.class in classes) { + if (note.class && classes.has(note.class)) { g.setEdge( note.id, getGraphId(note.class), diff --git a/packages/mermaid/src/diagrams/class/classTypes.ts b/packages/mermaid/src/diagrams/class/classTypes.ts index c2f158702..9d0d47569 100644 --- a/packages/mermaid/src/diagrams/class/classTypes.ts +++ b/packages/mermaid/src/diagrams/class/classTypes.ts @@ -5,7 +5,9 @@ export interface ClassNode { id: string; type: string; label: string; - cssClasses: string[]; + shape: string; + text: string; + cssClasses: string; methods: ClassMember[]; members: ClassMember[]; annotations: string[]; @@ -16,6 +18,7 @@ export interface ClassNode { linkTarget?: string; haveCallback?: boolean; tooltip?: string; + look?: string; } export type Visibility = '#' | '+' | '~' | '-' | ''; @@ -30,6 +33,7 @@ export class ClassMember { cssStyle!: string; memberType!: 'method' | 'attribute'; visibility!: Visibility; + text: string; /** * denote if static or to determine which css class to apply to the node * @defaultValue '' @@ -50,6 +54,7 @@ export class ClassMember { this.memberType = memberType; this.visibility = ''; this.classifier = ''; + this.text = ''; const sanitizedInput = sanitizeText(input, getConfig()); this.parseMember(sanitizedInput); } @@ -77,7 +82,7 @@ export class ClassMember { if (this.memberType === 'method') { const methodRegEx = /([#+~-])?(.+)\((.*)\)([\s$*])?(.*)([$*])?/; - const match = input.match(methodRegEx); + const match = methodRegEx.exec(input); if (match) { const detectedVisibility = match[1] ? match[1].trim() : ''; @@ -85,14 +90,14 @@ export class ClassMember { this.visibility = detectedVisibility as Visibility; } - this.id = match[2].trim(); + this.id = match[2]; this.parameters = match[3] ? match[3].trim() : ''; potentialClassifier = match[4] ? match[4].trim() : ''; this.returnType = match[5] ? match[5].trim() : ''; if (potentialClassifier === '') { const lastChar = this.returnType.substring(this.returnType.length - 1); - if (lastChar.match(/[$*]/)) { + if (/[$*]/.exec(lastChar)) { potentialClassifier = lastChar; this.returnType = this.returnType.substring(0, this.returnType.length - 1); } @@ -107,7 +112,7 @@ export class ClassMember { this.visibility = firstChar as Visibility; } - if (lastChar.match(/[$*]/)) { + if (/[$*]/.exec(lastChar)) { potentialClassifier = lastChar; } @@ -118,6 +123,14 @@ export class ClassMember { } this.classifier = potentialClassifier; + // Preserve one space only + this.id = this.id.startsWith(' ') ? ' ' + this.id.trim() : this.id.trim(); + + const combinedText = `${this.visibility ? '\\' + this.visibility : ''}${parseGenericTypes(this.id)}${this.memberType === 'method' ? `(${parseGenericTypes(this.parameters)})${this.returnType ? ' : ' + parseGenericTypes(this.returnType) : ''}` : ''}`; + this.text = combinedText.replaceAll('<', '<').replaceAll('>', '>'); + if (this.text.startsWith('\\<')) { + this.text = this.text.replace('\\<', '~'); + } } parseClassifier() { @@ -154,6 +167,12 @@ export interface ClassRelation { }; } +export interface Interface { + id: string; + label: string; + classId: string; +} + export interface NamespaceNode { id: string; domId: string; @@ -161,5 +180,11 @@ export interface NamespaceNode { children: NamespaceMap; } -export type ClassMap = Record; -export type NamespaceMap = Record; +export interface StyleClass { + id: string; + styles: string[]; + textStyles: string[]; +} + +export type ClassMap = Map; +export type NamespaceMap = Map; diff --git a/packages/mermaid/src/diagrams/class/parser/class.spec.js b/packages/mermaid/src/diagrams/class/parser/class.spec.js new file mode 100644 index 000000000..fe0077a29 --- /dev/null +++ b/packages/mermaid/src/diagrams/class/parser/class.spec.js @@ -0,0 +1,18 @@ +import { parser } from './classDiagram.jison'; +import { ClassDB } from '../classDb.js'; + +describe('class diagram', function () { + let classDb; + beforeEach(function () { + classDb = new ClassDB(); + parser.yy = classDb; + parser.yy.clear(); + }); + + describe('prototype properties', function () { + it.each(['__proto__', 'constructor'])('should work with a %s property', function (prop) { + expect(() => parser.parse(`classDiagram\nclass ${prop}`)).not.toThrow(); + expect(() => parser.parse(`classDiagram\nnamespace ${prop} {\n\tclass A\n}`)).not.toThrow(); + }); + }); +}); diff --git a/packages/mermaid/src/diagrams/class/parser/classDiagram.jison b/packages/mermaid/src/diagrams/class/parser/classDiagram.jison index ed4e72027..83d9bd48e 100644 --- a/packages/mermaid/src/diagrams/class/parser/classDiagram.jison +++ b/packages/mermaid/src/diagrams/class/parser/classDiagram.jison @@ -61,6 +61,7 @@ Function arguments are optional: 'call ()' simply executes 'callb [^"]* return "STR"; <*>["] this.begin("string"); "style" return 'STYLE'; +"classDef" return 'CLASSDEF'; "namespace" { this.begin('namespace'); return 'NAMESPACE'; } \s*(\r?\n)+ { this.popState(); return 'NEWLINE'; } @@ -241,11 +242,13 @@ classLabel namespaceName : alphaNumToken { $$=$1; } + | alphaNumToken DOT namespaceName { $$=$1+'.'+$3; } | alphaNumToken namespaceName { $$=$1+$2; } ; className : alphaNumToken { $$=$1; } + | alphaNumToken DOT className { $$=$1+'.'+$3; } | classLiteralName { $$=$1; } | alphaNumToken className { $$=$1+$2; } | alphaNumToken GENERICTYPE { $$=$1+'~'+$2+'~'; } @@ -263,6 +266,7 @@ statement | styleStatement | cssClassStatement | noteStatement + | classDefStatement | direction | acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); } | acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); } @@ -270,12 +274,12 @@ statement ; namespaceStatement - : namespaceIdentifier STRUCT_START classStatements STRUCT_STOP {yy.addClassesToNamespace($1, $3);} - | namespaceIdentifier STRUCT_START NEWLINE classStatements STRUCT_STOP {yy.addClassesToNamespace($1, $4);} + : namespaceIdentifier STRUCT_START classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $3); } + | namespaceIdentifier STRUCT_START NEWLINE classStatements STRUCT_STOP { yy.addClassesToNamespace($1, $4); } ; namespaceIdentifier - : NAMESPACE namespaceName {$$=$2; yy.addNamespace($2);} + : NAMESPACE namespaceName { $$=$2; yy.addNamespace($2); } ; classStatements @@ -324,6 +328,15 @@ noteStatement | NOTE noteText { yy.addNote($2); } ; +classDefStatement + : CLASSDEF classList stylesOpt {$$ = $CLASSDEF;yy.defineClass($classList,$stylesOpt);} + ; + +classList + : ALPHA { $$ = [$ALPHA]; } + | classList COMMA ALPHA = { $$ = $classList.concat([$ALPHA]); } + ; + direction : direction_tb { yy.setDirection('TB');} diff --git a/packages/mermaid/src/diagrams/class/shapeUtil.ts b/packages/mermaid/src/diagrams/class/shapeUtil.ts new file mode 100644 index 000000000..94c8f817a --- /dev/null +++ b/packages/mermaid/src/diagrams/class/shapeUtil.ts @@ -0,0 +1,223 @@ +import { select } from 'd3'; +import { getConfig } from '../../config.js'; +import { getNodeClasses } from '../../rendering-util/rendering-elements/shapes/util.js'; +import { calculateTextWidth, decodeEntities } from '../../utils.js'; +import type { ClassMember, ClassNode } from './classTypes.js'; +import { sanitizeText } from '../../diagram-api/diagramAPI.js'; +import { createText } from '../../rendering-util/createText.js'; +import { evaluate, hasKatex } from '../common/common.js'; +import type { Node } from '../../rendering-util/types.js'; +import type { MermaidConfig } from '../../config.type.js'; +import type { D3Selection } from '../../types.js'; + +// Creates the shapeSvg and inserts text +export async function textHelper( + parent: D3Selection, + node: any, + config: MermaidConfig, + useHtmlLabels: boolean, + GAP = config.class!.padding ?? 12 +) { + const TEXT_PADDING = !useHtmlLabels ? 3 : 0; + const shapeSvg = parent + // @ts-ignore: Ignore error for using .insert on SVGAElement + .insert('g') + .attr('class', getNodeClasses(node)) + .attr('id', node.domId || node.id); + + let annotationGroup = null; + let labelGroup = null; + let membersGroup = null; + let methodsGroup = null; + + let annotationGroupHeight = 0; + let labelGroupHeight = 0; + let membersGroupHeight = 0; + + annotationGroup = shapeSvg.insert('g').attr('class', 'annotation-group text'); + if (node.annotations.length > 0) { + const annotation = node.annotations[0]; + await addText(annotationGroup, { text: `ÂĢ${annotation}Âģ` } as unknown as ClassMember, 0); + + const annotationGroupBBox = annotationGroup.node()!.getBBox(); + annotationGroupHeight = annotationGroupBBox.height; + } + + labelGroup = shapeSvg.insert('g').attr('class', 'label-group text'); + await addText(labelGroup, node, 0, ['font-weight: bolder']); + const labelGroupBBox = labelGroup.node()!.getBBox(); + labelGroupHeight = labelGroupBBox.height; + + membersGroup = shapeSvg.insert('g').attr('class', 'members-group text'); + let yOffset = 0; + for (const member of node.members) { + const height = await addText(membersGroup, member, yOffset, [member.parseClassifier()]); + yOffset += height + TEXT_PADDING; + } + membersGroupHeight = membersGroup.node()!.getBBox().height; + if (membersGroupHeight <= 0) { + membersGroupHeight = GAP / 2; + } + + methodsGroup = shapeSvg.insert('g').attr('class', 'methods-group text'); + let methodsYOffset = 0; + for (const method of node.methods) { + const height = await addText(methodsGroup, method, methodsYOffset, [method.parseClassifier()]); + methodsYOffset += height + TEXT_PADDING; + } + + let bbox = shapeSvg.node()!.getBBox(); + + // Center annotation + if (annotationGroup !== null) { + const annotationGroupBBox = annotationGroup.node()!.getBBox(); + annotationGroup.attr('transform', `translate(${-annotationGroupBBox.width / 2})`); + } + + // Adjust label + labelGroup.attr('transform', `translate(${-labelGroupBBox.width / 2}, ${annotationGroupHeight})`); + + bbox = shapeSvg.node()!.getBBox(); + + membersGroup.attr( + 'transform', + `translate(${0}, ${annotationGroupHeight + labelGroupHeight + GAP * 2})` + ); + bbox = shapeSvg.node()!.getBBox(); + methodsGroup.attr( + 'transform', + `translate(${0}, ${annotationGroupHeight + labelGroupHeight + (membersGroupHeight ? membersGroupHeight + GAP * 4 : GAP * 2)})` + ); + + bbox = shapeSvg.node()!.getBBox(); + + return { shapeSvg, bbox }; +} + +// Modified version of labelHelper() to help create and place text for classes +async function addText( + parentGroup: D3Selection, + node: Node | ClassNode | ClassMember, + yOffset: number, + styles: string[] = [] +) { + const textEl = parentGroup.insert('g').attr('class', 'label').attr('style', styles.join('; ')); + const config = getConfig(); + let useHtmlLabels = + 'useHtmlLabels' in node ? node.useHtmlLabels : (evaluate(config.htmlLabels) ?? true); + + let textContent = ''; + // Support regular node type (.label) and classNodes (.text) + if ('text' in node) { + textContent = node.text; + } else { + textContent = node.label!; + } + + // createText() will cause unwanted behavior because of classDiagram syntax so workarounds are needed + + if (!useHtmlLabels && textContent.startsWith('\\')) { + textContent = textContent.substring(1); + } + + if (hasKatex(textContent)) { + useHtmlLabels = true; + } + + const text = await createText( + textEl, + sanitizeText(decodeEntities(textContent)), + { + width: calculateTextWidth(textContent, config) + 50, // Add room for error when splitting text into multiple lines + classes: 'markdown-node-label', + useHtmlLabels, + }, + config + ); + let bbox; + let numberOfLines = 1; + + if (!useHtmlLabels) { + // Undo font-weight normal + if (styles.includes('font-weight: bolder')) { + select(text).selectAll('tspan').attr('font-weight', ''); + } + + numberOfLines = text.children.length; + + const textChild = text.children[0]; + if (text.textContent === '' || text.textContent.includes('>')) { + textChild.textContent = + textContent[0] + + textContent.substring(1).replaceAll('>', '>').replaceAll('<', '<').trim(); + + // Text was improperly removed due to spaces (preserve one space if present) + const preserveSpace = textContent[1] === ' '; + if (preserveSpace) { + textChild.textContent = textChild.textContent[0] + ' ' + textChild.textContent.substring(1); + } + } + + // To support empty boxes + if (textChild.textContent === 'undefined') { + textChild.textContent = ''; + } + + // Get the bounding box after the text update + bbox = text.getBBox(); + } else { + const div = text.children[0]; + const dv = select(text); + + numberOfLines = div.innerHTML.split('
').length; + // Katex math support + if (div.innerHTML.includes('')) { + numberOfLines += div.innerHTML.split('').length - 1; + } + + // Support images + const images = div.getElementsByTagName('img'); + if (images) { + const noImgText = textContent.replace(/]*>/g, '').trim() === ''; + await Promise.all( + [...images].map( + (img) => + new Promise((res) => { + function setupImage() { + img.style.display = 'flex'; + img.style.flexDirection = 'column'; + + if (noImgText) { + // default size if no text + const bodyFontSize = + config.fontSize?.toString() ?? window.getComputedStyle(document.body).fontSize; + const enlargingFactor = 5; + const width = parseInt(bodyFontSize, 10) * enlargingFactor + 'px'; + img.style.minWidth = width; + img.style.maxWidth = width; + } else { + img.style.width = '100%'; + } + res(img); + } + setTimeout(() => { + if (img.complete) { + setupImage(); + } + }); + img.addEventListener('error', setupImage); + img.addEventListener('load', setupImage); + }) + ) + ); + } + + bbox = div.getBoundingClientRect(); + dv.attr('width', bbox.width); + dv.attr('height', bbox.height); + } + + // Center text and offset by yOffset + textEl.attr('transform', 'translate(0,' + (-bbox.height / (2 * numberOfLines) + yOffset) + ')'); + return bbox.height; +} diff --git a/packages/mermaid/src/diagrams/class/styles.js b/packages/mermaid/src/diagrams/class/styles.js index 9bad27f38..4a888a265 100644 --- a/packages/mermaid/src/diagrams/class/styles.js +++ b/packages/mermaid/src/diagrams/class/styles.js @@ -20,6 +20,10 @@ const getStyles = (options) => .label text { fill: ${options.classText}; } + +.labelBkg { + background: ${options.mainBkg}; +} .edgeLabel .label span { background: ${options.mainBkg}; } diff --git a/packages/mermaid/src/diagrams/class/svgDraw.js b/packages/mermaid/src/diagrams/class/svgDraw.js index d6ed7bca4..73cf97aeb 100644 --- a/packages/mermaid/src/diagrams/class/svgDraw.js +++ b/packages/mermaid/src/diagrams/class/svgDraw.js @@ -315,10 +315,10 @@ export const getClassTitleString = function (classDef) { * @param {SVGSVGElement} elem The element to draw it into * @param {{id: string; text: string; class: string;}} note * @param conf - * @param diagObj + * @param _diagObj * @todo Add more information in the JSDOC here */ -export const drawNote = function (elem, note, conf, diagObj) { +export const drawNote = function (elem, note, conf, _diagObj) { log.debug('Rendering note ', note, conf); const id = note.id; diff --git a/packages/mermaid/src/diagrams/common/common.spec.ts b/packages/mermaid/src/diagrams/common/common.spec.ts index 9af244406..3c7e0fdb8 100644 --- a/packages/mermaid/src/diagrams/common/common.spec.ts +++ b/packages/mermaid/src/diagrams/common/common.spec.ts @@ -28,7 +28,7 @@ describe('when securityLevel is antiscript, all script must be removed', () => { it('should remove all javascript urls', () => { compareRemoveScript( `This is a clean link + clean link - and me too`, + and me too`, `This is a clean link + clean link and me too` ); diff --git a/packages/mermaid/src/diagrams/common/common.ts b/packages/mermaid/src/diagrams/common/common.ts index 50bc0ab4c..6c50e4cfc 100644 --- a/packages/mermaid/src/diagrams/common/common.ts +++ b/packages/mermaid/src/diagrams/common/common.ts @@ -32,15 +32,15 @@ const setupDompurifyHooksIfNotSetup = (() => { function setupDompurifyHooks() { const TEMPORARY_ATTRIBUTE = 'data-temp-href-target'; - DOMPurify.addHook('beforeSanitizeAttributes', (node: Element) => { - if (node.tagName === 'A' && node.hasAttribute('target')) { - node.setAttribute(TEMPORARY_ATTRIBUTE, node.getAttribute('target') || ''); + DOMPurify.addHook('beforeSanitizeAttributes', (node) => { + if (node instanceof Element && node.tagName === 'A' && node.hasAttribute('target')) { + node.setAttribute(TEMPORARY_ATTRIBUTE, node.getAttribute('target') ?? ''); } }); - DOMPurify.addHook('afterSanitizeAttributes', (node: Element) => { - if (node.tagName === 'A' && node.hasAttribute(TEMPORARY_ATTRIBUTE)) { - node.setAttribute('target', node.getAttribute(TEMPORARY_ATTRIBUTE) || ''); + DOMPurify.addHook('afterSanitizeAttributes', (node) => { + if (node instanceof Element && node.tagName === 'A' && node.hasAttribute(TEMPORARY_ATTRIBUTE)) { + node.setAttribute('target', node.getAttribute(TEMPORARY_ATTRIBUTE) ?? ''); node.removeAttribute(TEMPORARY_ATTRIBUTE); if (node.getAttribute('target') === '_blank') { node.setAttribute('rel', 'noopener'); @@ -337,19 +337,21 @@ export const renderKatex = async (text: string, config: MermaidConfig): Promise< return text; } - if (!isMathMLSupported() && !config.legacyMathML) { + if (!(isMathMLSupported() || config.legacyMathML || config.forceLegacyMathML)) { return text.replace(katexRegex, 'MathML is unsupported in this environment.'); } if (includeLargeFeatures) { const { default: katex } = await import('katex'); + const outputMode = + config.forceLegacyMathML || (!isMathMLSupported() && config.legacyMathML) + ? 'htmlAndMathml' + : 'mathml'; return text .split(lineBreakRegex) .map((line) => hasKatex(line) - ? `
- ${line} -
` + ? `
${line}
` : `
${line}
` ) .join('') @@ -358,7 +360,7 @@ export const renderKatex = async (text: string, config: MermaidConfig): Promise< .renderToString(c, { throwOnError: true, displayMode: true, - output: isMathMLSupported() ? 'mathml' : 'htmlAndMathml', + output: outputMode, }) .replace(/\n/g, ' ') .replace(//g, '') diff --git a/packages/mermaid/src/diagrams/common/svgDrawCommon.ts b/packages/mermaid/src/diagrams/common/svgDrawCommon.ts index cf962f33e..59c6d43cf 100644 --- a/packages/mermaid/src/diagrams/common/svgDrawCommon.ts +++ b/packages/mermaid/src/diagrams/common/svgDrawCommon.ts @@ -1,5 +1,6 @@ import { sanitizeUrl } from '@braintree/sanitize-url'; -import type { Group, SVG } from '../../diagram-api/types.js'; +import type { SVG, SVGGroup } from '../../diagram-api/types.js'; +import { lineBreakRegex } from './common.js'; import type { Bound, D3ImageElement, @@ -11,9 +12,8 @@ import type { TextData, TextObject, } from './commonTypes.js'; -import { lineBreakRegex } from './common.js'; -export const drawRect = (element: SVG | Group, rectData: RectData): D3RectElement => { +export const drawRect = (element: SVG | SVGGroup, rectData: RectData): D3RectElement => { const rectElement: D3RectElement = element.append('rect'); rectElement.attr('x', rectData.x); rectElement.attr('y', rectData.y); @@ -24,8 +24,12 @@ export const drawRect = (element: SVG | Group, rectData: RectData): D3RectElemen if (rectData.name) { rectElement.attr('name', rectData.name); } - rectData.rx !== undefined && rectElement.attr('rx', rectData.rx); - rectData.ry !== undefined && rectElement.attr('ry', rectData.ry); + if (rectData.rx) { + rectElement.attr('rx', rectData.rx); + } + if (rectData.ry) { + rectElement.attr('ry', rectData.ry); + } if (rectData.attrs !== undefined) { for (const attrKey in rectData.attrs) { @@ -33,7 +37,9 @@ export const drawRect = (element: SVG | Group, rectData: RectData): D3RectElemen } } - rectData.class !== undefined && rectElement.attr('class', rectData.class); + if (rectData.class) { + rectElement.attr('class', rectData.class); + } return rectElement; }; @@ -44,7 +50,7 @@ export const drawRect = (element: SVG | Group, rectData: RectData): D3RectElemen * @param element - Diagram (reference for bounds) * @param bounds - Shape of the rectangle */ -export const drawBackgroundRect = (element: SVG | Group, bounds: Bound): void => { +export const drawBackgroundRect = (element: SVG | SVGGroup, bounds: Bound): void => { const rectData: RectData = { x: bounds.startx, y: bounds.starty, @@ -58,7 +64,7 @@ export const drawBackgroundRect = (element: SVG | Group, bounds: Bound): void => rectElement.lower(); }; -export const drawText = (element: SVG | Group, textData: TextData): D3TextElement => { +export const drawText = (element: SVG | SVGGroup, textData: TextData): D3TextElement => { const nText: string = textData.text.replace(lineBreakRegex, ' '); const textElem: D3TextElement = element.append('text'); @@ -67,7 +73,9 @@ export const drawText = (element: SVG | Group, textData: TextData): D3TextElemen textElem.attr('class', 'legend'); textElem.style('text-anchor', textData.anchor); - textData.class !== undefined && textElem.attr('class', textData.class); + if (textData.class) { + textElem.attr('class', textData.class); + } const tspan: D3TSpanElement = textElem.append('tspan'); tspan.attr('x', textData.x + textData.textMargin * 2); @@ -76,7 +84,7 @@ export const drawText = (element: SVG | Group, textData: TextData): D3TextElemen return textElem; }; -export const drawImage = (elem: SVG | Group, x: number, y: number, link: string): void => { +export const drawImage = (elem: SVG | SVGGroup, x: number, y: number, link: string): void => { const imageElement: D3ImageElement = elem.append('image'); imageElement.attr('x', x); imageElement.attr('y', y); @@ -85,7 +93,7 @@ export const drawImage = (elem: SVG | Group, x: number, y: number, link: string) }; export const drawEmbeddedImage = ( - element: SVG | Group, + element: SVG | SVGGroup, x: number, y: number, link: string diff --git a/packages/mermaid/src/diagrams/er/erDb.js b/packages/mermaid/src/diagrams/er/erDb.js deleted file mode 100644 index a58b9bbc1..000000000 --- a/packages/mermaid/src/diagrams/er/erDb.js +++ /dev/null @@ -1,99 +0,0 @@ -import { log } from '../../logger.js'; -import { getConfig } from '../../diagram-api/diagramAPI.js'; - -import { - setAccTitle, - getAccTitle, - getAccDescription, - setAccDescription, - clear as commonClear, - setDiagramTitle, - getDiagramTitle, -} from '../common/commonDb.js'; - -let entities = {}; -let relationships = []; - -const Cardinality = { - ZERO_OR_ONE: 'ZERO_OR_ONE', - ZERO_OR_MORE: 'ZERO_OR_MORE', - ONE_OR_MORE: 'ONE_OR_MORE', - ONLY_ONE: 'ONLY_ONE', - MD_PARENT: 'MD_PARENT', -}; - -const Identification = { - NON_IDENTIFYING: 'NON_IDENTIFYING', - IDENTIFYING: 'IDENTIFYING', -}; - -const addEntity = function (name, alias = undefined) { - if (entities[name] === undefined) { - entities[name] = { attributes: [], alias: alias }; - log.info('Added new entity :', name); - } else if (entities[name] && !entities[name].alias && alias) { - entities[name].alias = alias; - log.info(`Add alias '${alias}' to entity '${name}'`); - } - - return entities[name]; -}; - -const getEntities = () => entities; - -const addAttributes = function (entityName, attribs) { - let entity = addEntity(entityName); // May do nothing (if entity has already been added) - - // Process attribs in reverse order due to effect of recursive construction (last attribute is first) - let i; - for (i = attribs.length - 1; i >= 0; i--) { - entity.attributes.push(attribs[i]); - log.debug('Added attribute ', attribs[i].attributeName); - } -}; - -/** - * Add a relationship - * - * @param entA The first entity in the relationship - * @param rolA The role played by the first entity in relation to the second - * @param entB The second entity in the relationship - * @param rSpec The details of the relationship between the two entities - */ -const addRelationship = function (entA, rolA, entB, rSpec) { - let rel = { - entityA: entA, - roleA: rolA, - entityB: entB, - relSpec: rSpec, - }; - - relationships.push(rel); - log.debug('Added new relationship :', rel); -}; - -const getRelationships = () => relationships; - -const clear = function () { - entities = {}; - relationships = []; - commonClear(); -}; - -export default { - Cardinality, - Identification, - getConfig: () => getConfig().er, - addEntity, - addAttributes, - getEntities, - addRelationship, - getRelationships, - clear, - setAccTitle, - getAccTitle, - setAccDescription, - getAccDescription, - setDiagramTitle, - getDiagramTitle, -}; diff --git a/packages/mermaid/src/diagrams/er/erDb.ts b/packages/mermaid/src/diagrams/er/erDb.ts new file mode 100644 index 000000000..95f2210b7 --- /dev/null +++ b/packages/mermaid/src/diagrams/er/erDb.ts @@ -0,0 +1,251 @@ +import { log } from '../../logger.js'; +import { getConfig } from '../../diagram-api/diagramAPI.js'; +import type { Edge, Node } from '../../rendering-util/types.js'; +import type { EntityNode, Attribute, Relationship, EntityClass, RelSpec } from './erTypes.js'; +import { + setAccTitle, + getAccTitle, + getAccDescription, + setAccDescription, + clear as commonClear, + setDiagramTitle, + getDiagramTitle, +} from '../common/commonDb.js'; +import { getEdgeId } from '../../utils.js'; +import type { DiagramDB } from '../../diagram-api/types.js'; + +export class ErDB implements DiagramDB { + private entities = new Map(); + private relationships: Relationship[] = []; + private classes = new Map(); + private direction = 'TB'; + + private Cardinality = { + ZERO_OR_ONE: 'ZERO_OR_ONE', + ZERO_OR_MORE: 'ZERO_OR_MORE', + ONE_OR_MORE: 'ONE_OR_MORE', + ONLY_ONE: 'ONLY_ONE', + MD_PARENT: 'MD_PARENT', + }; + + private Identification = { + NON_IDENTIFYING: 'NON_IDENTIFYING', + IDENTIFYING: 'IDENTIFYING', + }; + + constructor() { + this.clear(); + this.addEntity = this.addEntity.bind(this); + this.addAttributes = this.addAttributes.bind(this); + this.addRelationship = this.addRelationship.bind(this); + this.setDirection = this.setDirection.bind(this); + this.addCssStyles = this.addCssStyles.bind(this); + this.addClass = this.addClass.bind(this); + this.setClass = this.setClass.bind(this); + this.setAccTitle = this.setAccTitle.bind(this); + this.setAccDescription = this.setAccDescription.bind(this); + } + + /** + * Add entity + * @param name - The name of the entity + * @param alias - The alias of the entity + */ + public addEntity(name: string, alias = ''): EntityNode { + if (!this.entities.has(name)) { + this.entities.set(name, { + id: `entity-${name}-${this.entities.size}`, + label: name, + attributes: [], + alias, + shape: 'erBox', + look: getConfig().look ?? 'default', + cssClasses: 'default', + cssStyles: [], + }); + log.info('Added new entity :', name); + } else if (!this.entities.get(name)?.alias && alias) { + this.entities.get(name)!.alias = alias; + log.info(`Add alias '${alias}' to entity '${name}'`); + } + + return this.entities.get(name)!; + } + + public getEntity(name: string) { + return this.entities.get(name); + } + + public getEntities() { + return this.entities; + } + + public getClasses() { + return this.classes; + } + + public addAttributes(entityName: string, attribs: Attribute[]) { + const entity = this.addEntity(entityName); // May do nothing (if entity has already been added) + + // Process attribs in reverse order due to effect of recursive construction (last attribute is first) + let i; + for (i = attribs.length - 1; i >= 0; i--) { + if (!attribs[i].keys) { + attribs[i].keys = []; + } + if (!attribs[i].comment) { + attribs[i].comment = ''; + } + entity.attributes.push(attribs[i]); + log.debug('Added attribute ', attribs[i].name); + } + } + + /** + * Add a relationship + * + * @param entA - The first entity in the relationship + * @param rolA - The role played by the first entity in relation to the second + * @param entB - The second entity in the relationship + * @param rSpec - The details of the relationship between the two entities + */ + public addRelationship(entA: string, rolA: string, entB: string, rSpec: RelSpec) { + const entityA = this.entities.get(entA); + const entityB = this.entities.get(entB); + if (!entityA || !entityB) { + return; + } + + const rel = { + entityA: entityA.id, + roleA: rolA, + entityB: entityB.id, + relSpec: rSpec, + }; + + this.relationships.push(rel); + log.debug('Added new relationship :', rel); + } + + public getRelationships() { + return this.relationships; + } + + public getDirection() { + return this.direction; + } + + public setDirection(dir: string) { + this.direction = dir; + } + + private getCompiledStyles(classDefs: string[]) { + let compiledStyles: string[] = []; + for (const customClass of classDefs) { + const cssClass = this.classes.get(customClass); + if (cssClass?.styles) { + compiledStyles = [...compiledStyles, ...(cssClass.styles ?? [])].map((s) => s.trim()); + } + if (cssClass?.textStyles) { + compiledStyles = [...compiledStyles, ...(cssClass.textStyles ?? [])].map((s) => s.trim()); + } + } + return compiledStyles; + } + + public addCssStyles(ids: string[], styles: string[]) { + for (const id of ids) { + const entity = this.entities.get(id); + if (!styles || !entity) { + return; + } + for (const style of styles) { + entity.cssStyles!.push(style); + } + } + } + + public addClass(ids: string[], style: string[]) { + ids.forEach((id) => { + let classNode = this.classes.get(id); + if (classNode === undefined) { + classNode = { id, styles: [], textStyles: [] }; + this.classes.set(id, classNode); + } + + if (style) { + style.forEach(function (s) { + if (/color/.exec(s)) { + const newStyle = s.replace('fill', 'bgFill'); + classNode.textStyles.push(newStyle); + } + classNode.styles.push(s); + }); + } + }); + } + + public setClass(ids: string[], classNames: string[]) { + for (const id of ids) { + const entity = this.entities.get(id); + if (entity) { + for (const className of classNames) { + entity.cssClasses += ' ' + className; + } + } + } + } + + public clear() { + this.entities = new Map(); + this.classes = new Map(); + this.relationships = []; + commonClear(); + } + + public getData() { + const nodes: Node[] = []; + const edges: Edge[] = []; + const config = getConfig(); + + for (const entityKey of this.entities.keys()) { + const entityNode = this.entities.get(entityKey); + if (entityNode) { + entityNode.cssCompiledStyles = this.getCompiledStyles(entityNode.cssClasses!.split(' ')); + nodes.push(entityNode as unknown as Node); + } + } + + let count = 0; + for (const relationship of this.relationships) { + const edge: Edge = { + id: getEdgeId(relationship.entityA, relationship.entityB, { + prefix: 'id', + counter: count++, + }), + type: 'normal', + curve: 'basis', + start: relationship.entityA, + end: relationship.entityB, + label: relationship.roleA, + labelpos: 'c', + thickness: 'normal', + classes: 'relationshipLine', + arrowTypeStart: relationship.relSpec.cardB.toLowerCase(), + arrowTypeEnd: relationship.relSpec.cardA.toLowerCase(), + pattern: relationship.relSpec.relType == 'IDENTIFYING' ? 'solid' : 'dashed', + look: config.look, + }; + edges.push(edge); + } + return { nodes, edges, other: {}, config, direction: 'TB' }; + } + + public setAccTitle = setAccTitle; + public getAccTitle = getAccTitle; + public setAccDescription = setAccDescription; + public getAccDescription = getAccDescription; + public setDiagramTitle = setDiagramTitle; + public getDiagramTitle = getDiagramTitle; + public getConfig = () => getConfig().er; +} diff --git a/packages/mermaid/src/diagrams/er/erDiagram.ts b/packages/mermaid/src/diagrams/er/erDiagram.ts index adfa525fc..1e3f0a4e1 100644 --- a/packages/mermaid/src/diagrams/er/erDiagram.ts +++ b/packages/mermaid/src/diagrams/er/erDiagram.ts @@ -1,12 +1,14 @@ // @ts-ignore: TODO: Fix ts errors import erParser from './parser/erDiagram.jison'; -import erDb from './erDb.js'; -import erRenderer from './erRenderer.js'; +import { ErDB } from './erDb.js'; +import * as renderer from './erRenderer-unified.js'; import erStyles from './styles.js'; export const diagram = { parser: erParser, - db: erDb, - renderer: erRenderer, + get db() { + return new ErDB(); + }, + renderer, styles: erStyles, }; diff --git a/packages/mermaid/src/diagrams/er/erRenderer-unified.ts b/packages/mermaid/src/diagrams/er/erRenderer-unified.ts new file mode 100644 index 000000000..9735dd3bb --- /dev/null +++ b/packages/mermaid/src/diagrams/er/erRenderer-unified.ts @@ -0,0 +1,66 @@ +import { getConfig } from '../../diagram-api/diagramAPI.js'; +import { log } from '../../logger.js'; +import { getDiagramElement } from '../../rendering-util/insertElementsForSize.js'; +import { getRegisteredLayoutAlgorithm, render } from '../../rendering-util/render.js'; +import { setupViewPortForSVG } from '../../rendering-util/setupViewPortForSVG.js'; +import type { LayoutData } from '../../rendering-util/types.js'; +import utils from '../../utils.js'; +import { select } from 'd3'; + +export const draw = async function (text: string, id: string, _version: string, diag: any) { + log.info('REF0:'); + log.info('Drawing er diagram (unified)', id); + const { securityLevel, er: conf, layout } = getConfig(); + + // The getData method provided in all supported diagrams is used to extract the data from the parsed structure + // into the Layout data format + const data4Layout = diag.db.getData() as LayoutData; + + // Create the root SVG - the element is the div containing the SVG element + const svg = getDiagramElement(id, securityLevel); + + data4Layout.type = diag.type; + data4Layout.layoutAlgorithm = getRegisteredLayoutAlgorithm(layout); + + // Workaround as when rendering and setting up the graph it uses flowchart spacing before data4Layout spacing? + data4Layout.config.flowchart!.nodeSpacing = conf?.nodeSpacing || 140; + data4Layout.config.flowchart!.rankSpacing = conf?.rankSpacing || 80; + data4Layout.direction = diag.db.getDirection(); + + data4Layout.markers = ['only_one', 'zero_or_one', 'one_or_more', 'zero_or_more']; + data4Layout.diagramId = id; + await render(data4Layout, svg); + // Elk layout algorithm displays markers above nodes, so move edges to top so they are "painted" over by the nodes. + if (data4Layout.layoutAlgorithm === 'elk') { + svg.select('.edges').lower(); + } + + // Sets the background nodes to the same position as their original counterparts. + // Background nodes are created when the look is handDrawn so the ER diagram markers do not show underneath. + const backgroundNodes = svg.selectAll('[id*="-background"]'); + // eslint-disable-next-line unicorn/prefer-spread + if (Array.from(backgroundNodes).length > 0) { + backgroundNodes.each(function (this: SVGElement) { + const backgroundNode = select(this); + const backgroundId = backgroundNode.attr('id'); + + const nonBackgroundId = backgroundId.replace('-background', ''); + const nonBackgroundNode = svg.select(`#${CSS.escape(nonBackgroundId)}`); + + if (!nonBackgroundNode.empty()) { + const transform = nonBackgroundNode.attr('transform'); + backgroundNode.attr('transform', transform); + } + }); + } + + const padding = 8; + utils.insertTitle( + svg, + 'erDiagramTitleText', + conf?.titleTopMargin ?? 25, + diag.db.getDiagramTitle() + ); + + setupViewPortForSVG(svg, padding, 'erDiagram', conf?.useMaxWidth ?? true); +}; diff --git a/packages/mermaid/src/diagrams/er/erRenderer.js b/packages/mermaid/src/diagrams/er/erRenderer.js index e8b25d50b..0327bfc9d 100644 --- a/packages/mermaid/src/diagrams/er/erRenderer.js +++ b/packages/mermaid/src/diagrams/er/erRenderer.js @@ -296,12 +296,12 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => { * Use D3 to construct the svg elements for the entities * * @param svgNode The svg node that contains the diagram - * @param entities The entities to be drawn + * @param {Map} entities The entities to be drawn * @param graph The graph that contains the vertex and edge definitions post-layout * @returns {object} The first entity that was inserted */ const drawEntities = function (svgNode, entities, graph) { - const keys = Object.keys(entities); + const keys = [...entities.keys()]; let firstOne; keys.forEach(function (entityName) { @@ -326,12 +326,12 @@ const drawEntities = function (svgNode, entities, graph) { .style('text-anchor', 'middle') .style('font-family', getConfig().fontFamily) .style('font-size', conf.fontSize + 'px') - .text(entities[entityName].alias ?? entityName); + .text(entities.get(entityName).alias ?? entityName); const { width: entityWidth, height: entityHeight } = drawAttributes( groupNode, textNode, - entities[entityName].attributes + entities.get(entityName).attributes ); // Draw the rectangle - insert it before the text so that the text is not obscured @@ -519,6 +519,8 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert, diagObj) { // Append a text node containing the label const labelId = 'rel' + relCnt; + const labelText = rel.roleA.split(/
/g); + const labelNode = svg .append('text') .classed('er relationshipLabel', true) @@ -528,8 +530,20 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert, diagObj) { .style('text-anchor', 'middle') .style('dominant-baseline', 'middle') .style('font-family', getConfig().fontFamily) - .style('font-size', conf.fontSize + 'px') - .text(rel.roleA); + .style('font-size', conf.fontSize + 'px'); + + if (labelText.length == 1) { + labelNode.text(rel.roleA); + } else { + const firstShift = -(labelText.length - 1) * 0.5; + labelText.forEach((txt, i) => { + labelNode + .append('tspan') + .attr('x', labelPoint.x) + .attr('dy', `${i === 0 ? firstShift : 1}em`) + .text(txt); + }); + } // Figure out how big the opaque 'container' rectangle needs to be const labelBBox = labelNode.node().getBBox(); diff --git a/packages/mermaid/src/diagrams/er/erTypes.ts b/packages/mermaid/src/diagrams/er/erTypes.ts new file mode 100644 index 000000000..13f9b2669 --- /dev/null +++ b/packages/mermaid/src/diagrams/er/erTypes.ts @@ -0,0 +1,37 @@ +export interface EntityNode { + id: string; + label: string; + attributes: Attribute[]; + alias: string; + shape: string; + look?: string; + cssClasses?: string; + cssStyles?: string[]; + cssCompiledStyles?: string[]; +} + +export interface Attribute { + type: string; + name: string; + keys: ('PK' | 'FK' | 'UK')[]; + comment: string; +} + +export interface Relationship { + entityA: string; + roleA: string; + entityB: string; + relSpec: RelSpec; +} + +export interface RelSpec { + cardA: string; + cardB: string; + relType: string; +} + +export interface EntityClass { + id: string; + styles: string[]; + textStyles: string[]; +} diff --git a/packages/mermaid/src/diagrams/er/parser/erDiagram.jison b/packages/mermaid/src/diagrams/er/parser/erDiagram.jison index 135efc784..2b59309fb 100644 --- a/packages/mermaid/src/diagrams/er/parser/erDiagram.jison +++ b/packages/mermaid/src/diagrams/er/parser/erDiagram.jison @@ -5,6 +5,7 @@ %x acc_title %x acc_descr %x acc_descr_multiline +%x style %% accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; } @@ -14,6 +15,10 @@ accDescr\s*":"\s* { this.begin("ac accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} [\}] { this.popState(); } [^\}]* return "acc_descr_multiline_value"; +.*direction\s+TB[^\n]* return 'direction_tb'; +.*direction\s+BT[^\n]* return 'direction_bt'; +.*direction\s+RL[^\n]* return 'direction_rl'; +.*direction\s+LR[^\n]* return 'direction_lr'; [\n]+ return 'NEWLINE'; \s+ /* skip whitespace */ [\s]+ return 'SPACE'; @@ -21,11 +26,15 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili \"[^"]*\" return 'WORD'; "erDiagram" return 'ER_DIAGRAM'; "{" { this.begin("block"); return 'BLOCK_START'; } -"," return 'COMMA'; +\# return 'BRKT'; +"#" return 'BRKT'; +"," return 'COMMA'; +":::" return 'STYLE_SEPARATOR'; +":" return 'COLON'; \s+ /* skip whitespace in block */ \b((?:PK)|(?:FK)|(?:UK))\b return 'ATTRIBUTE_KEY' -(.*?)[~](.*?)*[~] return 'ATTRIBUTE_WORD'; -[\*A-Za-z_][A-Za-z0-9\-_\[\]\(\)]* return 'ATTRIBUTE_WORD' +([^\s]*)[~].*[~]([^\s]*) return 'ATTRIBUTE_WORD'; +([\*A-Za-z_\u00C0-\uFFFF][A-Za-z0-9\-\_\[\]\(\)\u00C0-\uFFFF\*]*) return 'ATTRIBUTE_WORD'; \"[^"]*\" return 'COMMENT'; [\n]+ /* nothing */ "}" { this.popState(); return 'BLOCK_STOP'; } @@ -33,6 +42,14 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili "[" return 'SQS'; "]" return 'SQE'; +"style" { this.begin("style"); return 'STYLE'; } + diff --git a/packages/mermaid/src/docs/.vitepress/config.ts b/packages/mermaid/src/docs/.vitepress/config.ts index d937daf63..a07d1aea3 100644 --- a/packages/mermaid/src/docs/.vitepress/config.ts +++ b/packages/mermaid/src/docs/.vitepress/config.ts @@ -1,5 +1,6 @@ -import { defineConfig, MarkdownOptions } from 'vitepress'; -import { version } from '../../../package.json'; +import type { MarkdownOptions } from 'vitepress'; +import { defineConfig } from 'vitepress'; +import packageJson from '../../../package.json' assert { type: 'json' }; import MermaidExample from './mermaid-markdown-all.js'; const allMarkdownTransformers: MarkdownOptions = { @@ -8,8 +9,9 @@ const allMarkdownTransformers: MarkdownOptions = { light: 'github-light', dark: 'github-dark', }, - config: async (md) => { - await MermaidExample(md); + + config: (md) => { + MermaidExample(md); }, }; @@ -56,7 +58,7 @@ export default defineConfig({ { icon: 'github', link: 'https://github.com/mermaid-js/mermaid' }, { icon: 'discord', - link: 'https://discord.gg/AgrbSrBer3', + link: 'https://discord.gg/sKeNQX4Wtj', }, { icon: { @@ -93,7 +95,7 @@ function nav() { activeMatch: '/announcements', }, { - text: version, + text: packageJson.version, items: [ { text: 'Changelog', @@ -146,15 +148,18 @@ function sidebarSyntax() { { text: 'Pie Chart', link: '/syntax/pie' }, { text: 'Quadrant Chart', link: '/syntax/quadrantChart' }, { text: 'Requirement Diagram', link: '/syntax/requirementDiagram' }, - { text: 'Gitgraph (Git) Diagram', link: '/syntax/gitgraph' }, + { text: 'GitGraph (Git) Diagram', link: '/syntax/gitgraph' }, { text: 'C4 Diagram đŸĻēâš ī¸', link: '/syntax/c4' }, { text: 'Mindmaps', link: '/syntax/mindmap' }, { text: 'Timeline', link: '/syntax/timeline' }, - { text: 'Zenuml', link: '/syntax/zenuml' }, + { text: 'ZenUML', link: '/syntax/zenuml' }, { text: 'Sankey đŸ”Ĩ', link: '/syntax/sankey' }, - { text: 'XYChart đŸ”Ĩ', link: '/syntax/xyChart' }, + { text: 'XY Chart đŸ”Ĩ', link: '/syntax/xyChart' }, { text: 'Block Diagram đŸ”Ĩ', link: '/syntax/block' }, { text: 'Packet đŸ”Ĩ', link: '/syntax/packet' }, + { text: 'Kanban đŸ”Ĩ', link: '/syntax/kanban' }, + { text: 'Architecture đŸ”Ĩ', link: '/syntax/architecture' }, + { text: 'Radar đŸ”Ĩ', link: '/syntax/radar' }, { text: 'Other Examples', link: '/syntax/examples' }, ], }, @@ -171,6 +176,7 @@ function sidebarConfig() { { text: 'API-Usage', link: '/config/usage' }, { text: 'Mermaid API Configuration', link: '/config/setup/README' }, { text: 'Mermaid Configuration Options', link: '/config/schema-docs/config' }, + { text: 'Registering icons', link: '/config/icons' }, { text: 'Directives', link: '/config/directives' }, { text: 'Theming', link: '/config/theming' }, { text: 'Math', link: '/config/math' }, @@ -228,8 +234,6 @@ function sidebarNews() { /** * Return a string that puts together the pagePage, a '#', then the given id - * @param pagePath - * @param id * @returns the fully formed path */ function pathToId(pagePath: string, id = ''): string { diff --git a/packages/mermaid/src/docs/.vitepress/contributors.ts b/packages/mermaid/src/docs/.vitepress/contributors.ts index 93eeee2e2..e61cf57e8 100644 --- a/packages/mermaid/src/docs/.vitepress/contributors.ts +++ b/packages/mermaid/src/docs/.vitepress/contributors.ts @@ -1,5 +1,6 @@ import contributorUsernamesJson from './contributor-names.json'; -import { CoreTeam, knut, plainTeamMembers } from './teamMembers.js'; +import type { CoreTeam } from './teamMembers.js'; +import { knut, plainTeamMembers } from './teamMembers.js'; const contributorUsernames: string[] = contributorUsernamesJson; diff --git a/packages/mermaid/src/docs/.vitepress/mermaid-markdown-all.ts b/packages/mermaid/src/docs/.vitepress/mermaid-markdown-all.ts index 64a069b4c..d1aeee5ac 100644 --- a/packages/mermaid/src/docs/.vitepress/mermaid-markdown-all.ts +++ b/packages/mermaid/src/docs/.vitepress/mermaid-markdown-all.ts @@ -1,6 +1,6 @@ import type { MarkdownRenderer } from 'vitepress'; -const MermaidExample = async (md: MarkdownRenderer) => { +const MermaidExample = (md: MarkdownRenderer) => { const defaultRenderer = md.renderer.rules.fence; if (!defaultRenderer) { diff --git a/packages/mermaid/src/docs/.vitepress/scripts/fetch-avatars.ts b/packages/mermaid/src/docs/.vitepress/scripts/fetch-avatars.ts index cd78be782..23c359444 100644 --- a/packages/mermaid/src/docs/.vitepress/scripts/fetch-avatars.ts +++ b/packages/mermaid/src/docs/.vitepress/scripts/fetch-avatars.ts @@ -32,11 +32,11 @@ async function fetchAvatars() { }); contributors = JSON.parse(await readFile(pathContributors, { encoding: 'utf-8' })); - let avatars = contributors.map((name) => { - download(`https://github.com/${name}.png?size=100`, getAvatarPath(name)); - }); + const avatars = contributors.map((name) => + download(`https://github.com/${name}.png?size=100`, getAvatarPath(name)) + ); await Promise.allSettled(avatars); } -fetchAvatars(); +void fetchAvatars(); diff --git a/packages/mermaid/src/docs/.vitepress/scripts/fetch-contributors.ts b/packages/mermaid/src/docs/.vitepress/scripts/fetch-contributors.ts index da7621b29..54144cf62 100644 --- a/packages/mermaid/src/docs/.vitepress/scripts/fetch-contributors.ts +++ b/packages/mermaid/src/docs/.vitepress/scripts/fetch-contributors.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ // Adapted from https://github.dev/vitest-dev/vitest/blob/991ff33ab717caee85ef6cbe1c16dc514186b4cc/scripts/update-contributors.ts#L6 import { writeFile } from 'node:fs/promises'; diff --git a/packages/mermaid/src/docs/.vitepress/teamMembers.ts b/packages/mermaid/src/docs/.vitepress/teamMembers.ts index d95f49ed8..e307b81c4 100644 --- a/packages/mermaid/src/docs/.vitepress/teamMembers.ts +++ b/packages/mermaid/src/docs/.vitepress/teamMembers.ts @@ -1,3 +1,4 @@ +/* eslint-disable @cspell/spellchecker */ export interface Contributor { name: string; avatar: string; diff --git a/packages/mermaid/src/docs/.vitepress/theme/index.ts b/packages/mermaid/src/docs/.vitepress/theme/index.ts index 3ebb7614a..3ec200937 100644 --- a/packages/mermaid/src/docs/.vitepress/theme/index.ts +++ b/packages/mermaid/src/docs/.vitepress/theme/index.ts @@ -1,19 +1,21 @@ +/* eslint-disable no-console */ import DefaultTheme from 'vitepress/theme'; import './custom.css'; -// @ts-ignore +// @ts-ignore Type not available import Mermaid from './Mermaid.vue'; -// @ts-ignore +// @ts-ignore Type not available import Contributors from '../components/Contributors.vue'; -// @ts-ignore +// @ts-ignore Type not available import HomePage from '../components/HomePage.vue'; -// @ts-ignore +// @ts-ignore Type not available import TopBar from '../components/TopBar.vue'; import { getRedirect } from './redirect.js'; -import { h } from 'vue'; -import Theme from 'vitepress/theme'; -import '../style/main.css'; +// @ts-ignore Type not available import 'uno.css'; import type { EnhanceAppContext } from 'vitepress'; +import Theme from 'vitepress/theme'; +import { h } from 'vue'; +import '../style/main.css'; export default { ...DefaultTheme, @@ -22,6 +24,7 @@ export default { // Keeping this as comment as it took a lot of time to figure out how to add a component to the top bar. 'home-hero-before': () => h(TopBar), 'home-features-after': () => h(HomePage), + 'doc-before': () => h(TopBar), }); }, enhanceApp({ app, router }: EnhanceAppContext) { @@ -33,7 +36,7 @@ export default { const url = new URL(window.location.origin + to); const newPath = getRedirect(url); if (newPath) { - console.log(`Redirecting to ${newPath} from ${window.location}`); + console.log(`Redirecting to ${newPath} from ${window.location.toString()}`); // router.go isn't loading the ID properly. window.location.href = `/${newPath}`; } diff --git a/packages/mermaid/src/docs/.vitepress/theme/mermaid.ts b/packages/mermaid/src/docs/.vitepress/theme/mermaid.ts index 47e238692..2357fe384 100644 --- a/packages/mermaid/src/docs/.vitepress/theme/mermaid.ts +++ b/packages/mermaid/src/docs/.vitepress/theme/mermaid.ts @@ -2,6 +2,13 @@ import mermaid, { type MermaidConfig } from 'mermaid'; import zenuml from '../../../../../mermaid-zenuml/dist/mermaid-zenuml.core.mjs'; const init = mermaid.registerExternalDiagrams([zenuml]); +mermaid.registerIconPacks([ + { + name: 'logos', + loader: () => + fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()), + }, +]); export const render = async (id: string, code: string, config: MermaidConfig): Promise => { await init; diff --git a/packages/mermaid/src/docs/.vitepress/theme/redirect.ts b/packages/mermaid/src/docs/.vitepress/theme/redirect.ts index 1b04e01d5..8283951ac 100644 --- a/packages/mermaid/src/docs/.vitepress/theme/redirect.ts +++ b/packages/mermaid/src/docs/.vitepress/theme/redirect.ts @@ -116,3 +116,5 @@ export const getRedirect = (url: URL): string | undefined => { return `${idRedirectMap[path]}.html${id ? `#${id}` : ''}`; } }; + +// cspell:ignore mermaidapi, breakingchanges, classdiagram, entityrelationshipdiagram, mermaidapi, mermaidcli, gettingstarted, syntaxreference, newdiagram, requirementdiagram, sequencediagram diff --git a/packages/mermaid/src/docs/adding-new-shape.md b/packages/mermaid/src/docs/adding-new-shape.md new file mode 100644 index 000000000..8ba5d083c --- /dev/null +++ b/packages/mermaid/src/docs/adding-new-shape.md @@ -0,0 +1,225 @@ +# Custom SVG Shapes Library + +This library provides a collection of custom SVG shapes, utilities, and helpers for generating diagram components. The shapes are designed to be used within an SVG container and include a variety of common and complex shapes. + +## Overview + +## Shape Helpers and Utilities + +Before starting with shape creation, it's essential to familiarize yourself with the utilities provided in the `utils.ts` file from `packages/mermaid/src/rendering-util/rendering-elements/shapes/util.js`. These utilities are designed to assist with various aspects of SVG shape manipulation and ensure consistent and accurate rendering. + +## Available Utilities + +### 1. `labelHelper` + +- **Purpose**: This function creates and inserts labels inside SVG shapes. +- **Features**: + - Handles both HTML labels and plain text. + - Calculates the bounding box dimensions of the label. + - Ensures proper positioning of labels within shapes. + +### 2. `updateNodeBounds` + +- **Purpose**: Updates the bounding box dimensions (width and height) of a node. +- **Usage**: + - Adjusts the size of the node to fit the content or shape. + - Useful for ensuring that shapes resize appropriately based on their content. + +### 3. `insertPolygonShape` + +- **Purpose**: Inserts a polygon shape into an SVG container. +- **Features**: + - Handles the creation and insertion of complex polygonal shapes. + - Configures the shape's appearance and positioning within the SVG container. + +### 4. `getNodeClasses` + +- **Purpose**: Returns the appropriate CSS classes for a node based on its configuration. +- **Usage**: + - Dynamically applies CSS classes to nodes for styling purposes. + - Ensures that nodes adhere to the desired design and theme. + +### 5. `createPathFromPoints` + +- **Purpose**: Generates an SVG path string from an array of points. +- **Usage**: + - Converts a list of points into a smooth path. + - Useful for creating custom shapes or paths within the SVG. + +### 6. `generateFullSineWavePoints` + +- **Purpose**: Generates points for a sine wave, useful for creating wavy-edged shapes. +- **Usage**: + - Facilitates the creation of shapes with wavy or sine-wave edges. + - Can be used to add decorative or dynamic edges to shapes. + +## Getting Started + +To utilize these utilities, simply import them from the `utils.ts` file into your shape creation script. These helpers will streamline the process of building and customizing SVG shapes, ensuring consistent results across your projects. + +```typescript +import { + labelHelper, + updateNodeBounds, + insertPolygonShape, + getNodeClasses, + createPathFromPoints, + generateFullSineWavePoints, +} from './utils.ts'; +``` + +## Example Usage + +Here’s a basic example of how you might use some of these utilities: + +```typescript +import { labelHelper, insertPolygonShape } from './utils.ts'; + +const svgContainer = document.getElementById('svgContainer'); + +// Insert a polygon shape +insertPolygonShape(svgContainer /* shape-specific parameters */); + +// Create and insert a label inside the shape +labelHelper(svgContainer /* label-specific parameters */); +``` + +## Adding New Shapes + +### 1. Create the Shape Function + +To add a new shape: + +- **Create the shape function**: Create a new file of name of the shape and export a function in the `shapes` directory that generates your shape. The file and function should follow the pattern used in existing shapes and return an SVG element. + +- **Example**: + + ```typescript + import { Node, RenderOptions } from '../../types.ts'; + + export const myNewShape = async ( + parent: SVGAElement, + node: Node, + renderOptions: RenderOptions + ) => { + // Create your shape here + const shape = parent.insert('g').attr('class', 'my-new-shape'); + // Add other elements or styles as needed + return shape; + }; + ``` + +### 2. Register the Shape + +- **Register the shape**: Add your shape to the `shapes` object in the [main shapes module](../rendering-util/rendering-elements/shapes.ts). This allows your shape to be recognized and used within the system. + +- **Example**: + + ```typescript + import { myNewShape } from './shapes/myNewShape'; + + const shapes = { + ..., + { + semanticName: 'My Shape', + name: 'Shape Name', + shortName: '', + description: '', + aliases: ['', '', '', ''], + handler: myNewShape, + }, + }; + ``` + +# Shape Intersection Algorithms + +This contains algorithms and utilities for calculating intersection points for various shapes in SVG. Arrow intersection points are crucial for accurately determining where arrows connect with shapes. Ensuring precise intersection points enhances the clarity and accuracy of flowcharts and diagrams. + +## Shape Intersection Functions + +### 1. `Ellipse` + +Calculates the intersection points for an ellipse. + +**Usage**: + +```javascript +import intersectEllipse from './intersect-ellipse.js'; + +const intersection = intersectEllipse(node, rx, ry, point); +``` + +- **Parameters**: + - `node`: The SVG node element. + - `rx`: The x-radius of the ellipse. + - `ry`: The y-radius of the ellipse. + - `point`: The point from which the intersection is calculated. + +### 2. `intersectRect` + +Calculates the intersection points for a rectangle. + +**Usage**: + +```javascript +import intersectRect from './intersect-rect.js'; + +const intersection = intersectRect(node, point); +``` + +- **Parameters**: + - `node`: The SVG node element. + - `point`: The point from which the intersection is calculated. + +### 3. `intersectPolygon` + +Calculates the intersection points for a polygon. + +**Usage**: + +```javascript +import intersectPolygon from './intersect-polygon.js'; + +const intersection = intersectPolygon(node, polyPoints, point); +``` + +- **Parameters**: + - `node`: The SVG node element. + - `polyPoints`: Array of points defining the polygon. + - `point`: The point from which the intersection is calculated. + +## Cypress Tests + +To ensure the robustness of the flowchart shapes, there are implementation of comprehensive Cypress test cases in `newShapes.spec.ts` file. These tests cover various aspects such as: + +- **Shapes**: Testing new shapes like `bowTieRect`, `waveRectangle`, `trapezoidalPentagon`, etc. +- **Looks**: Verifying shapes under different visual styles (`classic` and `handDrawn`). +- **Directions**: Ensuring correct rendering in all flow directions of arrows : + - `TB` `(Top -> Bottom)` + - `BT` `(Bottom -> Top)` + - `LR` `(Left -> Right)` + - `RL` `(Right -> Left)` +- **Labels**: Testing shapes with different labels, including: + - No labels + - Short labels + - Very long labels + - Markdown with `htmlLabels:true` and `htmlLabels:false` +- **Styles**: Applying custom styles to shapes and verifying correct rendering. +- **Class Definitions**: Using `classDef` to apply custom classes and testing their impact. + +### Running the Tests + +To run the Cypress tests, follow these steps: + +1. Ensure you have all dependencies installed by running: + ```bash + pnpm install + ``` +2. Start the Cypress test runner: + + ```bash + cypress open --env updateSnapshots=true + + ``` + +3. Select the test suite from the Cypress interface to run all the flowchart shape tests. diff --git a/packages/mermaid/src/docs/community/contributing.md b/packages/mermaid/src/docs/community/contributing.md index 195146a61..62d06f72f 100644 --- a/packages/mermaid/src/docs/community/contributing.md +++ b/packages/mermaid/src/docs/community/contributing.md @@ -52,7 +52,7 @@ The following commands must be sufficient enough to start with: ```bash curl -fsSL https://get.pnpm.io/install.sh | sh - -pnpm env use --global 18 +pnpm env use --global 20 ``` You may also need to reload `.shrc` or `.bashrc` afterwards. @@ -240,6 +240,22 @@ Code is the heart of every software project. We strive to make it better. Who if The core of Mermaid is located under `packages/mermaid/src`. +### Building Mermaid Locally + +**Host** + +```bash +pnpm run build +``` + +**Docker** + +```bash +./run build +``` + +This will build the Mermaid library and the documentation site. + ### Running Mermaid Locally **Host** @@ -371,9 +387,9 @@ If the users have no way to know that things have changed, then you haven't real Likewise, if users don't know that there is a new feature that you've implemented, it will forever remain unknown and unused. The documentation has to be updated for users to know that things have been changed and added! -If you are adding a new feature, add `(v10.8.0+)` in the title or description. It will be replaced automatically with the current version number when the release happens. +If you are adding a new feature, add `(v+)` in the title or description. It will be replaced automatically with the current version number when the release happens. -eg: `# Feature Name (v10.8.0+)` +eg: `# Feature Name (v+)` We know it can sometimes be hard to code _and_ write user documentation. @@ -481,14 +497,14 @@ This is a danger alert ### Navigation -If you want to propose changes to how the documentation is _organized_, such as adding a new section or re-arranging or renaming a section, you must update the **sidebar navigation**, which is defined in [the vitepress config](../.vitepress/config.ts). The same goes to **topbar**. +If you want to propose changes to how the documentation is _organized_, such as adding a new section or re-arranging or renaming a section, you must update the **sidebar navigation**, which is defined in [the vitepress config](../.vitepress/config.ts). The same goes for **topbar**. ### Build Docs -The content of `/docs` folder is built with Github Actions. +The content of `/docs` folder is built with GitHub Actions. ```warning -So as to allow automatic compilation of documentation pages you have to enable Github Actions on your fork first +So as to allow automatic compilation of documentation pages you have to enable GitHub Actions on your fork first ``` ## Submit your pull request diff --git a/packages/mermaid/src/docs/community/intro.md b/packages/mermaid/src/docs/community/intro.md index a83b96380..45a23b1da 100644 --- a/packages/mermaid/src/docs/community/intro.md +++ b/packages/mermaid/src/docs/community/intro.md @@ -39,7 +39,7 @@ Where to start: - You could work on a new feature! [These](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Area%3A+Development%22+label%3A%22Type%3A+Enhancement%22+label%3A%22Status%3A+Approved%22+) are some ideas! - You could confirm the bugs in [these issues](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Status%3A+Triage%22++label%3A%22Type%3A+Bug+%2F+Error%22). -[You can join our Discord server if you want closer contact!](https://discord.gg/AgrbSrBer3) +[You can join our Discord server if you want closer contact!](https://discord.gg/sKeNQX4Wtj) ## A Question Or a Suggestion? @@ -53,6 +53,6 @@ If you have faced a vulnerability [report it to us](./security.md). Don't get daunted if it is hard in the beginning. We have a great community with only encouraging words. So, if you get stuck, ask for help and hints in the Slack forum. If you want to show off something good, show it off there. -[You can join our Discord server if you want closer contact!](https://discord.gg/AgrbSrBer3) +[You can join our Discord server if you want closer contact!](https://discord.gg/sKeNQX4Wtj) ![Image of superhero wishing you good luck](https://media.giphy.com/media/l49JHz7kJvl6MCj3G/giphy.gif) diff --git a/packages/mermaid/src/docs/config/8.6.0_docs.md b/packages/mermaid/src/docs/config/8.6.0_docs.md index efd29bfdc..342e05763 100644 --- a/packages/mermaid/src/docs/config/8.6.0_docs.md +++ b/packages/mermaid/src/docs/config/8.6.0_docs.md @@ -75,7 +75,7 @@ When deployed within code, init is called before the graph/diagram description. **for example**: -```mermaid +```mermaid-example %%{init: {"theme": "default", "logLevel": 1 }}%% graph LR a-->b diff --git a/packages/mermaid/src/docs/config/accessibility.md b/packages/mermaid/src/docs/config/accessibility.md index b53567f73..c4f019aa4 100644 --- a/packages/mermaid/src/docs/config/accessibility.md +++ b/packages/mermaid/src/docs/config/accessibility.md @@ -190,12 +190,12 @@ Here is the HTML generated for the SVG element: _(Note that some of the SVG attr ``` -##### Gitgraph +##### GitGraph ```mermaid-example gitGraph - accTitle: My Gitgraph Accessibility Title - accDescr: My Gitgraph Accessibility Description + accTitle: My GitGraph Accessibility Title + accDescr: My GitGraph Accessibility Description commit commit diff --git a/packages/mermaid/src/docs/config/directives.md b/packages/mermaid/src/docs/config/directives.md index 0e211161c..017fc486b 100644 --- a/packages/mermaid/src/docs/config/directives.md +++ b/packages/mermaid/src/docs/config/directives.md @@ -88,7 +88,7 @@ Here the directive declaration will set the `logLevel` to `debug` and the `theme Note: You can use 'init' or 'initialize' as both are acceptable as init directives. Also note that `%%init%%` and `%%initialize%%` directives will be grouped together after they are parsed. -```mermaid +```mermaid-example %%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%% %%{initialize: { 'logLevel': 'fatal', "theme":'dark', 'startOnLoad': true } }%% ... diff --git a/packages/mermaid/src/docs/config/faq.md b/packages/mermaid/src/docs/config/faq.md index 698061def..6d1261fc1 100644 --- a/packages/mermaid/src/docs/config/faq.md +++ b/packages/mermaid/src/docs/config/faq.md @@ -1,11 +1,11 @@ # Frequently Asked Questions -1. [How to add title to flowchart?](https://github.com/knsv/mermaid/issues/556#issuecomment-363182217) +1. [How to add title to flowchart?](https://github.com/mermaid-js/mermaid/issues/556#issuecomment-363182217) 1. [How to specify custom CSS file?](https://github.com/mermaidjs/mermaid.cli/pull/24#issuecomment-373402785) -1. [How to fix tooltip misplacement issue?](https://github.com/knsv/mermaid/issues/542#issuecomment-3343564621) -1. [How to specify gantt diagram xAxis format?](https://github.com/knsv/mermaid/issues/269#issuecomment-373229136) -1. [How to bind an event?](https://github.com/knsv/mermaid/issues/372) -1. [How to add newline in the text?](https://github.com/knsv/mermaid/issues/384#issuecomment-281339381) -1. [How to have special characters in link text?](https://github.com/knsv/mermaid/issues/407#issuecomment-329944735) -1. [How to change Flowchart curve style?](https://github.com/knsv/mermaid/issues/580#issuecomment-373929046) +1. [How to fix tooltip misplacement issue?](https://github.com/mermaid-js/mermaid/issues/542#issuecomment-3343564621) +1. [How to specify gantt diagram xAxis format?](https://github.com/mermaid-js/mermaid/issues/269#issuecomment-373229136) +1. [How to bind an event?](https://github.com/mermaid-js/mermaid/issues/372) +1. [How to add newline in the text?](https://github.com/mermaid-js/mermaid/issues/384#issuecomment-281339381) +1. [How to have special characters in link text?](https://github.com/mermaid-js/mermaid/issues/407#issuecomment-329944735) +1. [How to change Flowchart curve style?](https://github.com/mermaid-js/mermaid/issues/580#issuecomment-373929046) 1. [How to create a Flowchart end-Node that says "End"](https://github.com/mermaid-js/mermaid/issues/1444#issuecomment-639528897) diff --git a/packages/mermaid/src/docs/config/icons.md b/packages/mermaid/src/docs/config/icons.md new file mode 100644 index 000000000..db079f841 --- /dev/null +++ b/packages/mermaid/src/docs/config/icons.md @@ -0,0 +1,49 @@ +# Registering icon pack in mermaid + +The icon packs available can be found at [icones.js.org](https://icones.js.org/). +We use the name defined when registering the icon pack, to override the prefix field of the iconify pack. This allows the user to use shorter names for the icons. It also allows us to load a particular pack only when it is used in a diagram. + +Using JSON file directly from CDN: + +```js +import mermaid from 'CDN/mermaid.esm.mjs'; +mermaid.registerIconPacks([ + { + name: 'logos', + loader: () => + fetch('https://unpkg.com/@iconify-json/logos@1/icons.json').then((res) => res.json()), + }, +]); +``` + +Using packages and a bundler: + +```bash +npm install @iconify-json/logos@1 +``` + +With lazy loading + +```js +import mermaid from 'mermaid'; + +mermaid.registerIconPacks([ + { + name: 'logos', + loader: () => import('@iconify-json/logos').then((module) => module.icons), + }, +]); +``` + +Without lazy loading + +```js +import mermaid from 'mermaid'; +import { icons } from '@iconify-json/logos'; +mermaid.registerIconPacks([ + { + name: icons.prefix, // To use the prefix defined in the icon pack + icons, + }, +]); +``` diff --git a/packages/mermaid/src/docs/config/img/mathMLDifferences.png b/packages/mermaid/src/docs/config/img/mathMLDifferences.png new file mode 100644 index 000000000..6b7a86400 Binary files /dev/null and b/packages/mermaid/src/docs/config/img/mathMLDifferences.png differ diff --git a/packages/mermaid/src/docs/config/math.md b/packages/mermaid/src/docs/config/math.md index 22b398e08..bb6556b6c 100644 --- a/packages/mermaid/src/docs/config/math.md +++ b/packages/mermaid/src/docs/config/math.md @@ -10,7 +10,7 @@ Note that at the moment, the only supported diagrams are below: ### Flowcharts -```mermaid +```mermaid-example graph LR A["$$x^2$$"] -->|"$$\sqrt{x+3}$$"| B("$$\frac{1}{2}$$") A -->|"$$\overbrace{a+b+c}^{\text{note}}$$"| C("$$\pi r^2$$") @@ -20,7 +20,7 @@ Note that at the moment, the only supported diagrams are below: ### Sequence -```mermaid +```mermaid-example sequenceDiagram autonumber participant 1 as $$\alpha$$ @@ -60,3 +60,13 @@ Example with legacy mode enabled (the latest version of KaTeX's stylesheet can b ``` + +## Handling Rendering Differences + +Due to differences between default fonts across operating systems and browser's MathML implementations, inconsistent results can be seen across platforms. If having consistent results are important, or the most optimal rendered results are desired, `forceLegacyMathML` can be enabled in the config. + +This option will always use KaTeX's stylesheet instead of only when MathML is not supported (as with `legacyMathML`). Note that only `forceLegacyMathML` needs to be set. + +If including KaTeX's stylesheet is not a concern, enabling this option is recommended to avoid scenarios where no MathML implementation within a browser provides the desired output (as seen below). + +![Image showing differences between Browsers](img/mathMLDifferences.png) diff --git a/packages/mermaid/src/docs/config/theming.md b/packages/mermaid/src/docs/config/theming.md index 3863202b4..7a9304706 100644 --- a/packages/mermaid/src/docs/config/theming.md +++ b/packages/mermaid/src/docs/config/theming.md @@ -2,7 +2,7 @@ Dynamic and integrated theme configuration was introduced in Mermaid version 8.7.0. -Themes can now be customized at the site-wide level, or on individual Mermaid diagrams. For site-wide theme customization, the `initialize` call is used. For diagram specific customization, the `init` directive is used. +Themes can now be customized at the site-wide level, or on individual Mermaid diagrams. For site-wide theme customization, the `initialize` call is used. For diagram specific customization, frontmatter config is used. ## Available Themes @@ -18,12 +18,12 @@ Themes can now be customized at the site-wide level, or on individual Mermaid di ## Site-wide Theme -To customize themes site-wide, call the `initialize` method on the `mermaidAPI`. +To customize themes site-wide, call the `initialize` method on the `mermaid`. Example of `initialize` call setting `theme` to `base`: ```javascript -mermaidAPI.initialize({ +mermaid.initialize({ securityLevel: 'loose', theme: 'base', }); @@ -31,18 +31,15 @@ mermaidAPI.initialize({ ## Diagram-specific Themes -To customize the theme of an individual diagram, use the `init` directive. +To customize the theme of an individual diagram, use frontmatter config. -Example of `init` directive setting the `theme` to `forest`: +Example of frontmatter config setting the `theme` to `forest`: ```mermaid-example -%%{init: {'theme':'forest'}}%% - graph TD - a --> b -``` - -```mermaid -%%{init: {'theme':'forest'}}%% +--- +config: + theme: 'forest' +--- graph TD a --> b ``` @@ -51,60 +48,28 @@ Example of `init` directive setting the `theme` to `forest`: ## Customizing Themes with `themeVariables` -To make a custom theme, modify `themeVariables` via `init`. +To make a custom theme, modify `themeVariables` via frontmatter config. You will need to use the [base](#available-themes) theme as it is the only modifiable theme. -| Parameter | Description | Type | Properties | -| -------------- | ------------------------------------ | ------ | ----------------------------------------------------------------------------------- | -| themeVariables | Modifiable with the `init` directive | Object | `primaryColor`, `primaryTextColor`, `lineColor` ([see full list](#theme-variables)) | +| Parameter | Description | Type | Properties | +| -------------- | ---------------------------------- | ------ | ----------------------------------------------------------------------------------- | +| themeVariables | Modifiable with frontmatter config | Object | `primaryColor`, `primaryTextColor`, `lineColor` ([see full list](#theme-variables)) | -Example of modifying `themeVariables` using the `init` directive: +Example of modifying `themeVariables` using frontmatter config: ```mermaid-example -%%{ - init: { - 'theme': 'base', - 'themeVariables': { - 'primaryColor': '#BB2528', - 'primaryTextColor': '#fff', - 'primaryBorderColor': '#7C0000', - 'lineColor': '#F8B229', - 'secondaryColor': '#006100', - 'tertiaryColor': '#fff' - } - } -}%% - graph TD - A[Christmas] -->|Get money| B(Go shopping) - B --> C{Let me think} - B --> G[/Another/] - C ==>|One| D[Laptop] - C -->|Two| E[iPhone] - C -->|Three| F[fa:fa-car Car] - subgraph section - C - D - E - F - G - end -``` - -```mermaid -%%{ - init: { - 'theme': 'base', - 'themeVariables': { - 'primaryColor': '#BB2528', - 'primaryTextColor': '#fff', - 'primaryBorderColor': '#7C0000', - 'lineColor': '#F8B229', - 'secondaryColor': '#006100', - 'tertiaryColor': '#fff' - } - } -}%% +--- +config: + theme: 'base' + themeVariables: + primaryColor: '#BB2528' + primaryTextColor: '#fff' + primaryBorderColor: '#7C0000' + lineColor: '#F8B229' + secondaryColor: '#006100' + tertiaryColor: '#fff' +--- graph TD A[Christmas] -->|Get money| B(Go shopping) B --> C{Let me think} diff --git a/packages/mermaid/src/docs/config/usage.md b/packages/mermaid/src/docs/config/usage.md index eec87e49f..0886a0e44 100644 --- a/packages/mermaid/src/docs/config/usage.md +++ b/packages/mermaid/src/docs/config/usage.md @@ -188,7 +188,7 @@ await mermaid.run({ ### Calling `mermaid.init` - Deprecated ```warning -mermaid.init is deprecated in v10 and will be removed in v11. Please use mermaid.run instead. +mermaid.init is deprecated in v10 and will be removed in a future release. Please use mermaid.run instead. ``` By default, `mermaid.init` will be called when the document is ready, finding all elements with @@ -213,10 +213,6 @@ Or with no config object, and a jQuery selection: mermaid.init(undefined, $('#someId .yetAnotherClass')); ``` -```warning -This type of integration is deprecated. Instead the preferred way of handling more complex integration is to use the mermaidAPI instead. -``` - ## Usage with webpack mermaid fully supports webpack. Here is a [working demo](https://github.com/mermaidjs/mermaid-webpack-demo). diff --git a/packages/mermaid/src/docs/ecosystem/img/python-mermaid-integration-updated.png b/packages/mermaid/src/docs/ecosystem/img/python-mermaid-integration-updated.png new file mode 100644 index 000000000..37ad58420 Binary files /dev/null and b/packages/mermaid/src/docs/ecosystem/img/python-mermaid-integration-updated.png differ diff --git a/packages/mermaid/src/docs/ecosystem/integrations-community.md b/packages/mermaid/src/docs/ecosystem/integrations-community.md index 95e71d626..c756f3eeb 100644 --- a/packages/mermaid/src/docs/ecosystem/integrations-community.md +++ b/packages/mermaid/src/docs/ecosystem/integrations-community.md @@ -35,8 +35,12 @@ To add an integration to this list, see the [Integrations - create page](./integ - [Mermaid Charts & Diagrams for Jira](https://marketplace.atlassian.com/apps/1224537/) - [Mermaid for Jira Cloud - Draw UML diagrams easily](https://marketplace.atlassian.com/apps/1223053/mermaid-for-jira-cloud-draw-uml-diagrams-easily?hosting=cloud&tab=overview) - [CloudScript.io Mermaid Addon](https://marketplace.atlassian.com/apps/1219878/cloudscript-io-mermaid-addon?hosting=cloud&tab=overview) + - [Mermaid plus for Confluence](https://marketplace.atlassian.com/apps/1236814/mermaid-plus-for-confluence?hosting=cloud&tab=overview) - [Azure Devops](https://learn.microsoft.com/en-us/azure/devops/project/wiki/markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) ✅ - [Deepdwn](https://billiam.itch.io/deepdwn) ✅ +- [Doctave](https://www.doctave.com/) ✅ + - [Mermaid in Markdown code blocks](https://docs.doctave.com/components/mermaid) ✅ +- [Forgejo](https://forgejo.org/) ✅ - [GitBook](https://gitbook.com) - [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid) - [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf) @@ -49,22 +53,26 @@ To add an integration to this list, see the [Integrations - create page](./integ - [SVG diagram generator](https://github.com/SimonKenyonShepard/mermaidjs-github-svg-generator) - [GitLab](https://docs.gitlab.com/ee/user/markdown.html#diagrams-and-flowcharts) ✅ - [Mermaid Plugin for JetBrains IDEs](https://plugins.jetbrains.com/plugin/20146-mermaid) +- [MonsterWriter](https://www.monsterwriter.com/) ✅ - [Joplin](https://joplinapp.org) ✅ - [LiveBook](https://livebook.dev) ✅ +- [Slidev](https://sli.dev) ✅ - [Tuleap](https://docs.tuleap.org/user-guide/writing-in-tuleap.html#graphs) ✅ - [Mermaid Flow Visual Editor](https://www.mermaidflow.app) ✅ - [Mermerd](https://github.com/KarnerTh/mermerd) - [Slab](https://slab.com) ✅ -- [Swimm](https://docs.swimm.io/features/diagrams-and-charts/#mermaid--swimm--up-to-date-diagrams-) ✅ +- [Swimm](https://docs.swimm.io/features/diagrams-and-charts) ✅ - [NotesHub](https://noteshub.app) ✅ - [Notion](https://notion.so) ✅ - [Observable](https://observablehq.com/@observablehq/mermaid) ✅ - [Obsidian](https://help.obsidian.md/Editing+and+formatting/Advanced+formatting+syntax#Diagram) ✅ +- [Outline](https://docs.getoutline.com/s/guide/doc/diagrams-KQiKoT4wzK) ✅ - [Redmine](https://redmine.org) - [Mermaid Macro](https://www.redmine.org/plugins/redmine_mermaid_macro) - [Markdown for mermaid plugin](https://github.com/jamieh-mongolian/markdown-for-mermaid-plugin) - [redmine-mermaid](https://github.com/styz/redmine_mermaid) - Visual Studio Code [Polyglot Interactive Notebooks](https://github.com/dotnet/interactive#net-interactive) +- [Microsoft Loop](https://loop.cloud.microsoft) ✅ ### LLM integrations @@ -89,8 +97,7 @@ Blogging frameworks and platforms - [Nextra](https://nextra.site/) - [Mermaid](https://nextra.site/docs/guide/mermaid) - [WordPress](https://wordpress.org) - - [WordPress Markdown Editor](https://wordpress.org/plugins/wp-githuber-md) - - [WP-ReliableMD](https://wordpress.org/plugins/wp-reliablemd/) + - [MerPRess](https://wordpress.org/plugins/merpress/) ### CMS/ECM @@ -126,7 +133,7 @@ Communication tools and platforms ### Wikis - [DokuWiki](https://dokuwiki.org) - - [ComboStrap](https://combostrap.com/mermaid) + - [ComboStrap](https://combostrap.com/utility/create-diagram-with-mermaid-vh3ab9yj) - [Mermaid Plugin](https://www.dokuwiki.org/plugin:mermaid) - [Foswiki](https://foswiki.org) - [Mermaid Plugin](https://foswiki.org/Extensions/MermaidPlugin) @@ -135,7 +142,7 @@ Communication tools and platforms - [Mermaid Extension](https://www.mediawiki.org/wiki/Extension:Mermaid) - [PmWiki](https://www.pmwiki.org) - [MermaidJs Cookbook recipe](https://www.pmwiki.org/wiki/Cookbook/MermaidJs) -- [Semantic Media Wiki](https://semantic-mediawiki.org) +- [Semantic Media Wiki](https://www.semantic-mediawiki.org) - [Mermaid Plugin](https://github.com/SemanticMediaWiki/Mermaid) - [TiddlyWiki](https://tiddlywiki.com/) - [mermaid-tw5: wrapper for Mermaid Live](https://github.com/efurlanm/mermaid-tw5) @@ -175,8 +182,6 @@ Communication tools and platforms - [=Diagram block](https://github.com/zag/podlite/tree/main/packages/podlite-diagrams) - [Standard Notes](https://standardnotes.com/) - [Mermaid Extension](https://github.com/nienow/sn-mermaid) -- [Sublime Text 3](https://sublimetext.com) - - [Mermaid Package](https://packagecontrol.io/packages/Mermaid) - [VS Code](https://code.visualstudio.com/) - [Mermaid Editor](https://marketplace.visualstudio.com/items?itemName=tomoyukim.vscode-mermaid-editor) - [Mermaid Export](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.mermaid-export) @@ -190,23 +195,31 @@ Communication tools and platforms - [Vim](https://www.vim.org) - [Vim Diagram Syntax](https://github.com/zhaozg/vim-diagram) - [Official Vim Syntax and ft plugin](https://github.com/craigmac/vim-mermaid) +- [Zed](https://zed.dev) + - [zed-mermaid](https://github.com/gabeidx/zed-mermaid) ### Document Generation +- [Astro](https://astro.build/) + - [Adding diagrams to your Astro site with MermaidJS and Playwright](https://agramont.net/blog/diagraming-with-mermaidjs-astro/) - [Codedoc](https://codedoc.cc/) - [codedoc-mermaid-plugin](https://www.npmjs.com/package/codedoc-mermaid-plugin) - [Docsy Hugo Theme](https://www.docsy.dev/docs/adding-content/lookandfeel/#diagrams-with-mermaid) ✅ - [Docusaurus](https://docusaurus.io/docs/markdown-features/diagrams) ✅ - [Gatsby](https://www.gatsbyjs.com/) - [gatsby-remark-mermaid](https://github.com/remcohaszing/gatsby-remark-mermaid) +- [Jekyll](https://jekyllrb.com/) + - [jekyll-mermaid](https://rubygems.org/gems/jekyll-mermaid) + - [jekyll-mermaid-diagrams](https://github.com/fuzhibo/jekyll-mermaid-diagrams) - [JSDoc](https://jsdoc.app/) - [jsdoc-mermaid](https://github.com/Jellyvision/jsdoc-mermaid) +- [Madness](https://madness.dannyb.co/) - [mdBook](https://rust-lang.github.io/mdBook/index.html) - [mdbook-mermaid](https://github.com/badboy/mdbook-mermaid) - [MkDocs](https://www.mkdocs.org) - [mkdocs-mermaid2-plugin](https://github.com/fralau/mkdocs-mermaid2-plugin) - [mkdocs-material](https://github.com/squidfunk/mkdocs-material), check the [docs](https://squidfunk.github.io/mkdocs-material/reference/diagrams/) - - [Quarto](https://quarto.org/) +- [Quarto](https://quarto.org/) ✅ - [rehype](https://github.com/rehypejs/rehype) - [rehype-mermaid](https://github.com/remcohaszing/rehype-mermaid) - [remark](https://remark.js.org/) @@ -241,9 +254,7 @@ Communication tools and platforms - [Codemia: A tool to practice system design problems](https://codemia.io) ✅ - [ExDoc](https://github.com/elixir-lang/ex_doc) - [Rendering Mermaid graphs](https://github.com/elixir-lang/ex_doc#rendering-mermaid-graphs) -- [Jekyll](https://jekyllrb.com/) - - [jekyll-mermaid](https://rubygems.org/gems/jekyll-mermaid) - - [jekyll-mermaid-diagrams](https://github.com/fuzhibo/jekyll-mermaid-diagrams) +- [MarkChart: Preview Mermaid diagrams on macOS](https://markchart.app/) - [mermaid-isomorphic](https://github.com/remcohaszing/mermaid-isomorphic) - [mermaid-server: Generate diagrams using a HTTP request](https://github.com/TomWright/mermaid-server) - [NiceGUI: Let any browser be the frontend of your Python code](https://nicegui.io) ✅ @@ -252,7 +263,5 @@ Communication tools and platforms - [reveal.js-mermaid-plugin](https://github.com/ludwick/reveal.js-mermaid-plugin) - [Reveal CK](https://github.com/jedcn/reveal-ck) - [reveal-ck-mermaid-plugin](https://github.com/tmtm/reveal-ck-mermaid-plugin) -- [mermaid-isomorphic](https://github.com/remcohaszing/mermaid-isomorphic) -- [mermaid-server: Generate diagrams using a HTTP request](https://github.com/TomWright/mermaid-server) diff --git a/packages/mermaid/src/docs/ecosystem/integrations-create.md b/packages/mermaid/src/docs/ecosystem/integrations-create.md index b14c43ec2..0341f1bf8 100644 --- a/packages/mermaid/src/docs/ecosystem/integrations-create.md +++ b/packages/mermaid/src/docs/ecosystem/integrations-create.md @@ -18,7 +18,7 @@ Currently pending [IANA](https://www.iana.org/) recognition. ### Mermaid Discord workspace -We would love to see what you create with Mermaid. Please share your creations with us in our [Discord](https://discord.gg/AgrbSrBer3) server [#showcase](https://discord.com/channels/1079455296289788015/1079502635054399649) channel. +We would love to see what you create with Mermaid. Please share your creations with us in our [Discord](https://discord.gg/sKeNQX4Wtj) server [#showcase](https://discord.com/channels/1079455296289788015/1079502635054399649) channel. ### Add to Mermaid Ecosystem diff --git a/packages/mermaid/src/docs/ecosystem/mermaid-chart.md b/packages/mermaid/src/docs/ecosystem/mermaid-chart.md index 94b6773e4..416d0b595 100644 --- a/packages/mermaid/src/docs/ecosystem/mermaid-chart.md +++ b/packages/mermaid/src/docs/ecosystem/mermaid-chart.md @@ -1,8 +1,12 @@ # Mermaid Chart +The Future of Diagramming & Visual Collaboration + +Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an account at [Mermaid Chart](https://www.mermaidchart.com/app/sign-up). +
-Mermaid Chart - A smarter way to create diagrams | Product Hunt +Mermaid Chart - A smarter way to create diagrams | Product Hunt ## About @@ -12,36 +16,41 @@ - **Editor** - A web based editor for creating and editing Mermaid diagrams. -- **Presentation** - A presentation mode for viewing Mermaid diagrams in a slideshow format. +- **Mermaid AI** - Use our embedded AI Chat to generate diagrams from natural language descriptions. -- **Collaboration** - A web based collaboration feature for multi-user editing on Mermaid diagrams in real-time (Pro plan). +- **Whiteboard** - A virtual whiteboard for creating and editing Mermaid diagrams. - **Plugins** - A plugin system for extending the functionality of Mermaid. - Plugins are available for: + Official Mermaid Chart plugins: - - [ChatGPT](https://docs.mermaidchart.com/plugins/chatgpt) - - [JetBrains IDE](https://plugins.jetbrains.com/plugin/23043-mermaid-chart) - - [Microsoft PowerPoint and Word](https://appsource.microsoft.com/en-us/product/office/WA200006214?tab=Overview) + - [Mermaid Chart GPT](https://chat.openai.com/g/g-1IRFKwq4G-mermaid-chart) + - [Confluence](https://marketplace.atlassian.com/apps/1234056/mermaid-chart-for-confluence?hosting=cloud&tab=overview) + - [Jira](https://marketplace.atlassian.com/apps/1234810/mermaid-chart-for-jira?tab=overview&hosting=cloud) - [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=MermaidChart.vscode-mermaid-chart) + - [JetBrains IDE](https://plugins.jetbrains.com/plugin/23043-mermaid-chart) + - [Google Docs](https://gsuite.google.com/marketplace/app/mermaidchart/947683068472) + - [Microsoft PowerPoint and Word](https://appsource.microsoft.com/en-us/product/office/WA200006214?tab=Overview) -- **AI diagramming** - A feature for generating Mermaid diagrams from text using AI (Pro plan). + Visit our [Plugins](https://www.mermaidchart.com/plugins) page for more information. -- **More** - To learn more, visit our [Product](https://www.mermaidchart.com/product) page. +- **Collaboration** - A web based collaboration feature for multi-user editing on Mermaid diagrams in real-time (Pro and Enterprise plans). + +- **Comments** - Enhance collaboration by adding comments to diagrams. + +- **Presentations** - A presentation mode for viewing Mermaid diagrams in a slideshow format. ## Plans -- **Free** - A free plan that includes five diagrams. +- **Free** - A free plan that includes three diagrams. - **Pro** - A paid plan that includes unlimited diagrams, access to the collaboration feature, and more. - **Enterprise** - A paid plan for enterprise use that includes all Pro features, and more. -## Access +To learn more, visit our [Pricing](https://mermaidchart.com/pricing) page. -Sign up for a free account at [Mermaid Chart](https://www.mermaidchart.com/app/sign-up). - -Mermaid Chart is currently offering a 14-day free trial of our newly-launched Pro tier. To learn more, visit our [Pricing](https://mermaidchart.com/pricing) page. +Mermaid Chart is currently offering a 7-day free trial on our Pro and Enterprise tiers. Sign up for a free account at [Mermaid Chart](https://www.mermaidchart.com/app/sign-up). ## Mermaid JS contributions diff --git a/packages/mermaid/src/docs/ecosystem/tutorials.md b/packages/mermaid/src/docs/ecosystem/tutorials.md index d5bf9330d..9f0f351a2 100644 --- a/packages/mermaid/src/docs/ecosystem/tutorials.md +++ b/packages/mermaid/src/docs/ecosystem/tutorials.md @@ -46,28 +46,33 @@ https://codepen.io/Ryuno-Ki/pen/LNxwgR [K8s.dev blog: Improve your documentation with Mermaid.js diagrams](https://www.kubernetes.dev/blog/2021/12/01/improve-your-documentation-with-mermaid.js-diagrams/) -## Jupyter Integration with mermaid-js +## Jupyter / Python Integration with mermaid-js -Here's an example of Python integration with mermaid-js which uses the mermaid.ink service, that displays the graph in a Jupyter notebook. +Here's an example of Python integration with mermaid-js which uses the mermaid.ink service, that displays the graph in a Jupyter notebook and save it as _.png_ image with the stated resolution (in this example, `dpi=1200`). ```python import base64 +import io, requests from IPython.display import Image, display +from PIL import Image as im import matplotlib.pyplot as plt def mm(graph): graphbytes = graph.encode("utf8") - base64_bytes = base64.b64encode(graphbytes) + base64_bytes = base64.urlsafe_b64encode(graphbytes) base64_string = base64_bytes.decode("ascii") - display(Image(url="https://mermaid.ink/img/" + base64_string)) + img = im.open(io.BytesIO(requests.get('https://mermaid.ink/img/' + base64_string).content)) + plt.imshow(img) + plt.axis('off') # allow to hide axis + plt.savefig('image.png', dpi=1200) mm(""" graph LR; - A--> B & C & D; - B--> A & E; - C--> A & E; - D--> A & E; - E--> B & C & D; + A--> B & C & D + B--> A & E + C--> A & E + D--> A & E + E--> B & C & D """) ``` @@ -75,4 +80,4 @@ graph LR; ![Example graph of the Python integration](img/python-mermaid-integration.png) - + diff --git a/packages/mermaid/src/docs/intro/getting-started.md b/packages/mermaid/src/docs/intro/getting-started.md index 2bfa36bb7..8e6482ae2 100644 --- a/packages/mermaid/src/docs/intro/getting-started.md +++ b/packages/mermaid/src/docs/intro/getting-started.md @@ -41,7 +41,7 @@ In the `Code` panel, write or edit Mermaid code, and instantly `Preview` the ren Here is an example of Mermaid code and its rendered result: -```mermaid +```mermaid-example graph TD A[Enter Chart Definition] --> B(Preview) B --> C{decide} @@ -146,7 +146,7 @@ For a list of Mermaid Plugins and Integrations, visit the [Integrations page](.. Mermaid Chart plugins are available for: -- [ChatGPT](https://docs.mermaidchart.com/plugins/chatgpt) +- [ChatGPT](https://docs.mermaidchart.com/plugins/mermaid-chart-gpt) - [JetBrains IDE](https://docs.mermaidchart.com/plugins/jetbrains-ide) - [Microsoft PowerPoint](https://docs.mermaidchart.com/plugins/microsoft-powerpoint) - [Microsoft Word](https://docs.mermaidchart.com/plugins/microsoft-word) diff --git a/packages/mermaid/src/docs/intro/index.md b/packages/mermaid/src/docs/intro/index.md index ed2df32dc..ff37d549b 100644 --- a/packages/mermaid/src/docs/intro/index.md +++ b/packages/mermaid/src/docs/intro/index.md @@ -16,7 +16,7 @@ It is a JavaScript based diagramming and charting tool that renders Markdown-ins [![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid) [![NPM](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid) -[![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/AgrbSrBer3) +[![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/sKeNQX4Wtj) [![Twitter Follow](https://img.shields.io/twitter/follow/mermaidjs_?style=social)](https://twitter.com/mermaidjs_)
@@ -44,12 +44,16 @@ For a more detailed introduction to Mermaid and some of its more basic uses, loo 🌐 [CDN](https://www.jsdelivr.com/package/npm/mermaid) | 📖 [Documentation](https://mermaidjs.github.io) | 🙌 [Contribution](../community/contributing.md) | 🔌 [Plug-Ins](../ecosystem/integrations-community.md) -> 🖖 Keep a steady pulse: mermaid needs more Collaborators, [Read More](https://github.com/knsv/mermaid/issues/866). +> 🖖 Keep a steady pulse: [mermaid needs more Collaborators](https://github.com/mermaid-js/mermaid/issues/866). :trophy: **Mermaid was nominated and won the [JS Open Source Awards (2019)](https://osawards.com/javascript/#nominees) in the category "The most exciting use of technology"!!!** **Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project 🙏** +Our PR Visual Regression Testing is powered by [Argos](https://argos-ci.com/?utm_source=mermaid&utm_campaign=oss) with their generous Open Source plan. It makes the process of reviewing PRs with visual changes a breeze. + +[![Covered by Argos Visual Testing](https://argos-ci.com/badge-large.svg)](https://argos-ci.com?utm_source=mermaid&utm_campaign=oss) + In our release process we rely heavily on visual regression tests using [applitools](https://applitools.com/). Applitools is a great service which has been easy to use and integrate with our tests. @@ -188,7 +192,7 @@ For public sites, it can be precarious to retrieve text from users on the intern As an extra level of security for sites with external users we are happy to introduce a new security level in which the diagram is rendered in a sandboxed iframe preventing JavaScript in the code from being executed. This is a great step forward for better security. -_Unfortunately you can not have a cake and eat it at the same time which in this case means that some of the interactive functionality gets blocked along with the possible malicious code._ +_Unfortunately you cannot have a cake and eat it at the same time which in this case means that some of the interactive functionality gets blocked along with the possible malicious code._ ## Reporting vulnerabilities @@ -204,7 +208,7 @@ A quick note from Knut Sveidqvist: > > _Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017._ > -> _Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!_ +> _Thank you to the ever-growing list of [contributors](https://github.com/mermaid-js/mermaid/graphs/contributors) that brought the project this far!_ --- diff --git a/packages/mermaid/src/docs/intro/syntax-reference.md b/packages/mermaid/src/docs/intro/syntax-reference.md index d4ee1067f..a479f6f0e 100644 --- a/packages/mermaid/src/docs/intro/syntax-reference.md +++ b/packages/mermaid/src/docs/intro/syntax-reference.md @@ -65,3 +65,111 @@ Allows for the limited reconfiguration of a diagram just before it is rendered. ### [Theme Manipulation](../config/theming.md) An application of using Directives to change [Themes](../config/theming.md). `Theme` is a value within Mermaid's configuration that dictates the color scheme for diagrams. + +### Layout and look + +We've restructured how Mermaid renders diagrams, enabling new features like selecting layout and look. **Currently, this is supported for flowcharts and state diagrams**, with plans to extend support to all diagram types. + +### Selecting Diagram Looks + +Mermaid offers a variety of styles or “looks” for your diagrams, allowing you to tailor the visual appearance to match your specific needs or preferences. Whether you prefer a hand-drawn or classic style, you can easily customize your diagrams. + +**Available Looks:** + +- Hand-Drawn Look: For a more personal, creative touch, the hand-drawn look brings a sketch-like quality to your diagrams. This style is perfect for informal settings or when you want to add a bit of personality to your diagrams. +- Classic Look: If you prefer the traditional Mermaid style, the classic look maintains the original appearance that many users are familiar with. It’s great for consistency across projects or when you want to keep the familiar aesthetic. + +**How to Select a Look:** + +You can select a look by adding the look parameter in the metadata section of your Mermaid diagram code. Here’s an example: + +```mermaid-example +--- +config: + look: handDrawn + theme: neutral +--- +flowchart LR + A[Start] --> B{Decision} + B -->|Yes| C[Continue] + B -->|No| D[Stop] +``` + +#### Selecting Layout Algorithms + +In addition to customizing the look of your diagrams, Mermaid Chart now allows you to choose different layout algorithms to better organize and present your diagrams, especially when dealing with more complex structures. The layout algorithm dictates how nodes and edges are arranged on the page. + +#### Supported Layout Algorithms: + +- Dagre (default): This is the classic layout algorithm that has been used in Mermaid for a long time. It provides a good balance of simplicity and visual clarity, making it ideal for most diagrams. +- ELK: For those who need more sophisticated layout capabilities, especially when working with large or intricate diagrams, the ELK (Eclipse Layout Kernel) layout offers advanced options. It provides a more optimized arrangement, potentially reducing overlapping and improving readability. This is not included out the box but needs to be added when integrating mermaid for sites/applications that want to have elk support. + +#### How to Select a Layout Algorithm: + +You can specify the layout algorithm directly in the metadata section of your Mermaid diagram code. Here’s an example: + +```mermaid-example +--- +config: + layout: elk + look: handDrawn + theme: dark +--- +flowchart TB + A[Start] --> B{Decision} + B -->|Yes| C[Continue] + B -->|No| D[Stop] +``` + +In this example, the `layout: elk` line configures the diagram to use the ELK layout algorithm, along with the hand drawn look and forest theme. + +#### Customizing ELK Layout: + +When using the ELK layout, you can further refine the diagram’s configuration, such as how nodes are placed and whether parallel edges should be combined: + +- To combine parallel edges, use mergeEdges: true | false. +- To configure node placement, use nodePlacementStrategy with the following options: + - SIMPLE + - NETWORK_SIMPLEX + - LINEAR_SEGMENTS + - BRANDES_KOEPF (default) + +**Example configuration:** + +``` +--- +config: + layout: elk + elk: + mergeEdges: true + nodePlacementStrategy: LINEAR_SEGMENTS +--- +flowchart LR + A[Start] --> B{Choose Path} + B -->|Option 1| C[Path 1] + B -->|Option 2| D[Path 2] + +``` + +#### Using Dagre Layout with Classic Look: + +Another example: + +``` +--- +config: + layout: dagre + look: classic + theme: default +--- + +flowchart LR +A[Start] --> B{Choose Path} +B -->|Option 1| C[Path 1] +B -->|Option 2| D[Path 2] + +``` + +These options give you the flexibility to create diagrams that not only look great but are also arranged to best suit your data’s structure and flow. + +When integrating Mermaid, you can include look and layout configuration with the initialize call. This is also where you add the loading of elk. diff --git a/packages/mermaid/src/docs/news/blog.md b/packages/mermaid/src/docs/news/blog.md index 267bd48a6..d774a932c 100644 --- a/packages/mermaid/src/docs/news/blog.md +++ b/packages/mermaid/src/docs/news/blog.md @@ -1,5 +1,101 @@ # Blog +## [GUI for editing Mermaid Class Diagrams](https://docs.mermaidchart.com/blog/posts/gui-for-editing-mermaid-class-diagrams) + +1/17/2025 â€ĸ 5 mins + +Discover how the latest update to the Mermaid Visual Editor transforms class diagramming. With new intuitive tools for creating and editing diagrams, dynamic relationship management, and customizable layouts, this feature-packed enhancement streamlines your diagramming experience like never before. + +## [7 ER Diagram Examples For Database Modeling from Mermaid AI](https://docs.mermaidchart.com/blog/posts/7-er-diagram-examples-for-database-modeling-from-mermaid-ai) + +1/16/2025 â€ĸ 6 mins + +Entity relationship (ER) diagrams are a cornerstone of database design, providing a blueprint for modeling your database and enabling clear communication across functions in your organization. As data volumes continue to soar and as AI models demand clean, well-organized data, ER diagrams have become more vital than ever. You can now quickly build ER diagrams with Mermaid Chart, Mermaid AI to kick-start and fine tune your diagrams . From e-commerce payment flows to social media interactions and healthcare systems, ER diagrams are powering modern, data-driven environments. + +## [Mermaid Whiteboard: Visual Collaboration Made Universal](https://docs.mermaidchart.com/blog/posts/mermaid-whiteboard-visual-collaboration-made-universal) + +12/6/2024 â€ĸ 2 mins + +The Mermaid Whiteboard combines Mermaid syntax with a drag-and-drop interface, making it easier for teams to create, edit, and refine diagrams together. Whether you prefer working with code, visuals, Mermaid AI or all three, this tool adapts to your needs while keeping everything tied to Mermaid’s syntax. Key Features 1. Dual-Mode Editing Switch seamlessly between [â€Ļ] + +## [Mermaid 11.4 is out: New Features and Kanban Diagramming](https://www.mermaidchart.com/blog/posts/mermaid-11-4-is-out-new-features-and-kanban-diagramming) + +October 31, 2024 ¡ 2 mins + +Mermaid 11.4 brings enhanced functionality with the introduction of Kanban diagrams, allowing users to create visual workflows with status columns and task details. + +## [How To Build an ER Diagram with Mermaid Chart](https://www.mermaidchart.com/blog/posts/how-to-build-an-er-diagram-with-mermaid-chart) + +October 24, 2024 ¡ 4 mins + +An entity relationship (ER) diagram acts like a blueprint for your database. This makes ER diagrams effective tools for anyone dealing with complex databases, data modeling, and AI model training. + +## [Expanding the Horizons of Mermaid Flowcharts: Introducing 30 New Shapes!](https://www.mermaidchart.com/blog/posts/new-mermaid-flowchart-shapes/) + +24 September 2024 ¡ 5 mins + +Discover 30 new shapes in Mermaid flowcharts, offering enhanced clarity, customization, and versatility for more dynamic and expressive visualizations. + +## [Introducing Architecture Diagrams in Mermaid](https://www.mermaidchart.com/blog/posts/mermaid-supports-architecture-diagrams/) + +2 September 2024 ¡ 2 mins + +Discover the fresh new and unique Neo and Hand-Drawn looks for Mermaid Diagrams, while still offering the classic look you love. + +## [Mermaid v11 is out!](https://www.mermaidchart.com/blog/posts/mermaid-v11/) + +23 August 2024 ¡ 2 mins + +Mermaid v11 introduces advanced layout options, new diagram types, and enhanced customization features, thanks to the incredible contributions from our community. + +## [Mermaid Innovation - Introducing New Looks for Mermaid Diagrams](https://www.mermaidchart.com/blog/posts/mermaid-innovation-introducing-new-looks-for-mermaid-diagrams/) + +6 August 2024 ¡3 mins + +Discover the fresh new and unique Neo and Hand-Drawn looks for Mermaid Diagrams, while still offering the classic look you love. + +## [The Mermaid Chart Plugin for Jira: A How-To User Guide](https://www.mermaidchart.com/blog/posts/the-mermaid-chart-plugin-for-jira-a-how-to-user-guide/) + +31 July 2024 ¡ 5 mins + +The Mermaid Chart plugin for Jira has arrived! + +## [Mermaid AI Is Here to Change the Game For Diagram Creation](https://www.mermaidchart.com/blog/posts/mermaid-ai-is-here-to-change-the-game-for-diagram-creation/) + +22 July 2024 ¡ 5 mins + +The Mermaid AI chat interface + +## [How to Make a Sequence Diagram with Mermaid Chart](https://www.mermaidchart.com/blog/posts/how-to-make-a-sequence-diagram-in-mermaid-chart-step-by-step-guide/) + +8 July 2024 ¡ 6 mins + +Sequence diagrams are important for communicating complex systems in a clear and concise manner. + +## [How to Use the New “Comments” Feature in Mermaid Chart](https://www.mermaidchart.com/blog/posts/how-to-use-the-new-comments-feature-in-mermaid-chart/) + +2 July 2024 ¡ 3 mins + +How to Use the New Comments Feature in Mermaid Chart + +## [How to Use the official Mermaid Chart for Confluence app](https://www.mermaidchart.com/blog/posts/how-to-use-the-official-mermaid-chart-for-confluence-app/) + +21 May 2024 ¡ 4 mins + +It doesn’t matter if you’re a data enthusiast, software engineer, or visual storyteller; our Confluence app can allow you to embed Mermaid Chart diagrams — and dynamically edit them — within your Confluence pages. + +## [How to Choose the Right Documentation Software](https://www.mermaidchart.com/blog/posts/how-to-choose-the-right-documentation-software/) + +7 May 2024 ¡ 5 mins + +How to Choose the Right Documentation Software. Reliable and efficient documentation software is crucial in the fast-paced world of software development. + +## [AI in software diagramming: What trends will define the future?](https://www.mermaidchart.com/blog/posts/ai-in-software-diagramming/) + +24 April 2024 ¡ 5 mins + +Artificial intelligence (AI) tools are changing the way developers work. + ## [Mermaid Chart Unveils Visual Editor for Sequence Diagrams](https://www.mermaidchart.com/blog/posts/mermaid-chart-unveils-visual-editor-for-sequence-diagrams/) 8 April 2024 ¡ 5 mins diff --git a/packages/mermaid/src/docs/package.json b/packages/mermaid/src/docs/package.json index 5f6e338a0..fb591f9d3 100644 --- a/packages/mermaid/src/docs/package.json +++ b/packages/mermaid/src/docs/package.json @@ -1,6 +1,7 @@ { - "name": "docs", + "name": "@mermaid-js/docs", "private": true, + "version": "0.0.1", "type": "module", "scripts": { "dev": "vitepress --port 3333 --open", @@ -15,26 +16,26 @@ "fetch-contributors": "tsx .vitepress/scripts/fetch-contributors.ts" }, "dependencies": { - "@mdi/font": "^7.0.0", - "@vueuse/core": "^10.9.0", + "@mdi/font": "^7.4.47", + "@vueuse/core": "^13.1.0", "font-awesome": "^4.7.0", - "jiti": "^1.21.0", + "jiti": "^2.4.2", "mermaid": "workspace:^", - "vue": "^3.4.21" + "vue": "^3.4.38" }, "devDependencies": { - "@iconify-json/carbon": "^1.1.31", - "@unocss/reset": "^0.59.0", - "@vite-pwa/vitepress": "^0.4.0", - "@vitejs/plugin-vue": "^5.0.0", - "fast-glob": "^3.3.2", + "@iconify-json/carbon": "^1.1.37", + "@unocss/reset": "^66.0.0", + "@vite-pwa/vitepress": "^1.0.0", + "@vitejs/plugin-vue": "^5.0.5", + "fast-glob": "^3.3.3", "https-localhost": "^4.7.1", - "pathe": "^1.1.2", - "unocss": "^0.59.0", - "unplugin-vue-components": "^0.26.0", - "vite": "^5.0.0", - "vite-plugin-pwa": "^0.19.7", - "vitepress": "1.1.0", - "workbox-window": "^7.0.0" + "pathe": "^2.0.3", + "unocss": "^66.0.0", + "unplugin-vue-components": "^28.4.0", + "vite": "^6.1.1", + "vite-plugin-pwa": "^1.0.0", + "vitepress": "1.6.3", + "workbox-window": "^7.3.0" } } diff --git a/packages/mermaid/src/docs/syntax/architecture.md b/packages/mermaid/src/docs/syntax/architecture.md new file mode 100644 index 000000000..26fdfb150 --- /dev/null +++ b/packages/mermaid/src/docs/syntax/architecture.md @@ -0,0 +1,175 @@ +# Architecture Diagrams Documentation (v11.1.0+) + +> In the context of mermaid-js, the architecture diagram is used to show the relationship between services and resources commonly found within the Cloud or CI/CD deployments. In an architecture diagram, services (nodes) are connected by edges. Related services can be placed within groups to better illustrate how they are organized. + +## Example + +```mermaid-example +architecture-beta + group api(cloud)[API] + + service db(database)[Database] in api + service disk1(disk)[Storage] in api + service disk2(disk)[Storage] in api + service server(server)[Server] in api + + db:L -- R:server + disk1:T -- B:server + disk2:T -- B:db +``` + +## Syntax + +The building blocks of an architecture are `groups`, `services`, `edges`, and `junctions`. + +For supporting components, icons are declared by surrounding the icon name with `()`, while labels are declared by surrounding the text with `[]`. + +To begin an architecture diagram, use the keyword `architecture-beta`, followed by your groups, services, edges, and junctions. While each of the 3 building blocks can be declared in any order, care must be taken to ensure the identifier was previously declared by another component. + +### Groups + +The syntax for declaring a group is: + +``` +group {group id}({icon name})[{title}] (in {parent id})? +``` + +Put together: + +``` +group public_api(cloud)[Public API] +``` + +creates a group identified as `public_api`, uses the icon `cloud`, and has the label `Public API`. + +Additionally, groups can be placed within a group using the optional `in` keyword + +``` +group private_api(cloud)[Private API] in public_api +``` + +### Services + +The syntax for declaring a service is: + +``` +service {service id}({icon name})[{title}] (in {parent id})? +``` + +Put together: + +``` +service database1(database)[My Database] +``` + +creates the service identified as `database1`, using the icon `database`, with the label `My Database`. + +If the service belongs to a group, it can be placed inside it through the optional `in` keyword + +``` +service database1(database)[My Database] in private_api +``` + +### Edges + +The syntax for declaring an edge is: + +``` +{serviceId}{{group}}?:{T|B|L|R} {<}?--{>}? {T|B|L|R}:{serviceId}{{group}}? +``` + +#### Edge Direction + +The side of the service the edge comes out of is specified by adding a colon (`:`) to the side of the service connecting to the arrow and adding `L|R|T|B` + +For example: + +``` +db:R -- L:server +``` + +creates an edge between the services `db` and `server`, with the edge coming out of the right of `db` and the left of `server`. + +``` +db:T -- L:server +``` + +creates a 90 degree edge between the services `db` and `server`, with the edge coming out of the top of `db` and the left of `server`. + +#### Arrows + +Arrows can be added to each side of an edge by adding `<` before the direction on the left, and/or `>` after the direction on the right. + +For example: + +``` +subnet:R --> L:gateway +``` + +creates an edge with the arrow going into the `gateway` service + +#### Edges out of Groups + +To have an edge go from a group to another group or service within another group, the `{group}` modifier can be added after the `serviceId`. + +For example: + +``` +service server[Server] in groupOne +service subnet[Subnet] in groupTwo + +server{group}:B --> T:subnet{group} +``` + +creates an edge going out of `groupOne`, adjacent to `server`, and into `groupTwo`, adjacent to `subnet`. + +It's important to note that `groupId`s cannot be used for specifying edges and the `{group}` modifier can only be used for services within a group. + +### Junctions + +Junctions are a special type of node which acts as a potential 4-way split between edges. + +The syntax for declaring a junction is: + +``` +junction {junction id} (in {parent id})? +``` + +```mermaid-example +architecture-beta + service left_disk(disk)[Disk] + service top_disk(disk)[Disk] + service bottom_disk(disk)[Disk] + service top_gateway(internet)[Gateway] + service bottom_gateway(internet)[Gateway] + junction junctionCenter + junction junctionRight + + left_disk:R -- L:junctionCenter + top_disk:B -- T:junctionCenter + bottom_disk:T -- B:junctionCenter + junctionCenter:R -- L:junctionRight + top_gateway:B -- T:junctionRight + bottom_gateway:T -- B:junctionRight +``` + +## Icons + +By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`. +Users can use any of the 200,000+ icons available in iconify.design, or [add custom icons](../config/icons.md). + +After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack. + +```mermaid-example +architecture-beta + group api(logos:aws-lambda)[API] + + service db(logos:aws-aurora)[Database] in api + service disk1(logos:aws-glacier)[Storage] in api + service disk2(logos:aws-s3)[Storage] in api + service server(logos:aws-ec2)[Server] in api + + db:L -- R:server + disk1:T -- B:server + disk2:T -- B:db +``` diff --git a/packages/mermaid/src/docs/syntax/block.md b/packages/mermaid/src/docs/syntax/block.md index 7c5907dc7..9c721104e 100644 --- a/packages/mermaid/src/docs/syntax/block.md +++ b/packages/mermaid/src/docs/syntax/block.md @@ -7,7 +7,7 @@ outline: 'deep' # shows all h3 headings in outline in Vitepress ## Introduction to Block Diagrams -```mermaid +```mermaid-example block-beta columns 1 db(("DB")) @@ -106,7 +106,7 @@ block-beta a["A label"] b:2 c:2 d ``` -In this example, the block labeled "A wide one" spans two columns, while blocks 'b', 'c', and 'd' are allocated their own columns. This flexibility in block sizing is crucial for accurately representing systems with components of varying significance or size. +In this example, the block labeled "A labels" spans one column, while blocks 'b', 'c' span 2 columns, and 'd' is again allocated its own column. This flexibility in block sizing is crucial for accurately representing systems with components of varying significance or size. ### Creating Composite Blocks @@ -153,6 +153,19 @@ block-beta This example demonstrates how Mermaid dynamically adjusts the width of the columns to accommodate the widest block, in this case, 'a' and the composite block 'e'. This dynamic adjustment is essential for creating visually balanced and easy-to-understand diagrams. +**Merging Blocks Horizontally:** +In scenarios where you need to stack blocks horizontally, you can use column width to accomplish the task. Blocks can be arranged vertically by putting them in a single column. Here is how you can create a block diagram in which 4 blocks are stacked on top of each other: + +```mermaid-example +block-beta + block + columns 1 + a["A label"] b c d + end +``` + +In this example, the width of the merged block dynamically adjusts to the width of the largest child block. + With these advanced configuration options, Mermaid's block diagrams can be tailored to represent a wide array of complex systems and structures. The flexibility offered by these features enables users to create diagrams that are both informative and visually appealing. In the following sections, we will explore further capabilities, including different block shapes and linking options. ## 4. Block Varieties and Shapes @@ -445,7 +458,7 @@ block-beta ``` **Correction**: -Ensure that links between blocks are correctly specified with arrows (--> or ---) to define the direction and type of connection. Also remember that one of the fundaments for block diagram is to give the author full control of where the boxes are positioned so in the example you need to add a space between the boxes: +Ensure that links between blocks are correctly specified with arrows (--> or ---) to define the direction and type of connection. Also remember that one of the fundamentals for block diagram is to give the author full control of where the boxes are positioned so in the example you need to add a space between the boxes: ```mermaid-example block-beta diff --git a/packages/mermaid/src/docs/syntax/c4.md b/packages/mermaid/src/docs/syntax/c4.md index 81120d3c0..c9b7eb6ad 100644 --- a/packages/mermaid/src/docs/syntax/c4.md +++ b/packages/mermaid/src/docs/syntax/c4.md @@ -257,7 +257,7 @@ UpdateRelStyle(customerA, bankA, $offsetY="60") title Component diagram for Internet Banking System - API Application Container(spa, "Single Page Application", "javascript and angular", "Provides all the internet banking functionality to customers via their web browser.") - Container(ma, "Mobile App", "Xamarin", "Provides a limited subset to the internet banking functionality to customers via their mobile mobile device.") + Container(ma, "Mobile App", "Xamarin", "Provides a limited subset to the internet banking functionality to customers via their mobile device.") ContainerDb(db, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.") System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.") diff --git a/packages/mermaid/src/docs/syntax/classDiagram.md b/packages/mermaid/src/docs/syntax/classDiagram.md index 029d11b54..f2cec2ec5 100644 --- a/packages/mermaid/src/docs/syntax/classDiagram.md +++ b/packages/mermaid/src/docs/syntax/classDiagram.md @@ -248,7 +248,7 @@ classE o-- classF : aggregation Relations can logically represent an N:M association: -```mermaid +```mermaid-example classDiagram Animal <|--|> Zebra ``` @@ -277,6 +277,34 @@ And `Link` can be one of: | -- | Solid | | .. | Dashed | +### Lollipop Interfaces + +Classes can also be given a special relation type that defines a lollipop interface on the class. A lollipop interface is defined using the following syntax: + +- `bar ()-- foo` +- `foo --() bar` + +The interface (bar) with the lollipop connects to the class (foo). + +Note: Each interface that is defined is unique and is meant to not be shared between classes / have multiple edges connecting to it. + +```mermaid-example +classDiagram + bar ()-- foo +``` + +```mermaid-example +classDiagram + class Class01 { + int amount + draw() + } + Class01 --() bar + Class02 --() bar + + foo ()-- Class01 +``` + ## Define Namespace A namespace groups classes. @@ -518,10 +546,12 @@ Beginner's tip—a full example using interactive links in an HTML page: ## Styling -### Styling a node (v10.7.0+) +### Styling a node It is possible to apply specific styles such as a thicker border or a different background color to an individual node using the `style` keyword. +Note that notes and namespaces cannot be styled individually but do support themes. + ```mermaid-example classDiagram class Animal @@ -533,11 +563,78 @@ classDiagram #### Classes More convenient than defining the style every time is to define a class of styles and attach this class to the nodes that -should have a different look. This is done by predefining classes in css styles that can be applied from the graph definition using the `cssClass` statement or the `:::` short hand. +should have a different look. + +A class definition looks like the example below: + +``` +classDef className fill:#f9f,stroke:#333,stroke-width:4px; +``` + +Also, it is possible to define style to multiple classes in one statement: + +``` +classDef firstClassName,secondClassName font-size:12pt; +``` + +Attachment of a class to a node is done as per below: + +``` +cssClass "nodeId1" className; +``` + +It is also possible to attach a class to a list of nodes in one statement: + +``` +cssClass "nodeId1,nodeId2" className; +``` + +A shorter form of adding a class is to attach the classname to the node using the `:::` operator: + +```mermaid-example +classDiagram + class Animal:::someclass + classDef someclass fill:#f96 +``` + +Or: + +```mermaid-example +classDiagram + class Animal:::someclass { + -int sizeInFeet + -canEat() + } + classDef someclass fill:#f96 +``` + +### Default class + +If a class is named default it will be applied to all nodes. Specific styles and classes should be defined afterwards to override the applied default styling. + +``` +classDef default fill:#f9f,stroke:#333,stroke-width:4px; +``` + +```mermaid-example +classDiagram + class Animal:::pink + class Mineral + + classDef default fill:#f96,color:red + classDef pink color:#f9f +``` + +### CSS Classes + +It is also possible to predefine classes in CSS styles that can be applied from the graph definition as in the example +below: + +**Example style** ```html ``` -Then attaching that class to a specific node: - -``` - cssClass "nodeId1" styleClass; -``` - -It is also possible to attach a class to a list of nodes in one statement: - -``` - cssClass "nodeId1,nodeId2" styleClass; -``` - -A shorter form of adding a class is to attach the classname to the node using the `:::` operator: +**Example definition** ```mermaid-example classDiagram class Animal:::styleClass ``` -Or: - -```mermaid-example -classDiagram - class Animal:::styleClass { - -int sizeInFeet - -canEat() - } -``` - -?> cssClasses cannot be added using this shorthand method at the same time as a relation statement. - -?> Due to limitations with existing markup for class diagrams, it is not currently possible to define css classes within the diagram itself. **_Coming soon!_** - -### Default Styles - -The main styling of the class diagram is done with a preset number of css classes. During rendering these classes are extracted from the file located at src/themes/class.scss. The classes used here are described below: - -| Class | Description | -| ------------------ | ----------------------------------------------------------------- | -| g.classGroup text | Styles for general class text | -| classGroup .title | Styles for general class title | -| g.classGroup rect | Styles for class diagram rectangle | -| g.classGroup line | Styles for class diagram line | -| .classLabel .box | Styles for class label box | -| .classLabel .label | Styles for class label text | -| composition | Styles for composition arrow head and arrow line | -| aggregation | Styles for aggregation arrow head and arrow line(dashed or solid) | -| dependency | Styles for dependency arrow head and arrow line | - -#### Sample stylesheet - -```scss -body { - background: white; -} - -g.classGroup text { - fill: $nodeBorder; - stroke: none; - font-family: 'trebuchet ms', verdana, arial; - font-family: var(--mermaid-font-family); - font-size: 10px; - - .title { - font-weight: bolder; - } -} - -g.classGroup rect { - fill: $nodeBkg; - stroke: $nodeBorder; -} - -g.classGroup line { - stroke: $nodeBorder; - stroke-width: 1; -} - -.classLabel .box { - stroke: none; - stroke-width: 0; - fill: $nodeBkg; - opacity: 0.5; -} - -.classLabel .label { - fill: $nodeBorder; - font-size: 10px; -} - -.relation { - stroke: $nodeBorder; - stroke-width: 1; - fill: none; -} - -@mixin composition { - fill: $nodeBorder; - stroke: $nodeBorder; - stroke-width: 1; -} - -#compositionStart { - @include composition; -} - -#compositionEnd { - @include composition; -} - -@mixin aggregation { - fill: $nodeBkg; - stroke: $nodeBorder; - stroke-width: 1; -} - -#aggregationStart { - @include aggregation; -} - -#aggregationEnd { - @include aggregation; -} - -#dependencyStart { - @include composition; -} - -#dependencyEnd { - @include composition; -} - -#extensionStart { - @include composition; -} - -#extensionEnd { - @include composition; -} -``` +> cssClasses cannot be added using this shorthand method at the same time as a relation statement. ## Configuration -`Coming soon!` +### Members Box + +It is possible to hide the empty members box of a class node. + +This is done by changing the **hideEmptyMembersBox** value of the class diagram configuration. For more information on how to edit the Mermaid configuration see the [configuration page.](https://mermaid.js.org/config/configuration.html) + +```mermaid-example +--- + config: + class: + hideEmptyMembersBox: true +--- +classDiagram + class Duck +``` diff --git a/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md b/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md index ca7cb79c3..f9ed8df9b 100644 --- a/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md +++ b/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md @@ -56,7 +56,7 @@ Mermaid syntax for ER diagrams is compatible with PlantUML, with an extension to Where: -- `first-entity` is the name of an entity. Names must begin with an alphabetic character or an underscore (from v10.5.0+), and may also contain digits and hyphens. +- `first-entity` is the name of an entity. Names support any unicode characters and can include spaces if surrounded by double quotes (e.g. "name with space"). - `relationship` describes the way that both entities inter-relate. See below. - `second-entity` is the name of the other entity. - `relationship-label` describes the relationship from the perspective of the first entity. @@ -71,6 +71,24 @@ This statement can be read as _a property contains one or more rooms, and a room Only the `first-entity` part of a statement is mandatory. This makes it possible to show an entity with no relationships, which can be useful during iterative construction of diagrams. If any other parts of a statement are specified, then all parts are mandatory. +#### Unicode text + +Entity names, relationships, and attributes all support unicode text. + +```mermaid-example +erDiagram + "This ❤ Unicode" +``` + +#### Markdown formatting + +Markdown formatting and text is also supported. + +```mermaid-example +erDiagram + "This **is** _Markdown_" +``` + ### Relationship Syntax The `relationship` part of each statement can be broken down into three sub-components: @@ -100,14 +118,19 @@ Cardinality is a property that describes how many elements of another entity can | 1+ | 1+ | One or more | | zero or more | zero or more | Zero or more | | zero or many | zero or many | Zero or more | -| many(0) | many(1) | Zero or more | +| many(0) | many(0) | Zero or more | | 0+ | 0+ | Zero or more | | only one | only one | Exactly one | | 1 | 1 | Exactly one | ### Identification -Relationships may be classified as either _identifying_ or _non-identifying_ and these are rendered with either solid or dashed lines respectively. This is relevant when one of the entities in question can not have independent existence without the other. For example a firm that insures people to drive cars might need to store data on `NAMED-DRIVER`s. In modelling this we might start out by observing that a `CAR` can be driven by many `PERSON` instances, and a `PERSON` can drive many `CAR`s - both entities can exist without the other, so this is a non-identifying relationship that we might specify in Mermaid as: `PERSON }|..|{ CAR : "driver"`. Note the two dots in the middle of the relationship that will result in a dashed line being drawn between the two entities. But when this many-to-many relationship is resolved into two one-to-many relationships, we observe that a `NAMED-DRIVER` cannot exist without both a `PERSON` and a `CAR` - the relationships become identifying and would be specified using hyphens, which translate to a solid line: +Relationships may be classified as either _identifying_ or _non-identifying_ and these are rendered with either solid or dashed lines respectively. This is relevant when one of the entities in question cannot have independent existence without the other. For example a firm that insures people to drive cars might need to store data on `NAMED-DRIVER`s. In modelling this we might start out by observing that a `CAR` can be driven by many `PERSON` instances, and a `PERSON` can drive many `CAR`s - both entities can exist without the other, so this is a non-identifying relationship that we might specify in Mermaid as: `PERSON }|..|{ CAR : "driver"`. Note the two dots in the middle of the relationship that will result in a dashed line being drawn between the two entities. But when this many-to-many relationship is resolved into two one-to-many relationships, we observe that a `NAMED-DRIVER` cannot exist without both a `PERSON` and a `CAR` - the relationships become identifying and would be specified using hyphens, which translate to a solid line: + +| Value | Alias for | +| :---: | :---------------: | +| -- | _identifying_ | +| .. | _non-identifying_ | **Aliases** @@ -116,10 +139,16 @@ Relationships may be classified as either _identifying_ or _non-identifying_ and | to | _identifying_ | | optionally to | _non-identifying_ | -```mermaid +```mermaid-example erDiagram CAR ||--o{ NAMED-DRIVER : allows - PERSON ||--o{ NAMED-DRIVER : is + PERSON }o..o{ NAMED-DRIVER : is +``` + +```mermaid-example +erDiagram + CAR 1 to zero or more NAMED-DRIVER : allows + PERSON many(0) optionally to 0+ NAMED-DRIVER : is ``` ### Attributes @@ -144,9 +173,9 @@ erDiagram The `type` values must begin with an alphabetic character and may contain digits, hyphens, underscores, parentheses and square brackets. The `name` values follow a similar format to `type`, but may start with an asterisk as another option to indicate an attribute is a primary key. Other than that, there are no restrictions, and there is no implicit set of valid data types. -### Entity Name Aliases (v10.5.0+) +### Entity Name Aliases -An alias can be added to an entity using square brackets. If provided, the alias will be showed in the diagram instead of the entity name. +An alias can be added to an entity using square brackets. If provided, the alias will be showed in the diagram instead of the entity name. Alias names follow all of the same rules as entity names. ```mermaid-example erDiagram @@ -162,7 +191,7 @@ erDiagram #### Attribute Keys and Comments -Attributes may also have a `key` or comment defined. Keys can be `PK`, `FK` or `UK`, for Primary Key, Foreign Key or Unique Key. To specify multiple key constraints on a single attribute, separate them with a comma (e.g., `PK, FK`). A `comment` is defined by double quotes at the end of an attribute. Comments themselves cannot have double-quote characters in them. +Attributes may also have a `key` or comment defined. Keys can be `PK`, `FK` or `UK`, for Primary Key, Foreign Key or Unique Key (markdown formatting and unicode is not supported for keys). To specify multiple key constraints on a single attribute, separate them with a comma (e.g., `PK, FK`). A `comment` is defined by double quotes at the end of an attribute. Comments themselves cannot have double-quote characters in them. ```mermaid-example erDiagram @@ -188,34 +217,225 @@ erDiagram MANUFACTURER only one to zero or more CAR : makes ``` -### Other Things +### Direction -- If you want the relationship label to be more than one word, you must use double quotes around the phrase -- If you don't want a label at all on a relationship, you must use an empty double-quoted string +The direction statement declares the direction of the diagram. -## Styling +This declares that the diagram is oriented from top to bottom (`TB`). This can be reversed to be oriented from bottom to top (`BT`). -### Config options +```mermaid-example +erDiagram + direction TB + CUSTOMER ||--o{ ORDER : places + CUSTOMER { + string name + string custNumber + string sector + } + ORDER ||--|{ LINE-ITEM : contains + ORDER { + int orderNumber + string deliveryAddress + } + LINE-ITEM { + string productCode + int quantity + float pricePerUnit + } +``` -For simple color customization: +This declares that the diagram is oriented from left to right (`LR`). This can be reversed to be oriented from right to left (`RL`). -| Name | Used as | -| :------- | :------------------------------------------------------------------- | -| `fill` | Background color of an entity or attribute | -| `stroke` | Border color of an entity or attribute, line color of a relationship | +```mermaid-example +erDiagram + direction LR + CUSTOMER ||--o{ ORDER : places + CUSTOMER { + string name + string custNumber + string sector + } + ORDER ||--|{ LINE-ITEM : contains + ORDER { + int orderNumber + string deliveryAddress + } + LINE-ITEM { + string productCode + int quantity + float pricePerUnit + } +``` -### Classes used +Possible diagram orientations are: -The following CSS class selectors are available for richer styling: +- TB - Top to bottom +- BT - Bottom to top +- RL - Right to left +- LR - Left to right -| Selector | Description | -| :------------------------- | :---------------------------------------------------- | -| `.er.attributeBoxEven` | The box containing attributes on even-numbered rows | -| `.er.attributeBoxOdd` | The box containing attributes on odd-numbered rows | -| `.er.entityBox` | The box representing an entity | -| `.er.entityLabel` | The label for an entity | -| `.er.relationshipLabel` | The label for a relationship | -| `.er.relationshipLabelBox` | The box surrounding a relationship label | -| `.er.relationshipLine` | The line representing a relationship between entities | +### Styling a node + +It is possible to apply specific styles such as a thicker border or a different background color to a node. + +```mermaid-example +erDiagram + id1||--||id2 : label + style id1 fill:#f9f,stroke:#333,stroke-width:4px + style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 +``` + +It is also possible to attach styles to a list of nodes in one statement: + +``` + style nodeId1,nodeId2 styleList +``` + +#### Classes + +More convenient than defining the style every time is to define a class of styles and attach this class to the nodes that +should have a different look. + +A class definition looks like the example below: + +``` + classDef className fill:#f9f,stroke:#333,stroke-width:4px +``` + +It is also possible to define multiple classes in one statement: + +``` + classDef firstClassName,secondClassName font-size:12pt +``` + +Attachment of a class to a node is done as per below: + +``` + class nodeId1 className +``` + +It is also possible to attach a class to a list of nodes in one statement: + +``` + class nodeId1,nodeId2 className +``` + +Multiple classes can be attached at the same time as well: + +``` + class nodeId1,nodeId2 className1,className2 +``` + +A shorter form of adding a class is to attach the classname to the node using the `:::`operator as per below: + +```mermaid-example +erDiagram + direction TB + CAR:::someclass { + string registrationNumber + string make + string model + } + PERSON:::someclass { + string firstName + string lastName + int age + } + HOUSE:::someclass + + classDef someclass fill:#f96 +``` + +This form can be used when declaring relationships between entities: + +```mermaid-example +erDiagram + CAR { + string registrationNumber + string make + string model + } + PERSON { + string firstName + string lastName + int age + } + PERSON:::foo ||--|| CAR : owns + PERSON o{--|| HOUSE:::bar : has + + classDef foo stroke:#f00 + classDef bar stroke:#0f0 + classDef foobar stroke:#00f +``` + +Similar to the class statement, the shorthand syntax can also apply multiple classes at once: + +``` + nodeId:::className1,className2 +``` + +### Default class + +If a class is named default it will be assigned to all classes without specific class definitions. + +``` + classDef default fill:#f9f,stroke:#333,stroke-width:4px; +``` + +> **Note:** Custom styles from style or other class statements take priority and will overwrite the default styles. (e.g. The `default` class gives nodes a background color of pink but the `blue` class will give that node a background color of blue if applied.) + +```mermaid-example +erDiagram + CAR { + string registrationNumber + string make + string model + } + PERSON { + string firstName + string lastName + int age + } + PERSON:::foo ||--|| CAR : owns + PERSON o{--|| HOUSE:::bar : has + + classDef default fill:#f9f,stroke-width:4px + classDef foo stroke:#f00 + classDef bar stroke:#0f0 + classDef foobar stroke:#00f +``` + +## Configuration + +### Layout + +The layout of the diagram is handled by [`render()`](../config/setup/mermaid/interfaces/Mermaid.md#render). The default layout is dagre. + +For larger or more-complex diagrams, you can alternatively apply the ELK (Eclipse Layout Kernel) layout using your YAML frontmatter's `config`. For more information, see [Customizing ELK Layout](../intro/syntax-reference.md#customizing-elk-layout). + +```yaml +--- +config: + layout: elk +--- +``` + +Your Mermaid code should be similar to the following: + +```mermaid-example +--- +title: Order example +config: + layout: elk +--- +erDiagram + CUSTOMER ||--o{ ORDER : places + ORDER ||--|{ LINE-ITEM : contains + CUSTOMER }|..|{ DELIVERY-ADDRESS : uses +``` + +```note +Note that the site needs to use mermaid version 9.4+ for this to work and have this featured enabled in the lazy-loading configuration. +``` diff --git a/packages/mermaid/src/docs/syntax/examples.md b/packages/mermaid/src/docs/syntax/examples.md index 64e85815f..48af4dc77 100644 --- a/packages/mermaid/src/docs/syntax/examples.md +++ b/packages/mermaid/src/docs/syntax/examples.md @@ -141,7 +141,7 @@ sequenceDiagram ## A commit flow diagram. -```mermaid +```mermaid-example gitGraph: commit "Ashish" branch newbranch diff --git a/packages/mermaid/src/docs/syntax/flowchart.md b/packages/mermaid/src/docs/syntax/flowchart.md index ba0e9ce9e..5d9dce324 100644 --- a/packages/mermaid/src/docs/syntax/flowchart.md +++ b/packages/mermaid/src/docs/syntax/flowchart.md @@ -64,7 +64,11 @@ flowchart LR Use double quotes and backticks "\` text \`" to enclose the markdown text. ```mermaid-example -%%{init: {"flowchart": {"htmlLabels": false}} }%% +--- +config: + flowchart: + htmlLabels: false +--- flowchart LR markdown["`This **is** _Markdown_`"] newLines["`Line1 @@ -194,6 +198,404 @@ flowchart TD id1(((This is the text in the circle))) ``` +## Expanded Node Shapes in Mermaid Flowcharts (v11.3.0+) + +Mermaid introduces 30 new shapes to enhance the flexibility and precision of flowchart creation. These new shapes provide more options to represent processes, decisions, events, data storage visually, and other elements within your flowcharts, improving clarity and semantic meaning. + +New Syntax for Shape Definition + +Mermaid now supports a general syntax for defining shape types to accommodate the growing number of shapes. This syntax allows you to assign specific shapes to nodes using a clear and flexible format: + +``` +A@{ shape: rect } +``` + +This syntax creates a node A as a rectangle. It renders in the same way as `A["A"]`, or `A`. + +### Complete List of New Shapes + +Below is a comprehensive list of the newly introduced shapes and their corresponding semantic meanings, short names, and aliases: + + + +### Example Flowchart with New Shapes + +Here’s an example flowchart that utilizes some of the newly introduced shapes: + +```mermaid-example +flowchart RL + A@{ shape: manual-file, label: "File Handling"} + B@{ shape: manual-input, label: "User Input"} + C@{ shape: docs, label: "Multiple Documents"} + D@{ shape: procs, label: "Process Automation"} + E@{ shape: paper-tape, label: "Paper Records"} +``` + +### Process + +```mermaid-example +flowchart TD + A@{ shape: rect, label: "This is a process" } +``` + +### Event + +```mermaid-example +flowchart TD + A@{ shape: rounded, label: "This is an event" } +``` + +### Terminal Point (Stadium) + +```mermaid-example +flowchart TD + A@{ shape: stadium, label: "Terminal point" } +``` + +### Subprocess + +```mermaid-example +flowchart TD + A@{ shape: subproc, label: "This is a subprocess" } +``` + +### Database (Cylinder) + +```mermaid-example +flowchart TD + A@{ shape: cyl, label: "Database" } +``` + +### Start (Circle) + +```mermaid-example +flowchart TD + A@{ shape: circle, label: "Start" } +``` + +### Odd + +```mermaid-example +flowchart TD + A@{ shape: odd, label: "Odd shape" } +``` + +### Decision (Diamond) + +```mermaid-example +flowchart TD + A@{ shape: diamond, label: "Decision" } +``` + +### Prepare Conditional (Hexagon) + +```mermaid-example +flowchart TD + A@{ shape: hex, label: "Prepare conditional" } +``` + +### Data Input/Output (Lean Right) + +```mermaid-example +flowchart TD + A@{ shape: lean-r, label: "Input/Output" } +``` + +### Data Input/Output (Lean Left) + +```mermaid-example +flowchart TD + A@{ shape: lean-l, label: "Output/Input" } +``` + +### Priority Action (Trapezoid Base Bottom) + +```mermaid-example +flowchart TD + A@{ shape: trap-b, label: "Priority action" } +``` + +### Manual Operation (Trapezoid Base Top) + +```mermaid-example +flowchart TD + A@{ shape: trap-t, label: "Manual operation" } +``` + +### Stop (Double Circle) + +```mermaid-example +flowchart TD + A@{ shape: dbl-circ, label: "Stop" } +``` + +### Text Block + +```mermaid-example +flowchart TD + A@{ shape: text, label: "This is a text block" } +``` + +### Card (Notched Rectangle) + +```mermaid-example +flowchart TD + A@{ shape: notch-rect, label: "Card" } +``` + +### Lined/Shaded Process + +```mermaid-example +flowchart TD + A@{ shape: lin-rect, label: "Lined process" } +``` + +### Start (Small Circle) + +```mermaid-example +flowchart TD + A@{ shape: sm-circ, label: "Small start" } +``` + +### Stop (Framed Circle) + +```mermaid-example +flowchart TD + A@{ shape: framed-circle, label: "Stop" } +``` + +### Fork/Join (Long Rectangle) + +```mermaid-example +flowchart TD + A@{ shape: fork, label: "Fork or Join" } +``` + +### Collate (Hourglass) + +```mermaid-example +flowchart TD + A@{ shape: hourglass, label: "Collate" } +``` + +### Comment (Curly Brace) + +```mermaid-example +flowchart TD + A@{ shape: comment, label: "Comment" } +``` + +### Comment Right (Curly Brace Right) + +```mermaid-example +flowchart TD + A@{ shape: brace-r, label: "Comment" } +``` + +### Comment with braces on both sides + +```mermaid-example +flowchart TD + A@{ shape: braces, label: "Comment" } +``` + +### Com Link (Lightning Bolt) + +```mermaid-example +flowchart TD + A@{ shape: bolt, label: "Communication link" } +``` + +### Document + +```mermaid-example +flowchart TD + A@{ shape: doc, label: "Document" } +``` + +### Delay (Half-Rounded Rectangle) + +```mermaid-example +flowchart TD + A@{ shape: delay, label: "Delay" } +``` + +### Direct Access Storage (Horizontal Cylinder) + +```mermaid-example +flowchart TD + A@{ shape: das, label: "Direct access storage" } +``` + +### Disk Storage (Lined Cylinder) + +```mermaid-example +flowchart TD + A@{ shape: lin-cyl, label: "Disk storage" } +``` + +### Display (Curved Trapezoid) + +```mermaid-example +flowchart TD + A@{ shape: curv-trap, label: "Display" } +``` + +### Divided Process (Divided Rectangle) + +```mermaid-example +flowchart TD + A@{ shape: div-rect, label: "Divided process" } +``` + +### Extract (Small Triangle) + +```mermaid-example +flowchart TD + A@{ shape: tri, label: "Extract" } +``` + +### Internal Storage (Window Pane) + +```mermaid-example +flowchart TD + A@{ shape: win-pane, label: "Internal storage" } +``` + +### Junction (Filled Circle) + +```mermaid-example +flowchart TD + A@{ shape: f-circ, label: "Junction" } +``` + +### Lined Document + +```mermaid-example +flowchart TD + A@{ shape: lin-doc, label: "Lined document" } +``` + +### Loop Limit (Notched Pentagon) + +```mermaid-example +flowchart TD + A@{ shape: notch-pent, label: "Loop limit" } +``` + +### Manual File (Flipped Triangle) + +```mermaid-example +flowchart TD + A@{ shape: flip-tri, label: "Manual file" } +``` + +### Manual Input (Sloped Rectangle) + +```mermaid-example +flowchart TD + A@{ shape: sl-rect, label: "Manual input" } +``` + +### Multi-Document (Stacked Document) + +```mermaid-example +flowchart TD + A@{ shape: docs, label: "Multiple documents" } +``` + +### Multi-Process (Stacked Rectangle) + +```mermaid-example +flowchart TD + A@{ shape: processes, label: "Multiple processes" } +``` + +### Paper Tape (Flag) + +```mermaid-example +flowchart TD + A@{ shape: flag, label: "Paper tape" } +``` + +### Stored Data (Bow Tie Rectangle) + +```mermaid-example +flowchart TD + A@{ shape: bow-rect, label: "Stored data" } +``` + +### Summary (Crossed Circle) + +```mermaid-example +flowchart TD + A@{ shape: cross-circ, label: "Summary" } +``` + +### Tagged Document + +```mermaid-example +flowchart TD + A@{ shape: tag-doc, label: "Tagged document" } +``` + +### Tagged Process (Tagged Rectangle) + +```mermaid-example +flowchart TD + A@{ shape: tag-rect, label: "Tagged process" } +``` + +## Special shapes in Mermaid Flowcharts (v11.3.0+) + +Mermaid also introduces 2 special shapes to enhance your flowcharts: **icon** and **image**. These shapes allow you to include icons and images directly within your flowcharts, providing more visual context and clarity. + +### Icon Shape + +You can use the `icon` shape to include an icon in your flowchart. To use icons, you need to register the icon pack first. Follow the instructions to [add custom icons](../config/icons.md). The syntax for defining an icon shape is as follows: + +```mermaid-example +flowchart TD + A@{ icon: "fa:user", form: "square", label: "User Icon", pos: "t", h: 60 } +``` + +### Parameters + +- **icon**: The name of the icon from the registered icon pack. +- **form**: Specifies the background shape of the icon. If not defined there will be no background to icon. Options include: + - `square` + - `circle` + - `rounded` +- **label**: The text label associated with the icon. This can be any string. If not defined, no label will be displayed. +- **pos**: The position of the label. If not defined label will default to bottom of icon. Possible values are: + - `t` + - `b` +- **h**: The height of the icon. If not defined this will default to 48 which is minimum. + +### Image Shape + +You can use the `image` shape to include an image in your flowchart. The syntax for defining an image shape is as follows: + +```mermaid-example +flowchart TD + A@{ img: "https://example.com/image.png", label: "Image Label", pos: "t", w: 60, h: 60, constraint: "off" } +``` + +### Parameters + +- **img**: The URL of the image to be displayed. +- **label**: The text label associated with the image. This can be any string. If not defined, no label will be displayed. +- **pos**: The position of the label. If not defined, the label will default to the bottom of the image. Possible values are: + - `t` + - `b` +- **w**: The width of the image. If not defined, this will default to the natural width of the image. +- **h**: The height of the image. If not defined, this will default to the natural height of the image. +- **constraint**: Determines if the image should constrain the node size. This setting also ensures the image maintains its original aspect ratio, adjusting the height (`h`) accordingly to the width (`w`). If not defined, this will default to `off` Possible values are: + - `on` + - `off` + +These new shapes provide additional flexibility and visual appeal to your flowcharts, making them more informative and engaging. + ## Links between nodes Nodes can be connected with links/edges. It is possible to have different types of links or attach a text string to a link. @@ -313,6 +715,67 @@ flowchart TB B --> D ``` +### Attaching an ID to Edges + +Mermaid now supports assigning IDs to edges, similar to how IDs and metadata can be attached to nodes. This feature lays the groundwork for more advanced styling, classes, and animation capabilities on edges. + +**Syntax:** + +To give an edge an ID, prepend the edge syntax with the ID followed by an `@` character. For example: + +```mermaid +flowchart LR + A e1@--> B +``` + +In this example, `e1` is the ID of the edge connecting `A` to `B`. You can then use this ID in later definitions or style statements, just like with nodes. + +### Turning an Animation On + +Once you have assigned an ID to an edge, you can turn on animations for that edge by defining the edge’s properties: + +```mermaid +flowchart LR + A e1@==> B + e1@{ animate: true } +``` + +This tells Mermaid that the edge `e1` should be animated. + +### Selecting Type of Animation + +In the initial version, two animation speeds are supported: `fast` and `slow`. Selecting a specific animation type is a shorthand for enabling animation and setting the animation speed in one go. + +**Examples:** + +```mermaid +flowchart LR + A e1@--> B + e1@{ animation: fast } +``` + +This is equivalent to `{ animate: true, animation: fast }`. + +### Using classDef Statements for Animations + +You can also animate edges by assigning a class to them and then defining animation properties in a `classDef` statement. For example: + +```mermaid +flowchart LR + A e1@--> B + classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite; + class e1 animate +``` + +In this snippet: + +- `e1@-->` creates an edge with ID `e1`. +- `classDef animate` defines a class named `animate` with styling and animation properties. +- `class e1 animate` applies the `animate` class to the edge `e1`. + +**Note on Escaping Commas:** +When setting the `stroke-dasharray` property, remember to escape commas as `\,` since commas are used as delimiters in Mermaid’s style definitions. + ## New arrow types There are new types of arrows supported: @@ -517,7 +980,10 @@ flowchart LR The "Markdown Strings" feature enhances flowcharts and mind maps by offering a more versatile string type, which supports text formatting options such as bold and italics, and automatically wraps text within labels. ```mermaid-example -%%{init: {"flowchart": {"htmlLabels": false}} }%% +config: + flowchart: + htmlLabels: false +--- flowchart LR subgraph "One" a("`The **cat** @@ -567,7 +1033,7 @@ Examples of tooltip usage below: ```html @@ -588,7 +1054,7 @@ flowchart LR > **Success** The tooltip functionality and the ability to link to urls are available from version 0.5.2. -?> Due to limitations with how Docsify handles JavaScript callback functions, an alternate working demo for the above code can be viewed at [this jsfiddle](https://jsfiddle.net/Ogglas/2o73vdez/7). +?> Due to limitations with how Docsify handles JavaScript callback functions, an alternate working demo for the above code can be viewed at [this jsfiddle](https://jsfiddle.net/yk4h7qou/2/). Links are opened in the same browser tab/window by default. It is possible to change this by adding a link target to the click definition (`_self`, `_blank`, `_parent` and `_top` are supported): @@ -620,7 +1086,7 @@ Beginner's tip—a full example using interactive links in a html context:
``` -You can also refer the implementation in the live editor [here](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done. +You can also refer the [implementation in the live editor](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done. Not Urgent y-axis Not Important --> "Important ❤" @@ -146,7 +153,7 @@ Points can either be styled directly or with defined shared classes ```md Point A: [0.9, 0.0] radius: 12 Point B: [0.8, 0.1] color: #ff3300, radius: 10 -Point C: [0.7, 0.2] radius: 25, color: #00ff33, stroke-color: #10f0f0 +Point C: [0.7, 0.2] radius: 25, color: #00ff33, stroke-color: #10f0f0 Point D: [0.6, 0.3] radius: 15, stroke-color: #00ff0f, stroke-width: 5px ,color: #ff33f0 ``` diff --git a/packages/mermaid/src/docs/syntax/radar.md b/packages/mermaid/src/docs/syntax/radar.md new file mode 100644 index 000000000..124cebb24 --- /dev/null +++ b/packages/mermaid/src/docs/syntax/radar.md @@ -0,0 +1,210 @@ +# Radar Diagram (v11.6.0+) + +## Introduction + +A radar diagram is a simple way to plot low-dimensional data in a circular format. + +It is also known as a **radar chart**, **spider chart**, **star chart**, **cobweb chart**, **polar chart**, or **Kiviat diagram**. + +## Usage + +This diagram type is particularly useful for developers, data scientists, and engineers who require a clear and concise way to represent data in a circular format. + +It is commonly used to graphically summarize and compare the performance of multiple entities across multiple dimensions. + +## Syntax + +```md +radar-beta +axis A, B, C, D, E +curve c1{1,2,3,4,5} +curve c2{5,4,3,2,1} +... More Fields ... +``` + +## Examples + +```mermaid-example +--- +title: "Grades" +--- +radar-beta + axis m["Math"], s["Science"], e["English"] + axis h["History"], g["Geography"], a["Art"] + curve a["Alice"]{85, 90, 80, 70, 75, 90} + curve b["Bob"]{70, 75, 85, 80, 90, 85} + + max 100 + min 0 +``` + +```mermaid-example +radar-beta + title Restaurant Comparison + axis food["Food Quality"], service["Service"], price["Price"] + axis ambiance["Ambiance"], + + curve a["Restaurant A"]{4, 3, 2, 4} + curve b["Restaurant B"]{3, 4, 3, 3} + curve c["Restaurant C"]{2, 3, 4, 2} + curve d["Restaurant D"]{2, 2, 4, 3} + + graticule polygon + max 5 + +``` + +## Details of Syntax + +### Title + +`title`: The title is an optional field that allows to render a title at the top of the radar diagram. + +``` +radar-beta + title Title of the Radar Diagram + ... +``` + +### Axis + +`axis`: The axis keyword is used to define the axes of the radar diagram. + +Each axis is represented by an ID and an optional label. + +Multiple axes can be defined in a single line. + +``` +radar-beta + axis id1["Label1"] + axis id2["Label2"], id3["Label3"] + ... +``` + +### Curve + +`curve`: The curve keyword is used to define the data points for a curve in the radar diagram. + +Each curve is represented by an ID, an optional label, and a list of values. + +Values can be defined by a list of numbers or a list of key-value pairs. If key-value pairs are used, the key represents the axis ID and the value represents the data point. Else, the data points are assumed to be in the order of the axes defined. + +Multiple curves can be defined in a single line. + +``` +radar-beta + axis axis1, axis2, axis3 + curve id1["Label1"]{1, 2, 3} + curve id2["Label2"]{4, 5, 6}, id3{7, 8, 9} + curve id4{ axis3: 30, axis1: 20, axis2: 10 } + ... +``` + +### Options + +- `showLegend`: The showLegend keyword is used to show or hide the legend in the radar diagram. The legend is shown by default. +- `max`: The maximum value for the radar diagram. This is used to scale the radar diagram. If not provided, the maximum value is calculated from the data points. +- `min`: The minimum value for the radar diagram. This is used to scale the radar diagram. If not provided, the minimum value is `0`. +- `graticule`: The graticule keyword is used to define the type of graticule to be rendered in the radar diagram. The graticule can be `circle` or `polygon`. If not provided, the default graticule is `circle`. +- `ticks`: The ticks keyword is used to define the number of ticks on the graticule. It is the number of concentric circles or polygons drawn to indicate the scale of the radar diagram. If not provided, the default number of ticks is `5`. + +``` +radar-beta + ... + showLegend true + max 100 + min 0 + graticule circle + ticks 5 + ... +``` + +## Configuration + +Please refer to the [configuration](/config/schema-docs/config-defs-radar-diagram-config.html) guide for details. + +| Parameter | Description | Default Value | +| --------------- | ---------------------------------------- | ------------- | +| width | Width of the radar diagram | `600` | +| height | Height of the radar diagram | `600` | +| marginTop | Top margin of the radar diagram | `50` | +| marginBottom | Bottom margin of the radar diagram | `50` | +| marginLeft | Left margin of the radar diagram | `50` | +| marginRight | Right margin of the radar diagram | `50` | +| axisScaleFactor | Scale factor for the axis | `1` | +| axisLabelFactor | Factor to adjust the axis label position | `1.05` | +| curveTension | Tension for the rounded curves | `0.17` | + +## Theme Variables + +### Global Theme Variables + +```note +The default values for these variables depend on the theme used. To override the default values, set the desired values in the themeVariables section of the configuration: + +--- +config: + themeVariables: + cScale0: "#FF0000" + cScale1: "#00FF00" +--- +``` + +Radar charts support the color scales `cScale${i}` where `i` is a number from `0` to the theme's maximum number of colors in its color scale. Usually, the maximum number of colors is `12`. + +| Property | Description | +| ---------- | ------------------------------ | +| fontSize | Font size of the title | +| titleColor | Color of the title | +| cScale${i} | Color scale for the i-th curve | + +### Radar Style Options + +```note +Specific variables for radar resides inside the `radar` key. To set the radar style options, use this syntax. + +--- +config: + themeVariables: + radar: + axisColor: "#FF0000" +--- +``` + +| Property | Description | Default Value | +| -------------------- | ---------------------------- | ------------- | +| axisColor | Color of the axis lines | `black` | +| axisStrokeWidth | Width of the axis lines | `1` | +| axisLabelFontSize | Font size of the axis labels | `12px` | +| curveOpacity | Opacity of the curves | `0.7` | +| curveStrokeWidth | Width of the curves | `2` | +| graticuleColor | Color of the graticule | `black` | +| graticuleOpacity | Opacity of the graticule | `0.5` | +| graticuleStrokeWidth | Width of the graticule | `1` | +| legendBoxSize | Size of the legend box | `10` | +| legendFontSize | Font size of the legend | `14px` | + +## Example on config and theme + +```mermaid-example +--- +config: + radar: + axisScaleFactor: 0.25 + curveTension: 0.1 + theme: base + themeVariables: + cScale0: "#FF0000" + cScale1: "#00FF00" + cScale2: "#0000FF" + radar: + curveOpacity: 0 +--- +radar-beta + axis A, B, C, D, E + curve c1{1,2,3,4,5} + curve c2{5,4,3,2,1} + curve c3{3,3,3,3,3} +``` + + diff --git a/packages/mermaid/src/docs/syntax/requirementDiagram.md b/packages/mermaid/src/docs/syntax/requirementDiagram.md index be46b73cc..06e7ac29e 100644 --- a/packages/mermaid/src/docs/syntax/requirementDiagram.md +++ b/packages/mermaid/src/docs/syntax/requirementDiagram.md @@ -27,7 +27,7 @@ There are three types of components to a requirement diagram: requirement, eleme The grammar for defining each is defined below. Words denoted in angle brackets, such as ``, are enumerated keywords that have options elaborated in a table. `user_defined_...` is use in any place where user input is expected. -An important note on user text: all input can be surrounded in quotes or not. For example, both `Id: "here is an example"` and `Id: here is an example` are both valid. However, users must be careful with unquoted input. The parser will fail if another keyword is detected. +An important note on user text: all input can be surrounded in quotes or not. For example, both `id: "here is an example"` and `id: here is an example` are both valid. However, users must be careful with unquoted input. The parser will fail if another keyword is detected. ### Requirement @@ -61,6 +61,26 @@ element user_defined_name { } ``` +### Markdown Formatting + +In places where user defined text is possible (like names, requirement text, element docref, etc.), you can: + +- Surround the text in quotes: `"example text"` +- Use markdown formatting inside quotes: `"**bold text** and *italics*"` + +Example: + +```mermaid-example +requirementDiagram + +requirement "__test_req__" { + id: 1 + text: "*italicized text* **bold text**" + risk: high + verifymethod: test +} +``` + ### Relationship Relationships are comprised of a source node, destination node, and relationship type. @@ -157,4 +177,140 @@ This example uses all features of the diagram. test_req <- copies - test_entity2 ``` +## Direction + +The diagram can be rendered in different directions using the `direction` statement. Valid values are: + +- `TB` - Top to Bottom (default) +- `BT` - Bottom to Top +- `LR` - Left to Right +- `RL` - Right to Left + +Example: + +```mermaid-example +requirementDiagram + +direction LR + +requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test +} + +element test_entity { + type: simulation +} + +test_entity - satisfies -> test_req +``` + +## Styling + +Requirements and elements can be styled using direct styling or classes. As a rule of thumb, when applying styles or classes, it accepts a list of requirement or element names and a list of class names allowing multiple assignments at a time (The only exception is the shorthand syntax `:::` which can assign multiple classes but only to one requirement or element at a time). + +### Direct Styling + +Use the `style` keyword to apply CSS styles directly: + +```mermaid-example +requirementDiagram + +requirement test_req { + id: 1 + text: styling example + risk: low + verifymethod: test +} + +element test_entity { + type: simulation +} + +style test_req fill:#ffa,stroke:#000, color: green +style test_entity fill:#f9f,stroke:#333, color: blue +``` + +### Class Definitions + +Define reusable styles using `classDef`: + +```mermaid-example +requirementDiagram + +requirement test_req { + id: 1 + text: "class styling example" + risk: low + verifymethod: test +} + +element test_entity { + type: simulation +} + +classDef important fill:#f96,stroke:#333,stroke-width:4px +classDef test fill:#ffa,stroke:#000 +``` + +### Default class + +If a class is named default it will be applied to all nodes. Specific styles and classes should be defined afterwards to override the applied default styling. + +``` +classDef default fill:#f9f,stroke:#333,stroke-width:4px; +``` + +### Applying Classes + +Classes can be applied in two ways: + +1. Using the `class` keyword: + +``` +class test_req,test_entity important +``` + +2. Using the shorthand syntax with `:::` either during the definition or afterwards: + +``` +requirement test_req:::important { + id: 1 + text: class styling example + risk: low + verifymethod: test +} +``` + +``` +element test_elem { +} + +test_elem:::myClass +``` + +### Combined Example + +```mermaid-example +requirementDiagram + +requirement test_req:::important { + id: 1 + text: "class styling example" + risk: low + verifymethod: test +} + +element test_entity { + type: simulation +} + +classDef important font-weight:bold + +class test_entity important +style test_entity fill:#f9f,stroke:#333 +``` + diff --git a/packages/mermaid/src/docs/syntax/sequenceDiagram.md b/packages/mermaid/src/docs/syntax/sequenceDiagram.md index 4fc25bd12..3087eb743 100644 --- a/packages/mermaid/src/docs/syntax/sequenceDiagram.md +++ b/packages/mermaid/src/docs/syntax/sequenceDiagram.md @@ -105,6 +105,9 @@ end box rgb(33,66,99) ... actors ... end +box rgba(33,66,99,0.5) +... actors ... +end ``` ```note @@ -141,18 +144,20 @@ Messages can be of two displayed either solid or with a dotted line. [Actor][Arrow][Actor]:Message text ``` -There are six types of arrows currently supported: +There are ten types of arrows currently supported: -| Type | Description | -| ------ | ------------------------------------------------ | -| `->` | Solid line without arrow | -| `-->` | Dotted line without arrow | -| `->>` | Solid line with arrowhead | -| `-->>` | Dotted line with arrowhead | -| `-x` | Solid line with a cross at the end | -| `--x` | Dotted line with a cross at the end. | -| `-)` | Solid line with an open arrow at the end (async) | -| `--)` | Dotted line with a open arrow at the end (async) | +| Type | Description | +| -------- | ---------------------------------------------------- | +| `->` | Solid line without arrow | +| `-->` | Dotted line without arrow | +| `->>` | Solid line with arrowhead | +| `-->>` | Dotted line with arrowhead | +| `<<->>` | Solid line with bidirectional arrowheads (v11.0.0+) | +| `<<-->>` | Dotted line with bidirectional arrowheads (v11.0.0+) | +| `-x` | Solid line with a cross at the end | +| `--x` | Dotted line with a cross at the end | +| `-)` | Solid line with an open arrow at the end (async) | +| `--)` | Dotted line with a open arrow at the end (async) | ## Activations @@ -205,11 +210,22 @@ sequenceDiagram Note over Alice,John: A typical interaction ``` -It is also possible to add a line break (applies to text input in general): +## Line breaks + +Line break can be added to Note and Message: ```mermaid-example sequenceDiagram - Alice->John: Hello John, how are you? + Alice->John: Hello John,
how are you? + Note over Alice,John: A typical interaction
But now in two lines +``` + +Line breaks in Actor names requires aliases: + +```mermaid-example +sequenceDiagram + participant Alice as Alice
Johnson + Alice->John: Hello John,
how are you? Note over Alice,John: A typical interaction
But now in two lines ``` @@ -381,6 +397,12 @@ sequenceDiagram It is possible to highlight flows by providing colored background rects. This is done by the notation +``` +rect COLOR +... content ... +end +``` + The colors are defined using rgb and rgba syntax. ``` @@ -420,7 +442,7 @@ sequenceDiagram Comments can be entered within a sequence diagram, which will be ignored by the parser. Comments need to be on their own line, and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any diagram syntax -```mermaid +```mermaid-example sequenceDiagram Alice->>John: Hello John, how are you? %% this is a comment diff --git a/packages/mermaid/src/docs/syntax/stateDiagram.md b/packages/mermaid/src/docs/syntax/stateDiagram.md index d2b7282e4..ca95bd4bb 100644 --- a/packages/mermaid/src/docs/syntax/stateDiagram.md +++ b/packages/mermaid/src/docs/syntax/stateDiagram.md @@ -98,7 +98,7 @@ In a real world use of state diagrams you often end up with diagrams that are mu have several internal states. These are called composite states in this terminology. In order to define a composite state you need to use the state keyword followed by an id and the body of the composite -state between \{\}. See the example below: +state between \{\}. You can name a composite state on a separate line just like a simple state. See the example below: ```mermaid-example stateDiagram-v2 @@ -107,6 +107,14 @@ stateDiagram-v2 [*] --> second second --> [*] } + + [*] --> NamedComposite + NamedComposite: Another Composite + state NamedComposite { + [*] --> namedSimple + namedSimple --> [*] + namedSimple: Another simple + } ``` You can do this in several layers: @@ -152,7 +160,7 @@ stateDiagram-v2 } ``` -_You can not define transitions between internal states belonging to different composite states_ +_You cannot define transitions between internal states belonging to different composite states_ ## Choice @@ -280,8 +288,8 @@ a _[valid CSS property name](https://www.w3.org/TR/CSS/#properties)_ followed by Here is an example of a classDef with just one property-value pair: -``` - classDef movement font-style:italic; +```txt +classDef movement font-style:italic; ``` where @@ -293,8 +301,8 @@ If you want to have more than one _property-value pair_ then you put a comma (`, Here is an example with three property-value pairs: -``` - classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow +```txt +classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow ``` where @@ -319,7 +327,7 @@ There are two ways to apply a `classDef` style to a state: A `class` statement tells Mermaid to apply the named classDef to one or more classes. The form is: ```txt - class [one or more state names, separated by commas] [name of a style defined with classDef] +class [one or more state names, separated by commas] [name of a style defined with classDef] ``` Here is an example applying the `badBadEvent` style to a state named `Crash`: diff --git a/packages/mermaid/src/docs/syntax/timeline.md b/packages/mermaid/src/docs/syntax/timeline.md index 165fd6260..26e30f80b 100644 --- a/packages/mermaid/src/docs/syntax/timeline.md +++ b/packages/mermaid/src/docs/syntax/timeline.md @@ -12,7 +12,7 @@ timeline 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter ``` @@ -51,7 +51,7 @@ timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter ``` @@ -134,7 +134,7 @@ However, if there is no section defined, then we have two possibilities: title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter ``` @@ -160,12 +160,18 @@ mermaid.initialize({ let us look at same example, where we have disabled the multiColor option. ```mermaid-example - %%{init: { 'logLevel': 'debug', 'theme': 'base', 'timeline': {'disableMulticolor': true}}}%% +--- +config: + logLevel: 'debug' + theme: 'base' + timeline: + disableMulticolor: true +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter ``` @@ -184,16 +190,22 @@ Example: Now let's override the default values for the `cScale0` to `cScale2` variables: ```mermaid-example - %%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': { - 'cScale0': '#ff0000', 'cScaleLabel0': '#ffffff', - 'cScale1': '#00ff00', - 'cScale2': '#0000ff', 'cScaleLabel2': '#ffffff' - } } }%% +--- +config: + logLevel: 'debug' + theme: 'default' + themeVariables: + cScale0: '#ff0000' + cScaleLabel0: '#ffffff' + cScale1: '#00ff00' + cScale2: '#0000ff' + cScaleLabel2: '#ffffff' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -205,7 +217,7 @@ See how the colors are changed to the values specified in the theme variables. ## Themes -Mermaid supports a bunch of pre-defined themes which you can use to find the right one for you. PS: you can actually override an existing theme's variable to get your own custom theme going. Learn more about theming your diagram [here](../config/theming.md). +Mermaid supports a bunch of pre-defined themes which you can use to find the right one for you. PS: you can actually override an existing theme's variable to get your own custom theme going. Learn more about [theming your diagram](../config/theming.md). The following are the different pre-defined theme options: @@ -221,12 +233,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ### Base Theme ```mermaid-example -%%{init: { 'logLevel': 'debug', 'theme': 'base' } }%% +--- +config: + logLevel: 'debug' + theme: 'base' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -236,12 +252,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ### Forest Theme ```mermaid-example -%%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%% +--- +config: + logLevel: 'debug' + theme: 'forest' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -251,12 +271,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ### Dark Theme ```mermaid-example -%%{init: { 'logLevel': 'debug', 'theme': 'dark' } }%% +--- +config: + logLevel: 'debug' + theme: 'dark' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -266,12 +290,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ### Default Theme ```mermaid-example -%%{init: { 'logLevel': 'debug', 'theme': 'default' } }%% +--- +config: + logLevel: 'debug' + theme: 'default' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -281,12 +309,16 @@ Let's put them to use, and see how our sample diagram looks in different themes: ### Neutral Theme ```mermaid-example -%%{init: { 'logLevel': 'debug', 'theme': 'neutral' } }%% +--- +config: + logLevel: 'debug' + theme: 'neutral' +--- timeline title History of Social Media Platform 2002 : LinkedIn 2004 : Facebook : Google - 2005 : Youtube + 2005 : YouTube 2006 : Twitter 2007 : Tumblr 2008 : Instagram @@ -305,4 +337,4 @@ You can use this method to add mermaid including the timeline diagram to a web p ``` -You can also refer the implementation in the live editor [here](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done. +You can also refer the [implementation in the live editor](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done. diff --git a/packages/mermaid/src/docs/syntax/xyChart.md b/packages/mermaid/src/docs/syntax/xyChart.md index e6e969462..7de3d4144 100644 --- a/packages/mermaid/src/docs/syntax/xyChart.md +++ b/packages/mermaid/src/docs/syntax/xyChart.md @@ -95,17 +95,18 @@ xychart-beta ## Chart Configurations -| Parameter | Description | Default value | -| ------------------------ | ---------------------------------------------- | :-----------: | -| width | Width of the chart | 700 | -| height | Height of the chart | 500 | -| titlePadding | Top and Bottom padding of the title | 10 | -| titleFontSize | Title font size | 20 | -| showTitle | Title to be shown or not | true | -| xAxis | xAxis configuration | AxisConfig | -| yAxis | yAxis configuration | AxisConfig | -| chartOrientation | 'vertical' or 'horizontal' | 'vertical' | -| plotReservedSpacePercent | Minimum space plots will take inside the chart | 50 | +| Parameter | Description | Default value | +| ------------------------ | ------------------------------------------------------------- | :-----------: | +| width | Width of the chart | 700 | +| height | Height of the chart | 500 | +| titlePadding | Top and Bottom padding of the title | 10 | +| titleFontSize | Title font size | 20 | +| showTitle | Title to be shown or not | true | +| xAxis | xAxis configuration | AxisConfig | +| yAxis | yAxis configuration | AxisConfig | +| chartOrientation | 'vertical' or 'horizontal' | 'vertical' | +| plotReservedSpacePercent | Minimum space plots will take inside the chart | 50 | +| showDataLabel | Should show the value corresponding to the bar within the bar | false | ### AxisConfig @@ -125,9 +126,15 @@ xychart-beta ## Chart Theme Variables -```note -Themes for xychart resides inside xychart attribute so to set the variables use this syntax -%%{init: { "themeVariables": {"xyChart": {"titleColor": "#ff0000"} } }}%% +Themes for xychart resides inside xychart attribute so to set the variables use this syntax: + +```yaml +--- +config: + themeVariables: + xyChart: + titleColor: '#ff0000' +--- ``` | Parameter | Description | @@ -152,6 +159,7 @@ config: xyChart: width: 900 height: 600 + showDataLabel: true themeVariables: xyChart: titleColor: "#ff0000" diff --git a/packages/mermaid/src/docs/tsconfig.json b/packages/mermaid/src/docs/tsconfig.json new file mode 100644 index 000000000..8225d4f96 --- /dev/null +++ b/packages/mermaid/src/docs/tsconfig.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": ["../../../../tsconfig.json"], + "compilerOptions": { + "noEmit": true + }, + "include": ["./**/*.ts", "./.vitepress/**/*.ts"] +} diff --git a/packages/mermaid/src/docs/vite.config.ts b/packages/mermaid/src/docs/vite.config.ts index ed5f4bab9..399e5c65e 100644 --- a/packages/mermaid/src/docs/vite.config.ts +++ b/packages/mermaid/src/docs/vite.config.ts @@ -49,12 +49,12 @@ export default defineConfig({ // TODO: will be fixed in the next vitepress release. name: 'fix-virtual', - async resolveId(id: string) { + resolveId(id: string) { if (id === virtualModuleId) { return resolvedVirtualModuleId; } }, - async load(this, id: string) { + load(this, id: string) { if (id === resolvedVirtualModuleId) { return `export default ${JSON.stringify({ securityLevel: 'loose', diff --git a/packages/mermaid/src/internals.ts b/packages/mermaid/src/internals.ts new file mode 100644 index 000000000..7cc058cb3 --- /dev/null +++ b/packages/mermaid/src/internals.ts @@ -0,0 +1,33 @@ +import { getConfig } from './config.js'; +import common from './diagrams/common/common.js'; +import { log } from './logger.js'; +import { insertCluster } from './rendering-util/rendering-elements/clusters.js'; +import { + insertEdge, + insertEdgeLabel, + positionEdgeLabel, +} from './rendering-util/rendering-elements/edges.js'; +import insertMarkers from './rendering-util/rendering-elements/markers.js'; +import { insertNode } from './rendering-util/rendering-elements/nodes.js'; +import { labelHelper } from './rendering-util/rendering-elements/shapes/util.js'; +import { interpolateToCurve } from './utils.js'; + +/** + * Internal helpers for mermaid + * @deprecated - This should not be used by external packages, as the definitions will change without notice. + */ +export const internalHelpers = { + common, + getConfig, + insertCluster, + insertEdge, + insertEdgeLabel, + insertMarkers, + insertNode, + interpolateToCurve, + labelHelper, + log, + positionEdgeLabel, +}; + +export type InternalHelpers = typeof internalHelpers; diff --git a/packages/mermaid/src/logger.ts b/packages/mermaid/src/logger.ts index 44b98315c..cffd2112c 100644 --- a/packages/mermaid/src/logger.ts +++ b/packages/mermaid/src/logger.ts @@ -1,6 +1,6 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-empty-function */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + /* eslint-disable no-console */ import dayjs from 'dayjs'; @@ -29,12 +29,11 @@ export const log: Record = { * * @param level - The level to set the logging to. Default is `"fatal"` */ -export const setLogLevel = function (level: keyof typeof LEVELS | number | string = 'fatal') { +export const setLogLevel = function (level: keyof typeof LEVELS | number = 'fatal') { let numericLevel: number = LEVELS.fatal; if (typeof level === 'string') { - level = level.toLowerCase(); - if (level in LEVELS) { - numericLevel = LEVELS[level as keyof typeof LEVELS]; + if (level.toLowerCase() in LEVELS) { + numericLevel = LEVELS[level]; } } else if (typeof level === 'number') { numericLevel = level; diff --git a/packages/mermaid/src/mermaid.spec.ts b/packages/mermaid/src/mermaid.spec.ts index 9360f7bab..586d3605c 100644 --- a/packages/mermaid/src/mermaid.spec.ts +++ b/packages/mermaid/src/mermaid.spec.ts @@ -5,7 +5,7 @@ import { addDiagrams } from './diagram-api/diagram-orchestration.js'; import { beforeAll, describe, it, expect, vi, afterEach } from 'vitest'; import type { DiagramDefinition } from './diagram-api/types.js'; -beforeAll(async () => { +beforeAll(() => { addDiagrams(); }); const spyOn = vi.spyOn; @@ -18,7 +18,7 @@ afterEach(() => { describe('when using mermaid and ', () => { describe('when detecting chart type ', () => { - it('should not start rendering with mermaid.startOnLoad set to false', async () => { + it('should not start rendering with mermaid.startOnLoad set to false', () => { mermaid.startOnLoad = false; document.body.innerHTML = '
graph TD;\na;
'; spyOn(mermaid, 'run'); @@ -26,7 +26,7 @@ describe('when using mermaid and ', () => { expect(mermaid.run).not.toHaveBeenCalled(); }); - it('should start rendering with both startOnLoad set', async () => { + it('should start rendering with both startOnLoad set', () => { mermaid.startOnLoad = true; document.body.innerHTML = '
graph TD;\na;
'; spyOn(mermaid, 'run'); @@ -34,7 +34,7 @@ describe('when using mermaid and ', () => { expect(mermaid.run).toHaveBeenCalled(); }); - it('should start rendering with mermaid.startOnLoad', async () => { + it('should start rendering with mermaid.startOnLoad', () => { mermaid.startOnLoad = true; document.body.innerHTML = '
graph TD;\na;
'; spyOn(mermaid, 'run'); @@ -42,7 +42,7 @@ describe('when using mermaid and ', () => { expect(mermaid.run).toHaveBeenCalled(); }); - it('should start rendering as a default with no changes performed', async () => { + it('should start rendering as a default with no changes performed', () => { document.body.innerHTML = '
graph TD;\na;
'; spyOn(mermaid, 'run'); mermaid.contentLoaded(); @@ -74,7 +74,7 @@ describe('when using mermaid and ', () => { [ { id: 'dummyError', - detector: (text) => /dummyError/.test(text), + detector: (text) => text.includes('dummyError'), loader: () => Promise.reject('dummyError'), }, ], @@ -114,7 +114,7 @@ describe('when using mermaid and ', () => { [ { id: 'dummy', - detector: (text) => /dummy/.test(text), + detector: (text) => text.includes('dummy'), loader: () => { loaded = true; return Promise.resolve({ @@ -133,7 +133,7 @@ describe('when using mermaid and ', () => { [ { id: 'dummy2', - detector: (text) => /dummy2/.test(text), + detector: (text) => text.includes('dummy2'), loader: () => { loaded = true; return Promise.resolve({ @@ -207,7 +207,7 @@ describe('when using mermaid and ', () => { [Error: Parse error on line 2: ...equenceDiagramAlice:->Bob: Hello Bob, h... ----------------------^ - Expecting 'SOLID_OPEN_ARROW', 'DOTTED_OPEN_ARROW', 'SOLID_ARROW', 'DOTTED_ARROW', 'SOLID_CROSS', 'DOTTED_CROSS', 'SOLID_POINT', 'DOTTED_POINT', got 'TXT'] + Expecting 'SOLID_OPEN_ARROW', 'DOTTED_OPEN_ARROW', 'SOLID_ARROW', 'BIDIRECTIONAL_SOLID_ARROW', 'DOTTED_ARROW', 'BIDIRECTIONAL_DOTTED_ARROW', 'SOLID_CROSS', 'DOTTED_CROSS', 'SOLID_POINT', 'DOTTED_POINT', got 'TXT'] `); }); diff --git a/packages/mermaid/src/mermaid.ts b/packages/mermaid/src/mermaid.ts index 8194872d4..3ab31ee25 100644 --- a/packages/mermaid/src/mermaid.ts +++ b/packages/mermaid/src/mermaid.ts @@ -2,29 +2,39 @@ * Web page integration module for the mermaid framework. It uses the mermaidAPI for mermaid * functionality and to render the diagrams to svg code! */ +import { registerIconPacks } from './rendering-util/icons.js'; import { dedent } from 'ts-dedent'; import type { MermaidConfig } from './config.type.js'; -import { log } from './logger.js'; -import utils from './utils.js'; -import type { ParseOptions, ParseResult, RenderResult } from './mermaidAPI.js'; -import { mermaidAPI } from './mermaidAPI.js'; -import { registerLazyLoadedDiagrams, detectType } from './diagram-api/detectType.js'; -import { loadRegisteredDiagrams } from './diagram-api/loadDiagram.js'; -import type { ParseErrorFunction } from './Diagram.js'; -import { isDetailedError } from './utils.js'; -import type { DetailedError } from './utils.js'; -import type { ExternalDiagramDefinition } from './diagram-api/types.js'; -import type { UnknownDiagramError } from './errors.js'; +import { detectType, registerLazyLoadedDiagrams } from './diagram-api/detectType.js'; import { addDiagrams } from './diagram-api/diagram-orchestration.js'; +import { loadRegisteredDiagrams } from './diagram-api/loadDiagram.js'; +import type { ExternalDiagramDefinition, SVG, SVGGroup } from './diagram-api/types.js'; +import type { ParseErrorFunction } from './Diagram.js'; +import type { UnknownDiagramError } from './errors.js'; +import type { InternalHelpers } from './internals.js'; +import { log } from './logger.js'; +import { mermaidAPI } from './mermaidAPI.js'; +import type { LayoutLoaderDefinition, RenderOptions } from './rendering-util/render.js'; +import { registerLayoutLoaders } from './rendering-util/render.js'; +import type { LayoutData } from './rendering-util/types.js'; +import type { ParseOptions, ParseResult, RenderResult } from './types.js'; +import type { DetailedError } from './utils.js'; +import utils, { isDetailedError } from './utils.js'; export type { - MermaidConfig, DetailedError, ExternalDiagramDefinition, + InternalHelpers, + LayoutData, + LayoutLoaderDefinition, + MermaidConfig, ParseErrorFunction, - RenderResult, ParseOptions, ParseResult, + RenderOptions, + RenderResult, + SVG, + SVGGroup, UnknownDiagramError, }; @@ -277,7 +287,7 @@ if (typeof document !== 'undefined') { * ## setParseErrorHandler Alternative to directly setting parseError using: * * ```js - * mermaid.parseError = function(err,hash){= + * mermaid.parseError = function(err,hash) { * forExampleDisplayErrorInGui(err); // do something with the error * }; * ``` @@ -357,7 +367,7 @@ const parse: typeof mermaidAPI.parse = async (text, parseOptions) => { }; /** - * Function that renders an svg with a graph from a chart definition. Usage example below. + * Function that renders an SVG with a graph from a chart definition. Usage example below. * * ```javascript * element = document.querySelector('#graphDiv'); @@ -408,16 +418,25 @@ const render: typeof mermaidAPI.render = (id, text, container) => { export interface Mermaid { startOnLoad: boolean; parseError?: ParseErrorFunction; + /** + * @deprecated Use {@link parse} and {@link render} instead. Please [open a discussion](https://github.com/mermaid-js/mermaid/discussions) if your use case does not fit the new API. + * @internal + */ mermaidAPI: typeof mermaidAPI; parse: typeof parse; render: typeof render; + /** + * @deprecated Use {@link initialize} and {@link run} instead. + */ init: typeof init; run: typeof run; + registerLayoutLoaders: typeof registerLayoutLoaders; registerExternalDiagrams: typeof registerExternalDiagrams; initialize: typeof initialize; contentLoaded: typeof contentLoaded; setParseErrorHandler: typeof setParseErrorHandler; detectType: typeof detectType; + registerIconPacks: typeof registerIconPacks; } const mermaid: Mermaid = { @@ -428,11 +447,13 @@ const mermaid: Mermaid = { init, run, registerExternalDiagrams, + registerLayoutLoaders, initialize, parseError: undefined, contentLoaded, setParseErrorHandler, detectType, + registerIconPacks, }; export default mermaid; diff --git a/packages/mermaid/src/mermaidAPI.spec.ts b/packages/mermaid/src/mermaidAPI.spec.ts index 40efd776b..3e28dbfd4 100644 --- a/packages/mermaid/src/mermaidAPI.spec.ts +++ b/packages/mermaid/src/mermaidAPI.spec.ts @@ -1,4 +1,4 @@ -import { vi, it, expect, describe, beforeEach } from 'vitest'; +import { assert, beforeEach, describe, expect, it, vi } from 'vitest'; // ------------------------------------- // Mocks and mocking @@ -30,7 +30,8 @@ vi.mock('./diagrams/packet/renderer.js'); vi.mock('./diagrams/xychart/xychartRenderer.js'); vi.mock('./diagrams/requirement/requirementRenderer.js'); vi.mock('./diagrams/sequence/sequenceRenderer.js'); -vi.mock('./diagrams/state/stateRenderer-v2.js'); +vi.mock('./diagrams/radar/renderer.js'); +vi.mock('./diagrams/architecture/architectureRenderer.js'); // ------------------------------------- @@ -67,8 +68,13 @@ vi.mock('stylis', () => { }); import { compile, serialize } from 'stylis'; -import { decodeEntities, encodeEntities } from './utils.js'; import { Diagram } from './Diagram.js'; +import { ClassDB } from './diagrams/class/classDb.js'; +import { FlowDB } from './diagrams/flowchart/flowDb.js'; +import { SequenceDB } from './diagrams/sequence/sequenceDb.js'; +import { decodeEntities, encodeEntities } from './utils.js'; +import { toBase64 } from './utils/base64.js'; +import { StateDB } from './diagrams/state/stateDb.js'; /** * @see https://vitest.dev/guide/mocking.html Mock part of a module @@ -176,7 +182,7 @@ describe('mermaidAPI', () => { }); describe('putIntoIFrame', () => { - const inputSvgCode = 'this is the SVG code'; + const inputSvgCode = 'this is the SVG code â›ĩ'; it('uses the default SVG iFrame height is used if no svgElement given', () => { const result = putIntoIFrame(inputSvgCode); @@ -199,11 +205,10 @@ describe('mermaidAPI', () => { }); it('sets src to base64 version of svgCode', () => { - const base64encodedSrc = btoa('' + inputSvgCode + ''); - const expectedRegExp = new RegExp('src="data:text/html;base64,' + base64encodedSrc + '"'); - + const base64encodedSrc = toBase64(`${inputSvgCode}`); + const expectedSrc = `src="data:text/html;charset=UTF-8;base64,${base64encodedSrc}"`; const result = putIntoIFrame(inputSvgCode); - expect(result).toMatch(expectedRegExp); + expect(result).toContain(expectedSrc); }); it('uses the height and appends px from the svgElement given', () => { @@ -295,7 +300,7 @@ describe('mermaidAPI', () => { expect(styles).toMatch(/^\ndefault(.*)/); }); it('gets the fontFamily from the config', () => { - const styles = createCssStyles(mocked_config_with_htmlLabels, {}); + const styles = createCssStyles(mocked_config_with_htmlLabels, new Map()); expect(styles).toMatch(/(.*)\n:root { --mermaid-font-family: serif(.*)/); }); it('gets the alt fontFamily from the config', () => { @@ -375,7 +380,7 @@ describe('mermaidAPI', () => { // @todo TODO Can't figure out how to spy on the cssImportantStyles method. // That would be a much better approach than manually checking the result - const styles = createCssStyles(mocked_config, classDefs); + const styles = createCssStyles(mocked_config, new Map(Object.entries(classDefs))); htmlElements.forEach((htmlElement) => { expect_styles_matchesHtmlElements(styles, htmlElement); }); @@ -413,7 +418,10 @@ describe('mermaidAPI', () => { it('creates CSS styles for every style and textStyle in every classDef', () => { // TODO Can't figure out how to spy on the cssImportantStyles method. That would be a much better approach than manually checking the result. - const styles = createCssStyles(mocked_config_no_htmlLabels, classDefs); + const styles = createCssStyles( + mocked_config_no_htmlLabels, + new Map(Object.entries(classDefs)) + ); htmlElements.forEach((htmlElement) => { expect_styles_matchesHtmlElements(styles, htmlElement); }); @@ -437,7 +445,7 @@ describe('mermaidAPI', () => { it('gets the css styles created', () => { // @todo TODO if a single function in the module can be mocked, do it for createCssStyles and mock the results. - createUserStyles(mockConfig, 'flowchart-v2', { classDef1 }, 'someId'); + createUserStyles(mockConfig, 'flowchart-v2', new Map([['classDef1', classDef1]]), 'someId'); const expectedStyles = '\ndefault' + '\n.classDef1 > * { style1-1 !important; }' + @@ -448,12 +456,12 @@ describe('mermaidAPI', () => { }); it('calls getStyles to get css for all graph, user css styles, and config theme variables', () => { - createUserStyles(mockConfig, 'someDiagram', {}, 'someId'); + createUserStyles(mockConfig, 'someDiagram', new Map(), 'someId'); expect(getStyles).toHaveBeenCalled(); }); it('returns the result of compiling, stringifying, and serializing the css code with stylis', () => { - const result = createUserStyles(mockConfig, 'someDiagram', {}, 'someId'); + const result = createUserStyles(mockConfig, 'someDiagram', new Map(), 'someId'); expect(compile).toHaveBeenCalled(); expect(serialize).toHaveBeenCalled(); expect(result).toEqual('stylis serialized css'); @@ -590,7 +598,6 @@ describe('mermaidAPI', () => { mermaidAPI.initialize({ securityLevel: 'loose' }); }, }; - // mermaidAPI.reinitialize(config); expect(mermaidAPI.getConfig().secure).toEqual(mermaidAPI.getSiteConfig().secure); expect(mermaidAPI.getConfig().securityLevel).toBe('strict'); mermaidAPI.reset(); @@ -603,27 +610,27 @@ describe('mermaidAPI', () => { let error: any = { message: '' }; try { - // @ts-ignore This is a read-only property. Typescript will not allow assignment, but regular javascript might. - mermaidAPI['defaultConfig'] = config; + // @ts-ignore This is a read-only property. TypeScript will not allow assignment, but regular javascript might. + mermaidAPI.defaultConfig = config; } catch (e) { error = e; } expect(error.message).toBe( "Cannot assign to read only property 'defaultConfig' of object '#'" ); - expect(mermaidAPI.defaultConfig['logLevel']).toBe(5); + expect(mermaidAPI.defaultConfig.logLevel).toBe(5); }); it('prevents changes to global defaults (direct)', () => { let error: any = { message: '' }; try { - mermaidAPI.defaultConfig['logLevel'] = 0; + mermaidAPI.defaultConfig.logLevel = 0; } catch (e) { error = e; } expect(error.message).toBe( "Cannot assign to read only property 'logLevel' of object '#'" ); - expect(mermaidAPI.defaultConfig['logLevel']).toBe(5); + expect(mermaidAPI.defaultConfig.logLevel).toBe(5); }); it('prevents sneaky changes to global defaults (assignWithDepth)', () => { const config = { @@ -638,7 +645,7 @@ describe('mermaidAPI', () => { expect(error.message).toBe( "Cannot assign to read only property 'logLevel' of object '#'" ); - expect(mermaidAPI.defaultConfig['logLevel']).toBe(5); + expect(mermaidAPI.defaultConfig.logLevel).toBe(5); }); }); @@ -646,7 +653,7 @@ describe('mermaidAPI', () => { it('allows dompurify config to be set', () => { mermaidAPI.initialize({ dompurifyConfig: { ADD_ATTR: ['onclick'] } }); - expect(mermaidAPI!.getConfig()!.dompurifyConfig!.ADD_ATTR).toEqual(['onclick']); + expect(mermaidAPI.getConfig().dompurifyConfig!.ADD_ATTR).toEqual(['onclick']); }); }); @@ -692,18 +699,79 @@ describe('mermaidAPI', () => { await expect(mermaidAPI.parse('graph TD;A--x|text including URL space|B;')).resolves .toMatchInlineSnapshot(` { + "config": {}, "diagramType": "flowchart-v2", } `); }); + it('returns config when defined in frontmatter', async () => { + await expect( + mermaidAPI.parse(`--- +config: + theme: base + flowchart: + htmlLabels: true +--- +graph TD;A--x|text including URL space|B;`) + ).resolves.toMatchInlineSnapshot(` + { + "config": { + "flowchart": { + "htmlLabels": true, + }, + "theme": "base", + }, + "diagramType": "flowchart-v2", + } +`); + }); + + it('returns config when defined in directive', async () => { + await expect( + mermaidAPI.parse(`%%{init: { 'theme': 'base' } }%% +graph TD;A--x|text including URL space|B;`) + ).resolves.toMatchInlineSnapshot(` + { + "config": { + "theme": "base", + }, + "diagramType": "flowchart-v2", + } +`); + }); + + it('returns merged config when defined in frontmatter and directive', async () => { + await expect( + mermaidAPI.parse(`--- +config: + theme: forest + flowchart: + htmlLabels: true +--- +%%{init: { 'theme': 'base' } }%% +graph TD;A--x|text including URL space|B;`) + ).resolves.toMatchInlineSnapshot(` + { + "config": { + "flowchart": { + "htmlLabels": true, + }, + "theme": "base", + }, + "diagramType": "flowchart-v2", + } +`); + }); + it('returns true for valid definition with silent option', async () => { await expect( mermaidAPI.parse('graph TD;A--x|text including URL space|B;', { suppressErrors: true }) ).resolves.toMatchInlineSnapshot(` - { - "diagramType": "flowchart-v2", - } - `); + { + "config": {}, + "diagramType": "flowchart-v2", + } + `); }); }); @@ -717,7 +785,7 @@ describe('mermaidAPI', () => { // We have to have both the specific textDiagramType and the expected type name because the expected type may be slightly different than was is put in the diagram text (ex: in -v2 diagrams) const diagramTypesAndExpectations = [ { textDiagramType: 'C4Context', expectedType: 'c4' }, - { textDiagramType: 'classDiagram', expectedType: 'classDiagram' }, + { textDiagramType: 'classDiagram', expectedType: 'class' }, { textDiagramType: 'classDiagram-v2', expectedType: 'classDiagram' }, { textDiagramType: 'erDiagram', expectedType: 'er' }, { textDiagramType: 'graph', expectedType: 'flowchart-v2' }, @@ -731,6 +799,8 @@ describe('mermaidAPI', () => { { textDiagramType: 'requirementDiagram', expectedType: 'requirement' }, { textDiagramType: 'sequenceDiagram', expectedType: 'sequence' }, { textDiagramType: 'stateDiagram-v2', expectedType: 'stateDiagram' }, + { textDiagramType: 'radar-beta', expectedType: 'radar' }, + { textDiagramType: 'architecture-beta', expectedType: 'architecture' }, ]; describe('accessibility', () => { @@ -770,5 +840,108 @@ describe('mermaidAPI', () => { expect(diagram).toBeInstanceOf(Diagram); expect(diagram.type).toBe('flowchart-v2'); }); + + it('should not modify db when rendering different diagrams', async () => { + const stateDiagram1 = await mermaidAPI.getDiagramFromText( + `stateDiagram + direction LR + [*] --> Still + Still --> [*] + Still --> Moving + Moving --> Still + Moving --> Crash + Crash --> [*]` + ); + const stateDiagram2 = await mermaidAPI.getDiagramFromText( + `stateDiagram + direction TB + [*] --> Still + Still --> [*] + Still --> Moving + Moving --> Still + Moving --> Crash + Crash --> [*]` + ); + expect(stateDiagram1.db).not.toBe(stateDiagram2.db); + assert(stateDiagram1.db instanceof StateDB); + assert(stateDiagram2.db instanceof StateDB); + expect(stateDiagram1.db.getDirection()).not.toEqual(stateDiagram2.db.getDirection()); + + const flowDiagram1 = await mermaidAPI.getDiagramFromText( + `flowchart LR + A -- text --> B -- text2 --> C` + ); + const flowDiagram2 = await mermaidAPI.getDiagramFromText( + `flowchart TD + A -- text --> B -- text2 --> C` + ); + // Since flowDiagram will return new Db object each time, we can compare the db to be different. + expect(flowDiagram1.db).not.toBe(flowDiagram2.db); + assert(flowDiagram1.db instanceof FlowDB); + assert(flowDiagram2.db instanceof FlowDB); + expect(flowDiagram1.db.getDirection()).not.toEqual(flowDiagram2.db.getDirection()); + + const classDiagram1 = await mermaidAPI.getDiagramFromText( + `classDiagram + direction TB + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides` + ); + const classDiagram2 = await mermaidAPI.getDiagramFromText( + `classDiagram + direction LR + class Student { + -idCard : IdCard + } + class IdCard{ + -id : int + -name : string + } + class Bike{ + -id : int + -name : string + } + Student "1" --o "1" IdCard : carries + Student "1" --o "1" Bike : rides` + ); + // Since classDiagram will return new Db object each time, we can compare the db to be different. + expect(classDiagram1.db).not.toBe(classDiagram2.db); + assert(classDiagram1.db instanceof ClassDB); + assert(classDiagram2.db instanceof ClassDB); + expect(classDiagram1.db.getDirection()).not.toEqual(classDiagram2.db.getDirection()); + + const sequenceDiagram1 = await mermaidAPI.getDiagramFromText( + `sequenceDiagram + Alice->>+John: Hello John, how are you? + Alice->>+John: John, can you hear me? + John-->>-Alice: Hi Alice, I can hear you! + John-->>-Alice: I feel great!` + ); + const sequenceDiagram2 = await mermaidAPI.getDiagramFromText( + `sequenceDiagram + actor A1 + Alice->>+John: Hello John, how are you? + Alice->>+John: John, can you hear me? + John-->>-Alice: Hi Alice, I can hear you! + John-->>-Alice: I feel great!` + ); + + // Since sequenceDiagram will return new Db object each time, we can compare the db to be different. + expect(sequenceDiagram1.db).not.toBe(sequenceDiagram2.db); + assert(sequenceDiagram1.db instanceof SequenceDB); + assert(sequenceDiagram2.db instanceof SequenceDB); + expect(sequenceDiagram1.db.getActors()).not.toEqual(sequenceDiagram2.db.getActors()); + }); }); }); diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index 1d5ba8cc2..cf08d02f8 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -1,38 +1,30 @@ /** - * This is the API to be used when optionally handling the integration with the web page, instead of - * using the default integration provided by mermaid.js. - * - * The core of this api is the [**render**](Setup.md?id=render) function which, given a graph - * definition as text, renders the graph/diagram and returns an svg element for the graph. - * - * It is then up to the user of the API to make use of the svg, either insert it somewhere in the - * page or do something completely different. - * - * In addition to the render function, a number of behavioral configuration options are available. + * This file contains functions that are used internally by mermaid + * and is not intended to be used by the end user. */ // @ts-ignore TODO: Investigate D3 issue import { select } from 'd3'; import { compile, serialize, stringify } from 'stylis'; -// @ts-ignore: TODO Fix ts errors -import { version as packageVersion } from '../package.json'; +import DOMPurify from 'dompurify'; +import isEmpty from 'lodash-es/isEmpty.js'; +import packageJson from '../package.json' assert { type: 'json' }; +import { addSVGa11yTitleDescription, setA11yDiagramInfo } from './accessibility.js'; +import assignWithDepth from './assignWithDepth.js'; import * as configApi from './config.js'; +import type { MermaidConfig } from './config.type.js'; import { addDiagrams } from './diagram-api/diagram-orchestration.js'; +import type { DiagramMetadata, DiagramStyleClassDef } from './diagram-api/types.js'; import { Diagram } from './Diagram.js'; +import { evaluate } from './diagrams/common/common.js'; import errorRenderer from './diagrams/error/errorRenderer.js'; import { attachFunctions } from './interactionDb.js'; import { log, setLogLevel } from './logger.js'; +import { preprocessDiagram } from './preprocess.js'; import getStyles from './styles.js'; import theme from './themes/index.js'; -import DOMPurify from 'dompurify'; -import type { MermaidConfig } from './config.type.js'; -import { evaluate } from './diagrams/common/common.js'; -import isEmpty from 'lodash-es/isEmpty.js'; -import { setA11yDiagramInfo, addSVGa11yTitleDescription } from './accessibility.js'; -import type { DiagramMetadata, DiagramStyleClassDef } from './diagram-api/types.js'; -import { preprocessDiagram } from './preprocess.js'; +import type { D3Element, ParseOptions, ParseResult, RenderResult } from './types.js'; import { decodeEntities } from './utils.js'; - -const version = packageVersion + (includeLargeFeatures ? '' : '-tiny'); +import { toBase64 } from './utils/base64.js'; const MAX_TEXTLENGTH = 50_000; const MAX_TEXTLENGTH_EXCEEDED_MSG = @@ -58,44 +50,6 @@ const IFRAME_NOT_SUPPORTED_MSG = 'The "iframe" tag is not supported by your brow const DOMPURIFY_TAGS = ['foreignobject']; const DOMPURIFY_ATTR = ['dominant-baseline']; -export interface ParseOptions { - /** - * If `true`, parse will return `false` instead of throwing error when the diagram is invalid. - * The `parseError` function will not be called. - */ - suppressErrors?: boolean; -} - -export interface ParseResult { - /** - * The diagram type, e.g. 'flowchart', 'sequence', etc. - */ - diagramType: string; -} -// This makes it clear that we're working with a d3 selected element of some kind, even though it's hard to specify the exact type. -export type D3Element = any; - -export interface RenderResult { - /** - * The svg code for the rendered graph. - */ - svg: string; - /** - * The diagram type, e.g. 'flowchart', 'sequence', etc. - */ - diagramType: string; - /** - * Bind function to be called after the svg has been inserted into the DOM. - * This is necessary for adding event listeners to the elements in the svg. - * ```js - * const { svg, bindFunctions } = mermaidAPI.render('id1', 'graph TD;A-->B'); - * div.innerHTML = svg; - * bindFunctions?.(div); // To call bindFunctions only if it's present. - * ``` - */ - bindFunctions?: (element: Element) => void; -} - function processAndSetConfigs(text: string) { const processed = preprocessDiagram(text); configApi.reset(); @@ -118,9 +72,9 @@ async function parse(text: string, parseOptions?: ParseOptions): Promise { addDiagrams(); try { - const { code } = processAndSetConfigs(text); + const { code, config } = processAndSetConfigs(text); const diagram = await getDiagramFromText(code); - return { diagramType: diagram.type }; + return { diagramType: diagram.type, config }; } catch (error) { if (parseOptions?.suppressErrors) { return false; @@ -154,7 +108,7 @@ export const cssImportantStyles = ( */ export const createCssStyles = ( config: MermaidConfig, - classDefs: Record | null | undefined = {} + classDefs: Map | null | undefined = new Map() ): string => { let cssStyles = ''; @@ -173,8 +127,8 @@ export const createCssStyles = ( } // classDefs defined in the diagram text - if (!isEmpty(classDefs)) { - const htmlLabels = config.htmlLabels || config.flowchart?.htmlLabels; // TODO why specifically check the Flowchart diagram config? + if (classDefs instanceof Map) { + const htmlLabels = config.htmlLabels ?? config.flowchart?.htmlLabels; // TODO why specifically check the Flowchart diagram config? const cssHtmlElements = ['> *', 'span']; // TODO make a constant const cssShapeElements = ['rect', 'polygon', 'ellipse', 'circle', 'path']; // TODO make a constant @@ -182,8 +136,7 @@ export const createCssStyles = ( const cssElements = htmlLabels ? cssHtmlElements : cssShapeElements; // create the CSS styles needed for each styleClass definition and css element - for (const classId in classDefs) { - const styleClassDef = classDefs[classId]; + classDefs.forEach((styleClassDef) => { // create the css styles for each cssElement and the styles (only if there are styles) if (!isEmpty(styleClassDef.styles)) { cssElements.forEach((cssElement) => { @@ -192,9 +145,13 @@ export const createCssStyles = ( } // create the css styles for the tspan element and the text styles (only if there are textStyles) if (!isEmpty(styleClassDef.textStyles)) { - cssStyles += cssImportantStyles(styleClassDef.id, 'tspan', styleClassDef.textStyles); + cssStyles += cssImportantStyles( + styleClassDef.id, + 'tspan', + (styleClassDef?.textStyles || []).map((s) => s.replace('color', 'fill')) + ); } - } + }); } return cssStyles; }; @@ -202,7 +159,7 @@ export const createCssStyles = ( export const createUserStyles = ( config: MermaidConfig, graphType: string, - classDefs: Record | undefined, + classDefs: Map | undefined, svgId: string ): string => { const userCSSstyles = createCssStyles(config, classDefs); @@ -251,14 +208,13 @@ export const cleanUpSvgCode = ( * @param svgCode - the svg code to put inside the iFrame * @param svgElement - the d3 node that has the current svgElement so we can get the height from it * @returns - the code with the iFrame that now contains the svgCode - * TODO replace btoa(). Replace with buf.toString('base64')? */ export const putIntoIFrame = (svgCode = '', svgElement?: D3Element): string => { const height = svgElement?.viewBox?.baseVal?.height ? svgElement.viewBox.baseVal.height + 'px' : IFRAME_HEIGHT; - const base64encodedSrc = btoa('' + svgCode + ''); - return ``; }; @@ -465,12 +421,12 @@ const render = async function ( // ------------------------------------------------------------------------------- // Draw the diagram with the renderer try { - await diag.renderer.draw(text, id, version, diag); + await diag.renderer.draw(text, id, packageJson.version, diag); } catch (e) { if (config.suppressErrorRendering) { removeTempElements(); } else { - errorRenderer.draw(text, id, version); + errorRenderer.draw(text, id, packageJson.version); } throw e; } @@ -498,6 +454,7 @@ const render = async function ( svgCode = DOMPurify.sanitize(svgCode, { ADD_TAGS: DOMPURIFY_TAGS, ADD_ATTR: DOMPURIFY_ATTR, + HTML_INTEGRATION_POINTS: { foreignobject: true }, }); } @@ -517,9 +474,10 @@ const render = async function ( }; /** - * @param options - Initial Mermaid options + * @param userOptions - Initial Mermaid options */ -function initialize(options: MermaidConfig = {}) { +function initialize(userOptions: MermaidConfig = {}) { + const options: MermaidConfig = assignWithDepth({}, userOptions); // Handle legacy location of font-family configuration if (options?.fontFamily && !options.themeVariables?.fontFamily) { if (!options.themeVariables) { @@ -571,69 +529,8 @@ function addA11yInfo( } /** - * ## mermaidAPI configuration defaults - * - * ```ts - * const config = { - * theme: 'default', - * logLevel: 'fatal', - * securityLevel: 'strict', - * startOnLoad: true, - * arrowMarkerAbsolute: false, - * suppressErrorRendering: false, - * - * er: { - * diagramPadding: 20, - * layoutDirection: 'TB', - * minEntityWidth: 100, - * minEntityHeight: 75, - * entityPadding: 15, - * stroke: 'gray', - * fill: 'honeydew', - * fontSize: 12, - * useMaxWidth: true, - * }, - * flowchart: { - * diagramPadding: 8, - * htmlLabels: true, - * curve: 'basis', - * }, - * sequence: { - * diagramMarginX: 50, - * diagramMarginY: 10, - * actorMargin: 50, - * width: 150, - * height: 65, - * boxMargin: 10, - * boxTextMargin: 5, - * noteMargin: 10, - * messageMargin: 35, - * messageAlign: 'center', - * mirrorActors: true, - * bottomMarginAdj: 1, - * useMaxWidth: true, - * rightAngles: false, - * showSequenceNumbers: false, - * }, - * gantt: { - * titleTopMargin: 25, - * barHeight: 20, - * barGap: 4, - * topPadding: 50, - * leftPadding: 75, - * gridLineStartPadding: 35, - * fontSize: 11, - * fontFamily: '"Open Sans", sans-serif', - * numberSectionStyles: 4, - * axisFormat: '%Y-%m-%d', - * topAxis: false, - * displayMode: '', - * }, - * }; - * mermaid.initialize(config); - * ``` + * @internal - Use mermaid.function instead of mermaid.mermaidAPI.function */ - export const mermaidAPI = Object.freeze({ render, parse, diff --git a/packages/mermaid/src/preprocess.ts b/packages/mermaid/src/preprocess.ts index 6e386e744..a62326070 100644 --- a/packages/mermaid/src/preprocess.ts +++ b/packages/mermaid/src/preprocess.ts @@ -33,9 +33,7 @@ const processDirectives = (code: string) => { const initDirective = utils.detectInit(code) ?? {}; const wrapDirectives = utils.detectDirective(code, 'wrap'); if (Array.isArray(wrapDirectives)) { - initDirective.wrap = wrapDirectives.some(({ type }) => { - type === 'wrap'; - }); + initDirective.wrap = wrapDirectives.some(({ type }) => type === 'wrap'); } else if (wrapDirectives?.type === 'wrap') { initDirective.wrap = true; } @@ -51,7 +49,7 @@ const processDirectives = (code: string) => { * @param code - The code to preprocess. * @returns The object containing the preprocessed code, title, and configuration. */ -export function preprocessDiagram(code: string): DiagramMetadata & { code: string } { +export function preprocessDiagram(code: string) { const cleanedCode = cleanupText(code); const frontMatterResult = processFrontmatter(cleanedCode); const directiveResult = processDirectives(frontMatterResult.text); @@ -61,5 +59,5 @@ export function preprocessDiagram(code: string): DiagramMetadata & { code: strin code, title: frontMatterResult.title, config, - }; + } satisfies DiagramMetadata & { code: string }; } diff --git a/packages/mermaid/src/rendering-util/createText.ts b/packages/mermaid/src/rendering-util/createText.ts index 0a7e3bbb0..7d31101e9 100644 --- a/packages/mermaid/src/rendering-util/createText.ts +++ b/packages/mermaid/src/rendering-util/createText.ts @@ -1,7 +1,10 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ // @ts-nocheck TODO: Fix types +import { getConfig } from '../diagram-api/diagramAPI.js'; +import common, { hasKatex, renderKatex } from '../diagrams/common/common.js'; +import { select } from 'd3'; import type { MermaidConfig } from '../config.type.js'; -import type { Group } from '../diagram-api/types.js'; +import type { SVGGroup } from '../diagram-api/types.js'; import type { D3TSpanElement, D3TextElement } from '../diagrams/common/commonTypes.js'; import { log } from '../logger.js'; import { markdownToHTML, markdownToLines } from '../rendering-util/handle-markdown-text.js'; @@ -15,24 +18,30 @@ function applyStyle(dom, styleFn) { } } -function addHtmlSpan(element, node, width, classes, addBackground = false) { +async function addHtmlSpan(element, node, width, classes, addBackground = false) { const fo = element.append('foreignObject'); - const div = fo.append('xhtml:div'); + // This is not the final width but used in order to make sure the foreign + // object in firefox gets a width at all. The final width is fetched from the div + fo.attr('width', `${10 * width}px`); + fo.attr('height', `${10 * width}px`); - const label = node.label; + const div = fo.append('xhtml:div'); + let label = node.label; + if (node.label && hasKatex(node.label)) { + label = await renderKatex(node.label.replace(common.lineBreakRegex, '\n'), getConfig()); + } const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel'; - div.html( - `' + - label + - '' - ); + const span = div.append('span'); + span.html(label); + applyStyle(span, node.labelStyle); + span.attr('class', `${labelClass} ${classes}`); applyStyle(div, node.labelStyle); div.style('display', 'table-cell'); div.style('white-space', 'nowrap'); + div.style('line-height', '1.5'); div.style('max-width', width + 'px'); + div.style('text-align', 'center'); div.attr('xmlns', 'http://www.w3.org/1999/xhtml'); if (addBackground) { div.attr('class', 'labelBkg'); @@ -46,8 +55,8 @@ function addHtmlSpan(element, node, width, classes, addBackground = false) { bbox = div.node().getBoundingClientRect(); } - fo.style('width', bbox.width); - fo.style('height', bbox.height); + // fo.style('width', bbox.width); + // fo.style('height', bbox.height); return fo.node(); } @@ -79,7 +88,7 @@ function computeWidthOfText(parentNode: any, lineHeight: number, line: MarkdownL } export function computeDimensionOfText( - parentNode: Group, + parentNode: SVGGroup, lineHeight: number, text: string ): DOMRect | undefined { @@ -110,7 +119,7 @@ function createFormattedText( ) { const lineHeight = 1.1; const labelGroup = g.append('g'); - const bkg = labelGroup.insert('rect').attr('class', 'background'); + const bkg = labelGroup.insert('rect').attr('class', 'background').attr('style', 'stroke: none'); const textElement = labelGroup.append('text').attr('y', '-10.1'); let lineIndex = 0; for (const line of structuredText) { @@ -132,8 +141,8 @@ function createFormattedText( const bbox = textElement.node().getBBox(); const padding = 2; bkg - .attr('x', -padding) - .attr('y', -padding) + .attr('x', bbox.x - padding) + .attr('y', bbox.y - padding) .attr('width', bbox.width + 2 * padding) .attr('height', bbox.height + 2 * padding); @@ -156,7 +165,7 @@ function updateTextContentAndStyles(tspan: any, wrappedLine: MarkdownWord[]) { wrappedLine.forEach((word, index) => { const innerTspan = tspan .append('tspan') - .attr('font-style', word.type === 'emphasis' ? 'italic' : 'normal') + .attr('font-style', word.type === 'em' ? 'italic' : 'normal') .attr('class', 'text-inner-tspan') .attr('font-weight', word.type === 'strong' ? 'bold' : 'normal'); if (index === 0) { @@ -181,9 +190,9 @@ export function replaceIconSubstring(text: string) { ); } -// Note when using from flowcharts converting the API isNode means classes should be set accordingly. When using htmlLabels => to sett classes to'nodeLabel' when isNode=true otherwise 'edgeLabel' +// Note when using from flowcharts converting the API isNode means classes should be set accordingly. When using htmlLabels => to set classes to 'nodeLabel' when isNode=true otherwise 'edgeLabel' // When not using htmlLabels => to set classes to 'title-row' when isTitle=true otherwise 'title-row' -export const createText = ( +export const createText = async ( el, text = '', { @@ -195,24 +204,79 @@ export const createText = ( width = 200, addSvgBackground = false, } = {}, - config: MermaidConfig + config?: MermaidConfig ) => { - log.info('createText', text, style, isTitle, classes, useHtmlLabels, isNode, addSvgBackground); + log.debug( + 'XYZ createText', + text, + style, + isTitle, + classes, + useHtmlLabels, + isNode, + 'addSvgBackground: ', + addSvgBackground + ); if (useHtmlLabels) { // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? const htmlText = markdownToHTML(text, config); const decodedReplacedText = replaceIconSubstring(decodeEntities(htmlText)); + + //for Katex the text could contain escaped characters, \\relax that should be transformed to \relax + const inputForKatex = text.replace(/\\\\/g, '\\'); + const node = { isNode, - label: decodedReplacedText, + label: hasKatex(text) ? inputForKatex : decodedReplacedText, labelStyle: style.replace('fill:', 'color:'), }; - const vertexNode = addHtmlSpan(el, node, width, classes, addSvgBackground); + const vertexNode = await addHtmlSpan(el, node, width, classes, addSvgBackground); return vertexNode; } else { - const structuredText = markdownToLines(text, config); - const svgLabel = createFormattedText(width, el, structuredText, addSvgBackground); + //sometimes the user might add br tags with 1 or more spaces in between, so we need to replace them with
+ const sanitizeBR = text.replace(//g, '
'); + const structuredText = markdownToLines(sanitizeBR.replace('
', '
'), config); + const svgLabel = createFormattedText( + width, + el, + structuredText, + text ? addSvgBackground : false + ); + if (isNode) { + if (/stroke:/.exec(style)) { + style = style.replace('stroke:', 'lineColor:'); + } + + const nodeLabelTextStyle = style + .replace(/stroke:[^;]+;?/g, '') + .replace(/stroke-width:[^;]+;?/g, '') + .replace(/fill:[^;]+;?/g, '') + .replace(/color:/g, 'fill:'); + select(svgLabel).attr('style', nodeLabelTextStyle); + // svgLabel.setAttribute('style', style); + } else { + //On style, assume `stroke`, `stroke-width` are used for edge path, so remove them + // remove `fill` + // use `background` as `fill` for label rect, + + const edgeLabelRectStyle = style + .replace(/stroke:[^;]+;?/g, '') + .replace(/stroke-width:[^;]+;?/g, '') + .replace(/fill:[^;]+;?/g, '') + .replace(/background:/g, 'fill:'); + select(svgLabel) + .select('rect') + .attr('style', edgeLabelRectStyle.replace(/background:/g, 'fill:')); + + // for text, update fill color with `color` + const edgeLabelTextStyle = style + .replace(/stroke:[^;]+;?/g, '') + .replace(/stroke-width:[^;]+;?/g, '') + .replace(/fill:[^;]+;?/g, '') + .replace(/color:/g, 'fill:'); + select(svgLabel).select('text').attr('style', edgeLabelTextStyle); + } return svgLabel; } }; diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts index 7362e6f70..3ab4167a2 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-irregular-whitespace */ import { markdownToLines, markdownToHTML } from './handle-markdown-text.js'; import { test, expect } from 'vitest'; @@ -37,9 +36,9 @@ Here is a line *with an italic* section`; { content: 'is', type: 'normal' }, { content: 'a', type: 'normal' }, { content: 'line', type: 'normal' }, - { content: 'with', type: 'emphasis' }, - { content: 'an', type: 'emphasis' }, - { content: 'italic', type: 'emphasis' }, + { content: 'with', type: 'em' }, + { content: 'an', type: 'em' }, + { content: 'italic', type: 'em' }, { content: 'section', type: 'normal' }, ], ]; @@ -143,7 +142,7 @@ test('markdownToLines - Only italic formatting', () => { { content: 'This', type: 'normal' }, { content: 'is', type: 'normal' }, { content: 'an', type: 'normal' }, - { content: 'italic', type: 'emphasis' }, + { content: 'italic', type: 'em' }, { content: 'test', type: 'normal' }, ], ]; @@ -156,7 +155,7 @@ it('markdownToLines - Mixed formatting', () => { let input = `*Italic* and **bold** formatting`; let expected = [ [ - { content: 'Italic', type: 'emphasis' }, + { content: 'Italic', type: 'em' }, { content: 'and', type: 'normal' }, { content: 'bold', type: 'strong' }, { content: 'formatting', type: 'normal' }, @@ -167,9 +166,9 @@ it('markdownToLines - Mixed formatting', () => { input = `*Italic with space* and **bold ws** formatting`; expected = [ [ - { content: 'Italic', type: 'emphasis' }, - { content: 'with', type: 'emphasis' }, - { content: 'space', type: 'emphasis' }, + { content: 'Italic', type: 'em' }, + { content: 'with', type: 'em' }, + { content: 'space', type: 'em' }, { content: 'and', type: 'normal' }, { content: 'bold', type: 'strong' }, { content: 'ws', type: 'strong' }, @@ -191,9 +190,9 @@ Word!`; { content: 'the', type: 'strong' }, { content: 'hog...', type: 'normal' }, { content: 'a', type: 'normal' }, - { content: 'very', type: 'emphasis' }, - { content: 'long', type: 'emphasis' }, - { content: 'text', type: 'emphasis' }, + { content: 'very', type: 'em' }, + { content: 'long', type: 'em' }, + { content: 'text', type: 'em' }, { content: 'about', type: 'normal' }, { content: 'it', type: 'normal' }, ], @@ -215,13 +214,13 @@ test('markdownToLines - No auto wrapping', () => { [ [ { - "content": "Hello, how do", + "content": "Hello, how do", "type": "normal", }, ], [ { - "content": "you do?", + "content": "you do?", "type": "normal", }, ], @@ -298,3 +297,13 @@ test('markdownToHTML - no auto wrapping', () => { ) ).toMatchInlineSnapshot('"

Hello, how do
you do?

"'); }); + +test('markdownToHTML - auto wrapping', () => { + expect( + markdownToHTML( + `Hello, how do + you do?`, + { markdownAutoWrap: true } + ) + ).toMatchInlineSnapshot('"

Hello, how do
you do?

"'); +}); diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.ts index c539f7268..f898875cf 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.ts +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.ts @@ -1,5 +1,5 @@ -import type { Content } from 'mdast'; -import { fromMarkdown } from 'mdast-util-from-markdown'; +import type { MarkedToken, Token } from 'marked'; +import { marked } from 'marked'; import { dedent } from 'ts-dedent'; import type { MarkdownLine, MarkdownWordType } from './types.js'; import type { MermaidConfig } from '../config.type.js'; @@ -9,8 +9,10 @@ import type { MermaidConfig } from '../config.type.js'; * @returns processed markdown */ function preprocessMarkdown(markdown: string, { markdownAutoWrap }: MermaidConfig): string { + //Replace
with \n + const withoutBR = markdown.replace(//g, '\n'); // Replace multiple newlines with a single newline - const withoutMultipleNewlines = markdown.replace(/\n{2,}/g, '\n'); + const withoutMultipleNewlines = withoutBR.replace(/\n{2,}/g, '\n'); // Remove extra spaces at the beginning of each line const withoutExtraSpaces = dedent(withoutMultipleNewlines); if (markdownAutoWrap === false) { @@ -24,36 +26,41 @@ function preprocessMarkdown(markdown: string, { markdownAutoWrap }: MermaidConfi */ export function markdownToLines(markdown: string, config: MermaidConfig = {}): MarkdownLine[] { const preprocessedMarkdown = preprocessMarkdown(markdown, config); - const { children } = fromMarkdown(preprocessedMarkdown); + const nodes = marked.lexer(preprocessedMarkdown); const lines: MarkdownLine[] = [[]]; let currentLine = 0; - function processNode(node: Content, parentType: MarkdownWordType = 'normal') { + function processNode(node: MarkedToken, parentType: MarkdownWordType = 'normal') { if (node.type === 'text') { - const textLines = node.value.split('\n'); + const textLines = node.text.split('\n'); textLines.forEach((textLine, index) => { if (index !== 0) { currentLine++; lines.push([]); } textLine.split(' ').forEach((word) => { + word = word.replace(/'/g, `'`); if (word) { lines[currentLine].push({ content: word, type: parentType }); } }); }); - } else if (node.type === 'strong' || node.type === 'emphasis') { - node.children.forEach((contentNode) => { - processNode(contentNode, node.type); + } else if (node.type === 'strong' || node.type === 'em') { + node.tokens.forEach((contentNode) => { + processNode(contentNode as MarkedToken, node.type); }); + } else if (node.type === 'html') { + lines[currentLine].push({ content: node.text, type: 'normal' }); } } - children.forEach((treeNode) => { + nodes.forEach((treeNode) => { if (treeNode.type === 'paragraph') { - treeNode.children.forEach((contentNode) => { - processNode(contentNode); + treeNode.tokens?.forEach((contentNode) => { + processNode(contentNode as MarkedToken); }); + } else if (treeNode.type === 'html') { + lines[currentLine].push({ content: treeNode.text, type: 'normal' }); } }); @@ -61,23 +68,29 @@ export function markdownToLines(markdown: string, config: MermaidConfig = {}): M } export function markdownToHTML(markdown: string, { markdownAutoWrap }: MermaidConfig = {}) { - const { children } = fromMarkdown(markdown); + const nodes = marked.lexer(markdown); - function output(node: Content): string { + function output(node: Token): string { if (node.type === 'text') { if (markdownAutoWrap === false) { - return node.value.replace(/\n/g, '
').replace(/ /g, ' '); + return node.text.replace(/\n */g, '
').replace(/ /g, ' '); } - return node.value.replace(/\n/g, '
'); + return node.text.replace(/\n */g, '
'); } else if (node.type === 'strong') { - return `${node.children.map(output).join('')}`; - } else if (node.type === 'emphasis') { - return `${node.children.map(output).join('')}`; + return `${node.tokens?.map(output).join('')}`; + } else if (node.type === 'em') { + return `${node.tokens?.map(output).join('')}`; } else if (node.type === 'paragraph') { - return `

${node.children.map(output).join('')}

`; + return `

${node.tokens?.map(output).join('')}

`; + } else if (node.type === 'space') { + return ''; + } else if (node.type === 'html') { + return `${node.text}`; + } else if (node.type === 'escape') { + return node.text; } return `Unsupported markdown: ${node.type}`; } - return children.map(output).join(''); + return nodes.map(output).join(''); } diff --git a/packages/mermaid/src/rendering-util/icons.ts b/packages/mermaid/src/rendering-util/icons.ts new file mode 100644 index 000000000..5eef3f7eb --- /dev/null +++ b/packages/mermaid/src/rendering-util/icons.ts @@ -0,0 +1,100 @@ +import { log } from '../logger.js'; +import type { ExtendedIconifyIcon, IconifyIcon, IconifyJSON } from '@iconify/types'; +import type { IconifyIconCustomisations } from '@iconify/utils'; +import { getIconData, iconToHTML, iconToSVG, replaceIDs, stringToIcon } from '@iconify/utils'; + +interface AsyncIconLoader { + name: string; + loader: () => Promise; +} + +interface SyncIconLoader { + name: string; + icons: IconifyJSON; +} + +export type IconLoader = AsyncIconLoader | SyncIconLoader; + +export const unknownIcon: IconifyIcon = { + body: '?', + height: 80, + width: 80, +}; + +const iconsStore = new Map(); +const loaderStore = new Map(); + +export const registerIconPacks = (iconLoaders: IconLoader[]) => { + for (const iconLoader of iconLoaders) { + if (!iconLoader.name) { + throw new Error( + 'Invalid icon loader. Must have a "name" property with non-empty string value.' + ); + } + log.debug('Registering icon pack:', iconLoader.name); + if ('loader' in iconLoader) { + loaderStore.set(iconLoader.name, iconLoader.loader); + } else if ('icons' in iconLoader) { + iconsStore.set(iconLoader.name, iconLoader.icons); + } else { + log.error('Invalid icon loader:', iconLoader); + throw new Error('Invalid icon loader. Must have either "icons" or "loader" property.'); + } + } +}; + +const getRegisteredIconData = async (iconName: string, fallbackPrefix?: string) => { + const data = stringToIcon(iconName, true, fallbackPrefix !== undefined); + if (!data) { + throw new Error(`Invalid icon name: ${iconName}`); + } + const prefix = data.prefix || fallbackPrefix; + if (!prefix) { + throw new Error(`Icon name must contain a prefix: ${iconName}`); + } + let icons = iconsStore.get(prefix); + if (!icons) { + const loader = loaderStore.get(prefix); + if (!loader) { + throw new Error(`Icon set not found: ${data.prefix}`); + } + try { + const loaded = await loader(); + icons = { ...loaded, prefix }; + iconsStore.set(prefix, icons); + } catch (e) { + log.error(e); + throw new Error(`Failed to load icon set: ${data.prefix}`); + } + } + const iconData = getIconData(icons, data.name); + if (!iconData) { + throw new Error(`Icon not found: ${iconName}`); + } + return iconData; +}; + +export const isIconAvailable = async (iconName: string) => { + try { + await getRegisteredIconData(iconName); + return true; + } catch { + return false; + } +}; + +export const getIconSVG = async ( + iconName: string, + customisations?: IconifyIconCustomisations & { fallbackPrefix?: string } +) => { + let iconData: ExtendedIconifyIcon; + try { + iconData = await getRegisteredIconData(iconName, customisations?.fallbackPrefix); + } catch (e) { + log.error(e); + iconData = unknownIcon; + } + const renderData = iconToSVG(iconData, customisations); + const svg = iconToHTML(replaceIDs(renderData.body), renderData.attributes); + return svg; +}; diff --git a/packages/mermaid/src/rendering-util/insertElementsForSize.js b/packages/mermaid/src/rendering-util/insertElementsForSize.js new file mode 100644 index 000000000..b71286351 --- /dev/null +++ b/packages/mermaid/src/rendering-util/insertElementsForSize.js @@ -0,0 +1,18 @@ +import { select } from 'd3'; + +export const getDiagramElement = (id, securityLevel) => { + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + + const svg = root.select(`[id="${id}"]`); + + // Run the renderer. This is what draws the final graph. + + return svg; +}; diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js new file mode 100644 index 000000000..e9f0266e2 --- /dev/null +++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js @@ -0,0 +1,379 @@ +import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js'; +import * as graphlibJson from 'dagre-d3-es/src/graphlib/json.js'; +import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; +import insertMarkers from '../../rendering-elements/markers.js'; +import { updateNodeBounds } from '../../rendering-elements/shapes/util.js'; +import { + clear as clearGraphlib, + clusterDb, + adjustClustersAndEdges, + findNonClusterChild, + sortNodesByHierarchy, +} from './mermaid-graphlib.js'; +import { + insertNode, + positionNode, + clear as clearNodes, + setNodeElem, +} from '../../rendering-elements/nodes.js'; +import { insertCluster, clear as clearClusters } from '../../rendering-elements/clusters.js'; +import { + insertEdgeLabel, + positionEdgeLabel, + insertEdge, + clear as clearEdges, +} from '../../rendering-elements/edges.js'; +import { log } from '../../../logger.js'; +import { getSubGraphTitleMargins } from '../../../utils/subGraphTitleMargins.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; + +const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, siteConfig) => { + log.warn('Graph in recursive render:XAX', graphlibJson.write(graph), parentCluster); + const dir = graph.graph().rankdir; + log.trace('Dir in recursive render - dir:', dir); + + const elem = _elem.insert('g').attr('class', 'root'); + if (!graph.nodes()) { + log.info('No nodes found for', graph); + } else { + log.info('Recursive render XXX', graph.nodes()); + } + if (graph.edges().length > 0) { + log.info('Recursive edges', graph.edge(graph.edges()[0])); + } + const clusters = elem.insert('g').attr('class', 'clusters'); + const edgePaths = elem.insert('g').attr('class', 'edgePaths'); + const edgeLabels = elem.insert('g').attr('class', 'edgeLabels'); + const nodes = elem.insert('g').attr('class', 'nodes'); + + // Insert nodes, this will insert them into the dom and each node will get a size. The size is updated + // to the abstract node and is later used by dagre for the layout + await Promise.all( + graph.nodes().map(async function (v) { + const node = graph.node(v); + if (parentCluster !== undefined) { + const data = JSON.parse(JSON.stringify(parentCluster.clusterData)); + // data.clusterPositioning = true; + log.trace( + 'Setting data for parent cluster XXX\n Node.id = ', + v, + '\n data=', + data.height, + '\nParent cluster', + parentCluster.height + ); + graph.setNode(parentCluster.id, data); + if (!graph.parent(v)) { + log.trace('Setting parent', v, parentCluster.id); + graph.setParent(v, parentCluster.id, data); + } + } + log.info('(Insert) Node XXX' + v + ': ' + JSON.stringify(graph.node(v))); + if (node?.clusterNode) { + // const children = graph.children(v); + log.info('Cluster identified XBX', v, node.width, graph.node(v)); + + // `node.graph.setGraph` applies the graph configurations such as nodeSpacing to subgraphs as without this the default values would be used + // We override only the `ranksep` and `nodesep` configurations to allow for setting subgraph spacing while avoiding overriding other properties + const { ranksep, nodesep } = graph.graph(); + node.graph.setGraph({ + ...node.graph.graph(), + ranksep: ranksep + 25, + nodesep, + }); + + // "o" will contain the full cluster not just the children + const o = await recursiveRender( + nodes, + node.graph, + diagramType, + id, + graph.node(v), + siteConfig + ); + const newEl = o.elem; + updateNodeBounds(node, newEl); + // node.height = o.diff; + node.diff = o.diff || 0; + log.info( + 'New compound node after recursive render XAX', + v, + 'width', + // node, + node.width, + 'height', + node.height + // node.x, + // node.y + ); + setNodeElem(newEl, node); + } else { + if (graph.children(v).length > 0) { + // This is a cluster but not to be rendered recursively + // Render as before + log.trace( + 'Cluster - the non recursive path XBX', + v, + node.id, + node, + node.width, + 'Graph:', + graph + ); + log.trace(findNonClusterChild(node.id, graph)); + clusterDb.set(node.id, { id: findNonClusterChild(node.id, graph), node }); + // insertCluster(clusters, graph.node(v)); + } else { + log.trace('Node - the non recursive path XAX', v, nodes, graph.node(v), dir); + await insertNode(nodes, graph.node(v), { config: siteConfig, dir }); + } + } + }) + ); + + const processEdges = async () => { + const edgePromises = graph.edges().map(async function (e) { + const edge = graph.edge(e.v, e.w, e.name); + log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e)); + log.info('Edge ' + e.v + ' -> ' + e.w + ': ', e, ' ', JSON.stringify(graph.edge(e))); + + // Check if link is either from or to a cluster + log.info( + 'Fix', + clusterDb, + 'ids:', + e.v, + e.w, + 'Translating: ', + clusterDb.get(e.v), + clusterDb.get(e.w) + ); + await insertEdgeLabel(edgeLabels, edge); + }); + + await Promise.all(edgePromises); + }; + + await processEdges(); + + log.info('Graph before layout:', JSON.stringify(graphlibJson.write(graph))); + + log.info('############################################# XXX'); + log.info('### Layout ### XXX'); + log.info('############################################# XXX'); + + dagreLayout(graph); + + log.info('Graph after layout:', JSON.stringify(graphlibJson.write(graph))); + // Move the nodes to the correct place + let diff = 0; + let { subGraphTitleTotalMargin } = getSubGraphTitleMargins(siteConfig); + await Promise.all( + sortNodesByHierarchy(graph).map(async function (v) { + const node = graph.node(v); + log.info( + 'Position XBX => ' + v + ': (' + node.x, + ',' + node.y, + ') width: ', + node.width, + ' height: ', + node.height + ); + if (node?.clusterNode) { + // Adjust for padding when on root level + node.y += subGraphTitleTotalMargin; + + log.info( + 'A tainted cluster node XBX1', + v, + node.id, + node.width, + node.height, + node.x, + node.y, + graph.parent(v) + ); + clusterDb.get(node.id).node = node; + positionNode(node); + } else { + // A tainted cluster node + if (graph.children(v).length > 0) { + log.info( + 'A pure cluster node XBX1', + v, + node.id, + node.x, + node.y, + node.width, + node.height, + graph.parent(v) + ); + node.height += subGraphTitleTotalMargin; + graph.node(node.parentId); + const halfPadding = node?.padding / 2 || 0; + const labelHeight = node?.labelBBox?.height || 0; + const offsetY = labelHeight - halfPadding || 0; + log.debug('OffsetY', offsetY, 'labelHeight', labelHeight, 'halfPadding', halfPadding); + await insertCluster(clusters, node); + + // A cluster in the non-recursive way + clusterDb.get(node.id).node = node; + } else { + // Regular node + const parent = graph.node(node.parentId); + node.y += subGraphTitleTotalMargin / 2; + log.info( + 'A regular node XBX1 - using the padding', + node.id, + 'parent', + node.parentId, + node.width, + node.height, + node.x, + node.y, + 'offsetY', + node.offsetY, + 'parent', + parent, + parent?.offsetY, + node + ); + + positionNode(node); + } + } + }) + ); + + // Move the edge labels to the correct place after layout + graph.edges().forEach(function (e) { + const edge = graph.edge(e); + log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge); + + edge.points.forEach((point) => (point.y += subGraphTitleTotalMargin / 2)); + const startNode = graph.node(e.v); + var endNode = graph.node(e.w); + const paths = insertEdge(edgePaths, edge, clusterDb, diagramType, startNode, endNode, id); + positionEdgeLabel(edge, paths); + }); + + graph.nodes().forEach(function (v) { + const n = graph.node(v); + log.info(v, n.type, n.diff); + if (n.isGroup) { + diff = n.diff; + } + }); + log.warn('Returning from recursive render XAX', elem, diff); + return { elem, diff }; +}; + +export const render = async (data4Layout, svg) => { + const graph = new graphlib.Graph({ + multigraph: true, + compound: true, + }) + .setGraph({ + rankdir: data4Layout.direction, + nodesep: + data4Layout.config?.nodeSpacing || + data4Layout.config?.flowchart?.nodeSpacing || + data4Layout.nodeSpacing, + ranksep: + data4Layout.config?.rankSpacing || + data4Layout.config?.flowchart?.rankSpacing || + data4Layout.rankSpacing, + marginx: 8, + marginy: 8, + }) + .setDefaultEdgeLabel(function () { + return {}; + }); + const element = svg.select('g'); + insertMarkers(element, data4Layout.markers, data4Layout.type, data4Layout.diagramId); + clearNodes(); + clearEdges(); + clearClusters(); + clearGraphlib(); + + data4Layout.nodes.forEach((node) => { + graph.setNode(node.id, { ...node }); + if (node.parentId) { + graph.setParent(node.id, node.parentId); + } + }); + + log.debug('Edges:', data4Layout.edges); + data4Layout.edges.forEach((edge) => { + // Handle self-loops + if (edge.start === edge.end) { + const nodeId = edge.start; + const specialId1 = nodeId + '---' + nodeId + '---1'; + const specialId2 = nodeId + '---' + nodeId + '---2'; + const node = graph.node(nodeId); + graph.setNode(specialId1, { + domId: specialId1, + id: specialId1, + parentId: node.parentId, + labelStyle: '', + label: '', + padding: 0, + shape: 'labelRect', + // shape: 'rect', + style: '', + width: 10, + height: 10, + }); + graph.setParent(specialId1, node.parentId); + graph.setNode(specialId2, { + domId: specialId2, + id: specialId2, + parentId: node.parentId, + labelStyle: '', + padding: 0, + // shape: 'rect', + shape: 'labelRect', + label: '', + style: '', + width: 10, + height: 10, + }); + graph.setParent(specialId2, node.parentId); + + const edge1 = structuredClone(edge); + const edgeMid = structuredClone(edge); + const edge2 = structuredClone(edge); + edge1.label = ''; + edge1.arrowTypeEnd = 'none'; + edge1.id = nodeId + '-cyclic-special-1'; + edgeMid.arrowTypeStart = 'none'; + edgeMid.arrowTypeEnd = 'none'; + edgeMid.id = nodeId + '-cyclic-special-mid'; + edge2.label = ''; + if (node.isGroup) { + edge1.fromCluster = nodeId; + edge2.toCluster = nodeId; + } + edge2.id = nodeId + '-cyclic-special-2'; + edge2.arrowTypeStart = 'none'; + graph.setEdge(nodeId, specialId1, edge1, nodeId + '-cyclic-special-0'); + graph.setEdge(specialId1, specialId2, edgeMid, nodeId + '-cyclic-special-1'); + graph.setEdge(specialId2, nodeId, edge2, nodeId + '-cyc { + descendants.clear(); + parents.clear(); + clusterDb.clear(); +}; + +const isDescendant = (id, ancestorId) => { + const ancestorDescendants = descendants.get(ancestorId) || []; + log.trace('In isDescendant', ancestorId, ' ', id, ' = ', ancestorDescendants.includes(id)); + return ancestorDescendants.includes(id); +}; + +const edgeInCluster = (edge, clusterId) => { + const clusterDescendants = descendants.get(clusterId) || []; + log.info('Descendants of ', clusterId, ' is ', clusterDescendants); + log.info('Edge is ', edge); + if (edge.v === clusterId || edge.w === clusterId) { + return false; + } + + if (!clusterDescendants) { + log.debug('Tilt, ', clusterId, ',not in descendants'); + return false; + } + + return ( + clusterDescendants.includes(edge.v) || + isDescendant(edge.v, clusterId) || + isDescendant(edge.w, clusterId) || + clusterDescendants.includes(edge.w) + ); +}; + +const copy = (clusterId, graph, newGraph, rootId) => { + log.warn( + 'Copying children of ', + clusterId, + 'root', + rootId, + 'data', + graph.node(clusterId), + rootId + ); + const nodes = graph.children(clusterId) || []; + + if (clusterId !== rootId) { + nodes.push(clusterId); + } + + log.warn('Copying (nodes) clusterId', clusterId, 'nodes', nodes); + + nodes.forEach((node) => { + if (graph.children(node).length > 0) { + copy(node, graph, newGraph, rootId); + } else { + const data = graph.node(node); + log.info('cp ', node, ' to ', rootId, ' with parent ', clusterId); + newGraph.setNode(node, data); + if (rootId !== graph.parent(node)) { + log.warn('Setting parent', node, graph.parent(node)); + newGraph.setParent(node, graph.parent(node)); + } + + if (clusterId !== rootId && node !== clusterId) { + log.debug('Setting parent', node, clusterId); + newGraph.setParent(node, clusterId); + } else { + log.info('In copy ', clusterId, 'root', rootId, 'data', graph.node(clusterId), rootId); + log.debug( + 'Not Setting parent for node=', + node, + 'cluster!==rootId', + clusterId !== rootId, + 'node!==clusterId', + node !== clusterId + ); + } + const edges = graph.edges(node); + log.debug('Copying Edges', edges); + edges.forEach((edge) => { + log.info('Edge', edge); + const data = graph.edge(edge.v, edge.w, edge.name); + log.info('Edge data', data, rootId); + try { + if (edgeInCluster(edge, rootId)) { + log.info('Copying as ', edge.v, edge.w, data, edge.name); + newGraph.setEdge(edge.v, edge.w, data, edge.name); + log.info('newGraph edges ', newGraph.edges(), newGraph.edge(newGraph.edges()[0])); + } else { + log.info( + 'Skipping copy of edge ', + edge.v, + '-->', + edge.w, + ' rootId: ', + rootId, + ' clusterId:', + clusterId + ); + } + } catch (e) { + log.error(e); + } + }); + } + log.debug('Removing node', node); + graph.removeNode(node); + }); +}; + +export const extractDescendants = (id, graph) => { + const children = graph.children(id); + let res = [...children]; + + for (const child of children) { + parents.set(child, id); + res = [...res, ...extractDescendants(child, graph)]; + } + + return res; +}; + +export const validate = (graph) => { + const edges = graph.edges(); + log.trace('Edges: ', edges); + for (const edge of edges) { + if (graph.children(edge.v).length > 0) { + log.trace('The node ', edge.v, ' is part of and edge even though it has children'); + return false; + } + if (graph.children(edge.w).length > 0) { + log.trace('The node ', edge.w, ' is part of and edge even though it has children'); + return false; + } + } + return true; +}; + +const findCommonEdges = (graph, id1, id2) => { + const edges1 = graph.edges().filter((edge) => edge.v === id1 || edge.w === id1); + const edges2 = graph.edges().filter((edge) => edge.v === id2 || edge.w === id2); + const edges1Prim = edges1.map((edge) => { + return { v: edge.v === id1 ? id2 : edge.v, w: edge.w === id1 ? id1 : edge.w }; + }); + const edges2Prim = edges2.map((edge) => { + return { v: edge.v, w: edge.w }; + }); + const result = edges1Prim.filter((edgeIn1) => { + return edges2Prim.some((edge) => edgeIn1.v === edge.v && edgeIn1.w === edge.w); + }); + + return result; +}; + +export const findNonClusterChild = (id, graph, clusterId) => { + const children = graph.children(id); + log.trace('Searching children of id ', id, children); + if (children.length < 1) { + return id; + } + let reserve; + for (const child of children) { + const _id = findNonClusterChild(child, graph, clusterId); + + const commonEdges = findCommonEdges(graph, clusterId, _id); + + if (_id) { + if (commonEdges.length > 0) { + reserve = _id; + } else { + return _id; + } + } + } + return reserve; +}; + +const getAnchorId = (id) => { + if (!clusterDb.has(id)) { + return id; + } + if (!clusterDb.get(id).externalConnections) { + return id; + } + + if (clusterDb.has(id)) { + return clusterDb.get(id).id; + } + return id; +}; + +export const adjustClustersAndEdges = (graph, depth) => { + if (!graph || depth > 10) { + log.debug('Opting out, no graph '); + return; + } else { + log.debug('Opting in, graph '); + } + + graph.nodes().forEach(function (id) { + const children = graph.children(id); + if (children.length > 0) { + log.warn( + 'Cluster identified', + id, + ' Replacement id in edges: ', + findNonClusterChild(id, graph, id) + ); + descendants.set(id, extractDescendants(id, graph)); + clusterDb.set(id, { id: findNonClusterChild(id, graph, id), clusterData: graph.node(id) }); + } + }); + + graph.nodes().forEach(function (id) { + const children = graph.children(id); + const edges = graph.edges(); + if (children.length > 0) { + log.debug('Cluster identified', id, descendants); + edges.forEach((edge) => { + const d1 = isDescendant(edge.v, id); + const d2 = isDescendant(edge.w, id); + + if (d1 ^ d2) { + log.warn('Edge: ', edge, ' leaves cluster ', id); + log.warn('Descendants of XXX ', id, ': ', descendants.get(id)); + clusterDb.get(id).externalConnections = true; + } + }); + } else { + log.debug('Not a cluster ', id, descendants); + } + }); + + for (let id of clusterDb.keys()) { + const nonClusterChild = clusterDb.get(id).id; + const parent = graph.parent(nonClusterChild); + + if (parent !== id && clusterDb.has(parent) && !clusterDb.get(parent).externalConnections) { + clusterDb.get(id).id = parent; + } + } + + graph.edges().forEach(function (e) { + const edge = graph.edge(e); + log.warn('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e)); + log.warn('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(graph.edge(e))); + + let v = e.v; + let w = e.w; + log.warn( + 'Fix XXX', + clusterDb, + 'ids:', + e.v, + e.w, + 'Translating: ', + clusterDb.get(e.v), + ' --- ', + clusterDb.get(e.w) + ); + if (clusterDb.get(e.v) || clusterDb.get(e.w)) { + log.warn('Fixing and trying - removing XXX', e.v, e.w, e.name); + v = getAnchorId(e.v); + w = getAnchorId(e.w); + graph.removeEdge(e.v, e.w, e.name); + if (v !== e.v) { + const parent = graph.parent(v); + clusterDb.get(parent).externalConnections = true; + edge.fromCluster = e.v; + } + if (w !== e.w) { + const parent = graph.parent(w); + clusterDb.get(parent).externalConnections = true; + edge.toCluster = e.w; + } + log.warn('Fix Replacing with XXX', v, w, e.name); + graph.setEdge(v, w, edge, e.name); + } + }); + log.warn('Adjusted Graph', graphlibJson.write(graph)); + extractor(graph, 0); + + log.trace(clusterDb); +}; + +export const extractor = (graph, depth) => { + log.warn('extractor - ', depth, graphlibJson.write(graph), graph.children('D')); + if (depth > 10) { + log.error('Bailing out'); + return; + } + let nodes = graph.nodes(); + let hasChildren = false; + for (const node of nodes) { + const children = graph.children(node); + hasChildren = hasChildren || children.length > 0; + } + + if (!hasChildren) { + log.debug('Done, no node has children', graph.nodes()); + return; + } + log.debug('Nodes = ', nodes, depth); + for (const node of nodes) { + log.debug( + 'Extracting node', + node, + clusterDb, + clusterDb.has(node) && !clusterDb.get(node).externalConnections, + !graph.parent(node), + graph.node(node), + graph.children('D'), + ' Depth ', + depth + ); + if (!clusterDb.has(node)) { + log.debug('Not a cluster', node, depth); + } else if ( + !clusterDb.get(node).externalConnections && + graph.children(node) && + graph.children(node).length > 0 + ) { + log.warn( + 'Cluster without external connections, without a parent and with children', + node, + depth + ); + + const graphSettings = graph.graph(); + let dir = graphSettings.rankdir === 'TB' ? 'LR' : 'TB'; + if (clusterDb.get(node)?.clusterData?.dir) { + dir = clusterDb.get(node).clusterData.dir; + log.warn('Fixing dir', clusterDb.get(node).clusterData.dir, dir); + } + + const clusterGraph = new graphlib.Graph({ + multigraph: true, + compound: true, + }) + .setGraph({ + rankdir: dir, + nodesep: 50, + ranksep: 50, + marginx: 8, + marginy: 8, + }) + .setDefaultEdgeLabel(function () { + return {}; + }); + + log.warn('Old graph before copy', graphlibJson.write(graph)); + copy(node, graph, clusterGraph, node); + graph.setNode(node, { + clusterNode: true, + id: node, + clusterData: clusterDb.get(node).clusterData, + label: clusterDb.get(node).label, + graph: clusterGraph, + }); + log.warn('New graph after copy node: (', node, ')', graphlibJson.write(clusterGraph)); + log.debug('Old graph after copy', graphlibJson.write(graph)); + } else { + log.warn( + 'Cluster ** ', + node, + ' **not meeting the criteria !externalConnections:', + !clusterDb.get(node).externalConnections, + ' no parent: ', + !graph.parent(node), + ' children ', + graph.children(node) && graph.children(node).length > 0, + graph.children('D'), + depth + ); + log.debug(clusterDb); + } + } + + nodes = graph.nodes(); + log.warn('New list of nodes', nodes); + for (const node of nodes) { + const data = graph.node(node); + log.warn(' Now next level', node, data); + if (data?.clusterNode) { + extractor(data.graph, depth + 1); + } + } +}; + +const sorter = (graph, nodes) => { + if (nodes.length === 0) { + return []; + } + let result = Object.assign([], nodes); + nodes.forEach((node) => { + const children = graph.children(node); + const sorted = sorter(graph, children); + result = [...result, ...sorted]; + }); + + return result; +}; + +export const sortNodesByHierarchy = (graph) => sorter(graph, graph.children()); diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.spec.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.spec.js new file mode 100644 index 000000000..11acd44eb --- /dev/null +++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.spec.js @@ -0,0 +1,508 @@ +import * as graphlibJson from 'dagre-d3-es/src/graphlib/json.js'; +import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; +import { + validate, + adjustClustersAndEdges, + extractDescendants, + sortNodesByHierarchy, +} from './mermaid-graphlib.js'; +import { setLogLevel, log } from '../../../logger.js'; + +describe('Graphlib decorations', () => { + let g; + beforeEach(function () { + setLogLevel(1); + g = new graphlib.Graph({ + multigraph: true, + compound: true, + }); + g.setGraph({ + rankdir: 'TB', + nodesep: 10, + ranksep: 10, + marginx: 8, + marginy: 8, + }); + g.setDefaultEdgeLabel(function () { + return {}; + }); + }); + + describe('validate', function () { + it('Validate should detect edges between clusters', function () { + /* + subgraph C1 + a --> b + end + subgraph C2 + c + end + C1 --> C2 + */ + g.setNode('a', { data: 1 }); + g.setNode('b', { data: 2 }); + g.setNode('c', { data: 3 }); + g.setParent('a', 'C1'); + g.setParent('b', 'C1'); + g.setParent('c', 'C2'); + g.setEdge('a', 'b'); + g.setEdge('C1', 'C2'); + + expect(validate(g)).toBe(false); + }); + it('Validate should not detect edges between clusters after adjustment', function () { + /* + subgraph C1 + a --> b + end + subgraph C2 + c + end + C1 --> C2 + */ + g.setNode('a', {}); + g.setNode('b', {}); + g.setNode('c', {}); + g.setParent('a', 'C1'); + g.setParent('b', 'C1'); + g.setParent('c', 'C2'); + g.setEdge('a', 'b'); + g.setEdge('C1', 'C2'); + + adjustClustersAndEdges(g); + log.info(g.edges()); + expect(validate(g)).toBe(true); + }); + + it('Validate should detect edges between clusters and transform clusters GLB4', function () { + /* + a --> b + subgraph C1 + subgraph C2 + a + end + b + end + C1 --> c + */ + g.setNode('a', { data: 1 }); + g.setNode('b', { data: 2 }); + g.setNode('c', { data: 3 }); + g.setNode('C1', { data: 4 }); + g.setNode('C2', { data: 5 }); + g.setParent('a', 'C2'); + g.setParent('b', 'C1'); + g.setParent('C2', 'C1'); + g.setEdge('a', 'b', { name: 'C1-internal-link' }); + g.setEdge('C1', 'c', { name: 'C1-external-link' }); + + adjustClustersAndEdges(g); + log.info(g.nodes()); + expect(g.nodes().length).toBe(2); + expect(validate(g)).toBe(true); + }); + it('Validate should detect edges between clusters and transform clusters GLB5', function () { + /* + a --> b + subgraph C1 + a + end + subgraph C2 + b + end + C1 --> + */ + g.setNode('a', { data: 1 }); + g.setNode('b', { data: 2 }); + g.setParent('a', 'C1'); + g.setParent('b', 'C2'); + // g.setEdge('a', 'b', { name: 'C1-internal-link' }); + g.setEdge('C1', 'C2', { name: 'C1-external-link' }); + + log.info(g.nodes()); + adjustClustersAndEdges(g); + log.info(g.nodes()); + expect(g.nodes().length).toBe(2); + expect(validate(g)).toBe(true); + }); + it('adjustClustersAndEdges GLB6', function () { + /* + subgraph C1 + a + end + C1 --> b + */ + g.setNode('a', { data: 1 }); + g.setNode('b', { data: 2 }); + g.setNode('C1', { data: 3 }); + g.setParent('a', 'C1'); + g.setEdge('C1', 'b', { data: 'link1' }, '1'); + + // log.info(g.edges()) + adjustClustersAndEdges(g); + log.info(g.edges()); + expect(g.nodes()).toEqual(['b', 'C1']); + expect(g.edges().length).toBe(1); + expect(validate(g)).toBe(true); + expect(g.node('C1').clusterNode).toBe(true); + + const C1Graph = g.node('C1').graph; + expect(C1Graph.nodes()).toEqual(['a']); + }); + it('adjustClustersAndEdges GLB7', function () { + /* + subgraph C1 + a + end + C1 --> b + C1 --> c + */ + g.setNode('a', { data: 1 }); + g.setNode('b', { data: 2 }); + g.setNode('c', { data: 3 }); + g.setParent('a', 'C1'); + g.setNode('C1', { data: 4 }); + g.setEdge('C1', 'b', { data: 'link1' }, '1'); + g.setEdge('C1', 'c', { data: 'link2' }, '2'); + + log.info(g.node('C1')); + adjustClustersAndEdges(g); + log.info(g.edges()); + expect(g.nodes()).toEqual(['b', 'c', 'C1']); + expect(g.nodes().length).toBe(3); + expect(g.edges().length).toBe(2); + + expect(g.edges().length).toBe(2); + const edgeData = g.edge(g.edges()[1]); + expect(edgeData.data).toBe('link2'); + expect(validate(g)).toBe(true); + + const C1Graph = g.node('C1').graph; + expect(C1Graph.nodes()).toEqual(['a']); + }); + it('adjustClustersAndEdges GLB8', function () { + /* + subgraph A + a + end + subgraph B + b + end + subgraph C + c + end + A --> B + A --> C + */ + g.setNode('a', { data: 1 }); + g.setNode('b', { data: 2 }); + g.setNode('c', { data: 3 }); + g.setParent('a', 'A'); + g.setParent('b', 'B'); + g.setParent('c', 'C'); + g.setEdge('A', 'B', { data: 'link1' }, '1'); + g.setEdge('A', 'C', { data: 'link2' }, '2'); + + // log.info(g.edges()) + adjustClustersAndEdges(g); + expect(g.nodes()).toEqual(['A', 'B', 'C']); + expect(g.edges().length).toBe(2); + + expect(g.edges().length).toBe(2); + const edgeData = g.edge(g.edges()[1]); + expect(edgeData.data).toBe('link2'); + expect(validate(g)).toBe(true); + + const CGraph = g.node('C').graph; + expect(CGraph.nodes()).toEqual(['c']); + }); + + it('adjustClustersAndEdges the extracted graphs shall contain the correct data GLB10', function () { + /* + subgraph C + subgraph D + d + end + end + */ + + g.setNode('C', { data: 1 }); + g.setNode('D', { data: 2 }); + g.setNode('d', { data: 3 }); + g.setParent('d', 'D'); + g.setParent('D', 'C'); + + // log.info('Graph before', g.node('D')) + // log.info('Graph before', graphlibJson.write(g)) + adjustClustersAndEdges(g); + // log.info('Graph after', graphlibJson.write(g), g.node('C').graph) + + const CGraph = g.node('C').graph; + const DGraph = CGraph.node('D').graph; + + expect(CGraph.nodes()).toEqual(['D']); + expect(DGraph.nodes()).toEqual(['d']); + + expect(g.nodes()).toEqual(['C']); + expect(g.nodes().length).toBe(1); + }); + + it('adjustClustersAndEdges the extracted graphs shall contain the correct data GLB11', function () { + /* + subgraph A + a + end + subgraph B + b + end + subgraph C + subgraph D + d + end + end + A --> B + A --> C + */ + + g.setNode('C', { data: 1 }); + g.setNode('D', { data: 2 }); + g.setNode('d', { data: 3 }); + g.setNode('B', { data: 4 }); + g.setNode('b', { data: 5 }); + g.setNode('A', { data: 6 }); + g.setNode('a', { data: 7 }); + g.setParent('a', 'A'); + g.setParent('b', 'B'); + g.setParent('d', 'D'); + g.setParent('D', 'C'); + g.setEdge('A', 'B', { data: 'link1' }, '1'); + g.setEdge('A', 'C', { data: 'link2' }, '2'); + + log.info('Graph before', g.node('D')); + log.info('Graph before', graphlibJson.write(g)); + adjustClustersAndEdges(g); + log.trace('Graph after', graphlibJson.write(g)); + expect(g.nodes()).toEqual(['C', 'B', 'A']); + expect(g.nodes().length).toBe(3); + expect(g.edges().length).toBe(2); + + const AGraph = g.node('A').graph; + const BGraph = g.node('B').graph; + const CGraph = g.node('C').graph; + // log.info(CGraph.nodes()); + const DGraph = CGraph.node('D').graph; + // log.info('DG', CGraph.children('D')); + + log.info('A', AGraph.nodes()); + expect(AGraph.nodes().length).toBe(1); + expect(AGraph.nodes()).toEqual(['a']); + log.trace('Nodes', BGraph.nodes()); + expect(BGraph.nodes().length).toBe(1); + expect(BGraph.nodes()).toEqual(['b']); + expect(CGraph.nodes()).toEqual(['D']); + expect(CGraph.nodes().length).toEqual(1); + + expect(AGraph.edges().length).toBe(0); + expect(BGraph.edges().length).toBe(0); + expect(CGraph.edges().length).toBe(0); + expect(DGraph.nodes()).toEqual(['d']); + expect(DGraph.edges().length).toBe(0); + // expect(CGraph.node('D')).toEqual({ data: 2 }); + expect(g.edges().length).toBe(2); + + // expect(g.edges().length).toBe(2); + // const edgeData = g.edge(g.edges()[1]); + // expect(edgeData.data).toBe('link2'); + // expect(validate(g)).toBe(true); + }); + it('adjustClustersAndEdges the extracted graphs shall contain the correct links GLB20', function () { + /* + a --> b + subgraph b [Test] + c --> d -->e + end + */ + g.setNode('a', { data: 1 }); + g.setNode('b', { data: 2 }); + g.setNode('c', { data: 3 }); + g.setNode('d', { data: 3 }); + g.setNode('e', { data: 3 }); + g.setParent('c', 'b'); + g.setParent('d', 'b'); + g.setParent('e', 'b'); + g.setEdge('a', 'b', { data: 'link1' }, '1'); + g.setEdge('c', 'd', { data: 'link2' }, '2'); + g.setEdge('d', 'e', { data: 'link2' }, '2'); + + log.info('Graph before', graphlibJson.write(g)); + adjustClustersAndEdges(g); + const bGraph = g.node('b').graph; + // log.trace('Graph after', graphlibJson.write(g)) + log.info('Graph after', graphlibJson.write(bGraph)); + expect(bGraph.nodes().length).toBe(3); + expect(bGraph.edges().length).toBe(2); + }); + it('adjustClustersAndEdges the extracted graphs shall contain the correct links GLB21', function () { + /* + state a { + state b { + state c { + e + } + } + } + */ + g.setNode('a', { data: 1 }); + g.setNode('b', { data: 2 }); + g.setNode('c', { data: 3 }); + g.setNode('e', { data: 3 }); + g.setParent('b', 'a'); + g.setParent('c', 'b'); + g.setParent('e', 'c'); + + log.info('Graph before', graphlibJson.write(g)); + adjustClustersAndEdges(g); + const aGraph = g.node('a').graph; + const bGraph = aGraph.node('b').graph; + log.info('Graph after', graphlibJson.write(aGraph)); + const cGraph = bGraph.node('c').graph; + // log.trace('Graph after', graphlibJson.write(g)) + expect(aGraph.nodes().length).toBe(1); + expect(bGraph.nodes().length).toBe(1); + expect(cGraph.nodes().length).toBe(1); + expect(bGraph.edges().length).toBe(0); + }); + }); + it('adjustClustersAndEdges should handle nesting GLB77', function () { + /* +flowchart TB + subgraph A + b-->B + a-->c + end + subgraph B + c + end + */ + + const exportedGraph = JSON.parse( + '{"options":{"directed":true,"multigraph":true,"compound":true},"nodes":[{"v":"A","value":{"labelStyle":"","shape":"rect","labelText":"A","rx":0,"ry":0,"cssClass":"default","style":"","id":"A","width":500,"type":"group","padding":15}},{"v":"B","value":{"labelStyle":"","shape":"rect","labelText":"B","rx":0,"ry":0,"class":"default","style":"","id":"B","width":500,"type":"group","padding":15},"parent":"A"},{"v":"b","value":{"labelStyle":"","shape":"rect","labelText":"b","rx":0,"ry":0,"class":"default","style":"","id":"b","padding":15},"parent":"A"},{"v":"c","value":{"labelStyle":"","shape":"rect","labelText":"c","rx":0,"ry":0,"class":"default","style":"","id":"c","padding":15},"parent":"B"},{"v":"a","value":{"labelStyle":"","shape":"rect","labelText":"a","rx":0,"ry":0,"class":"default","style":"","id":"a","padding":15},"parent":"A"}],"edges":[{"v":"b","w":"B","name":"1","value":{"minlen":1,"arrowhead":"normal","arrowTypeStart":"arrow_open","arrowTypeEnd":"arrow_point","thickness":"normal","pattern":"solid","style":"fill:none","labelStyle":"","arrowheadStyle":"fill: #333","labelpos":"c","labelType":"text","label":"","id":"L-b-B","cssClasses":"flowchart-link LS-b LE-B"}},{"v":"a","w":"c","name":"2","value":{"minlen":1,"arrowhead":"normal","arrowTypeStart":"arrow_open","arrowTypeEnd":"arrow_point","thickness":"normal","pattern":"solid","style":"fill:none","labelStyle":"","arrowheadStyle":"fill: #333","labelpos":"c","labelType":"text","label":"","id":"L-a-c","cssClasses":"flowchart-link LS-a LE-c"}}],"value":{"rankdir":"TB","nodesep":50,"ranksep":50,"marginx":8,"marginy":8}}' + ); + const gr = graphlibJson.read(exportedGraph); + + log.info('Graph before', graphlibJson.write(gr)); + adjustClustersAndEdges(gr); + const aGraph = gr.node('A').graph; + const bGraph = aGraph.node('B').graph; + log.info('Graph after', graphlibJson.write(aGraph)); + // log.trace('Graph after', graphlibJson.write(g)) + expect(aGraph.parent('c')).toBe('B'); + expect(aGraph.parent('B')).toBe(undefined); + }); +}); +describe('extractDescendants', function () { + let g; + beforeEach(function () { + setLogLevel(1); + g = new graphlib.Graph({ + multigraph: true, + compound: true, + }); + g.setGraph({ + rankdir: 'TB', + nodesep: 10, + ranksep: 10, + marginx: 8, + marginy: 8, + }); + g.setDefaultEdgeLabel(function () { + return {}; + }); + }); + it('Simple case of one level descendants GLB9', function () { + /* + subgraph A + a + end + subgraph B + b + end + subgraph C + c + end + A --> B + A --> C + */ + g.setNode('a', { data: 1 }); + g.setNode('b', { data: 2 }); + g.setNode('c', { data: 3 }); + g.setParent('a', 'A'); + g.setParent('b', 'B'); + g.setParent('c', 'C'); + g.setEdge('A', 'B', { data: 'link1' }, '1'); + g.setEdge('A', 'C', { data: 'link2' }, '2'); + + // log.info(g.edges()) + const d1 = extractDescendants('A', g); + const d2 = extractDescendants('B', g); + const d3 = extractDescendants('C', g); + + expect(d1).toEqual(['a']); + expect(d2).toEqual(['b']); + expect(d3).toEqual(['c']); + }); +}); +describe('sortNodesByHierarchy', function () { + let g; + beforeEach(function () { + setLogLevel(1); + g = new graphlib.Graph({ + multigraph: true, + compound: true, + }); + g.setGraph({ + rankdir: 'TB', + nodesep: 10, + ranksep: 10, + marginx: 8, + marginy: 8, + }); + g.setDefaultEdgeLabel(function () { + return {}; + }); + }); + it('should sort proper en nodes are in reverse order', function () { + /* + a -->b + subgraph B + b + end + subgraph A + B + end + */ + g.setNode('a', { data: 1 }); + g.setNode('b', { data: 2 }); + g.setParent('b', 'B'); + g.setParent('B', 'A'); + g.setEdge('a', 'b', '1'); + expect(sortNodesByHierarchy(g)).toEqual(['a', 'A', 'B', 'b']); + }); + it('should sort proper en nodes are in correct order', function () { + /* + a -->b + subgraph B + b + end + subgraph A + B + end + */ + g.setNode('a', { data: 1 }); + g.setParent('B', 'A'); + g.setParent('b', 'B'); + g.setNode('b', { data: 2 }); + g.setEdge('a', 'b', '1'); + expect(sortNodesByHierarchy(g)).toEqual(['a', 'A', 'B', 'b']); + }); +}); diff --git a/packages/mermaid/src/rendering-util/render.ts b/packages/mermaid/src/rendering-util/render.ts new file mode 100644 index 000000000..b975e7bf9 --- /dev/null +++ b/packages/mermaid/src/rendering-util/render.ts @@ -0,0 +1,71 @@ +import type { SVG } from '../diagram-api/types.js'; +import type { InternalHelpers } from '../internals.js'; +import { internalHelpers } from '../internals.js'; +import { log } from '../logger.js'; +import type { LayoutData } from './types.js'; + +export interface RenderOptions { + algorithm?: string; +} + +export interface LayoutAlgorithm { + render( + layoutData: LayoutData, + svg: SVG, + helpers: InternalHelpers, + options?: RenderOptions + ): Promise; +} + +export type LayoutLoader = () => Promise; +export interface LayoutLoaderDefinition { + name: string; + loader: LayoutLoader; + algorithm?: string; +} + +const layoutAlgorithms: Record = {}; + +export const registerLayoutLoaders = (loaders: LayoutLoaderDefinition[]) => { + for (const loader of loaders) { + layoutAlgorithms[loader.name] = loader; + } +}; + +// TODO: Should we load dagre without lazy loading? +const registerDefaultLayoutLoaders = () => { + registerLayoutLoaders([ + { + name: 'dagre', + loader: async () => await import('./layout-algorithms/dagre/index.js'), + }, + ]); +}; + +registerDefaultLayoutLoaders(); + +export const render = async (data4Layout: LayoutData, svg: SVG) => { + if (!(data4Layout.layoutAlgorithm in layoutAlgorithms)) { + throw new Error(`Unknown layout algorithm: ${data4Layout.layoutAlgorithm}`); + } + + const layoutDefinition = layoutAlgorithms[data4Layout.layoutAlgorithm]; + const layoutRenderer = await layoutDefinition.loader(); + return layoutRenderer.render(data4Layout, svg, internalHelpers, { + algorithm: layoutDefinition.algorithm, + }); +}; + +/** + * Get the registered layout algorithm. If the algorithm is not registered, use the fallback algorithm. + */ +export const getRegisteredLayoutAlgorithm = (algorithm = '', { fallback = 'dagre' } = {}) => { + if (algorithm in layoutAlgorithms) { + return algorithm; + } + if (fallback in layoutAlgorithms) { + log.warn(`Layout algorithm ${algorithm} is not registered. Using ${fallback} as fallback.`); + return fallback; + } + throw new Error(`Both layout algorithms ${algorithm} and ${fallback} are not registered.`); +}; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js new file mode 100644 index 000000000..1dd87d438 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js @@ -0,0 +1,517 @@ +import { getConfig } from '../../diagram-api/diagramAPI.js'; +import { evaluate } from '../../diagrams/common/common.js'; +import { log } from '../../logger.js'; +import { getSubGraphTitleMargins } from '../../utils/subGraphTitleMargins.js'; +import { select } from 'd3'; +import rough from 'roughjs'; +import { createText } from '../createText.ts'; +import intersectRect from '../rendering-elements/intersect/intersect-rect.js'; +import createLabel from './createLabel.js'; +import { createRoundedRectPathD } from './shapes/roundedRectPath.ts'; +import { styles2String, userNodeOverrides } from './shapes/handDrawnShapeStyles.js'; + +const rect = async (parent, node) => { + log.info('Creating subgraph rect for ', node.id, node); + const siteConfig = getConfig(); + const { themeVariables, handDrawnSeed } = siteConfig; + const { clusterBkg, clusterBorder } = themeVariables; + + const { labelStyles, nodeStyles, borderStyles, backgroundStyles } = styles2String(node); + + // Add outer g element + const shapeSvg = parent + .insert('g') + .attr('class', 'cluster ' + node.cssClasses) + .attr('id', node.id) + .attr('data-look', node.look); + + const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels); + + // Create the label and insert it after the rect + const labelEl = shapeSvg.insert('g').attr('class', 'cluster-label '); + + const text = await createText(labelEl, node.label, { + style: node.labelStyle, + useHtmlLabels, + isNode: true, + }); + + // Get the size of the label + let bbox = text.getBBox(); + + if (evaluate(siteConfig.flowchart.htmlLabels)) { + const div = text.children[0]; + const dv = select(text); + bbox = div.getBoundingClientRect(); + dv.attr('width', bbox.width); + dv.attr('height', bbox.height); + } + + const width = node.width <= bbox.width + node.padding ? bbox.width + node.padding : node.width; + if (node.width <= bbox.width + node.padding) { + node.diff = (width - node.width) / 2 - node.padding; + } else { + node.diff = -node.padding; + } + + const height = node.height; + const x = node.x - width / 2; + const y = node.y - height / 2; + + log.trace('Data ', node, JSON.stringify(node)); + let rect; + if (node.look === 'handDrawn') { + // @ts-ignore TODO: Fix rough typings + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { + roughness: 0.7, + fill: clusterBkg, + // fill: 'red', + stroke: clusterBorder, + fillWeight: 3, + seed: handDrawnSeed, + }); + const roughNode = rc.path(createRoundedRectPathD(x, y, width, height, 0), options); + rect = shapeSvg.insert(() => { + log.debug('Rough node insert CXC', roughNode); + return roughNode; + }, ':first-child'); + // Should we affect the options instead of doing this? + rect.select('path:nth-child(2)').attr('style', borderStyles.join(';')); + rect.select('path').attr('style', backgroundStyles.join(';').replace('fill', 'stroke')); + } else { + // add the rect + rect = shapeSvg.insert('rect', ':first-child'); + // center the rect around its coordinate + rect + .attr('style', nodeStyles) + .attr('rx', node.rx) + .attr('ry', node.ry) + .attr('x', x) + .attr('y', y) + .attr('width', width) + .attr('height', height); + } + const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig); + labelEl.attr( + 'transform', + // This puts the label on top of the box instead of inside it + `translate(${node.x - bbox.width / 2}, ${node.y - node.height / 2 + subGraphTitleTopMargin})` + ); + + if (labelStyles) { + const span = labelEl.select('span'); + if (span) { + span.attr('style', labelStyles); + } + } + // Center the label + + const rectBox = rect.node().getBBox(); + node.offsetX = 0; + node.width = rectBox.width; + node.height = rectBox.height; + // Used by layout engine to position subgraph in parent + node.offsetY = bbox.height - node.padding / 2; + + node.intersect = function (point) { + return intersectRect(node, point); + }; + + return { cluster: shapeSvg, labelBBox: bbox }; +}; + +/** + * Non visible cluster where the note is group with its + * + * @param {any} parent + * @param {any} node + * @returns {any} ShapeSvg + */ +const noteGroup = (parent, node) => { + // Add outer g element + const shapeSvg = parent.insert('g').attr('class', 'note-cluster').attr('id', node.id); + + // add the rect + const rect = shapeSvg.insert('rect', ':first-child'); + + const padding = 0 * node.padding; + const halfPadding = padding / 2; + + // center the rect around its coordinate + rect + .attr('rx', node.rx) + .attr('ry', node.ry) + .attr('x', node.x - node.width / 2 - halfPadding) + .attr('y', node.y - node.height / 2 - halfPadding) + .attr('width', node.width + padding) + .attr('height', node.height + padding) + .attr('fill', 'none'); + + const rectBox = rect.node().getBBox(); + node.width = rectBox.width; + node.height = rectBox.height; + + node.intersect = function (point) { + return intersectRect(node, point); + }; + + return { cluster: shapeSvg, labelBBox: { width: 0, height: 0 } }; +}; + +const roundedWithTitle = async (parent, node) => { + const siteConfig = getConfig(); + + const { themeVariables, handDrawnSeed } = siteConfig; + const { altBackground, compositeBackground, compositeTitleBackground, nodeBorder } = + themeVariables; + + // Add outer g element + const shapeSvg = parent + .insert('g') + .attr('class', node.cssClasses) + .attr('id', node.id) + .attr('data-id', node.id) + .attr('data-look', node.look); + + // add the rect + const outerRectG = shapeSvg.insert('g', ':first-child'); + + // Create the label and insert it after the rect + const label = shapeSvg.insert('g').attr('class', 'cluster-label'); + let innerRect = shapeSvg.append('rect'); + + const text = label + .node() + .appendChild(await createLabel(node.label, node.labelStyle, undefined, true)); + + // Get the size of the label + let bbox = text.getBBox(); + + if (evaluate(siteConfig.flowchart.htmlLabels)) { + const div = text.children[0]; + const dv = select(text); + bbox = div.getBoundingClientRect(); + dv.attr('width', bbox.width); + dv.attr('height', bbox.height); + } + + // Rounded With Title + const padding = 0 * node.padding; + const halfPadding = padding / 2; + + const width = + (node.width <= bbox.width + node.padding ? bbox.width + node.padding : node.width) + padding; + if (node.width <= bbox.width + node.padding) { + node.diff = (width - node.width) / 2 - node.padding; + } else { + node.diff = -node.padding; + } + + const height = node.height + padding; + // const height = node.height + padding; + const innerHeight = node.height + padding - bbox.height - 6; + const x = node.x - width / 2; + const y = node.y - height / 2; + node.width = width; + const innerY = node.y - node.height / 2 - halfPadding + bbox.height + 2; + + // add the rect + let rect; + if (node.look === 'handDrawn') { + const isAlt = node.cssClasses.includes('statediagram-cluster-alt'); + const rc = rough.svg(shapeSvg); + const roughOuterNode = + node.rx || node.ry + ? rc.path(createRoundedRectPathD(x, y, width, height, 10), { + roughness: 0.7, + fill: compositeTitleBackground, + fillStyle: 'solid', + stroke: nodeBorder, + seed: handDrawnSeed, + }) + : rc.rectangle(x, y, width, height, { seed: handDrawnSeed }); + + rect = shapeSvg.insert(() => roughOuterNode, ':first-child'); + const roughInnerNode = rc.rectangle(x, innerY, width, innerHeight, { + fill: isAlt ? altBackground : compositeBackground, + fillStyle: isAlt ? 'hachure' : 'solid', + stroke: nodeBorder, + seed: handDrawnSeed, + }); + + rect = shapeSvg.insert(() => roughOuterNode, ':first-child'); + innerRect = shapeSvg.insert(() => roughInnerNode); + } else { + rect = outerRectG.insert('rect', ':first-child'); + const outerRectClass = 'outer'; + + // center the rect around its coordinate + rect + .attr('class', outerRectClass) + .attr('x', x) + .attr('y', y) + .attr('width', width) + .attr('height', height) + .attr('data-look', node.look); + innerRect + .attr('class', 'inner') + .attr('x', x) + .attr('y', innerY) + .attr('width', width) + .attr('height', innerHeight); + } + + label.attr( + 'transform', + `translate(${node.x - bbox.width / 2}, ${y + 1 - (evaluate(siteConfig.flowchart.htmlLabels) ? 0 : 3)})` + ); + + const rectBox = rect.node().getBBox(); + node.height = rectBox.height; + node.offsetX = 0; + // Used by layout engine to position subgraph in parent + node.offsetY = bbox.height - node.padding / 2; + node.labelBBox = bbox; + + node.intersect = function (point) { + return intersectRect(node, point); + }; + + return { cluster: shapeSvg, labelBBox: bbox }; +}; +const kanbanSection = async (parent, node) => { + log.info('Creating subgraph rect for ', node.id, node); + const siteConfig = getConfig(); + const { themeVariables, handDrawnSeed } = siteConfig; + const { clusterBkg, clusterBorder } = themeVariables; + + const { labelStyles, nodeStyles, borderStyles, backgroundStyles } = styles2String(node); + + // Add outer g element + const shapeSvg = parent + .insert('g') + .attr('class', 'cluster ' + node.cssClasses) + .attr('id', node.id) + .attr('data-look', node.look); + + const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels); + + // Create the label and insert it after the rect + const labelEl = shapeSvg.insert('g').attr('class', 'cluster-label '); + + const text = await createText(labelEl, node.label, { + style: node.labelStyle, + useHtmlLabels, + isNode: true, + width: node.width, + }); + + // Get the size of the label + let bbox = text.getBBox(); + + if (evaluate(siteConfig.flowchart.htmlLabels)) { + const div = text.children[0]; + const dv = select(text); + bbox = div.getBoundingClientRect(); + dv.attr('width', bbox.width); + dv.attr('height', bbox.height); + } + + const width = node.width <= bbox.width + node.padding ? bbox.width + node.padding : node.width; + if (node.width <= bbox.width + node.padding) { + node.diff = (width - node.width) / 2 - node.padding; + } else { + node.diff = -node.padding; + } + + const height = node.height; + const x = node.x - width / 2; + const y = node.y - height / 2; + + log.trace('Data ', node, JSON.stringify(node)); + let rect; + if (node.look === 'handDrawn') { + // @ts-ignore TODO: Fix rough typings + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { + roughness: 0.7, + fill: clusterBkg, + // fill: 'red', + stroke: clusterBorder, + fillWeight: 4, + seed: handDrawnSeed, + }); + const roughNode = rc.path(createRoundedRectPathD(x, y, width, height, node.rx), options); + rect = shapeSvg.insert(() => { + log.debug('Rough node insert CXC', roughNode); + return roughNode; + }, ':first-child'); + // Should we affect the options instead of doing this? + rect.select('path:nth-child(2)').attr('style', borderStyles.join(';')); + rect.select('path').attr('style', backgroundStyles.join(';').replace('fill', 'stroke')); + } else { + // add the rect + rect = shapeSvg.insert('rect', ':first-child'); + // center the rect around its coordinate + rect + .attr('style', nodeStyles) + .attr('rx', node.rx) + .attr('ry', node.ry) + .attr('x', x) + .attr('y', y) + .attr('width', width) + .attr('height', height); + } + const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig); + labelEl.attr( + 'transform', + // This puts the label on top of the box instead of inside it + `translate(${node.x - bbox.width / 2}, ${node.y - node.height / 2 + subGraphTitleTopMargin})` + ); + + if (labelStyles) { + const span = labelEl.select('span'); + if (span) { + span.attr('style', labelStyles); + } + } + // Center the label + + const rectBox = rect.node().getBBox(); + node.offsetX = 0; + node.width = rectBox.width; + node.height = rectBox.height; + // Used by layout engine to position subgraph in parent + node.offsetY = bbox.height - node.padding / 2; + + node.intersect = function (point) { + return intersectRect(node, point); + }; + + return { cluster: shapeSvg, labelBBox: bbox }; +}; +const divider = (parent, node) => { + const siteConfig = getConfig(); + + const { themeVariables, handDrawnSeed } = siteConfig; + const { nodeBorder } = themeVariables; + + // Add outer g element + const shapeSvg = parent + .insert('g') + .attr('class', node.cssClasses) + .attr('id', node.id) + .attr('data-look', node.look); + + // add the rect + const outerRectG = shapeSvg.insert('g', ':first-child'); + + const padding = 0 * node.padding; + + const width = node.width + padding; + + node.diff = -node.padding; + + const height = node.height + padding; + // const height = node.height + padding; + const x = node.x - width / 2; + const y = node.y - height / 2; + node.width = width; + + // add the rect + let rect; + if (node.look === 'handDrawn') { + const rc = rough.svg(shapeSvg); + const roughOuterNode = rc.rectangle(x, y, width, height, { + fill: 'lightgrey', + roughness: 0.5, + strokeLineDash: [5], + stroke: nodeBorder, + seed: handDrawnSeed, + }); + + rect = shapeSvg.insert(() => roughOuterNode, ':first-child'); + } else { + rect = outerRectG.insert('rect', ':first-child'); + const outerRectClass = 'divider'; + + // center the rect around its coordinate + rect + .attr('class', outerRectClass) + .attr('x', x) + .attr('y', y) + .attr('width', width) + .attr('height', height) + .attr('data-look', node.look); + } + + const rectBox = rect.node().getBBox(); + node.height = rectBox.height; + node.offsetX = 0; + // Used by layout engine to position subgraph in parent + node.offsetY = 0; + + node.intersect = function (point) { + return intersectRect(node, point); + }; + + return { cluster: shapeSvg, labelBBox: {} }; +}; + +const squareRect = rect; +const shapes = { + rect, + squareRect, + roundedWithTitle, + noteGroup, + divider, + kanbanSection, +}; + +let clusterElems = new Map(); + +/** + * @typedef {keyof typeof shapes} ClusterShapeID + */ + +/** + * @param {import('../types.js').ClusterNode} node - Shape defaults to 'rect' + */ +export const insertCluster = async (elem, node) => { + const shape = node.shape || 'rect'; + const cluster = await shapes[shape](elem, node); + clusterElems.set(node.id, cluster); + return cluster; +}; + +export const getClusterTitleWidth = (elem, node) => { + const label = createLabel(node.label, node.labelStyle, undefined, true); + elem.node().appendChild(label); + const width = label.getBBox().width; + elem.node().removeChild(label); + return width; +}; + +export const clear = () => { + clusterElems = new Map(); +}; + +export const positionCluster = (node) => { + log.info( + 'Position cluster (' + + node.id + + ', ' + + node.x + + ', ' + + node.y + + ') (' + + node?.width + + ', ' + + node?.height + + ')', + clusterElems.get(node.id) + ); + const el = clusterElems.get(node.id); + el.cluster.attr('transform', 'translate(' + node.x + ', ' + node.y + ')'); +}; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/createLabel.js b/packages/mermaid/src/rendering-util/rendering-elements/createLabel.js new file mode 100644 index 000000000..482dbb9f1 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/createLabel.js @@ -0,0 +1,105 @@ +import { select } from 'd3'; +import { log } from '../../logger.js'; +import { getConfig } from '../../diagram-api/diagramAPI.js'; +import common, { evaluate, renderKatex, hasKatex } from '../../diagrams/common/common.js'; +import { decodeEntities } from '../../utils.js'; + +/** + * @param dom + * @param styleFn + */ +function applyStyle(dom, styleFn) { + if (styleFn) { + dom.attr('style', styleFn); + } +} + +/** + * @param {any} node + * @returns {Promise} Node + */ +async function addHtmlLabel(node) { + const fo = select(document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject')); + const div = fo.append('xhtml:div'); + + let label = node.label; + if (node.label && hasKatex(node.label)) { + label = await renderKatex(node.label.replace(common.lineBreakRegex, '\n'), getConfig()); + } + const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel'; + div.html( + '' + + label + + '' + ); + + applyStyle(div, node.labelStyle); + div.style('display', 'inline-block'); + div.style('padding-right', '1px'); + // Fix for firefox + div.style('white-space', 'nowrap'); + div.attr('xmlns', 'http://www.w3.org/1999/xhtml'); + return fo.node(); +} +/** + * @param _vertexText + * @param style + * @param isTitle + * @param isNode + * @deprecated svg-util/createText instead + */ +const createLabel = async (_vertexText, style, isTitle, isNode) => { + let vertexText = _vertexText || ''; + if (typeof vertexText === 'object') { + vertexText = vertexText[0]; + } + + if (evaluate(getConfig().flowchart.htmlLabels)) { + // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? + vertexText = vertexText.replace(/\\n|\n/g, '
'); + log.info('vertexText' + vertexText); + const node = { + isNode, + label: decodeEntities(vertexText).replace( + /fa[blrs]?:fa-[\w-]+/g, + (s) => `` + ), + labelStyle: style ? style.replace('fill:', 'color:') : style, + }; + let vertexNode = await addHtmlLabel(node); + // vertexNode.parentNode.removeChild(vertexNode); + return vertexNode; + } else { + const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text'); + svgLabel.setAttribute('style', style.replace('color:', 'fill:')); + let rows = []; + if (typeof vertexText === 'string') { + rows = vertexText.split(/\\n|\n|/gi); + } else if (Array.isArray(vertexText)) { + rows = vertexText; + } else { + rows = []; + } + + for (const row of rows) { + const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan'); + tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve'); + tspan.setAttribute('dy', '1em'); + tspan.setAttribute('x', '0'); + if (isTitle) { + tspan.setAttribute('class', 'title-row'); + } else { + tspan.setAttribute('class', 'row'); + } + tspan.textContent = row.trim(); + svgLabel.appendChild(tspan); + } + return svgLabel; + } +}; + +export default createLabel; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.spec.ts b/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.spec.ts new file mode 100644 index 000000000..7702782c2 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.spec.ts @@ -0,0 +1,80 @@ +/* eslint-disable @typescript-eslint/unbound-method */ +import type { SVG } from '../../diagram-api/types.js'; +import type { Mocked } from 'vitest'; +import { addEdgeMarkers } from './edgeMarker.js'; + +describe('addEdgeMarker', () => { + const svgPath = { + attr: vitest.fn(), + } as unknown as Mocked; + const url = 'http://example.com'; + const id = 'test'; + const diagramType = 'test'; + + beforeEach(() => { + svgPath.attr.mockReset(); + }); + + it('should add markers for arrow_cross:arrow_point', () => { + const arrowTypeStart = 'arrow_cross'; + const arrowTypeEnd = 'arrow_point'; + addEdgeMarkers(svgPath, { arrowTypeStart, arrowTypeEnd }, url, id, diagramType); + expect(svgPath.attr).toHaveBeenCalledWith( + 'marker-start', + `url(${url}#${id}_${diagramType}-crossStart)` + ); + expect(svgPath.attr).toHaveBeenCalledWith( + 'marker-end', + `url(${url}#${id}_${diagramType}-pointEnd)` + ); + }); + + it('should add markers for aggregation:arrow_point', () => { + const arrowTypeStart = 'aggregation'; + const arrowTypeEnd = 'arrow_point'; + addEdgeMarkers(svgPath, { arrowTypeStart, arrowTypeEnd }, url, id, diagramType); + expect(svgPath.attr).toHaveBeenCalledWith( + 'marker-start', + `url(${url}#${id}_${diagramType}-aggregationStart)` + ); + expect(svgPath.attr).toHaveBeenCalledWith( + 'marker-end', + `url(${url}#${id}_${diagramType}-pointEnd)` + ); + }); + + it('should add markers for arrow_point:aggregation', () => { + const arrowTypeStart = 'arrow_point'; + const arrowTypeEnd = 'aggregation'; + addEdgeMarkers(svgPath, { arrowTypeStart, arrowTypeEnd }, url, id, diagramType); + expect(svgPath.attr).toHaveBeenCalledWith( + 'marker-start', + `url(${url}#${id}_${diagramType}-pointStart)` + ); + expect(svgPath.attr).toHaveBeenCalledWith( + 'marker-end', + `url(${url}#${id}_${diagramType}-aggregationEnd)` + ); + }); + + it('should add markers for aggregation:composition', () => { + const arrowTypeStart = 'aggregation'; + const arrowTypeEnd = 'composition'; + addEdgeMarkers(svgPath, { arrowTypeStart, arrowTypeEnd }, url, id, diagramType); + expect(svgPath.attr).toHaveBeenCalledWith( + 'marker-start', + `url(${url}#${id}_${diagramType}-aggregationStart)` + ); + expect(svgPath.attr).toHaveBeenCalledWith( + 'marker-end', + `url(${url}#${id}_${diagramType}-compositionEnd)` + ); + }); + + it('should not add invalid markers', () => { + const arrowTypeStart = 'this is an invalid marker'; + const arrowTypeEnd = ') url(https://my-malicious-site.example)'; + addEdgeMarkers(svgPath, { arrowTypeStart, arrowTypeEnd }, url, id, diagramType); + expect(svgPath.attr).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.ts b/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.ts new file mode 100644 index 000000000..70d0e0ec8 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.ts @@ -0,0 +1,104 @@ +import type { SVG } from '../../diagram-api/types.js'; +import { log } from '../../logger.js'; +import type { EdgeData } from '../../types.js'; +/** + * Adds SVG markers to a path element based on the arrow types specified in the edge. + * + * @param svgPath - The SVG path element to add markers to. + * @param edge - The edge data object containing the arrow types. + * @param url - The URL of the SVG marker definitions. + * @param id - The ID prefix for the SVG marker definitions. + * @param diagramType - The type of diagram being rendered. + */ +export const addEdgeMarkers = ( + svgPath: SVG, + edge: Pick, + url: string, + id: string, + diagramType: string, + strokeColor?: string +) => { + if (edge.arrowTypeStart) { + addEdgeMarker(svgPath, 'start', edge.arrowTypeStart, url, id, diagramType, strokeColor); + } + if (edge.arrowTypeEnd) { + addEdgeMarker(svgPath, 'end', edge.arrowTypeEnd, url, id, diagramType, strokeColor); + } +}; + +const arrowTypesMap = { + arrow_cross: { type: 'cross', fill: false }, + arrow_point: { type: 'point', fill: true }, + arrow_barb: { type: 'barb', fill: true }, + arrow_circle: { type: 'circle', fill: false }, + aggregation: { type: 'aggregation', fill: false }, + extension: { type: 'extension', fill: false }, + composition: { type: 'composition', fill: true }, + dependency: { type: 'dependency', fill: true }, + lollipop: { type: 'lollipop', fill: false }, + only_one: { type: 'onlyOne', fill: false }, + zero_or_one: { type: 'zeroOrOne', fill: false }, + one_or_more: { type: 'oneOrMore', fill: false }, + zero_or_more: { type: 'zeroOrMore', fill: false }, + requirement_arrow: { type: 'requirement_arrow', fill: false }, + requirement_contains: { type: 'requirement_contains', fill: false }, +} as const; + +const addEdgeMarker = ( + svgPath: SVG, + position: 'start' | 'end', + arrowType: string, + url: string, + id: string, + diagramType: string, + strokeColor?: string +) => { + const arrowTypeInfo = arrowTypesMap[arrowType as keyof typeof arrowTypesMap]; + + if (!arrowTypeInfo) { + log.warn(`Unknown arrow type: ${arrowType}`); + return; // unknown arrow type, ignore + } + + const endMarkerType = arrowTypeInfo.type; + const suffix = position === 'start' ? 'Start' : 'End'; + const originalMarkerId = `${id}_${diagramType}-${endMarkerType}${suffix}`; + + // If stroke color is specified and non-empty, create or use a colored variant of the marker + if (strokeColor && strokeColor.trim() !== '') { + // Create a sanitized color value for use in IDs + const colorId = strokeColor.replace(/[^\dA-Za-z]/g, '_'); + const coloredMarkerId = `${originalMarkerId}_${colorId}`; + + // Check if the colored marker already exists + if (!document.getElementById(coloredMarkerId)) { + // Get the original marker + const originalMarker = document.getElementById(originalMarkerId); + if (originalMarker) { + // Clone the marker and create colored version + const coloredMarker = originalMarker.cloneNode(true) as Element; + coloredMarker.id = coloredMarkerId; + + // Apply colors to the paths inside the marker + const paths = coloredMarker.querySelectorAll('path, circle, line'); + paths.forEach((path) => { + path.setAttribute('stroke', strokeColor); + + // Apply fill only to markers that should be filled + if (arrowTypeInfo.fill) { + path.setAttribute('fill', strokeColor); + } + }); + + // Add the new colored marker to the defs section + originalMarker.parentNode?.appendChild(coloredMarker); + } + } + + // Use the colored marker + svgPath.attr(`marker-${position}`, `url(${url}#${coloredMarkerId})`); + } else { + // Always use the original marker for unstyled edges + svgPath.attr(`marker-${position}`, `url(${url}#${originalMarkerId})`); + } +}; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js new file mode 100644 index 000000000..ce4244ff2 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -0,0 +1,653 @@ +import { getConfig } from '../../diagram-api/diagramAPI.js'; +import { evaluate } from '../../diagrams/common/common.js'; +import { log } from '../../logger.js'; +import { createText } from '../createText.js'; +import utils from '../../utils.js'; +import { getLineFunctionsWithOffset } from '../../utils/lineWithOffset.js'; +import { getSubGraphTitleMargins } from '../../utils/subGraphTitleMargins.js'; + +import { + curveBasis, + curveLinear, + curveCardinal, + curveBumpX, + curveBumpY, + curveCatmullRom, + curveMonotoneX, + curveMonotoneY, + curveNatural, + curveStep, + curveStepAfter, + curveStepBefore, + line, + select, +} from 'd3'; +import rough from 'roughjs'; +import createLabel from './createLabel.js'; +import { addEdgeMarkers } from './edgeMarker.ts'; +import { isLabelStyle } from './shapes/handDrawnShapeStyles.js'; + +const edgeLabels = new Map(); +const terminalLabels = new Map(); + +export const clear = () => { + edgeLabels.clear(); + terminalLabels.clear(); +}; + +export const getLabelStyles = (styleArray) => { + let styles = styleArray ? styleArray.reduce((acc, style) => acc + ';' + style, '') : ''; + return styles; +}; + +export const insertEdgeLabel = async (elem, edge) => { + let useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels); + + const labelElement = await createText(elem, edge.label, { + style: getLabelStyles(edge.labelStyle), + useHtmlLabels, + addSvgBackground: true, + isNode: false, + }); + log.info('abc82', edge, edge.labelType); + + // Create outer g, edgeLabel, this will be positioned after graph layout + const edgeLabel = elem.insert('g').attr('class', 'edgeLabel'); + + // Create inner g, label, this will be positioned now for centering the text + const label = edgeLabel.insert('g').attr('class', 'label'); + label.node().appendChild(labelElement); + + // Center the label + let bbox = labelElement.getBBox(); + if (useHtmlLabels) { + const div = labelElement.children[0]; + const dv = select(labelElement); + bbox = div.getBoundingClientRect(); + dv.attr('width', bbox.width); + dv.attr('height', bbox.height); + } + label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')'); + + // Make element accessible by id for positioning + edgeLabels.set(edge.id, edgeLabel); + + // Update the abstract data of the edge with the new information about its width and height + edge.width = bbox.width; + edge.height = bbox.height; + + let fo; + if (edge.startLabelLeft) { + // Create the actual text element + const startLabelElement = await createLabel( + edge.startLabelLeft, + getLabelStyles(edge.labelStyle) + ); + const startEdgeLabelLeft = elem.insert('g').attr('class', 'edgeTerminals'); + const inner = startEdgeLabelLeft.insert('g').attr('class', 'inner'); + fo = inner.node().appendChild(startLabelElement); + const slBox = startLabelElement.getBBox(); + inner.attr('transform', 'translate(' + -slBox.width / 2 + ', ' + -slBox.height / 2 + ')'); + if (!terminalLabels.get(edge.id)) { + terminalLabels.set(edge.id, {}); + } + terminalLabels.get(edge.id).startLeft = startEdgeLabelLeft; + setTerminalWidth(fo, edge.startLabelLeft); + } + if (edge.startLabelRight) { + // Create the actual text element + const startLabelElement = await createLabel( + edge.startLabelRight, + getLabelStyles(edge.labelStyle) + ); + const startEdgeLabelRight = elem.insert('g').attr('class', 'edgeTerminals'); + const inner = startEdgeLabelRight.insert('g').attr('class', 'inner'); + fo = startEdgeLabelRight.node().appendChild(startLabelElement); + inner.node().appendChild(startLabelElement); + const slBox = startLabelElement.getBBox(); + inner.attr('transform', 'translate(' + -slBox.width / 2 + ', ' + -slBox.height / 2 + ')'); + + if (!terminalLabels.get(edge.id)) { + terminalLabels.set(edge.id, {}); + } + terminalLabels.get(edge.id).startRight = startEdgeLabelRight; + setTerminalWidth(fo, edge.startLabelRight); + } + if (edge.endLabelLeft) { + // Create the actual text element + const endLabelElement = await createLabel(edge.endLabelLeft, getLabelStyles(edge.labelStyle)); + const endEdgeLabelLeft = elem.insert('g').attr('class', 'edgeTerminals'); + const inner = endEdgeLabelLeft.insert('g').attr('class', 'inner'); + fo = inner.node().appendChild(endLabelElement); + const slBox = endLabelElement.getBBox(); + inner.attr('transform', 'translate(' + -slBox.width / 2 + ', ' + -slBox.height / 2 + ')'); + + endEdgeLabelLeft.node().appendChild(endLabelElement); + + if (!terminalLabels.get(edge.id)) { + terminalLabels.set(edge.id, {}); + } + terminalLabels.get(edge.id).endLeft = endEdgeLabelLeft; + setTerminalWidth(fo, edge.endLabelLeft); + } + if (edge.endLabelRight) { + // Create the actual text element + const endLabelElement = await createLabel(edge.endLabelRight, getLabelStyles(edge.labelStyle)); + const endEdgeLabelRight = elem.insert('g').attr('class', 'edgeTerminals'); + const inner = endEdgeLabelRight.insert('g').attr('class', 'inner'); + + fo = inner.node().appendChild(endLabelElement); + const slBox = endLabelElement.getBBox(); + inner.attr('transform', 'translate(' + -slBox.width / 2 + ', ' + -slBox.height / 2 + ')'); + + endEdgeLabelRight.node().appendChild(endLabelElement); + if (!terminalLabels.get(edge.id)) { + terminalLabels.set(edge.id, {}); + } + terminalLabels.get(edge.id).endRight = endEdgeLabelRight; + setTerminalWidth(fo, edge.endLabelRight); + } + return labelElement; +}; + +/** + * @param {any} fo + * @param {any} value + */ +function setTerminalWidth(fo, value) { + if (getConfig().flowchart.htmlLabels && fo) { + fo.style.width = value.length * 9 + 'px'; + fo.style.height = '12px'; + } +} + +export const positionEdgeLabel = (edge, paths) => { + log.debug('Moving label abc88 ', edge.id, edge.label, edgeLabels.get(edge.id), paths); + let path = paths.updatedPath ? paths.updatedPath : paths.originalPath; + const siteConfig = getConfig(); + const { subGraphTitleTotalMargin } = getSubGraphTitleMargins(siteConfig); + if (edge.label) { + const el = edgeLabels.get(edge.id); + let x = edge.x; + let y = edge.y; + if (path) { + const pos = utils.calcLabelPosition(path); + log.debug( + 'Moving label ' + edge.label + ' from (', + x, + ',', + y, + ') to (', + pos.x, + ',', + pos.y, + ') abc88' + ); + if (paths.updatedPath) { + x = pos.x; + y = pos.y; + } + } + el.attr('transform', `translate(${x}, ${y + subGraphTitleTotalMargin / 2})`); + } + + if (edge.startLabelLeft) { + const el = terminalLabels.get(edge.id).startLeft; + let x = edge.x; + let y = edge.y; + if (path) { + const pos = utils.calcTerminalLabelPosition(edge.arrowTypeStart ? 10 : 0, 'start_left', path); + x = pos.x; + y = pos.y; + } + el.attr('transform', `translate(${x}, ${y})`); + } + if (edge.startLabelRight) { + const el = terminalLabels.get(edge.id).startRight; + let x = edge.x; + let y = edge.y; + if (path) { + const pos = utils.calcTerminalLabelPosition( + edge.arrowTypeStart ? 10 : 0, + 'start_right', + path + ); + x = pos.x; + y = pos.y; + } + el.attr('transform', `translate(${x}, ${y})`); + } + if (edge.endLabelLeft) { + const el = terminalLabels.get(edge.id).endLeft; + let x = edge.x; + let y = edge.y; + if (path) { + const pos = utils.calcTerminalLabelPosition(edge.arrowTypeEnd ? 10 : 0, 'end_left', path); + x = pos.x; + y = pos.y; + } + el.attr('transform', `translate(${x}, ${y})`); + } + if (edge.endLabelRight) { + const el = terminalLabels.get(edge.id).endRight; + let x = edge.x; + let y = edge.y; + if (path) { + const pos = utils.calcTerminalLabelPosition(edge.arrowTypeEnd ? 10 : 0, 'end_right', path); + x = pos.x; + y = pos.y; + } + el.attr('transform', `translate(${x}, ${y})`); + } +}; + +const outsideNode = (node, point) => { + const x = node.x; + const y = node.y; + const dx = Math.abs(point.x - x); + const dy = Math.abs(point.y - y); + const w = node.width / 2; + const h = node.height / 2; + return dx >= w || dy >= h; +}; + +export const intersection = (node, outsidePoint, insidePoint) => { + log.debug(`intersection calc abc89: + outsidePoint: ${JSON.stringify(outsidePoint)} + insidePoint : ${JSON.stringify(insidePoint)} + node : x:${node.x} y:${node.y} w:${node.width} h:${node.height}`); + const x = node.x; + const y = node.y; + + const dx = Math.abs(x - insidePoint.x); + const w = node.width / 2; + let r = insidePoint.x < outsidePoint.x ? w - dx : w + dx; + const h = node.height / 2; + + const Q = Math.abs(outsidePoint.y - insidePoint.y); + const R = Math.abs(outsidePoint.x - insidePoint.x); + + if (Math.abs(y - outsidePoint.y) * w > Math.abs(x - outsidePoint.x) * h) { + // Intersection is top or bottom of rect. + let q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y; + r = (R * q) / Q; + const res = { + x: insidePoint.x < outsidePoint.x ? insidePoint.x + r : insidePoint.x - R + r, + y: insidePoint.y < outsidePoint.y ? insidePoint.y + Q - q : insidePoint.y - Q + q, + }; + + if (r === 0) { + res.x = outsidePoint.x; + res.y = outsidePoint.y; + } + if (R === 0) { + res.x = outsidePoint.x; + } + if (Q === 0) { + res.y = outsidePoint.y; + } + + log.debug(`abc89 top/bottom calc, Q ${Q}, q ${q}, R ${R}, r ${r}`, res); + + return res; + } else { + // Intersection on sides of rect + if (insidePoint.x < outsidePoint.x) { + r = outsidePoint.x - w - x; + } else { + r = x - w - outsidePoint.x; + } + let q = (Q * r) / R; + let _x = insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x - R + r; + let _y = insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q; + log.debug(`sides calc abc89, Q ${Q}, q ${q}, R ${R}, r ${r}`, { _x, _y }); + if (r === 0) { + _x = outsidePoint.x; + _y = outsidePoint.y; + } + if (R === 0) { + _x = outsidePoint.x; + } + if (Q === 0) { + _y = outsidePoint.y; + } + + return { x: _x, y: _y }; + } +}; + +const cutPathAtIntersect = (_points, boundaryNode) => { + log.warn('abc88 cutPathAtIntersect', _points, boundaryNode); + let points = []; + let lastPointOutside = _points[0]; + let isInside = false; + _points.forEach((point) => { + log.info('abc88 checking point', point, boundaryNode); + + if (!outsideNode(boundaryNode, point) && !isInside) { + const inter = intersection(boundaryNode, lastPointOutside, point); + log.debug('abc88 inside', point, lastPointOutside, inter); + log.debug('abc88 intersection', inter, boundaryNode); + + let pointPresent = false; + points.forEach((p) => { + pointPresent = pointPresent || (p.x === inter.x && p.y === inter.y); + }); + + if (!points.some((e) => e.x === inter.x && e.y === inter.y)) { + points.push(inter); + } else { + log.warn('abc88 no intersect', inter, points); + } + isInside = true; + } else { + log.warn('abc88 outside', point, lastPointOutside); + lastPointOutside = point; + if (!isInside) { + points.push(point); + } + } + }); + log.debug('returning points', points); + return points; +}; + +function extractCornerPoints(points) { + const cornerPoints = []; + const cornerPointPositions = []; + for (let i = 1; i < points.length - 1; i++) { + const prev = points[i - 1]; + const curr = points[i]; + const next = points[i + 1]; + if ( + prev.x === curr.x && + curr.y === next.y && + Math.abs(curr.x - next.x) > 5 && + Math.abs(curr.y - prev.y) > 5 + ) { + cornerPoints.push(curr); + cornerPointPositions.push(i); + } else if ( + prev.y === curr.y && + curr.x === next.x && + Math.abs(curr.x - prev.x) > 5 && + Math.abs(curr.y - next.y) > 5 + ) { + cornerPoints.push(curr); + cornerPointPositions.push(i); + } + } + return { cornerPoints, cornerPointPositions }; +} + +const findAdjacentPoint = function (pointA, pointB, distance) { + const xDiff = pointB.x - pointA.x; + const yDiff = pointB.y - pointA.y; + const length = Math.sqrt(xDiff * xDiff + yDiff * yDiff); + const ratio = distance / length; + return { x: pointB.x - ratio * xDiff, y: pointB.y - ratio * yDiff }; +}; + +const fixCorners = function (lineData) { + const { cornerPointPositions } = extractCornerPoints(lineData); + const newLineData = []; + for (let i = 0; i < lineData.length; i++) { + if (cornerPointPositions.includes(i)) { + const prevPoint = lineData[i - 1]; + const nextPoint = lineData[i + 1]; + const cornerPoint = lineData[i]; + + const newPrevPoint = findAdjacentPoint(prevPoint, cornerPoint, 5); + const newNextPoint = findAdjacentPoint(nextPoint, cornerPoint, 5); + + const xDiff = newNextPoint.x - newPrevPoint.x; + const yDiff = newNextPoint.y - newPrevPoint.y; + newLineData.push(newPrevPoint); + + const a = Math.sqrt(2) * 2; + let newCornerPoint = { x: cornerPoint.x, y: cornerPoint.y }; + if (Math.abs(nextPoint.x - prevPoint.x) > 10 && Math.abs(nextPoint.y - prevPoint.y) >= 10) { + log.debug( + 'Corner point fixing', + Math.abs(nextPoint.x - prevPoint.x), + Math.abs(nextPoint.y - prevPoint.y) + ); + const r = 5; + if (cornerPoint.x === newPrevPoint.x) { + newCornerPoint = { + x: xDiff < 0 ? newPrevPoint.x - r + a : newPrevPoint.x + r - a, + y: yDiff < 0 ? newPrevPoint.y - a : newPrevPoint.y + a, + }; + } else { + newCornerPoint = { + x: xDiff < 0 ? newPrevPoint.x - a : newPrevPoint.x + a, + y: yDiff < 0 ? newPrevPoint.y - r + a : newPrevPoint.y + r - a, + }; + } + } else { + log.debug( + 'Corner point skipping fixing', + Math.abs(nextPoint.x - prevPoint.x), + Math.abs(nextPoint.y - prevPoint.y) + ); + } + newLineData.push(newCornerPoint, newNextPoint); + } else { + newLineData.push(lineData[i]); + } + } + return newLineData; +}; + +export const insertEdge = function (elem, edge, clusterDb, diagramType, startNode, endNode, id) { + const { handDrawnSeed } = getConfig(); + let points = edge.points; + let pointsHasChanged = false; + const tail = startNode; + var head = endNode; + const edgeClassStyles = []; + for (const key in edge.cssCompiledStyles) { + if (isLabelStyle(key)) { + continue; + } + edgeClassStyles.push(edge.cssCompiledStyles[key]); + } + + if (head.intersect && tail.intersect) { + points = points.slice(1, edge.points.length - 1); + points.unshift(tail.intersect(points[0])); + log.debug( + 'Last point APA12', + edge.start, + '-->', + edge.end, + points[points.length - 1], + head, + head.intersect(points[points.length - 1]) + ); + points.push(head.intersect(points[points.length - 1])); + } + if (edge.toCluster) { + log.info('to cluster abc88', clusterDb.get(edge.toCluster)); + points = cutPathAtIntersect(edge.points, clusterDb.get(edge.toCluster).node); + + pointsHasChanged = true; + } + + if (edge.fromCluster) { + log.debug( + 'from cluster abc88', + clusterDb.get(edge.fromCluster), + JSON.stringify(points, null, 2) + ); + points = cutPathAtIntersect(points.reverse(), clusterDb.get(edge.fromCluster).node).reverse(); + + pointsHasChanged = true; + } + + let lineData = points.filter((p) => !Number.isNaN(p.y)); + lineData = fixCorners(lineData); + let curve = curveBasis; + curve = curveLinear; + switch (edge.curve) { + case 'linear': + curve = curveLinear; + break; + case 'basis': + curve = curveBasis; + break; + case 'cardinal': + curve = curveCardinal; + break; + case 'bumpX': + curve = curveBumpX; + break; + case 'bumpY': + curve = curveBumpY; + break; + case 'catmullRom': + curve = curveCatmullRom; + break; + case 'monotoneX': + curve = curveMonotoneX; + break; + case 'monotoneY': + curve = curveMonotoneY; + break; + case 'natural': + curve = curveNatural; + break; + case 'step': + curve = curveStep; + break; + case 'stepAfter': + curve = curveStepAfter; + break; + case 'stepBefore': + curve = curveStepBefore; + break; + default: + curve = curveBasis; + } + + const { x, y } = getLineFunctionsWithOffset(edge); + const lineFunction = line().x(x).y(y).curve(curve); + + let strokeClasses; + switch (edge.thickness) { + case 'normal': + strokeClasses = 'edge-thickness-normal'; + break; + case 'thick': + strokeClasses = 'edge-thickness-thick'; + break; + case 'invisible': + strokeClasses = 'edge-thickness-invisible'; + break; + default: + strokeClasses = 'edge-thickness-normal'; + } + switch (edge.pattern) { + case 'solid': + strokeClasses += ' edge-pattern-solid'; + break; + case 'dotted': + strokeClasses += ' edge-pattern-dotted'; + break; + case 'dashed': + strokeClasses += ' edge-pattern-dashed'; + break; + default: + strokeClasses += ' edge-pattern-solid'; + } + let svgPath; + let linePath = lineFunction(lineData); + const edgeStyles = Array.isArray(edge.style) ? edge.style : edge.style ? [edge.style] : []; + let strokeColor = edgeStyles.find((style) => style?.startsWith('stroke:')); + + if (edge.look === 'handDrawn') { + const rc = rough.svg(elem); + Object.assign([], lineData); + + const svgPathNode = rc.path(linePath, { + roughness: 0.3, + seed: handDrawnSeed, + }); + + strokeClasses += ' transition'; + + svgPath = select(svgPathNode) + .select('path') + .attr('id', edge.id) + .attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : '')) + .attr('style', edgeStyles ? edgeStyles.reduce((acc, style) => acc + ';' + style, '') : ''); + let d = svgPath.attr('d'); + svgPath.attr('d', d); + elem.node().appendChild(svgPath.node()); + } else { + const stylesFromClasses = edgeClassStyles.join(';'); + const styles = edgeStyles ? edgeStyles.reduce((acc, style) => acc + style + ';', '') : ''; + let animationClass = ''; + if (edge.animate) { + animationClass = ' edge-animation-fast'; + } + if (edge.animation) { + animationClass = ' edge-animation-' + edge.animation; + } + + const pathStyle = stylesFromClasses ? stylesFromClasses + ';' + styles + ';' : styles; + svgPath = elem + .append('path') + .attr('d', linePath) + .attr('id', edge.id) + .attr( + 'class', + ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : '') + (animationClass ?? '') + ) + .attr('style', pathStyle); + strokeColor = pathStyle.match(/stroke:([^;]+)/)?.[1]; + } + + // DEBUG code, DO NOT REMOVE + // adds a red circle at each edge coordinate + // cornerPoints.forEach((point) => { + // elem + // .append('circle') + // .style('stroke', 'blue') + // .style('fill', 'blue') + // .attr('r', 3) + // .attr('cx', point.x) + // .attr('cy', point.y); + // }); + // lineData.forEach((point) => { + // elem + // .append('circle') + // .style('stroke', 'blue') + // .style('fill', 'blue') + // .attr('r', 3) + // .attr('cx', point.x) + // .attr('cy', point.y); + // }); + + let url = ''; + if (getConfig().flowchart.arrowMarkerAbsolute || getConfig().state.arrowMarkerAbsolute) { + url = + window.location.protocol + + '//' + + window.location.host + + window.location.pathname + + window.location.search; + url = url.replace(/\(/g, '\\(').replace(/\)/g, '\\)'); + } + log.info('arrowTypeStart', edge.arrowTypeStart); + log.info('arrowTypeEnd', edge.arrowTypeEnd); + + addEdgeMarkers(svgPath, edge, url, id, diagramType, strokeColor); + + let paths = {}; + if (pointsHasChanged) { + paths.updatedPath = points; + } + paths.originalPath = edge.points; + return paths; +}; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/intersect/index.js b/packages/mermaid/src/rendering-util/rendering-elements/intersect/index.js new file mode 100644 index 000000000..47f71747d --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/intersect/index.js @@ -0,0 +1,17 @@ +/* + * Borrowed with love from dagre-d3. Many thanks to cpettitt! + */ + +import node from './intersect-node.js'; +import circle from './intersect-circle.js'; +import ellipse from './intersect-ellipse.js'; +import polygon from './intersect-polygon.js'; +import rect from './intersect-rect.js'; + +export default { + node, + circle, + ellipse, + polygon, + rect, +}; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-circle.js b/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-circle.js new file mode 100644 index 000000000..b71d297ed --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-circle.js @@ -0,0 +1,7 @@ +import intersectEllipse from './intersect-ellipse.js'; + +function intersectCircle(node, rx, point) { + return intersectEllipse(node, rx, rx, point); +} + +export default intersectCircle; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-ellipse.js b/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-ellipse.js new file mode 100644 index 000000000..def637b2c --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-ellipse.js @@ -0,0 +1,24 @@ +function intersectEllipse(node, rx, ry, point) { + // Formulae from: https://mathworld.wolfram.com/Ellipse-LineIntersection.html + + var cx = node.x; + var cy = node.y; + + var px = cx - point.x; + var py = cy - point.y; + + var det = Math.sqrt(rx * rx * py * py + ry * ry * px * px); + + var dx = Math.abs((rx * ry * px) / det); + if (point.x < cx) { + dx = -dx; + } + var dy = Math.abs((rx * ry * py) / det); + if (point.y < cy) { + dy = -dy; + } + + return { x: cx + dx, y: cy + dy }; +} + +export default intersectEllipse; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-line.js b/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-line.js new file mode 100644 index 000000000..bd3eb497f --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-line.js @@ -0,0 +1,69 @@ +/** + * Returns the point at which two lines, p and q, intersect or returns undefined if they do not intersect. + */ +function intersectLine(p1, p2, q1, q2) { + // Algorithm from J. Avro, (ed.) Graphics Gems, No 2, Morgan Kaufmann, 1994, + // p7 and p473. + + var a1, a2, b1, b2, c1, c2; + var r1, r2, r3, r4; + var denom, offset, num; + var x, y; + + // Compute a1, b1, c1, where line joining points 1 and 2 is F(x,y) = a1 x + + // b1 y + c1 = 0. + a1 = p2.y - p1.y; + b1 = p1.x - p2.x; + c1 = p2.x * p1.y - p1.x * p2.y; + + // Compute r3 and r4. + r3 = a1 * q1.x + b1 * q1.y + c1; + r4 = a1 * q2.x + b1 * q2.y + c1; + + // Check signs of r3 and r4. If both point 3 and point 4 lie on + // same side of line 1, the line segments do not intersect. + if (r3 !== 0 && r4 !== 0 && sameSign(r3, r4)) { + return /*DON'T_INTERSECT*/; + } + + // Compute a2, b2, c2 where line joining points 3 and 4 is G(x,y) = a2 x + b2 y + c2 = 0 + a2 = q2.y - q1.y; + b2 = q1.x - q2.x; + c2 = q2.x * q1.y - q1.x * q2.y; + + // Compute r1 and r2 + r1 = a2 * p1.x + b2 * p1.y + c2; + r2 = a2 * p2.x + b2 * p2.y + c2; + + // Check signs of r1 and r2. If both point 1 and point 2 lie + // on same side of second line segment, the line segments do + // not intersect. + if (r1 !== 0 && r2 !== 0 && sameSign(r1, r2)) { + return /*DON'T_INTERSECT*/; + } + + // Line segments intersect: compute intersection point. + denom = a1 * b2 - a2 * b1; + if (denom === 0) { + return /*COLLINEAR*/; + } + + offset = Math.abs(denom / 2); + + // The denom/2 is to get rounding instead of truncating. It + // is added or subtracted to the numerator, depending upon the + // sign of the numerator. + num = b1 * c2 - b2 * c1; + x = num < 0 ? (num - offset) / denom : (num + offset) / denom; + + num = a2 * c1 - a1 * c2; + y = num < 0 ? (num - offset) / denom : (num + offset) / denom; + + return { x: x, y: y }; +} + +function sameSign(r1, r2) { + return r1 * r2 > 0; +} + +export default intersectLine; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-node.js b/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-node.js new file mode 100644 index 000000000..08ed7b4c8 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-node.js @@ -0,0 +1,5 @@ +function intersectNode(node, point) { + return node.intersect(point); +} + +export default intersectNode; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-polygon.js b/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-polygon.js new file mode 100644 index 000000000..2e48ba8d0 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-polygon.js @@ -0,0 +1,63 @@ +import intersectLine from './intersect-line.js'; + +/** + * Returns the point ({x, y}) at which the point argument intersects with the node argument assuming + * that it has the shape specified by polygon. + */ +function intersectPolygon(node, polyPoints, point) { + let x1 = node.x; + let y1 = node.y; + + let intersections = []; + + let minX = Number.POSITIVE_INFINITY; + let minY = Number.POSITIVE_INFINITY; + if (typeof polyPoints.forEach === 'function') { + polyPoints.forEach(function (entry) { + minX = Math.min(minX, entry.x); + minY = Math.min(minY, entry.y); + }); + } else { + minX = Math.min(minX, polyPoints.x); + minY = Math.min(minY, polyPoints.y); + } + + let left = x1 - node.width / 2 - minX; + let top = y1 - node.height / 2 - minY; + + for (let i = 0; i < polyPoints.length; i++) { + let p1 = polyPoints[i]; + let p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0]; + let intersect = intersectLine( + node, + point, + { x: left + p1.x, y: top + p1.y }, + { x: left + p2.x, y: top + p2.y } + ); + if (intersect) { + intersections.push(intersect); + } + } + + if (!intersections.length) { + return node; + } + + if (intersections.length > 1) { + // More intersections, find the one nearest to edge end point + intersections.sort(function (p, q) { + let pdx = p.x - point.x; + let pdy = p.y - point.y; + let distp = Math.sqrt(pdx * pdx + pdy * pdy); + + let qdx = q.x - point.x; + let qdy = q.y - point.y; + let distq = Math.sqrt(qdx * qdx + qdy * qdy); + + return distp < distq ? -1 : distp === distq ? 0 : 1; + }); + } + return intersections[0]; +} + +export default intersectPolygon; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-rect.js b/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-rect.js new file mode 100644 index 000000000..daf6b5eea --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/intersect/intersect-rect.js @@ -0,0 +1,32 @@ +const intersectRect = (node, point) => { + var x = node.x; + var y = node.y; + + // Rectangle intersection algorithm from: + // https://math.stackexchange.com/questions/108113/find-edge-between-two-boxes + var dx = point.x - x; + var dy = point.y - y; + var w = node.width / 2; + var h = node.height / 2; + + var sx, sy; + if (Math.abs(dy) * w > Math.abs(dx) * h) { + // Intersection is top or bottom of rect. + if (dy < 0) { + h = -h; + } + sx = dy === 0 ? 0 : (h * dx) / dy; + sy = h; + } else { + // Intersection is left or right of rect. + if (dx < 0) { + w = -w; + } + sx = w; + sy = dx === 0 ? 0 : (w * dy) / dx; + } + + return { x: x + sx, y: y + sy }; +}; + +export default intersectRect; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/markers.js b/packages/mermaid/src/rendering-util/rendering-elements/markers.js new file mode 100644 index 000000000..0566a4dcc --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/markers.js @@ -0,0 +1,459 @@ +/** Setup arrow head and define the marker. The result is appended to the svg. */ +import { log } from '../../logger.js'; + +// Only add the number of markers that the diagram needs +const insertMarkers = (elem, markerArray, type, id) => { + markerArray.forEach((markerName) => { + markers[markerName](elem, type, id); + }); +}; + +const extension = (elem, type, id) => { + log.trace('Making markers for ', id); + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-extensionStart') + .attr('class', 'marker extension ' + type) + .attr('refX', 18) + .attr('refY', 7) + .attr('markerWidth', 190) + .attr('markerHeight', 240) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 1,7 L18,13 V 1 Z'); + + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-extensionEnd') + .attr('class', 'marker extension ' + type) + .attr('refX', 1) + .attr('refY', 7) + .attr('markerWidth', 20) + .attr('markerHeight', 28) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 1,1 V 13 L18,7 Z'); // this is actual shape for arrowhead +}; + +const composition = (elem, type, id) => { + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-compositionStart') + .attr('class', 'marker composition ' + type) + .attr('refX', 18) + .attr('refY', 7) + .attr('markerWidth', 190) + .attr('markerHeight', 240) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z'); + + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-compositionEnd') + .attr('class', 'marker composition ' + type) + .attr('refX', 1) + .attr('refY', 7) + .attr('markerWidth', 20) + .attr('markerHeight', 28) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z'); +}; +const aggregation = (elem, type, id) => { + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-aggregationStart') + .attr('class', 'marker aggregation ' + type) + .attr('refX', 18) + .attr('refY', 7) + .attr('markerWidth', 190) + .attr('markerHeight', 240) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z'); + + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-aggregationEnd') + .attr('class', 'marker aggregation ' + type) + .attr('refX', 1) + .attr('refY', 7) + .attr('markerWidth', 20) + .attr('markerHeight', 28) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z'); +}; +const dependency = (elem, type, id) => { + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-dependencyStart') + .attr('class', 'marker dependency ' + type) + .attr('refX', 6) + .attr('refY', 7) + .attr('markerWidth', 190) + .attr('markerHeight', 240) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 5,7 L9,13 L1,7 L9,1 Z'); + + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-dependencyEnd') + .attr('class', 'marker dependency ' + type) + .attr('refX', 13) + .attr('refY', 7) + .attr('markerWidth', 20) + .attr('markerHeight', 28) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z'); +}; +const lollipop = (elem, type, id) => { + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-lollipopStart') + .attr('class', 'marker lollipop ' + type) + .attr('refX', 13) + .attr('refY', 7) + .attr('markerWidth', 190) + .attr('markerHeight', 240) + .attr('orient', 'auto') + .append('circle') + .attr('stroke', 'black') + .attr('fill', 'transparent') + .attr('cx', 7) + .attr('cy', 7) + .attr('r', 6); + + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-lollipopEnd') + .attr('class', 'marker lollipop ' + type) + .attr('refX', 1) + .attr('refY', 7) + .attr('markerWidth', 190) + .attr('markerHeight', 240) + .attr('orient', 'auto') + .append('circle') + .attr('stroke', 'black') + .attr('fill', 'transparent') + .attr('cx', 7) + .attr('cy', 7) + .attr('r', 6); +}; +const point = (elem, type, id) => { + elem + .append('marker') + .attr('id', id + '_' + type + '-pointEnd') + .attr('class', 'marker ' + type) + .attr('viewBox', '0 0 10 10') + .attr('refX', 5) + .attr('refY', 5) + .attr('markerUnits', 'userSpaceOnUse') + .attr('markerWidth', 8) + .attr('markerHeight', 8) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 0 0 L 10 5 L 0 10 z') + .attr('class', 'arrowMarkerPath') + .style('stroke-width', 1) + .style('stroke-dasharray', '1,0'); + elem + .append('marker') + .attr('id', id + '_' + type + '-pointStart') + .attr('class', 'marker ' + type) + .attr('viewBox', '0 0 10 10') + .attr('refX', 4.5) + .attr('refY', 5) + .attr('markerUnits', 'userSpaceOnUse') + .attr('markerWidth', 8) + .attr('markerHeight', 8) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 0 5 L 10 10 L 10 0 z') + .attr('class', 'arrowMarkerPath') + .style('stroke-width', 1) + .style('stroke-dasharray', '1,0'); +}; +const circle = (elem, type, id) => { + elem + .append('marker') + .attr('id', id + '_' + type + '-circleEnd') + .attr('class', 'marker ' + type) + .attr('viewBox', '0 0 10 10') + .attr('refX', 11) + .attr('refY', 5) + .attr('markerUnits', 'userSpaceOnUse') + .attr('markerWidth', 11) + .attr('markerHeight', 11) + .attr('orient', 'auto') + .append('circle') + .attr('cx', '5') + .attr('cy', '5') + .attr('r', '5') + .attr('class', 'arrowMarkerPath') + .style('stroke-width', 1) + .style('stroke-dasharray', '1,0'); + + elem + .append('marker') + .attr('id', id + '_' + type + '-circleStart') + .attr('class', 'marker ' + type) + .attr('viewBox', '0 0 10 10') + .attr('refX', -1) + .attr('refY', 5) + .attr('markerUnits', 'userSpaceOnUse') + .attr('markerWidth', 11) + .attr('markerHeight', 11) + .attr('orient', 'auto') + .append('circle') + .attr('cx', '5') + .attr('cy', '5') + .attr('r', '5') + .attr('class', 'arrowMarkerPath') + .style('stroke-width', 1) + .style('stroke-dasharray', '1,0'); +}; +const cross = (elem, type, id) => { + elem + .append('marker') + .attr('id', id + '_' + type + '-crossEnd') + .attr('class', 'marker cross ' + type) + .attr('viewBox', '0 0 11 11') + .attr('refX', 12) + .attr('refY', 5.2) + .attr('markerUnits', 'userSpaceOnUse') + .attr('markerWidth', 11) + .attr('markerHeight', 11) + .attr('orient', 'auto') + .append('path') + // .attr('stroke', 'black') + .attr('d', 'M 1,1 l 9,9 M 10,1 l -9,9') + .attr('class', 'arrowMarkerPath') + .style('stroke-width', 2) + .style('stroke-dasharray', '1,0'); + + elem + .append('marker') + .attr('id', id + '_' + type + '-crossStart') + .attr('class', 'marker cross ' + type) + .attr('viewBox', '0 0 11 11') + .attr('refX', -1) + .attr('refY', 5.2) + .attr('markerUnits', 'userSpaceOnUse') + .attr('markerWidth', 11) + .attr('markerHeight', 11) + .attr('orient', 'auto') + .append('path') + // .attr('stroke', 'black') + .attr('d', 'M 1,1 l 9,9 M 10,1 l -9,9') + .attr('class', 'arrowMarkerPath') + .style('stroke-width', 2) + .style('stroke-dasharray', '1,0'); +}; +const barb = (elem, type, id) => { + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-barbEnd') + .attr('refX', 19) + .attr('refY', 7) + .attr('markerWidth', 20) + .attr('markerHeight', 14) + .attr('markerUnits', 'userSpaceOnUse') + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 19,7 L9,13 L14,7 L9,1 Z'); +}; +// erDiagram specific markers +const only_one = (elem, type, id) => { + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-onlyOneStart') + .attr('class', 'marker onlyOne ' + type) + .attr('refX', 0) + .attr('refY', 9) + .attr('markerWidth', 18) + .attr('markerHeight', 18) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M9,0 L9,18 M15,0 L15,18'); + + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-onlyOneEnd') + .attr('class', 'marker onlyOne ' + type) + .attr('refX', 18) + .attr('refY', 9) + .attr('markerWidth', 18) + .attr('markerHeight', 18) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M3,0 L3,18 M9,0 L9,18'); +}; + +const zero_or_one = (elem, type, id) => { + const startMarker = elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-zeroOrOneStart') + .attr('class', 'marker zeroOrOne ' + type) + .attr('refX', 0) + .attr('refY', 9) + .attr('markerWidth', 30) + .attr('markerHeight', 18) + .attr('orient', 'auto'); + startMarker + .append('circle') + .attr('fill', 'white') // Fill white for now? + .attr('cx', 21) + .attr('cy', 9) + .attr('r', 6); + startMarker.append('path').attr('d', 'M9,0 L9,18'); + + const endMarker = elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-zeroOrOneEnd') + .attr('class', 'marker zeroOrOne ' + type) + .attr('refX', 30) + .attr('refY', 9) + .attr('markerWidth', 30) + .attr('markerHeight', 18) + .attr('orient', 'auto'); + endMarker + .append('circle') + .attr('fill', 'white') // Fill white for now? + .attr('cx', 9) + .attr('cy', 9) + .attr('r', 6); + endMarker.append('path').attr('d', 'M21,0 L21,18'); +}; + +const one_or_more = (elem, type, id) => { + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-oneOrMoreStart') + .attr('class', 'marker oneOrMore ' + type) + .attr('refX', 18) + .attr('refY', 18) + .attr('markerWidth', 45) + .attr('markerHeight', 36) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M0,18 Q 18,0 36,18 Q 18,36 0,18 M42,9 L42,27'); + + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-oneOrMoreEnd') + .attr('class', 'marker oneOrMore ' + type) + .attr('refX', 27) + .attr('refY', 18) + .attr('markerWidth', 45) + .attr('markerHeight', 36) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M3,9 L3,27 M9,18 Q27,0 45,18 Q27,36 9,18'); +}; + +const zero_or_more = (elem, type, id) => { + const startMarker = elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-zeroOrMoreStart') + .attr('class', 'marker zeroOrMore ' + type) + .attr('refX', 18) + .attr('refY', 18) + .attr('markerWidth', 57) + .attr('markerHeight', 36) + .attr('orient', 'auto'); + startMarker.append('circle').attr('fill', 'white').attr('cx', 48).attr('cy', 18).attr('r', 6); + startMarker.append('path').attr('d', 'M0,18 Q18,0 36,18 Q18,36 0,18'); + + const endMarker = elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-zeroOrMoreEnd') + .attr('class', 'marker zeroOrMore ' + type) + .attr('refX', 39) + .attr('refY', 18) + .attr('markerWidth', 57) + .attr('markerHeight', 36) + .attr('orient', 'auto'); + endMarker.append('circle').attr('fill', 'white').attr('cx', 9).attr('cy', 18).attr('r', 6); + endMarker.append('path').attr('d', 'M21,18 Q39,0 57,18 Q39,36 21,18'); +}; + +const requirement_arrow = (elem, type, id) => { + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-requirement_arrowEnd') + .attr('refX', 20) + .attr('refY', 10) + .attr('markerWidth', 20) + .attr('markerHeight', 20) + .attr('orient', 'auto') + .append('path') + .attr( + 'd', + `M0,0 + L20,10 + M20,10 + L0,20` + ); +}; +const requirement_contains = (elem, type, id) => { + const containsNode = elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-requirement_containsStart') + .attr('refX', 0) + .attr('refY', 10) + .attr('markerWidth', 20) + .attr('markerHeight', 20) + .attr('orient', 'auto') + .append('g'); + + containsNode.append('circle').attr('cx', 10).attr('cy', 10).attr('r', 9).attr('fill', 'none'); + + containsNode.append('line').attr('x1', 1).attr('x2', 19).attr('y1', 10).attr('y2', 10); + + containsNode.append('line').attr('y1', 1).attr('y2', 19).attr('x1', 10).attr('x2', 10); +}; + +// TODO rename the class diagram markers to something shape descriptive and semantic free +const markers = { + extension, + composition, + aggregation, + dependency, + lollipop, + point, + circle, + cross, + barb, + only_one, + zero_or_one, + one_or_more, + zero_or_more, + requirement_arrow, + requirement_contains, +}; +export default insertMarkers; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/nodes.spec.ts b/packages/mermaid/src/rendering-util/rendering-elements/nodes.spec.ts new file mode 100644 index 000000000..c1f0e1437 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/nodes.spec.ts @@ -0,0 +1,236 @@ +import { shapes } from './shapes.js'; +import { describe, it, expect } from 'vitest'; + +describe('Test Alias for shapes', function () { + // for each shape in docs/syntax/flowchart.md, along with its semantic name, short name, and alias name, add a test case + // Process | rect | proc | rectangle + it('should support alias for rectangle shape ', function () { + expect(shapes.process).toBe(shapes.rect); + expect(shapes.proc).toBe(shapes.rect); + expect(shapes.rectangle).toBe(shapes.rect); + }); + + // event | rounded + it('should support alias for rounded shape ', function () { + expect(shapes.event).toBe(shapes.rounded); + }); + + // stadium | pill | term + it('should support alias for stadium shape ', function () { + expect(shapes.pill).toBe(shapes.stadium); + expect(shapes.terminal).toBe(shapes.stadium); + }); + + // fr-rect | subproc | framed-rectangle | subroutine + it('should support alias for subroutine shape ', function () { + expect(shapes['framed-rectangle']).toBe(shapes['fr-rect']); + expect(shapes.subproc).toBe(shapes['fr-rect']); + expect(shapes.subroutine).toBe(shapes['fr-rect']); + }); + + // cyl | db | cylinder + it('should support alias for cylinder shape ', function () { + expect(shapes.db).toBe(shapes.cylinder); + expect(shapes.cyl).toBe(shapes.cylinder); + }); + + // diam | decision | diamond + it('should support alias for diamond shape ', function () { + expect(shapes.diam).toBe(shapes.decision); + expect(shapes.diamond).toBe(shapes.decision); + }); + + // hex | hexagon | prepare + it('should support alias for hexagon shape ', function () { + expect(shapes.hex).toBe(shapes.hexagon); + expect(shapes.prepare).toBe(shapes.hexagon); + }); + + // l-r | lean-right | in-out + it('should support alias for lean-right shape ', function () { + expect(shapes['lean-r']).toBe(shapes['lean-right']); + expect(shapes['in-out']).toBe(shapes['lean-right']); + }); + + // l-l | lean-left | out-in + it('should support alias for lean-left shape ', function () { + expect(shapes['lean-l']).toBe(shapes['lean-left']); + expect(shapes['out-in']).toBe(shapes['lean-left']); + }); + + // trap-b | trapezoid-bottom | priority | trapezoid + it('should support alias for trapezoid shape ', function () { + expect(shapes['trapezoid-bottom']).toBe(shapes['trap-b']); + expect(shapes.priority).toBe(shapes['trap-b']); + expect(shapes.trapezoid).toBe(shapes['trap-b']); + }); + + // trap-t | trapezoid-top | manual | inv-trapezoid + it('should support alias for inv_trapezoid shape ', function () { + expect(shapes['trapezoid-top']).toBe(shapes['trap-t']); + expect(shapes.manual).toBe(shapes['trap-t']); + expect(shapes['inv-trapezoid']).toBe(shapes['trap-t']); + }); + + // dbl-circ| double-circle + it('should support alias for doublecircle shape ', function () { + expect(shapes['double-circle']).toBe(shapes['dbl-circ']); + }); + + // notched-rectangle | card | notch-rect + it('should support alias for notched-rectangle shape ', function () { + expect(shapes.card).toBe(shapes['notched-rectangle']); + expect(shapes['notch-rect']).toBe(shapes['notched-rectangle']); + }); + + it('should support alias for shadedProcess shape ', function () { + const aliases = ['lined-process', 'lined-rectangle', 'lin-proc', 'lin-rect'] as const; + for (const alias of aliases) { + expect(shapes[alias]).toBe(shapes['shaded-process']); + } + }); + + // sm-circ | small-circle | start + it('should support alias for smallCircle shape ', function () { + expect(shapes['small-circle']).toBe(shapes['sm-circ']); + expect(shapes.start).toBe(shapes['sm-circ']); + }); + + // framed-circle | stop + it('should support alias for framed circle shape ', function () { + expect(shapes.stop).toBe(shapes['framed-circle']); + }); + + // fork | join + it('should support alias for fork shape ', function () { + expect(shapes.join).toBe(shapes.fork); + }); + + // brace | comment | brace-l + it('should support alias for brace shape ', function () { + expect(shapes.comment).toBe(shapes.brace); + expect(shapes['brace-l']).toBe(shapes.brace); + }); + + // bolt | com-link | lightning-bolt + it('should support alias for bolt shape ', function () { + expect(shapes['com-link']).toBe(shapes.bolt); + expect(shapes['lightning-bolt']).toBe(shapes.bolt); + }); + + // document | doc + it('should support alias for waveEdgedRectangle shape ', function () { + expect(shapes.doc).toBe(shapes.document); + }); + + // delay | half-rounded-rectangle + it('should support alias for halfRoundedRectangle shape ', function () { + expect(shapes.delay).toBe(shapes['half-rounded-rectangle']); + }); + + // h-cyl | das | horizontal-cylinder + it('should support alias for horizontal-cylinder shape ', function () { + expect(shapes.das).toBe(shapes['h-cyl']); + expect(shapes['horizontal-cylinder']).toBe(shapes['h-cyl']); + }); + + // lin-cyl | disk | lined-cylinder + it('should support alias for linedCylinder shape ', function () { + expect(shapes.disk).toBe(shapes['lin-cyl']); + expect(shapes['lined-cylinder']).toBe(shapes['lin-cyl']); + }); + + // curv-trap | display | curved-trapezoid + it('should support alias for curvedTrapezoid shape ', function () { + expect(shapes.display).toBe(shapes['curv-trap']); + expect(shapes['curved-trapezoid']).toBe(shapes['curv-trap']); + }); + + // div-rect | div-proc | divided-rectangle + it('should support alias for dividedRectangle shape ', function () { + expect(shapes['div-proc']).toBe(shapes['div-rect']); + expect(shapes['divided-rectangle']).toBe(shapes['div-rect']); + }); + + // sm-tri | extract | small-triangle | triangle + it('should support alias for smallTriangle shape ', function () { + expect(shapes.extract).toBe(shapes.tri); + expect(shapes.triangle).toBe(shapes.tri); + }); + + // win-pane | internal-storage | window-pane + it('should support alias for windowPane shape ', function () { + expect(shapes['internal-storage']).toBe(shapes['win-pane']); + expect(shapes['window-pane']).toBe(shapes['win-pane']); + }); + + // fc | junction | filled-circle + it('should support alias for filledCircle shape ', function () { + expect(shapes.junction).toBe(shapes['f-circ']); + expect(shapes['filled-circle']).toBe(shapes['f-circ']); + }); + + // | lin-doc | lined-document + it('should support alias for linedWaveEdgedRectangle shape ', function () { + expect(shapes['lin-doc']).toBe(shapes['lined-document']); + }); + + // notch-pent | loop-limit | notched-pentagon + it('should support alias for notchedPentagon shape ', function () { + expect(shapes['loop-limit']).toBe(shapes['notch-pent']); + expect(shapes['notched-pentagon']).toBe(shapes['notch-pent']); + }); + + // flip-tri | manual-file | flipped-triangle + it('should support alias for flippedTriangle shape ', function () { + expect(shapes['manual-file']).toBe(shapes['flip-tri']); + expect(shapes['flipped-triangle']).toBe(shapes['flip-tri']); + }); + + //sl-rect | manual-input | sloped-rectangle + it('should support alias for slopedRectangle shape ', function () { + expect(shapes['manual-input']).toBe(shapes['sl-rect']); + expect(shapes['sloped-rectangle']).toBe(shapes['sl-rect']); + }); + + // docs | documents | st-doc | stacked-document + it('should support alias for multiWaveEdgedRectangle shape ', function () { + expect(shapes.docs).toBe(shapes.documents); + expect(shapes['st-doc']).toBe(shapes['stacked-document']); + }); + + // procs | processes | st-rect | stacked-rectangle + it('should support alias for multiRect shape ', function () { + expect(shapes.procs).toBe(shapes.processes); + expect(shapes['st-rect']).toBe(shapes['stacked-rectangle']); + }); + + // flag | paper-tape + it('should support alias for paperTape shape ', function () { + expect(shapes['paper-tape']).toBe(shapes.flag); + }); + + // bow-rect| stored-data | bow-tie-rectangle + it('should support alias for bowTieRect shape ', function () { + expect(shapes['stored-data']).toBe(shapes['bow-rect']); + expect(shapes['bow-tie-rectangle']).toBe(shapes['bow-rect']); + }); + + // cross-circ | summary | crossed-circle + it('should support alias for crossedCircle shape ', function () { + expect(shapes.summary).toBe(shapes['cross-circ']); + expect(shapes['crossed-circle']).toBe(shapes['cross-circ']); + }); + + // tag-doc| tag-document + it('should support alias for taggedDocument shape ', function () { + expect(shapes['tag-doc']).toBe(shapes['tagged-document']); + }); + + // tag-rect | tag-proc | tagged-rectangle | tagged-process + it('should support alias for taggedRect shape ', function () { + expect(shapes['tag-proc']).toBe(shapes['tag-rect']); + expect(shapes['tagged-rectangle']).toBe(shapes['tag-rect']); + expect(shapes['tagged-process']).toBe(shapes['tag-rect']); + }); +}); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/nodes.ts b/packages/mermaid/src/rendering-util/rendering-elements/nodes.ts new file mode 100644 index 000000000..5af6cd17a --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/nodes.ts @@ -0,0 +1,96 @@ +import { log } from '../../logger.js'; +import { shapes } from './shapes.js'; +import type { Node, NonClusterNode, ShapeRenderOptions } from '../types.js'; +import type { SVGGroup } from '../../mermaid.js'; +import type { D3Selection } from '../../types.js'; +import type { graphlib } from 'dagre-d3-es'; + +type ShapeHandler = (typeof shapes)[keyof typeof shapes]; +type NodeElement = D3Selection | Awaited>; + +const nodeElems = new Map(); + +export async function insertNode( + elem: SVGGroup, + node: NonClusterNode, + renderOptions: ShapeRenderOptions +) { + let newEl: NodeElement | undefined; + let el; + + //special check for rect shape (with or without rounded corners) + if (node.shape === 'rect') { + if (node.rx && node.ry) { + node.shape = 'roundedRect'; + } else { + node.shape = 'squareRect'; + } + } + + const shapeHandler = node.shape ? shapes[node.shape] : undefined; + + if (!shapeHandler) { + throw new Error(`No such shape: ${node.shape}. Please check your syntax.`); + } + + if (node.link) { + // Add link when appropriate + let target; + if (renderOptions.config.securityLevel === 'sandbox') { + target = '_top'; + } else if (node.linkTarget) { + target = node.linkTarget || '_blank'; + } + newEl = elem + .insert('svg:a') + .attr('xlink:href', node.link) + .attr('target', target ?? null); + el = await shapeHandler(newEl, node, renderOptions); + } else { + el = await shapeHandler(elem, node, renderOptions); + newEl = el; + } + if (node.tooltip) { + el.attr('title', node.tooltip); + } + + nodeElems.set(node.id, newEl); + + if (node.haveCallback) { + newEl.attr('class', newEl.attr('class') + ' clickable'); + } + return newEl; +} + +export const setNodeElem = (elem: NodeElement, node: Pick) => { + nodeElems.set(node.id, elem); +}; + +export const clear = () => { + nodeElems.clear(); +}; + +export const positionNode = (node: ReturnType) => { + const el = nodeElems.get(node.id)!; + log.trace( + 'Transforming node', + node.diff, + node, + 'translate(' + (node.x - node.width / 2 - 5) + ', ' + node.width / 2 + ')' + ); + const padding = 8; + const diff = node.diff || 0; + if (node.clusterNode) { + el.attr( + 'transform', + 'translate(' + + (node.x + diff - node.width / 2) + + ', ' + + (node.y - node.height / 2 - padding) + + ')' + ); + } else { + el.attr('transform', 'translate(' + node.x + ', ' + node.y + ')'); + } + return diff; +}; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes.ts new file mode 100644 index 000000000..829f89a8f --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes.ts @@ -0,0 +1,512 @@ +import type { Entries } from 'type-fest'; +import type { D3Selection, MaybePromise } from '../../types.js'; +import type { Node, ShapeRenderOptions } from '../types.js'; +import { anchor } from './shapes/anchor.js'; +import { bowTieRect } from './shapes/bowTieRect.js'; +import { card } from './shapes/card.js'; +import { choice } from './shapes/choice.js'; +import { circle } from './shapes/circle.js'; +import { crossedCircle } from './shapes/crossedCircle.js'; +import { curlyBraceLeft } from './shapes/curlyBraceLeft.js'; +import { curlyBraceRight } from './shapes/curlyBraceRight.js'; +import { curlyBraces } from './shapes/curlyBraces.js'; +import { curvedTrapezoid } from './shapes/curvedTrapezoid.js'; +import { cylinder } from './shapes/cylinder.js'; +import { dividedRectangle } from './shapes/dividedRect.js'; +import { doublecircle } from './shapes/doubleCircle.js'; +import { filledCircle } from './shapes/filledCircle.js'; +import { flippedTriangle } from './shapes/flippedTriangle.js'; +import { forkJoin } from './shapes/forkJoin.js'; +import { halfRoundedRectangle } from './shapes/halfRoundedRectangle.js'; +import { hexagon } from './shapes/hexagon.js'; +import { hourglass } from './shapes/hourglass.js'; +import { icon } from './shapes/icon.js'; +import { iconCircle } from './shapes/iconCircle.js'; +import { iconRounded } from './shapes/iconRounded.js'; +import { iconSquare } from './shapes/iconSquare.js'; +import { imageSquare } from './shapes/imageSquare.js'; +import { inv_trapezoid } from './shapes/invertedTrapezoid.js'; +import { labelRect } from './shapes/labelRect.js'; +import { lean_left } from './shapes/leanLeft.js'; +import { lean_right } from './shapes/leanRight.js'; +import { lightningBolt } from './shapes/lightningBolt.js'; +import { linedCylinder } from './shapes/linedCylinder.js'; +import { linedWaveEdgedRect } from './shapes/linedWaveEdgedRect.js'; +import { multiRect } from './shapes/multiRect.js'; +import { multiWaveEdgedRectangle } from './shapes/multiWaveEdgedRectangle.js'; +import { note } from './shapes/note.js'; +import { question } from './shapes/question.js'; +import { rect_left_inv_arrow } from './shapes/rectLeftInvArrow.js'; +import { rectWithTitle } from './shapes/rectWithTitle.js'; +import { roundedRect } from './shapes/roundedRect.js'; +import { shadedProcess } from './shapes/shadedProcess.js'; +import { slopedRect } from './shapes/slopedRect.js'; +import { squareRect } from './shapes/squareRect.js'; +import { stadium } from './shapes/stadium.js'; +import { state } from './shapes/state.js'; +import { stateEnd } from './shapes/stateEnd.js'; +import { stateStart } from './shapes/stateStart.js'; +import { subroutine } from './shapes/subroutine.js'; +import { taggedRect } from './shapes/taggedRect.js'; +import { taggedWaveEdgedRectangle } from './shapes/taggedWaveEdgedRectangle.js'; +import { text } from './shapes/text.js'; +import { tiltedCylinder } from './shapes/tiltedCylinder.js'; +import { trapezoid } from './shapes/trapezoid.js'; +import { trapezoidalPentagon } from './shapes/trapezoidalPentagon.js'; +import { triangle } from './shapes/triangle.js'; +import { waveEdgedRectangle } from './shapes/waveEdgedRectangle.js'; +import { waveRectangle } from './shapes/waveRectangle.js'; +import { windowPane } from './shapes/windowPane.js'; +import { erBox } from './shapes/erBox.js'; +import { classBox } from './shapes/classBox.js'; +import { requirementBox } from './shapes/requirementBox.js'; +import { kanbanItem } from './shapes/kanbanItem.js'; + +type ShapeHandler = ( + parent: D3Selection, + node: Node, + options: ShapeRenderOptions +) => MaybePromise>; + +export interface ShapeDefinition { + semanticName: string; + name: string; + shortName: string; + description: string; + /** + * Aliases can include descriptive names, other short names, etc. + */ + aliases?: string[]; + /** + * These are names used by mermaid before the introduction of new shapes. These will not be in standard formats, and shouldn't be used by the users + */ + internalAliases?: string[]; + handler: ShapeHandler; +} + +export const shapesDefs = [ + { + semanticName: 'Process', + name: 'Rectangle', + shortName: 'rect', + description: 'Standard process shape', + aliases: ['proc', 'process', 'rectangle'], + internalAliases: ['squareRect'], + handler: squareRect, + }, + { + semanticName: 'Event', + name: 'Rounded Rectangle', + shortName: 'rounded', + description: 'Represents an event', + aliases: ['event'], + internalAliases: ['roundedRect'], + handler: roundedRect, + }, + { + semanticName: 'Terminal Point', + name: 'Stadium', + shortName: 'stadium', + description: 'Terminal point', + aliases: ['terminal', 'pill'], + handler: stadium, + }, + { + semanticName: 'Subprocess', + name: 'Framed Rectangle', + shortName: 'fr-rect', + description: 'Subprocess', + aliases: ['subprocess', 'subproc', 'framed-rectangle', 'subroutine'], + handler: subroutine, + }, + { + semanticName: 'Database', + name: 'Cylinder', + shortName: 'cyl', + description: 'Database storage', + aliases: ['db', 'database', 'cylinder'], + handler: cylinder, + }, + { + semanticName: 'Start', + name: 'Circle', + shortName: 'circle', + description: 'Starting point', + aliases: ['circ'], + handler: circle, + }, + { + semanticName: 'Decision', + name: 'Diamond', + shortName: 'diam', + description: 'Decision-making step', + aliases: ['decision', 'diamond', 'question'], + handler: question, + }, + { + semanticName: 'Prepare Conditional', + name: 'Hexagon', + shortName: 'hex', + description: 'Preparation or condition step', + aliases: ['hexagon', 'prepare'], + handler: hexagon, + }, + { + semanticName: 'Data Input/Output', + name: 'Lean Right', + shortName: 'lean-r', + description: 'Represents input or output', + aliases: ['lean-right', 'in-out'], + internalAliases: ['lean_right'], + handler: lean_right, + }, + { + semanticName: 'Data Input/Output', + name: 'Lean Left', + shortName: 'lean-l', + description: 'Represents output or input', + aliases: ['lean-left', 'out-in'], + internalAliases: ['lean_left'], + handler: lean_left, + }, + { + semanticName: 'Priority Action', + name: 'Trapezoid Base Bottom', + shortName: 'trap-b', + description: 'Priority action', + aliases: ['priority', 'trapezoid-bottom', 'trapezoid'], + handler: trapezoid, + }, + { + semanticName: 'Manual Operation', + name: 'Trapezoid Base Top', + shortName: 'trap-t', + description: 'Represents a manual task', + aliases: ['manual', 'trapezoid-top', 'inv-trapezoid'], + internalAliases: ['inv_trapezoid'], + handler: inv_trapezoid, + }, + { + semanticName: 'Stop', + name: 'Double Circle', + shortName: 'dbl-circ', + description: 'Represents a stop point', + aliases: ['double-circle'], + internalAliases: ['doublecircle'], + handler: doublecircle, + }, + { + semanticName: 'Text Block', + name: 'Text Block', + shortName: 'text', + description: 'Text block', + handler: text, + }, + { + semanticName: 'Card', + name: 'Notched Rectangle', + shortName: 'notch-rect', + description: 'Represents a card', + aliases: ['card', 'notched-rectangle'], + handler: card, + }, + { + semanticName: 'Lined/Shaded Process', + name: 'Lined Rectangle', + shortName: 'lin-rect', + description: 'Lined process shape', + aliases: ['lined-rectangle', 'lined-process', 'lin-proc', 'shaded-process'], + handler: shadedProcess, + }, + { + semanticName: 'Start', + name: 'Small Circle', + shortName: 'sm-circ', + description: 'Small starting point', + aliases: ['start', 'small-circle'], + internalAliases: ['stateStart'], + handler: stateStart, + }, + { + semanticName: 'Stop', + name: 'Framed Circle', + shortName: 'fr-circ', + description: 'Stop point', + aliases: ['stop', 'framed-circle'], + internalAliases: ['stateEnd'], + handler: stateEnd, + }, + { + semanticName: 'Fork/Join', + name: 'Filled Rectangle', + shortName: 'fork', + description: 'Fork or join in process flow', + aliases: ['join'], + internalAliases: ['forkJoin'], + handler: forkJoin, + }, + { + semanticName: 'Collate', + name: 'Hourglass', + shortName: 'hourglass', + description: 'Represents a collate operation', + aliases: ['hourglass', 'collate'], + handler: hourglass, + }, + { + semanticName: 'Comment', + name: 'Curly Brace', + shortName: 'brace', + description: 'Adds a comment', + aliases: ['comment', 'brace-l'], + handler: curlyBraceLeft, + }, + { + semanticName: 'Comment Right', + name: 'Curly Brace', + shortName: 'brace-r', + description: 'Adds a comment', + handler: curlyBraceRight, + }, + { + semanticName: 'Comment with braces on both sides', + name: 'Curly Braces', + shortName: 'braces', + description: 'Adds a comment', + handler: curlyBraces, + }, + { + semanticName: 'Com Link', + name: 'Lightning Bolt', + shortName: 'bolt', + description: 'Communication link', + aliases: ['com-link', 'lightning-bolt'], + handler: lightningBolt, + }, + { + semanticName: 'Document', + name: 'Document', + shortName: 'doc', + description: 'Represents a document', + aliases: ['doc', 'document'], + handler: waveEdgedRectangle, + }, + { + semanticName: 'Delay', + name: 'Half-Rounded Rectangle', + shortName: 'delay', + description: 'Represents a delay', + aliases: ['half-rounded-rectangle'], + handler: halfRoundedRectangle, + }, + { + semanticName: 'Direct Access Storage', + name: 'Horizontal Cylinder', + shortName: 'h-cyl', + description: 'Direct access storage', + aliases: ['das', 'horizontal-cylinder'], + handler: tiltedCylinder, + }, + { + semanticName: 'Disk Storage', + name: 'Lined Cylinder', + shortName: 'lin-cyl', + description: 'Disk storage', + aliases: ['disk', 'lined-cylinder'], + handler: linedCylinder, + }, + { + semanticName: 'Display', + name: 'Curved Trapezoid', + shortName: 'curv-trap', + description: 'Represents a display', + aliases: ['curved-trapezoid', 'display'], + handler: curvedTrapezoid, + }, + { + semanticName: 'Divided Process', + name: 'Divided Rectangle', + shortName: 'div-rect', + description: 'Divided process shape', + aliases: ['div-proc', 'divided-rectangle', 'divided-process'], + handler: dividedRectangle, + }, + { + semanticName: 'Extract', + name: 'Triangle', + shortName: 'tri', + description: 'Extraction process', + aliases: ['extract', 'triangle'], + handler: triangle, + }, + { + semanticName: 'Internal Storage', + name: 'Window Pane', + shortName: 'win-pane', + description: 'Internal storage', + aliases: ['internal-storage', 'window-pane'], + handler: windowPane, + }, + { + semanticName: 'Junction', + name: 'Filled Circle', + shortName: 'f-circ', + description: 'Junction point', + aliases: ['junction', 'filled-circle'], + handler: filledCircle, + }, + { + semanticName: 'Loop Limit', + name: 'Trapezoidal Pentagon', + shortName: 'notch-pent', + description: 'Loop limit step', + aliases: ['loop-limit', 'notched-pentagon'], + handler: trapezoidalPentagon, + }, + { + semanticName: 'Manual File', + name: 'Flipped Triangle', + shortName: 'flip-tri', + description: 'Manual file operation', + aliases: ['manual-file', 'flipped-triangle'], + handler: flippedTriangle, + }, + { + semanticName: 'Manual Input', + name: 'Sloped Rectangle', + shortName: 'sl-rect', + description: 'Manual input step', + aliases: ['manual-input', 'sloped-rectangle'], + handler: slopedRect, + }, + { + semanticName: 'Multi-Document', + name: 'Stacked Document', + shortName: 'docs', + description: 'Multiple documents', + aliases: ['documents', 'st-doc', 'stacked-document'], + handler: multiWaveEdgedRectangle, + }, + { + semanticName: 'Multi-Process', + name: 'Stacked Rectangle', + shortName: 'st-rect', + description: 'Multiple processes', + aliases: ['procs', 'processes', 'stacked-rectangle'], + handler: multiRect, + }, + { + semanticName: 'Stored Data', + name: 'Bow Tie Rectangle', + shortName: 'bow-rect', + description: 'Stored data', + aliases: ['stored-data', 'bow-tie-rectangle'], + handler: bowTieRect, + }, + { + semanticName: 'Summary', + name: 'Crossed Circle', + shortName: 'cross-circ', + description: 'Summary', + aliases: ['summary', 'crossed-circle'], + handler: crossedCircle, + }, + { + semanticName: 'Tagged Document', + name: 'Tagged Document', + shortName: 'tag-doc', + description: 'Tagged document', + aliases: ['tag-doc', 'tagged-document'], + handler: taggedWaveEdgedRectangle, + }, + { + semanticName: 'Tagged Process', + name: 'Tagged Rectangle', + shortName: 'tag-rect', + description: 'Tagged process', + aliases: ['tagged-rectangle', 'tag-proc', 'tagged-process'], + handler: taggedRect, + }, + { + semanticName: 'Paper Tape', + name: 'Flag', + shortName: 'flag', + description: 'Paper tape', + aliases: ['paper-tape'], + handler: waveRectangle, + }, + { + semanticName: 'Odd', + name: 'Odd', + shortName: 'odd', + description: 'Odd shape', + internalAliases: ['rect_left_inv_arrow'], + handler: rect_left_inv_arrow, + }, + { + semanticName: 'Lined Document', + name: 'Lined Document', + shortName: 'lin-doc', + description: 'Lined document', + aliases: ['lined-document'], + handler: linedWaveEdgedRect, + }, +] as const satisfies ShapeDefinition[]; + +const generateShapeMap = () => { + // These are the shapes that didn't have documentation present + const undocumentedShapes = { + // States + state, + choice, + note, + + // Rectangles + rectWithTitle, + labelRect, + + // Icons + iconSquare, + iconCircle, + icon, + iconRounded, + imageSquare, + anchor, + + // Kanban diagram + kanbanItem, + + // class diagram + classBox, + + // er diagram + erBox, + + // Requirement diagram + requirementBox, + } as const; + + const entries = [ + ...(Object.entries(undocumentedShapes) as Entries), + ...shapesDefs.flatMap((shape) => { + const aliases = [ + shape.shortName, + ...('aliases' in shape ? shape.aliases : []), + ...('internalAliases' in shape ? shape.internalAliases : []), + ]; + return aliases.map((alias) => [alias, shape.handler] as const); + }), + ]; + return Object.fromEntries(entries) as Record< + (typeof entries)[number][0], + (typeof entries)[number][1] + > satisfies Record; +}; + +export const shapes = generateShapeMap(); + +export function isValidShape(shape: string): shape is ShapeID { + return shape in shapes; +} + +export type ShapeID = keyof typeof shapes; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/anchor.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/anchor.ts new file mode 100644 index 000000000..11821a11b --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/anchor.ts @@ -0,0 +1,46 @@ +import { log } from '../../../logger.js'; +import { updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import { handleUndefinedAttr } from '../../../utils.js'; +import type { D3Selection } from '../../../types.js'; + +export function anchor(parent: D3Selection, node: Node) { + const { labelStyles } = styles2String(node); + node.labelStyle = labelStyles; + const classes = getNodeClasses(node); + let cssClasses = classes; + if (!classes) { + cssClasses = 'anchor'; + } + const shapeSvg = parent + .insert('g') + .attr('class', cssClasses) + .attr('id', node.domId || node.id); + + const radius = 1; + + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { fill: 'black', stroke: 'none', fillStyle: 'solid' }); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + } + const roughNode = rc.circle(0, 0, radius * 2, options); + const circleElem = shapeSvg.insert(() => roughNode, ':first-child'); + circleElem.attr('class', 'anchor').attr('style', handleUndefinedAttr(cssStyles)); + + updateNodeBounds(node, circleElem); + + node.intersect = function (point) { + log.info('Circle intersect', node, radius, point); + return intersect.circle(node, radius, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/bowTieRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/bowTieRect.ts new file mode 100644 index 000000000..d4b41103f --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/bowTieRect.ts @@ -0,0 +1,127 @@ +import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; + +function generateArcPoints( + x1: number, + y1: number, + x2: number, + y2: number, + rx: number, + ry: number, + clockwise: boolean +) { + const numPoints = 20; + // Calculate midpoint + const midX = (x1 + x2) / 2; + const midY = (y1 + y2) / 2; + + // Calculate the angle of the line connecting the points + const angle = Math.atan2(y2 - y1, x2 - x1); + + // Calculate transformed coordinates for the ellipse + const dx = (x2 - x1) / 2; + const dy = (y2 - y1) / 2; + + // Scale to unit circle + const transformedX = dx / rx; + const transformedY = dy / ry; + + // Calculate the distance between points on the unit circle + const distance = Math.sqrt(transformedX ** 2 + transformedY ** 2); + + // Check if the ellipse can be drawn with the given radii + if (distance > 1) { + throw new Error('The given radii are too small to create an arc between the points.'); + } + + // Calculate the distance from the midpoint to the center of the ellipse + const scaledCenterDistance = Math.sqrt(1 - distance ** 2); + + // Calculate the center of the ellipse + const centerX = midX + scaledCenterDistance * ry * Math.sin(angle) * (clockwise ? -1 : 1); + const centerY = midY - scaledCenterDistance * rx * Math.cos(angle) * (clockwise ? -1 : 1); + + // Calculate the start and end angles on the ellipse + const startAngle = Math.atan2((y1 - centerY) / ry, (x1 - centerX) / rx); + const endAngle = Math.atan2((y2 - centerY) / ry, (x2 - centerX) / rx); + + // Adjust angles for clockwise/counterclockwise + let angleRange = endAngle - startAngle; + if (clockwise && angleRange < 0) { + angleRange += 2 * Math.PI; + } + if (!clockwise && angleRange > 0) { + angleRange -= 2 * Math.PI; + } + + // Generate points + const points = []; + for (let i = 0; i < numPoints; i++) { + const t = i / (numPoints - 1); + const angle = startAngle + t * angleRange; + const x = centerX + rx * Math.cos(angle); + const y = centerY + ry * Math.sin(angle); + points.push({ x, y }); + } + + return points; +} + +export async function bowTieRect(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + const w = bbox.width + node.padding + 20; + const h = bbox.height + node.padding; + + const ry = h / 2; + const rx = ry / (2.5 + h / 50); + + // let shape: d3.Selection; + const { cssStyles } = node; + + const points = [ + { x: w / 2, y: -h / 2 }, + { x: -w / 2, y: -h / 2 }, + ...generateArcPoints(-w / 2, -h / 2, -w / 2, h / 2, rx, ry, false), + { x: w / 2, y: h / 2 }, + ...generateArcPoints(w / 2, h / 2, w / 2, -h / 2, rx, ry, true), + ]; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + const bowTieRectPath = createPathFromPoints(points); + const bowTieRectShapePath = rc.path(bowTieRectPath, options); + const bowTieRectShape = shapeSvg.insert(() => bowTieRectShapePath, ':first-child'); + + bowTieRectShape.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + bowTieRectShape.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + bowTieRectShape.selectAll('path').attr('style', nodeStyles); + } + + bowTieRectShape.attr('transform', `translate(${rx / 2}, 0)`); + + updateNodeBounds(node, bowTieRectShape); + + node.intersect = function (point) { + const pos = intersect.polygon(node, points, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/card.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/card.ts new file mode 100644 index 000000000..4aaf9222a --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/card.ts @@ -0,0 +1,70 @@ +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; + +import { insertPolygonShape } from './insertPolygonShape.js'; +import { createPathFromPoints } from './util.js'; +import type { D3Selection } from '../../../types.js'; + +// const createPathFromPoints = (points: { x: number; y: number }[]): string => { +// const pointStrings = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`); +// pointStrings.push('Z'); +// return pointStrings.join(' '); +// }; + +export async function card(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + + const h = bbox.height + node.padding; + const padding = 12; + const w = bbox.width + node.padding + padding; + const left = 0; + const right = w; + const top = -h; + const bottom = 0; + const points = [ + { x: left + padding, y: top }, + { x: right, y: top }, + { x: right, y: bottom }, + { x: left, y: bottom }, + { x: left, y: top + padding }, + { x: left + padding, y: top }, + ]; + + let polygon: D3Selection | Awaited>; + const { cssStyles } = node; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + const pathData = createPathFromPoints(points); + const roughNode = rc.path(pathData, options); + + polygon = shapeSvg + .insert(() => roughNode, ':first-child') + .attr('transform', `translate(${-w / 2}, ${h / 2})`); + + if (cssStyles) { + polygon.attr('style', cssStyles); + } + } else { + polygon = insertPolygonShape(shapeSvg, w, h, points); + } + + if (nodeStyles) { + polygon.attr('style', nodeStyles); + } + + updateNodeBounds(node, polygon); + + node.intersect = function (point) { + return intersect.polygon(node, points, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/choice.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/choice.ts new file mode 100644 index 000000000..4edd68587 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/choice.ts @@ -0,0 +1,55 @@ +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import rough from 'roughjs'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import { createPathFromPoints, getNodeClasses } from './util.js'; +import type { D3Selection } from '../../../types.js'; + +export function choice(parent: D3Selection, node: Node) { + const { nodeStyles } = styles2String(node); + node.label = ''; + const shapeSvg = parent + .insert('g') + .attr('class', getNodeClasses(node)) + .attr('id', node.domId ?? node.id); + const { cssStyles } = node; + + const s = Math.max(28, node.width ?? 0); + + const points = [ + { x: 0, y: s / 2 }, + { x: s / 2, y: 0 }, + { x: 0, y: -s / 2 }, + { x: -s / 2, y: 0 }, + ]; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const choicePath = createPathFromPoints(points); + const roughNode = rc.path(choicePath, options); + const choiceShape = shapeSvg.insert(() => roughNode, ':first-child'); + + if (cssStyles && node.look !== 'handDrawn') { + choiceShape.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + choiceShape.selectAll('path').attr('style', nodeStyles); + } + + node.width = 28; + node.height = 28; + + node.intersect = function (point) { + return intersect.polygon(node, points, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/circle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/circle.ts new file mode 100644 index 000000000..6b3be6765 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/circle.ts @@ -0,0 +1,45 @@ +import { log } from '../../../logger.js'; +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; +import { handleUndefinedAttr } from '../../../utils.js'; + +export async function circle(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, halfPadding } = await labelHelper(parent, node, getNodeClasses(node)); + + const radius = bbox.width / 2 + halfPadding; + let circleElem; + const { cssStyles } = node; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + const roughNode = rc.circle(0, 0, radius * 2, options); + + circleElem = shapeSvg.insert(() => roughNode, ':first-child'); + circleElem.attr('class', 'basic label-container').attr('style', handleUndefinedAttr(cssStyles)); + } else { + circleElem = shapeSvg + .insert('circle', ':first-child') + .attr('class', 'basic label-container') + .attr('style', nodeStyles) + .attr('r', radius) + .attr('cx', 0) + .attr('cy', 0); + } + + updateNodeBounds(node, circleElem); + + node.intersect = function (point) { + log.info('Circle intersect', node, radius, point); + return intersect.circle(node, radius, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/classBox.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/classBox.ts new file mode 100644 index 000000000..e35ee94ab --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/classBox.ts @@ -0,0 +1,207 @@ +import { updateNodeBounds } from './util.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; +import { select } from 'd3'; +import type { Node } from '../../types.js'; +import type { ClassNode } from '../../../diagrams/class/classTypes.js'; +import rough from 'roughjs'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import intersect from '../intersect/index.js'; +import { textHelper } from '../../../diagrams/class/shapeUtil.js'; +import { evaluate } from '../../../diagrams/common/common.js'; +import type { D3Selection } from '../../../types.js'; + +export async function classBox(parent: D3Selection, node: Node) { + const config = getConfig(); + const PADDING = config.class!.padding ?? 12; + const GAP = PADDING; + const useHtmlLabels = node.useHtmlLabels ?? evaluate(config.htmlLabels) ?? true; + // Treat node as classNode + const classNode = node as unknown as ClassNode; + classNode.annotations = classNode.annotations ?? []; + classNode.members = classNode.members ?? []; + classNode.methods = classNode.methods ?? []; + + const { shapeSvg, bbox } = await textHelper(parent, node, config, useHtmlLabels, GAP); + + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + + node.cssStyles = classNode.styles || ''; + + const styles = classNode.styles?.join(';') || nodeStyles || ''; + + if (!node.cssStyles) { + node.cssStyles = styles.replaceAll('!important', '').split(';'); + } + + const renderExtraBox = + classNode.members.length === 0 && + classNode.methods.length === 0 && + !config.class?.hideEmptyMembersBox; + + // Setup roughjs + // @ts-ignore TODO: Fix rough typings + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const w = bbox.width; + let h = bbox.height; + if (classNode.members.length === 0 && classNode.methods.length === 0) { + h += GAP; + } else if (classNode.members.length > 0 && classNode.methods.length === 0) { + h += GAP * 2; + } + const x = -w / 2; + const y = -h / 2; + + // Create and center rectangle + const roughRect = rc.rectangle( + x - PADDING, + y - + PADDING - + (renderExtraBox + ? PADDING + : classNode.members.length === 0 && classNode.methods.length === 0 + ? -PADDING / 2 + : 0), + w + 2 * PADDING, + h + + 2 * PADDING + + (renderExtraBox + ? PADDING * 2 + : classNode.members.length === 0 && classNode.methods.length === 0 + ? -PADDING + : 0), + options + ); + + const rect = shapeSvg.insert(() => roughRect, ':first-child'); + rect.attr('class', 'basic label-container'); + const rectBBox = rect.node()!.getBBox(); + + // Rect is centered so now adjust labels. + // TODO: Fix types + shapeSvg.selectAll('.text').each((_: any, i: number, nodes: any) => { + const text = select(nodes[i]); + // Get the current transform attribute + const transform = text.attr('transform'); + // Initialize variables for the translation values + let translateY = 0; + // Check if the transform attribute exists + if (transform) { + const regex = RegExp(/translate\(([^,]+),([^)]+)\)/); + const translate = regex.exec(transform); + if (translate) { + translateY = parseFloat(translate[2]); + } + } + // Add to the y value + let newTranslateY = + translateY + + y + + PADDING - + (renderExtraBox + ? PADDING + : classNode.members.length === 0 && classNode.methods.length === 0 + ? -PADDING / 2 + : 0); + if (!useHtmlLabels) { + // Fix so non html labels are better centered. + // BBox of text seems to be slightly different when calculated so we offset + newTranslateY -= 4; + } + let newTranslateX = x; + if ( + text.attr('class').includes('label-group') || + text.attr('class').includes('annotation-group') + ) { + newTranslateX = -text.node()?.getBBox().width / 2 || 0; + shapeSvg.selectAll('text').each(function (_: any, i: number, nodes: any) { + if (window.getComputedStyle(nodes[i]).textAnchor === 'middle') { + newTranslateX = 0; + } + }); + } + // Set the updated transform attribute + text.attr('transform', `translate(${newTranslateX}, ${newTranslateY})`); + }); + + // Render divider lines. + const annotationGroupHeight = + (shapeSvg.select('.annotation-group').node() as SVGGraphicsElement).getBBox().height - + (renderExtraBox ? PADDING / 2 : 0) || 0; + const labelGroupHeight = + (shapeSvg.select('.label-group').node() as SVGGraphicsElement).getBBox().height - + (renderExtraBox ? PADDING / 2 : 0) || 0; + const membersGroupHeight = + (shapeSvg.select('.members-group').node() as SVGGraphicsElement).getBBox().height - + (renderExtraBox ? PADDING / 2 : 0) || 0; + // First line (under label) + if (classNode.members.length > 0 || classNode.methods.length > 0 || renderExtraBox) { + const roughLine = rc.line( + rectBBox.x, + annotationGroupHeight + labelGroupHeight + y + PADDING, + rectBBox.x + rectBBox.width, + annotationGroupHeight + labelGroupHeight + y + PADDING, + options + ); + const line = shapeSvg.insert(() => roughLine); + line.attr('class', 'divider').attr('style', styles); + } + + // Second line (under members) + if (renderExtraBox || classNode.members.length > 0 || classNode.methods.length > 0) { + const roughLine = rc.line( + rectBBox.x, + annotationGroupHeight + labelGroupHeight + membersGroupHeight + y + GAP * 2 + PADDING, + rectBBox.x + rectBBox.width, + annotationGroupHeight + labelGroupHeight + membersGroupHeight + y + PADDING + GAP * 2, + options + ); + const line = shapeSvg.insert(() => roughLine); + line.attr('class', 'divider').attr('style', styles); + } + + /// Apply styles /// + if (classNode.look !== 'handDrawn') { + shapeSvg.selectAll('path').attr('style', styles); + } + // Apply other styles like stroke-width and stroke-dasharray to border (not background of shape) + rect.select(':nth-child(2)').attr('style', styles); + // Divider lines + shapeSvg.selectAll('.divider').select('path').attr('style', styles); + // Text elements + if (node.labelStyle) { + shapeSvg.selectAll('span').attr('style', node.labelStyle); + } else { + shapeSvg.selectAll('span').attr('style', styles); + } + // SVG text uses fill not color + if (!useHtmlLabels) { + // We just want to apply color to the text + const colorRegex = RegExp(/color\s*:\s*([^;]*)/); + const match = colorRegex.exec(styles); + if (match) { + const colorStyle = match[0].replace('color', 'fill'); + shapeSvg.selectAll('tspan').attr('style', colorStyle); + } else if (labelStyles) { + const match = colorRegex.exec(labelStyles); + if (match) { + const colorStyle = match[0].replace('color', 'fill'); + shapeSvg.selectAll('tspan').attr('style', colorStyle); + } + } + } + + updateNodeBounds(node, rect); + node.intersect = function (point) { + return intersect.rect(node, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/crossedCircle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/crossedCircle.ts new file mode 100644 index 000000000..eaacb9f34 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/crossedCircle.ts @@ -0,0 +1,67 @@ +import { log } from '../../../logger.js'; +import { getNodeClasses, updateNodeBounds } from './util.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import intersect from '../intersect/index.js'; +import type { D3Selection } from '../../../types.js'; + +function createLine(r: number) { + const xAxis45 = Math.cos(Math.PI / 4); // cosine of 45 degrees + const yAxis45 = Math.sin(Math.PI / 4); // sine of 45 degrees + const lineLength = r * 2; + + const pointQ1 = { x: (lineLength / 2) * xAxis45, y: (lineLength / 2) * yAxis45 }; // Quadrant I + const pointQ2 = { x: -(lineLength / 2) * xAxis45, y: (lineLength / 2) * yAxis45 }; // Quadrant II + const pointQ3 = { x: -(lineLength / 2) * xAxis45, y: -(lineLength / 2) * yAxis45 }; // Quadrant III + const pointQ4 = { x: (lineLength / 2) * xAxis45, y: -(lineLength / 2) * yAxis45 }; // Quadrant IV + + return `M ${pointQ2.x},${pointQ2.y} L ${pointQ4.x},${pointQ4.y} + M ${pointQ1.x},${pointQ1.y} L ${pointQ3.x},${pointQ3.y}`; +} + +export function crossedCircle(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + node.label = ''; + const shapeSvg = parent + .insert('g') + .attr('class', getNodeClasses(node)) + .attr('id', node.domId ?? node.id); + const radius = Math.max(30, node?.width ?? 0); + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const circleNode = rc.circle(0, 0, radius * 2, options); + const linePath = createLine(radius); + const lineNode = rc.path(linePath, options); + + const crossedCircle = shapeSvg.insert(() => circleNode, ':first-child'); + crossedCircle.insert(() => lineNode); + + if (cssStyles && node.look !== 'handDrawn') { + crossedCircle.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + crossedCircle.selectAll('path').attr('style', nodeStyles); + } + + updateNodeBounds(node, crossedCircle); + + node.intersect = function (point) { + log.info('crossedCircle intersect', node, { radius, point }); + const pos = intersect.circle(node, radius, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceLeft.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceLeft.ts new file mode 100644 index 000000000..00113ae4f --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceLeft.ts @@ -0,0 +1,115 @@ +import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; + +function generateCirclePoints( + centerX: number, + centerY: number, + radius: number, + numPoints = 100, + startAngle = 0, + endAngle = 180 +) { + const points = []; + + // Convert angles to radians + const startAngleRad = (startAngle * Math.PI) / 180; + const endAngleRad = (endAngle * Math.PI) / 180; + + // Calculate the angle range in radians + const angleRange = endAngleRad - startAngleRad; + + // Calculate the angle step + const angleStep = angleRange / (numPoints - 1); + + for (let i = 0; i < numPoints; i++) { + const angle = startAngleRad + i * angleStep; + const x = centerX + radius * Math.cos(angle); + const y = centerY + radius * Math.sin(angle); + points.push({ x: -x, y: -y }); + } + + return points; +} + +export async function curlyBraceLeft( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const w = bbox.width + (node.padding ?? 0); + const h = bbox.height + (node.padding ?? 0); + const radius = Math.max(5, h * 0.1); + + const { cssStyles } = node; + + const points = [ + ...generateCirclePoints(w / 2, -h / 2, radius, 30, -90, 0), + { x: -w / 2 - radius, y: radius }, + ...generateCirclePoints(w / 2 + radius * 2, -radius, radius, 20, -180, -270), + ...generateCirclePoints(w / 2 + radius * 2, radius, radius, 20, -90, -180), + { x: -w / 2 - radius, y: -h / 2 }, + ...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90), + ]; + + const rectPoints = [ + { x: w / 2, y: -h / 2 - radius }, + { x: -w / 2, y: -h / 2 - radius }, + ...generateCirclePoints(w / 2, -h / 2, radius, 20, -90, 0), + { x: -w / 2 - radius, y: -radius }, + ...generateCirclePoints(w / 2 + w * 0.1, -radius, radius, 20, -180, -270), + ...generateCirclePoints(w / 2 + w * 0.1, radius, radius, 20, -90, -180), + { x: -w / 2 - radius, y: h / 2 }, + ...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90), + { x: -w / 2, y: h / 2 + radius }, + { x: w / 2, y: h / 2 + radius }, + ]; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { fill: 'none' }); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + const curlyBraceLeftPath = createPathFromPoints(points); + const newCurlyBracePath = curlyBraceLeftPath.replace('Z', ''); + const curlyBraceLeftNode = rc.path(newCurlyBracePath, options); + const rectPath = createPathFromPoints(rectPoints); + const rectShape = rc.path(rectPath, { ...options }); + const curlyBraceLeftShape = shapeSvg.insert('g', ':first-child'); + curlyBraceLeftShape.insert(() => rectShape, ':first-child').attr('stroke-opacity', 0); + curlyBraceLeftShape.insert(() => curlyBraceLeftNode, ':first-child'); + curlyBraceLeftShape.attr('class', 'text'); + + if (cssStyles && node.look !== 'handDrawn') { + curlyBraceLeftShape.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + curlyBraceLeftShape.selectAll('path').attr('style', nodeStyles); + } + + curlyBraceLeftShape.attr('transform', `translate(${radius}, 0)`); + + label.attr( + 'transform', + `translate(${-w / 2 + radius - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) / 2 - (bbox.y - (bbox.top ?? 0))})` + ); + + updateNodeBounds(node, curlyBraceLeftShape); + + node.intersect = function (point) { + const pos = intersect.polygon(node, rectPoints, point); + + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceRight.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceRight.ts new file mode 100644 index 000000000..d208efc97 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceRight.ts @@ -0,0 +1,115 @@ +import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; + +function generateCirclePoints( + centerX: number, + centerY: number, + radius: number, + numPoints = 100, + startAngle = 0, + endAngle = 180 +) { + const points = []; + + // Convert angles to radians + const startAngleRad = (startAngle * Math.PI) / 180; + const endAngleRad = (endAngle * Math.PI) / 180; + + // Calculate the angle range in radians + const angleRange = endAngleRad - startAngleRad; + + // Calculate the angle step + const angleStep = angleRange / (numPoints - 1); + + for (let i = 0; i < numPoints; i++) { + const angle = startAngleRad + i * angleStep; + const x = centerX + radius * Math.cos(angle); + const y = centerY + radius * Math.sin(angle); + points.push({ x, y }); + } + + return points; +} + +export async function curlyBraceRight( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const w = bbox.width + (node.padding ?? 0); + const h = bbox.height + (node.padding ?? 0); + const radius = Math.max(5, h * 0.1); + + const { cssStyles } = node; + + const points = [ + ...generateCirclePoints(w / 2, -h / 2, radius, 20, -90, 0), + { x: w / 2 + radius, y: -radius }, + ...generateCirclePoints(w / 2 + radius * 2, -radius, radius, 20, -180, -270), + ...generateCirclePoints(w / 2 + radius * 2, radius, radius, 20, -90, -180), + { x: w / 2 + radius, y: h / 2 }, + ...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90), + ]; + + const rectPoints = [ + { x: -w / 2, y: -h / 2 - radius }, + { x: w / 2, y: -h / 2 - radius }, + ...generateCirclePoints(w / 2, -h / 2, radius, 20, -90, 0), + { x: w / 2 + radius, y: -radius }, + ...generateCirclePoints(w / 2 + radius * 2, -radius, radius, 20, -180, -270), + ...generateCirclePoints(w / 2 + radius * 2, radius, radius, 20, -90, -180), + { x: w / 2 + radius, y: h / 2 }, + ...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90), + { x: w / 2, y: h / 2 + radius }, + { x: -w / 2, y: h / 2 + radius }, + ]; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { fill: 'none' }); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + const curlyBraceRightPath = createPathFromPoints(points); + const newCurlyBracePath = curlyBraceRightPath.replace('Z', ''); + const curlyBraceRightNode = rc.path(newCurlyBracePath, options); + const rectPath = createPathFromPoints(rectPoints); + const rectShape = rc.path(rectPath, { ...options }); + const curlyBraceRightShape = shapeSvg.insert('g', ':first-child'); + curlyBraceRightShape.insert(() => rectShape, ':first-child').attr('stroke-opacity', 0); + curlyBraceRightShape.insert(() => curlyBraceRightNode, ':first-child'); + curlyBraceRightShape.attr('class', 'text'); + + if (cssStyles && node.look !== 'handDrawn') { + curlyBraceRightShape.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + curlyBraceRightShape.selectAll('path').attr('style', nodeStyles); + } + + curlyBraceRightShape.attr('transform', `translate(${-radius}, 0)`); + + label.attr( + 'transform', + `translate(${-w / 2 + (node.padding ?? 0) / 2 - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) / 2 - (bbox.y - (bbox.top ?? 0))})` + ); + + updateNodeBounds(node, curlyBraceRightShape); + + node.intersect = function (point) { + const pos = intersect.polygon(node, rectPoints, point); + + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraces.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraces.ts new file mode 100644 index 000000000..1fd9b6f05 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraces.ts @@ -0,0 +1,134 @@ +import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; + +function generateCirclePoints( + centerX: number, + centerY: number, + radius: number, + numPoints = 100, + startAngle = 0, + endAngle = 180 +) { + const points = []; + + // Convert angles to radians + const startAngleRad = (startAngle * Math.PI) / 180; + const endAngleRad = (endAngle * Math.PI) / 180; + + // Calculate the angle range in radians + const angleRange = endAngleRad - startAngleRad; + + // Calculate the angle step + const angleStep = angleRange / (numPoints - 1); + + for (let i = 0; i < numPoints; i++) { + const angle = startAngleRad + i * angleStep; + const x = centerX + radius * Math.cos(angle); + const y = centerY + radius * Math.sin(angle); + points.push({ x: -x, y: -y }); + } + + return points; +} + +export async function curlyBraces( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const w = bbox.width + (node.padding ?? 0); + const h = bbox.height + (node.padding ?? 0); + const radius = Math.max(5, h * 0.1); + + const { cssStyles } = node; + + const leftCurlyBracePoints = [ + ...generateCirclePoints(w / 2, -h / 2, radius, 30, -90, 0), + { x: -w / 2 - radius, y: radius }, + ...generateCirclePoints(w / 2 + radius * 2, -radius, radius, 20, -180, -270), + ...generateCirclePoints(w / 2 + radius * 2, radius, radius, 20, -90, -180), + { x: -w / 2 - radius, y: -h / 2 }, + ...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90), + ]; + + const rightCurlyBracePoints = [ + ...generateCirclePoints(-w / 2 + radius + radius / 2, -h / 2, radius, 20, -90, -180), + { x: w / 2 - radius / 2, y: radius }, + ...generateCirclePoints(-w / 2 - radius / 2, -radius, radius, 20, 0, 90), + ...generateCirclePoints(-w / 2 - radius / 2, radius, radius, 20, -90, 0), + { x: w / 2 - radius / 2, y: -radius }, + ...generateCirclePoints(-w / 2 + radius + radius / 2, h / 2, radius, 30, -180, -270), + ]; + + const rectPoints = [ + { x: w / 2, y: -h / 2 - radius }, + { x: -w / 2, y: -h / 2 - radius }, + ...generateCirclePoints(w / 2, -h / 2, radius, 20, -90, 0), + { x: -w / 2 - radius, y: -radius }, + ...generateCirclePoints(w / 2 + radius * 2, -radius, radius, 20, -180, -270), + ...generateCirclePoints(w / 2 + radius * 2, radius, radius, 20, -90, -180), + { x: -w / 2 - radius, y: h / 2 }, + ...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90), + { x: -w / 2, y: h / 2 + radius }, + { x: w / 2 - radius - radius / 2, y: h / 2 + radius }, + ...generateCirclePoints(-w / 2 + radius + radius / 2, -h / 2, radius, 20, -90, -180), + { x: w / 2 - radius / 2, y: radius }, + ...generateCirclePoints(-w / 2 - radius / 2, -radius, radius, 20, 0, 90), + ...generateCirclePoints(-w / 2 - radius / 2, radius, radius, 20, -90, 0), + { x: w / 2 - radius / 2, y: -radius }, + ...generateCirclePoints(-w / 2 + radius + radius / 2, h / 2, radius, 30, -180, -270), + ]; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { fill: 'none' }); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + const leftCurlyBracePath = createPathFromPoints(leftCurlyBracePoints); + const newLeftCurlyBracePath = leftCurlyBracePath.replace('Z', ''); + const leftCurlyBraceNode = rc.path(newLeftCurlyBracePath, options); + const rightCurlyBracePath = createPathFromPoints(rightCurlyBracePoints); + const newRightCurlyBracePath = rightCurlyBracePath.replace('Z', ''); + const rightCurlyBraceNode = rc.path(newRightCurlyBracePath, options); + const rectPath = createPathFromPoints(rectPoints); + const rectShape = rc.path(rectPath, { ...options }); + const curlyBracesShape = shapeSvg.insert('g', ':first-child'); + curlyBracesShape.insert(() => rectShape, ':first-child').attr('stroke-opacity', 0); + curlyBracesShape.insert(() => leftCurlyBraceNode, ':first-child'); + curlyBracesShape.insert(() => rightCurlyBraceNode, ':first-child'); + curlyBracesShape.attr('class', 'text'); + + if (cssStyles && node.look !== 'handDrawn') { + curlyBracesShape.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + curlyBracesShape.selectAll('path').attr('style', nodeStyles); + } + + curlyBracesShape.attr('transform', `translate(${radius - radius / 4}, 0)`); + + label.attr( + 'transform', + `translate(${-w / 2 + (node.padding ?? 0) / 2 - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) / 2 - (bbox.y - (bbox.top ?? 0))})` + ); + + updateNodeBounds(node, curlyBracesShape); + + node.intersect = function (point) { + const pos = intersect.polygon(node, rectPoints, point); + + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/curvedTrapezoid.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curvedTrapezoid.ts new file mode 100644 index 000000000..26339b65c --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curvedTrapezoid.ts @@ -0,0 +1,75 @@ +import { + labelHelper, + updateNodeBounds, + getNodeClasses, + createPathFromPoints, + generateCirclePoints, +} from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; + +export async function curvedTrapezoid( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + const minWidth = 80, + minHeight = 20; + const w = Math.max(minWidth, (bbox.width + (node.padding ?? 0) * 2) * 1.25, node?.width ?? 0); + const h = Math.max(minHeight, bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + const radius = h / 2; + + const { cssStyles } = node; + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const totalWidth = w, + totalHeight = h; + const rw = totalWidth - radius; + const tw = totalHeight / 4; + + const points = [ + { x: rw, y: 0 }, + { x: tw, y: 0 }, + { x: 0, y: totalHeight / 2 }, + { x: tw, y: totalHeight }, + { x: rw, y: totalHeight }, + ...generateCirclePoints(-rw, -totalHeight / 2, radius, 50, 270, 90), + ]; + + const pathData = createPathFromPoints(points); + const shapeNode = rc.path(pathData, options); + + const polygon = shapeSvg.insert(() => shapeNode, ':first-child'); + polygon.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + polygon.selectChildren('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + polygon.selectChildren('path').attr('style', nodeStyles); + } + + polygon.attr('transform', `translate(${-w / 2}, ${-h / 2})`); + + updateNodeBounds(node, polygon); + + node.intersect = function (point) { + const pos = intersect.polygon(node, points, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/cylinder.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/cylinder.ts new file mode 100644 index 000000000..9d2cd63f6 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/cylinder.ts @@ -0,0 +1,125 @@ +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; +import { handleUndefinedAttr } from '../../../utils.js'; + +export const createCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number +): string => { + return [ + `M${x},${y + ry}`, + `a${rx},${ry} 0,0,0 ${width},0`, + `a${rx},${ry} 0,0,0 ${-width},0`, + `l0,${height}`, + `a${rx},${ry} 0,0,0 ${width},0`, + `l0,${-height}`, + ].join(' '); +}; +export const createOuterCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number +): string => { + return [ + `M${x},${y + ry}`, + `M${x + width},${y + ry}`, + `a${rx},${ry} 0,0,0 ${-width},0`, + `l0,${height}`, + `a${rx},${ry} 0,0,0 ${width},0`, + `l0,${-height}`, + ].join(' '); +}; +export const createInnerCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number +): string => { + return [`M${x - width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 ${width},0`].join(' '); +}; +export async function cylinder(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const w = Math.max(bbox.width + node.padding, node.width ?? 0); + const rx = w / 2; + const ry = rx / (2.5 + w / 50); + const h = Math.max(bbox.height + ry + node.padding, node.height ?? 0); + + let cylinder: D3Selection | D3Selection; + const { cssStyles } = node; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry); + const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry); + const outerNode = rc.path(outerPathData, userNodeOverrides(node, {})); + const innerLine = rc.path(innerPathData, userNodeOverrides(node, { fill: 'none' })); + + cylinder = shapeSvg.insert(() => innerLine, ':first-child'); + cylinder = shapeSvg.insert(() => outerNode, ':first-child'); + cylinder.attr('class', 'basic label-container'); + if (cssStyles) { + cylinder.attr('style', cssStyles); + } + } else { + const pathData = createCylinderPathD(0, 0, w, h, rx, ry); + cylinder = shapeSvg + .insert('path', ':first-child') + .attr('d', pathData) + .attr('class', 'basic label-container') + .attr('style', handleUndefinedAttr(cssStyles)) + .attr('style', nodeStyles); + } + + cylinder.attr('label-offset-y', ry); + cylinder.attr('transform', `translate(${-w / 2}, ${-(h / 2 + ry)})`); + + updateNodeBounds(node, cylinder); + + label.attr( + 'transform', + `translate(${-(bbox.width / 2) - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) + (node.padding ?? 0) / 1.5 - (bbox.y - (bbox.top ?? 0))})` + ); + + node.intersect = function (point) { + const pos = intersect.rect(node, point); + const x = pos.x - (node.x ?? 0); + + if ( + rx != 0 && + (Math.abs(x) < (node.width ?? 0) / 2 || + (Math.abs(x) == (node.width ?? 0) / 2 && + Math.abs(pos.y - (node.y ?? 0)) > (node.height ?? 0) / 2 - ry)) + ) { + let y = ry * ry * (1 - (x * x) / (rx * rx)); + if (y > 0) { + y = Math.sqrt(y); + } + y = ry - y; + if (point.y - (node.y ?? 0) > 0) { + y = -y; + } + + pos.y += y; + } + + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/dividedRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/dividedRect.ts new file mode 100644 index 000000000..77df58155 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/dividedRect.ts @@ -0,0 +1,71 @@ +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; + +export async function dividedRectangle( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const w = bbox.width + node.padding; + const h = bbox.height + node.padding; + const rectOffset = h * 0.2; + + const x = -w / 2; + const y = -h / 2 - rectOffset / 2; + + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const pts = [ + { x, y: y + rectOffset }, + { x: -x, y: y + rectOffset }, + { x: -x, y: -y }, + { x, y: -y }, + { x, y }, + { x: -x, y }, + { x: -x, y: y + rectOffset }, + ]; + + const poly = rc.polygon( + pts.map((p) => [p.x, p.y]), + options + ); + + const polygon = shapeSvg.insert(() => poly, ':first-child'); + polygon.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + polygon.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + polygon.selectAll('path').attr('style', nodeStyles); + } + + label.attr( + 'transform', + `translate(${x + (node.padding ?? 0) / 2 - (bbox.x - (bbox.left ?? 0))}, ${y + rectOffset + (node.padding ?? 0) / 2 - (bbox.y - (bbox.top ?? 0))})` + ); + + updateNodeBounds(node, polygon); + + node.intersect = function (point) { + const pos = intersect.rect(node, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/document.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/document.ts new file mode 100644 index 000000000..d5ea3aa76 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/document.ts @@ -0,0 +1,120 @@ +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; +import { handleUndefinedAttr } from '../../../utils.js'; + +export const createCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number +): string => { + return [ + `M${x},${y + ry}`, + `a${rx},${ry} 0,0,0 ${width},0`, + `a${rx},${ry} 0,0,0 ${-width},0`, + `l0,${height}`, + `a${rx},${ry} 0,0,0 ${width},0`, + `l0,${-height}`, + ].join(' '); +}; +export const createOuterCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number +): string => { + return [ + `M${x},${y + ry}`, + `M${x + width},${y + ry}`, + `a${rx},${ry} 0,0,0 ${-width},0`, + `l0,${height}`, + `a${rx},${ry} 0,0,0 ${width},0`, + `l0,${-height}`, + ].join(' '); +}; +export const createInnerCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number +): string => { + return [`M${x - width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 ${width},0`].join(' '); +}; +export async function cylinder(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + const w = bbox.width + node.padding; + const rx = w / 2; + const ry = rx / (2.5 + w / 50); + const h = bbox.height + ry + node.padding; + + let cylinder: D3Selection | D3Selection; + const { cssStyles } = node; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry); + const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry); + const outerNode = rc.path(outerPathData, userNodeOverrides(node, {})); + const innerLine = rc.path(innerPathData, userNodeOverrides(node, { fill: 'none' })); + + cylinder = shapeSvg.insert(() => innerLine, ':first-child'); + cylinder = shapeSvg.insert(() => outerNode, ':first-child'); + cylinder.attr('class', 'basic label-container'); + if (cssStyles) { + cylinder.attr('style', cssStyles); + } + } else { + const pathData = createCylinderPathD(0, 0, w, h, rx, ry); + cylinder = shapeSvg + .insert('path', ':first-child') + .attr('d', pathData) + .attr('class', 'basic label-container') + .attr('style', handleUndefinedAttr(cssStyles)) + .attr('style', nodeStyles); + } + + cylinder.attr('label-offset-y', ry); + cylinder.attr('transform', `translate(${-w / 2}, ${-(h / 2 + ry)})`); + + updateNodeBounds(node, cylinder); + + node.intersect = function (point) { + const pos = intersect.rect(node, point); + const x = pos.x - (node.x ?? 0); + + if ( + rx != 0 && + (Math.abs(x) < (node.width ?? 0) / 2 || + (Math.abs(x) == (node.width ?? 0) / 2 && + Math.abs(pos.y - (node.y ?? 0)) > (node.height ?? 0) / 2 - ry)) + ) { + let y = ry * ry * (1 - (x * x) / (rx * rx)); + if (y != 0) { + y = Math.sqrt(y); + } + y = ry - y; + if (point.y - (node.y ?? 0) > 0) { + y = -y; + } + + pos.y += y; + } + + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/doubleCircle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/doubleCircle.ts new file mode 100644 index 000000000..bc0d844da --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/doubleCircle.ts @@ -0,0 +1,71 @@ +import { log } from '../../../logger.js'; +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; +import { handleUndefinedAttr } from '../../../utils.js'; + +export async function doublecircle( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, halfPadding } = await labelHelper(parent, node, getNodeClasses(node)); + const gap = 5; + const outerRadius = bbox.width / 2 + halfPadding + gap; + const innerRadius = bbox.width / 2 + halfPadding; + + let circleGroup; + const { cssStyles } = node; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const outerOptions = userNodeOverrides(node, { roughness: 0.2, strokeWidth: 2.5 }); + + const innerOptions = userNodeOverrides(node, { roughness: 0.2, strokeWidth: 1.5 }); + const outerRoughNode = rc.circle(0, 0, outerRadius * 2, outerOptions); + const innerRoughNode = rc.circle(0, 0, innerRadius * 2, innerOptions); + + circleGroup = shapeSvg.insert('g', ':first-child'); + // circleGroup = circleGroup.insert(() => outerRoughNode, ':first-child'); + circleGroup + .attr('class', handleUndefinedAttr(node.cssClasses)) + .attr('style', handleUndefinedAttr(cssStyles)); + + circleGroup.node()?.appendChild(outerRoughNode); + circleGroup.node()?.appendChild(innerRoughNode); + } else { + circleGroup = shapeSvg.insert('g', ':first-child'); + + const outerCircle = circleGroup.insert('circle', ':first-child'); + const innerCircle = circleGroup.insert('circle'); + circleGroup.attr('class', 'basic label-container').attr('style', nodeStyles); + + outerCircle + .attr('class', 'outer-circle') + .attr('style', nodeStyles) + .attr('r', outerRadius) + .attr('cx', 0) + .attr('cy', 0); + + innerCircle + .attr('class', 'inner-circle') + .attr('style', nodeStyles) + .attr('r', innerRadius) + .attr('cx', 0) + .attr('cy', 0); + } + + updateNodeBounds(node, circleGroup); + + node.intersect = function (point) { + log.info('DoubleCircle intersect', node, outerRadius, point); + return intersect.circle(node, outerRadius, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/drawRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/drawRect.ts new file mode 100644 index 000000000..707aed2c7 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/drawRect.ts @@ -0,0 +1,70 @@ +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node, RectOptions } from '../../types.js'; +import { createRoundedRectPathD } from './roundedRectPath.js'; +import { userNodeOverrides, styles2String } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; +import { handleUndefinedAttr } from '../../../utils.js'; + +export async function drawRect( + parent: D3Selection, + node: Node, + options: RectOptions +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + // console.log('IPI labelStyles:', labelStyles); + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + + const totalWidth = Math.max(bbox.width + options.labelPaddingX * 2, node?.width || 0); + const totalHeight = Math.max(bbox.height + options.labelPaddingY * 2, node?.height || 0); + const x = -totalWidth / 2; + const y = -totalHeight / 2; + + // log.info('IPI node = ', node); + + let rect; + let { rx, ry } = node; + const { cssStyles } = node; + + //use options rx, ry overrides if present + if (options?.rx && options.ry) { + rx = options.rx; + ry = options.ry; + } + + if (node.look === 'handDrawn') { + // @ts-ignore TODO: Fix rough typings + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + const roughNode = + rx || ry + ? rc.path(createRoundedRectPathD(x, y, totalWidth, totalHeight, rx || 0), options) + : rc.rectangle(x, y, totalWidth, totalHeight, options); + + rect = shapeSvg.insert(() => roughNode, ':first-child'); + rect.attr('class', 'basic label-container').attr('style', handleUndefinedAttr(cssStyles)); + } else { + rect = shapeSvg.insert('rect', ':first-child'); + + rect + .attr('class', 'basic label-container') + .attr('style', nodeStyles) + .attr('rx', handleUndefinedAttr(rx)) + .attr('ry', handleUndefinedAttr(ry)) + .attr('x', x) + .attr('y', y) + .attr('width', totalWidth) + .attr('height', totalHeight); + } + + updateNodeBounds(node, rect); + + node.intersect = function (point) { + return intersect.rect(node, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/erBox.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/erBox.ts new file mode 100644 index 000000000..af1e9945a --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/erBox.ts @@ -0,0 +1,359 @@ +import { updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { userNodeOverrides, styles2String } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import { drawRect } from './drawRect.js'; +import { getConfig } from '../../../config.js'; +import type { EntityNode } from '../../../diagrams/er/erTypes.js'; +import { createText } from '../../createText.js'; +import { evaluate, parseGenericTypes } from '../../../diagrams/common/common.js'; +import { select } from 'd3'; +import { calculateTextWidth } from '../../../utils.js'; +import type { MermaidConfig } from '../../../config.type.js'; +import type { D3Selection } from '../../../types.js'; + +export async function erBox(parent: D3Selection, node: Node) { + // Treat node as entityNode for certain entityNode checks + const entityNode = node as unknown as EntityNode; + if (entityNode.alias) { + node.label = entityNode.alias; + } + + // Background shapes are drawn to fill in the background color and cover up the ER diagram edge markers. + // Draw background shape once. + if (node.look === 'handDrawn') { + const { themeVariables } = getConfig(); + const { background } = themeVariables; + const backgroundNode = { + ...node, + id: node.id + '-background', + look: 'default', + cssStyles: ['stroke: none', `fill: ${background}`], + }; + await erBox(parent, backgroundNode); + } + + const config = getConfig(); + node.useHtmlLabels = config.htmlLabels; + let PADDING = config.er?.diagramPadding ?? 10; + let TEXT_PADDING = config.er?.entityPadding ?? 6; + + const { cssStyles } = node; + const { labelStyles } = styles2String(node); + + // Draw rect if no attributes are found + if (entityNode.attributes.length === 0 && node.label) { + const options = { + rx: 0, + ry: 0, + labelPaddingX: PADDING, + labelPaddingY: PADDING * 1.5, + classes: '', + }; + // Set minimum width + if ( + calculateTextWidth(node.label, config) + options.labelPaddingX * 2 < + config.er!.minEntityWidth! + ) { + node.width = config.er!.minEntityWidth; + } + const shapeSvg = await drawRect(parent, node, options); + + // drawRect doesn't center non-htmlLabels correctly as of now, so translate label + if (!evaluate(config.htmlLabels)) { + const textElement = shapeSvg.select('text'); + const bbox = (textElement.node() as SVGTextElement)?.getBBox(); + textElement.attr('transform', `translate(${-bbox.width / 2}, 0)`); + } + return shapeSvg; + } + + if (!config.htmlLabels) { + PADDING *= 1.25; + TEXT_PADDING *= 1.25; + } + + let cssClasses = getNodeClasses(node); + if (!cssClasses) { + cssClasses = 'node default'; + } + + const shapeSvg = parent + // @ts-ignore Ignore .insert on SVGAElement + .insert('g') + .attr('class', cssClasses) + .attr('id', node.domId || node.id); + + const nameBBox = await addText(shapeSvg, node.label ?? '', config, 0, 0, ['name'], labelStyles); + nameBBox.height += TEXT_PADDING; + let yOffset = 0; + const yOffsets = []; + let maxTypeWidth = 0; + let maxNameWidth = 0; + let maxKeysWidth = 0; + let maxCommentWidth = 0; + let keysPresent = true; + let commentPresent = true; + for (const attribute of entityNode.attributes) { + const typeBBox = await addText( + shapeSvg, + attribute.type, + config, + 0, + yOffset, + ['attribute-type'], + labelStyles + ); + maxTypeWidth = Math.max(maxTypeWidth, typeBBox.width + PADDING); + const nameBBox = await addText( + shapeSvg, + attribute.name, + config, + 0, + yOffset, + ['attribute-name'], + labelStyles + ); + maxNameWidth = Math.max(maxNameWidth, nameBBox.width + PADDING); + const keysBBox = await addText( + shapeSvg, + attribute.keys.join(), + config, + 0, + yOffset, + ['attribute-keys'], + labelStyles + ); + maxKeysWidth = Math.max(maxKeysWidth, keysBBox.width + PADDING); + const commentBBox = await addText( + shapeSvg, + attribute.comment, + config, + 0, + yOffset, + ['attribute-comment'], + labelStyles + ); + maxCommentWidth = Math.max(maxCommentWidth, commentBBox.width + PADDING); + + yOffset += + Math.max(typeBBox.height, nameBBox.height, keysBBox.height, commentBBox.height) + + TEXT_PADDING; + yOffsets.push(yOffset); + } + yOffsets.pop(); + let totalWidthSections = 4; + + if (maxKeysWidth <= PADDING) { + keysPresent = false; + maxKeysWidth = 0; + totalWidthSections--; + } + if (maxCommentWidth <= PADDING) { + commentPresent = false; + maxCommentWidth = 0; + totalWidthSections--; + } + + const shapeBBox = shapeSvg.node()!.getBBox(); + // Add extra padding to attribute components to accommodate for difference in width + if ( + nameBBox.width + PADDING * 2 - (maxTypeWidth + maxNameWidth + maxKeysWidth + maxCommentWidth) > + 0 + ) { + const difference = + nameBBox.width + PADDING * 2 - (maxTypeWidth + maxNameWidth + maxKeysWidth + maxCommentWidth); + maxTypeWidth += difference / totalWidthSections; + maxNameWidth += difference / totalWidthSections; + if (maxKeysWidth > 0) { + maxKeysWidth += difference / totalWidthSections; + } + if (maxCommentWidth > 0) { + maxCommentWidth += difference / totalWidthSections; + } + } + + const maxWidth = maxTypeWidth + maxNameWidth + maxKeysWidth + maxCommentWidth; + + // @ts-ignore TODO: Fix rough typings + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const w = Math.max(shapeBBox.width + PADDING * 2, node?.width || 0, maxWidth); + const h = Math.max(shapeBBox.height + (yOffsets[0] || yOffset) + TEXT_PADDING, node?.height || 0); + const x = -w / 2; + const y = -h / 2; + + // Translate attribute text labels + shapeSvg.selectAll('g:not(:first-child)').each((_: any, i: number, nodes: any) => { + const text = select(nodes[i]); + const transform = text.attr('transform'); + let translateX = 0; + let translateY = 0; + + if (transform) { + const regex = RegExp(/translate\(([^,]+),([^)]+)\)/); + const translate = regex.exec(transform); + if (translate) { + translateX = parseFloat(translate[1]); + translateY = parseFloat(translate[2]); + if (text.attr('class').includes('attribute-name')) { + translateX += maxTypeWidth; + } else if (text.attr('class').includes('attribute-keys')) { + translateX += maxTypeWidth + maxNameWidth; + } else if (text.attr('class').includes('attribute-comment')) { + translateX += maxTypeWidth + maxNameWidth + maxKeysWidth; + } + } + } + + text.attr( + 'transform', + `translate(${x + PADDING / 2 + translateX}, ${translateY + y + nameBBox.height + TEXT_PADDING / 2})` + ); + }); + // Center the name + shapeSvg + .select('.name') + .attr('transform', 'translate(' + -nameBBox.width / 2 + ', ' + (y + TEXT_PADDING / 2) + ')'); + + // Draw shape + const roughRect = rc.rectangle(x, y, w, h, options); + const rect = shapeSvg.insert(() => roughRect, ':first-child').attr('style', cssStyles!.join('')); + + const { themeVariables } = getConfig(); + const { rowEven, rowOdd, nodeBorder } = themeVariables; + + yOffsets.push(0); + // Draw row rects + for (const [i, yOffset] of yOffsets.entries()) { + if (i === 0 && yOffsets.length > 1) { + continue; + // Skip first row + } + const isEven = i % 2 === 0 && yOffset !== 0; + const roughRect = rc.rectangle(x, nameBBox.height + y + yOffset, w, nameBBox.height, { + ...options, + fill: isEven ? rowEven : rowOdd, + stroke: nodeBorder, + }); + shapeSvg + .insert(() => roughRect, 'g.label') + .attr('style', cssStyles!.join('')) + .attr('class', `row-rect-${i % 2 === 0 ? 'even' : 'odd'}`); + } + + // Draw divider lines + // Name line + let roughLine = rc.line(x, nameBBox.height + y, w + x, nameBBox.height + y, options); + shapeSvg.insert(() => roughLine).attr('class', 'divider'); + // First line + roughLine = rc.line(maxTypeWidth + x, nameBBox.height + y, maxTypeWidth + x, h + y, options); + shapeSvg.insert(() => roughLine).attr('class', 'divider'); + // Second line + if (keysPresent) { + roughLine = rc.line( + maxTypeWidth + maxNameWidth + x, + nameBBox.height + y, + maxTypeWidth + maxNameWidth + x, + h + y, + options + ); + shapeSvg.insert(() => roughLine).attr('class', 'divider'); + } + // Third line + if (commentPresent) { + roughLine = rc.line( + maxTypeWidth + maxNameWidth + maxKeysWidth + x, + nameBBox.height + y, + maxTypeWidth + maxNameWidth + maxKeysWidth + x, + h + y, + options + ); + shapeSvg.insert(() => roughLine).attr('class', 'divider'); + } + + // Attribute divider lines + for (const yOffset of yOffsets) { + roughLine = rc.line( + x, + nameBBox.height + y + yOffset, + w + x, + nameBBox.height + y + yOffset, + options + ); + shapeSvg.insert(() => roughLine).attr('class', 'divider'); + } + + updateNodeBounds(node, rect); + + node.intersect = function (point) { + return intersect.rect(node, point); + }; + return shapeSvg; +} + +// Helper function to add label text g with translate position and style +async function addText( + shapeSvg: D3Selection, + labelText: string, + config: MermaidConfig, + translateX = 0, + translateY = 0, + classes: string[] = [], + style = '' +) { + const label = shapeSvg + .insert('g') + .attr('class', `label ${classes.join(' ')}`) + .attr('transform', `translate(${translateX}, ${translateY})`) + .attr('style', style); + + // Return types need to be parsed + if (labelText !== parseGenericTypes(labelText)) { + labelText = parseGenericTypes(labelText); + // Work around + labelText = labelText.replaceAll('<', '<').replaceAll('>', '>'); + } + + const text = label.node()!.appendChild( + await createText( + label, + labelText, + { + width: calculateTextWidth(labelText, config) + 100, + style, + useHtmlLabels: config.htmlLabels, + }, + config + ) + ); + // Undo work around now that text passed through correctly + if (labelText.includes('<') || labelText.includes('>')) { + let child = text.children[0]; + child.textContent = child.textContent.replaceAll('<', '<').replaceAll('>', '>'); + while (child.childNodes[0]) { + child = child.childNodes[0]; + // Replace its text content + child.textContent = child.textContent.replaceAll('<', '<').replaceAll('>', '>'); + } + } + + let bbox = text.getBBox(); + if (evaluate(config.htmlLabels)) { + const div = text.children[0]; + div.style.textAlign = 'start'; + const dv = select(text); + bbox = div.getBoundingClientRect(); + dv.attr('width', bbox.width); + dv.attr('height', bbox.height); + } + + return bbox; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/filledCircle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/filledCircle.ts new file mode 100644 index 000000000..3469697c7 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/filledCircle.ts @@ -0,0 +1,56 @@ +import rough from 'roughjs'; +import { log } from '../../../logger.js'; +import type { Node, ShapeRenderOptions } from '../../types.js'; +import intersect from '../intersect/index.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import { getNodeClasses, updateNodeBounds } from './util.js'; +import type { D3Selection } from '../../../types.js'; + +export function filledCircle( + parent: D3Selection, + node: Node, + { config: { themeVariables } }: ShapeRenderOptions +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.label = ''; + node.labelStyle = labelStyles; + const shapeSvg = parent + .insert('g') + .attr('class', getNodeClasses(node)) + .attr('id', node.domId ?? node.id); + const radius = 7; + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const { nodeBorder } = themeVariables; + const options = userNodeOverrides(node, { fillStyle: 'solid' }); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + } + + const circleNode = rc.circle(0, 0, radius * 2, options); + + const filledCircle = shapeSvg.insert(() => circleNode, ':first-child'); + + filledCircle.selectAll('path').attr('style', `fill: ${nodeBorder} !important;`); + + if (cssStyles && cssStyles.length > 0 && node.look !== 'handDrawn') { + filledCircle.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + filledCircle.selectAll('path').attr('style', nodeStyles); + } + + updateNodeBounds(node, filledCircle); + + node.intersect = function (point) { + log.info('filledCircle intersect', node, { radius, point }); + const pos = intersect.circle(node, radius, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/flippedTriangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/flippedTriangle.ts new file mode 100644 index 000000000..33f65b326 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/flippedTriangle.ts @@ -0,0 +1,68 @@ +import { log } from '../../../logger.js'; +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import { createPathFromPoints } from './util.js'; +import type { D3Selection } from '../../../types.js'; + +export async function flippedTriangle( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + + const w = bbox.width + (node.padding ?? 0); + const h = w + bbox.height; + + const tw = w + bbox.height; + const points = [ + { x: 0, y: -h }, + { x: tw, y: -h }, + { x: tw / 2, y: 0 }, + ]; + + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + const pathData = createPathFromPoints(points); + const roughNode = rc.path(pathData, options); + + const flippedTriangle = shapeSvg + .insert(() => roughNode, ':first-child') + .attr('transform', `translate(${-h / 2}, ${h / 2})`); + + if (cssStyles && node.look !== 'handDrawn') { + flippedTriangle.selectChildren('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + flippedTriangle.selectChildren('path').attr('style', nodeStyles); + } + + node.width = w; + node.height = h; + + updateNodeBounds(node, flippedTriangle); + + label.attr( + 'transform', + `translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))}, ${-h / 2 + (node.padding ?? 0) / 2 + (bbox.y - (bbox.top ?? 0))})` + ); + + node.intersect = function (point) { + log.info('Triangle intersect', node, points, point); + return intersect.polygon(node, points, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts new file mode 100644 index 000000000..9ae587618 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts @@ -0,0 +1,66 @@ +import rough from 'roughjs'; +import type { Node, ShapeRenderOptions } from '../../types.js'; +import intersect from '../intersect/index.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import { getNodeClasses, updateNodeBounds } from './util.js'; +import type { D3Selection } from '../../../types.js'; + +export function forkJoin( + parent: D3Selection, + node: Node, + { dir, config: { state, themeVariables } }: ShapeRenderOptions +) { + const { nodeStyles } = styles2String(node); + node.label = ''; + const shapeSvg = parent + .insert('g') + .attr('class', getNodeClasses(node)) + .attr('id', node.domId ?? node.id); + + const { cssStyles } = node; + let width = Math.max(70, node?.width ?? 0); + let height = Math.max(10, node?.height ?? 0); + + if (dir === 'LR') { + width = Math.max(10, node?.width ?? 0); + height = Math.max(70, node?.height ?? 0); + } + + const x = (-1 * width) / 2; + const y = (-1 * height) / 2; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { + stroke: themeVariables.lineColor, + fill: themeVariables.lineColor, + }); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const roughNode = rc.rectangle(x, y, width, height, options); + + const shape = shapeSvg.insert(() => roughNode, ':first-child'); + + if (cssStyles && node.look !== 'handDrawn') { + shape.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + shape.selectAll('path').attr('style', nodeStyles); + } + + updateNodeBounds(node, shape); + const padding = state?.padding ?? 0; + if (node.width && node.height) { + node.width += padding / 2 || 0; + node.height += padding / 2 || 0; + } + node.intersect = function (point) { + return intersect.rect(node, point); + }; + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/halfRoundedRectangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/halfRoundedRectangle.ts new file mode 100644 index 000000000..330420cf0 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/halfRoundedRectangle.ts @@ -0,0 +1,72 @@ +import { log } from '../../../logger.js'; +import { + labelHelper, + updateNodeBounds, + getNodeClasses, + createPathFromPoints, + generateCirclePoints, +} from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; + +export async function halfRoundedRectangle( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const minWidth = 80, + minHeight = 50; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + const w = Math.max(minWidth, bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const h = Math.max(minHeight, bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + const radius = h / 2; + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const points = [ + { x: -w / 2, y: -h / 2 }, + { x: w / 2 - radius, y: -h / 2 }, + ...generateCirclePoints(-w / 2 + radius, 0, radius, 50, 90, 270), + { x: w / 2 - radius, y: h / 2 }, + { x: -w / 2, y: h / 2 }, + ]; + + const pathData = createPathFromPoints(points); + const shapeNode = rc.path(pathData, options); + const polygon = shapeSvg.insert(() => shapeNode, ':first-child'); + polygon.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + polygon.selectChildren('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + polygon.selectChildren('path').attr('style', nodeStyles); + } + + // label.attr( + // 'transform', + // `translate(${-w / 2 + (node.padding ?? 0) - (bbox.x - (bbox.left ?? 0))}, ${-h / 2 + (node.padding ?? 0) - (bbox.y - (bbox.top ?? 0))})` + // ); + + updateNodeBounds(node, polygon); + + node.intersect = function (point) { + log.info('Pill intersect', node, { radius, point }); + const pos = intersect.polygon(node, points, point); + return pos; + }; + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.ts new file mode 100644 index 000000000..99dedd919 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.ts @@ -0,0 +1,111 @@ +import { getConfig } from '../../../diagram-api/diagramAPI.js'; +import type { Node } from '../../types.js'; + +// Striped fill like start or fork nodes in state diagrams +export const solidStateFill = (color: string) => { + const { handDrawnSeed } = getConfig(); + return { + fill: color, + hachureAngle: 120, // angle of hachure, + hachureGap: 4, + fillWeight: 2, + roughness: 0.7, + stroke: color, + seed: handDrawnSeed, + }; +}; + +export const compileStyles = (node: Node) => { + // node.cssCompiledStyles is an array of strings in the form of 'key: value' where key is the css property and value is the value + // the array is the styles of node from the classes it is using + // node.cssStyles is an array of styles directly set on the node + // concat the arrays and remove duplicates such that the values from node.cssStyles are used if there are duplicates + const stylesMap = styles2Map([...(node.cssCompiledStyles || []), ...(node.cssStyles || [])]); + return { stylesMap, stylesArray: [...stylesMap] }; +}; + +export const styles2Map = (styles: string[]) => { + const styleMap = new Map(); + styles.forEach((style) => { + const [key, value] = style.split(':'); + styleMap.set(key.trim(), value?.trim()); + }); + return styleMap; +}; +export const isLabelStyle = (key: string) => { + return ( + key === 'color' || + key === 'font-size' || + key === 'font-family' || + key === 'font-weight' || + key === 'font-style' || + key === 'text-decoration' || + key === 'text-align' || + key === 'text-transform' || + key === 'line-height' || + key === 'letter-spacing' || + key === 'word-spacing' || + key === 'text-shadow' || + key === 'text-overflow' || + key === 'white-space' || + key === 'word-wrap' || + key === 'word-break' || + key === 'overflow-wrap' || + key === 'hyphens' + ); +}; +export const styles2String = (node: Node) => { + const { stylesArray } = compileStyles(node); + const labelStyles: string[] = []; + const nodeStyles: string[] = []; + const borderStyles: string[] = []; + const backgroundStyles: string[] = []; + + stylesArray.forEach((style) => { + const key = style[0]; + if (isLabelStyle(key)) { + labelStyles.push(style.join(':') + ' !important'); + } else { + nodeStyles.push(style.join(':') + ' !important'); + if (key.includes('stroke')) { + borderStyles.push(style.join(':') + ' !important'); + } + if (key === 'fill') { + backgroundStyles.push(style.join(':') + ' !important'); + } + } + }); + + return { + labelStyles: labelStyles.join(';'), + nodeStyles: nodeStyles.join(';'), + stylesArray, + borderStyles, + backgroundStyles, + }; +}; + +// Striped fill like start or fork nodes in state diagrams +// TODO remove any +export const userNodeOverrides = (node: Node, options: any) => { + const { themeVariables, handDrawnSeed } = getConfig(); + const { nodeBorder, mainBkg } = themeVariables; + const { stylesMap } = compileStyles(node); + + // index the style array to a map object + const result = Object.assign( + { + roughness: 0.7, + fill: stylesMap.get('fill') || mainBkg, + fillStyle: 'hachure', // solid fill + fillWeight: 4, + hachureGap: 5.2, + stroke: stylesMap.get('stroke') || nodeBorder, + seed: handDrawnSeed, + strokeWidth: stylesMap.get('stroke-width')?.replace('px', '') || 1.3, + fillLineDash: [0, 0], + }, + options + ); + return result; +}; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/hexagon.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/hexagon.ts new file mode 100644 index 000000000..52a4397a2 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/hexagon.ts @@ -0,0 +1,80 @@ +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import { insertPolygonShape } from './insertPolygonShape.js'; +import type { D3Selection } from '../../../types.js'; + +export const createHexagonPathD = ( + x: number, + y: number, + width: number, + height: number, + m: number +): string => { + return [ + `M${x + m},${y}`, + `L${x + width - m},${y}`, + `L${x + width},${y - height / 2}`, + `L${x + width - m},${y - height}`, + `L${x + m},${y - height}`, + `L${x},${y - height / 2}`, + 'Z', + ].join(' '); +}; + +export async function hexagon(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + + const f = 4; + const h = bbox.height + node.padding; + const m = h / f; + const w = bbox.width + 2 * m + node.padding; + const points = [ + { x: m, y: 0 }, + { x: w - m, y: 0 }, + { x: w, y: -h / 2 }, + { x: w - m, y: -h }, + { x: m, y: -h }, + { x: 0, y: -h / 2 }, + ]; + + let polygon: D3Selection | Awaited>; + const { cssStyles } = node; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + const pathData = createHexagonPathD(0, 0, w, h, m); + const roughNode = rc.path(pathData, options); + + polygon = shapeSvg + .insert(() => roughNode, ':first-child') + .attr('transform', `translate(${-w / 2}, ${h / 2})`); + + if (cssStyles) { + polygon.attr('style', cssStyles); + } + } else { + polygon = insertPolygonShape(shapeSvg, w, h, points); + } + + if (nodeStyles) { + polygon.attr('style', nodeStyles); + } + + node.width = w; + node.height = h; + + updateNodeBounds(node, polygon); + + node.intersect = function (point) { + return intersect.polygon(node, points, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/hourglass.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/hourglass.ts new file mode 100644 index 000000000..0a1f55a74 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/hourglass.ts @@ -0,0 +1,62 @@ +import { log } from '../../../logger.js'; +import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; + +export async function hourglass(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.label = ''; + node.labelStyle = labelStyles; + const { shapeSvg } = await labelHelper(parent, node, getNodeClasses(node)); + + const w = Math.max(30, node?.width ?? 0); + const h = Math.max(30, node?.height ?? 0); + + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const points = [ + { x: 0, y: 0 }, + { x: w, y: 0 }, + { x: 0, y: h }, + { x: w, y: h }, + ]; + + const pathData = createPathFromPoints(points); + const shapeNode = rc.path(pathData, options); + const polygon = shapeSvg.insert(() => shapeNode, ':first-child'); + polygon.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + polygon.selectChildren('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + polygon.selectChildren('path').attr('style', nodeStyles); + } + + polygon.attr('transform', `translate(${-w / 2}, ${-h / 2})`); + + updateNodeBounds(node, polygon); + + // label.attr('transform', `translate(${-bbox.width / 2}, ${(h/2)})`); // To transform text below hourglass shape + + node.intersect = function (point) { + log.info('Pill intersect', node, { points }); + const pos = intersect.polygon(node, points, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts new file mode 100644 index 000000000..e0735f3d3 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts @@ -0,0 +1,138 @@ +import rough from 'roughjs'; +import { log } from '../../../logger.js'; +import { getIconSVG } from '../../icons.js'; +import type { Node, ShapeRenderOptions } from '../../types.js'; +import intersect from '../intersect/index.js'; +import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import { labelHelper, updateNodeBounds } from './util.js'; +import type { D3Selection } from '../../../types.js'; + +export async function icon( + parent: D3Selection, + node: Node, + { config: { themeVariables, flowchart } }: ShapeRenderOptions +) { + const { labelStyles } = styles2String(node); + node.labelStyle = labelStyles; + const assetHeight = node.assetHeight ?? 48; + const assetWidth = node.assetWidth ?? 48; + const iconSize = Math.max(assetHeight, assetWidth); + const defaultWidth = flowchart?.wrappingWidth; + node.width = Math.max(iconSize, defaultWidth ?? 0); + const { shapeSvg, bbox, label } = await labelHelper(parent, node, 'icon-shape default'); + + const topLabel = node.pos === 't'; + + const height = iconSize; + const width = iconSize; + const { nodeBorder } = themeVariables; + const { stylesMap } = compileStyles(node); + + const x = -width / 2; + const y = -height / 2; + + const labelPadding = node.label ? 8 : 0; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { stroke: 'none', fill: 'none' }); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const iconNode = rc.rectangle(x, y, width, height, options); + + const outerWidth = Math.max(width, bbox.width); + const outerHeight = height + bbox.height + labelPadding; + + const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, { + ...options, + fill: 'transparent', + stroke: 'none', + }); + + const iconShape = shapeSvg.insert(() => iconNode, ':first-child'); + const outerShape = shapeSvg.insert(() => outerNode); + + if (node.icon) { + const iconElem = shapeSvg.append('g'); + iconElem.html( + `${await getIconSVG(node.icon, { + height: iconSize, + width: iconSize, + fallbackPrefix: '', + })}` + ); + const iconBBox = iconElem.node()!.getBBox(); + const iconWidth = iconBBox.width; + const iconHeight = iconBBox.height; + const iconX = iconBBox.x; + const iconY = iconBBox.y; + iconElem.attr( + 'transform', + `translate(${-iconWidth / 2 - iconX},${ + topLabel + ? bbox.height / 2 + labelPadding / 2 - iconHeight / 2 - iconY + : -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY + })` + ); + iconElem.attr('style', `color: ${stylesMap.get('stroke') ?? nodeBorder};`); + } + + label.attr( + 'transform', + `translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${ + topLabel ? -outerHeight / 2 : outerHeight / 2 - bbox.height + })` + ); + + iconShape.attr( + 'transform', + `translate(${0},${ + topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2 + })` + ); + + updateNodeBounds(node, outerShape); + + node.intersect = function (point) { + log.info('iconSquare intersect', node, point); + if (!node.label) { + return intersect.rect(node, point); + } + const dx = node.x ?? 0; + const dy = node.y ?? 0; + const nodeHeight = node.height ?? 0; + let points = []; + if (topLabel) { + points = [ + { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 }, + { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 }, + { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + { x: dx + width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + { x: dx + width / 2, y: dy + nodeHeight / 2 }, + { x: dx - width / 2, y: dy + nodeHeight / 2 }, + { x: dx - width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + ]; + } else { + points = [ + { x: dx - width / 2, y: dy - nodeHeight / 2 }, + { x: dx + width / 2, y: dy - nodeHeight / 2 }, + { x: dx + width / 2, y: dy - nodeHeight / 2 + height }, + { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + height }, + { x: dx + bbox.width / 2 / 2, y: dy + nodeHeight / 2 }, + { x: dx - bbox.width / 2, y: dy + nodeHeight / 2 }, + { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + height }, + { x: dx - width / 2, y: dy - nodeHeight / 2 + height }, + ]; + } + + const pos = intersect.polygon(node, points, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts new file mode 100644 index 000000000..e8e16853a --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts @@ -0,0 +1,104 @@ +import rough from 'roughjs'; +import { log } from '../../../logger.js'; +import { getIconSVG } from '../../icons.js'; +import type { Node, ShapeRenderOptions } from '../../types.js'; +import intersect from '../intersect/index.js'; +import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import { labelHelper, updateNodeBounds } from './util.js'; +import type { D3Selection } from '../../../types.js'; + +export async function iconCircle( + parent: D3Selection, + node: Node, + { config: { themeVariables, flowchart } }: ShapeRenderOptions +) { + const { labelStyles } = styles2String(node); + node.labelStyle = labelStyles; + const assetHeight = node.assetHeight ?? 48; + const assetWidth = node.assetWidth ?? 48; + const iconSize = Math.max(assetHeight, assetWidth); + const defaultWidth = flowchart?.wrappingWidth; + node.width = Math.max(iconSize, defaultWidth ?? 0); + const { shapeSvg, bbox, label } = await labelHelper(parent, node, 'icon-shape default'); + + const padding = 20; + const labelPadding = node.label ? 8 : 0; + + const topLabel = node.pos === 't'; + + const { nodeBorder, mainBkg } = themeVariables; + const { stylesMap } = compileStyles(node); + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + const fill = stylesMap.get('fill'); + options.stroke = fill ?? mainBkg; + + const iconElem = shapeSvg.append('g'); + if (node.icon) { + iconElem.html( + `${await getIconSVG(node.icon, { + height: iconSize, + width: iconSize, + fallbackPrefix: '', + })}` + ); + } + const iconBBox = iconElem.node()!.getBBox(); + const iconWidth = iconBBox.width; + const iconHeight = iconBBox.height; + const iconX = iconBBox.x; + const iconY = iconBBox.y; + + const diameter = Math.max(iconWidth, iconHeight) * Math.SQRT2 + padding * 2; + const iconNode = rc.circle(0, 0, diameter, options); + + const outerWidth = Math.max(diameter, bbox.width); + const outerHeight = diameter + bbox.height + labelPadding; + + const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, { + ...options, + fill: 'transparent', + stroke: 'none', + }); + + const iconShape = shapeSvg.insert(() => iconNode, ':first-child'); + const outerShape = shapeSvg.insert(() => outerNode); + iconElem.attr( + 'transform', + `translate(${-iconWidth / 2 - iconX},${ + topLabel + ? bbox.height / 2 + labelPadding / 2 - iconHeight / 2 - iconY + : -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY + })` + ); + iconElem.attr('style', `color: ${stylesMap.get('stroke') ?? nodeBorder};`); + label.attr( + 'transform', + `translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${ + topLabel ? -outerHeight / 2 : outerHeight / 2 - bbox.height + })` + ); + + iconShape.attr( + 'transform', + `translate(${0},${ + topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2 + })` + ); + + updateNodeBounds(node, outerShape); + + node.intersect = function (point) { + log.info('iconSquare intersect', node, point); + const pos = intersect.rect(node, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts new file mode 100644 index 000000000..40c427ef5 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts @@ -0,0 +1,145 @@ +import rough from 'roughjs'; +import { log } from '../../../logger.js'; +import { getIconSVG } from '../../icons.js'; +import type { Node, ShapeRenderOptions } from '../../types.js'; +import intersect from '../intersect/index.js'; +import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import { createRoundedRectPathD } from './roundedRectPath.js'; +import { labelHelper, updateNodeBounds } from './util.js'; +import type { D3Selection } from '../../../types.js'; + +export async function iconRounded( + parent: D3Selection, + node: Node, + { config: { themeVariables, flowchart } }: ShapeRenderOptions +) { + const { labelStyles } = styles2String(node); + node.labelStyle = labelStyles; + const assetHeight = node.assetHeight ?? 48; + const assetWidth = node.assetWidth ?? 48; + const iconSize = Math.max(assetHeight, assetWidth); + const defaultWidth = flowchart?.wrappingWidth; + node.width = Math.max(iconSize, defaultWidth ?? 0); + const { shapeSvg, bbox, halfPadding, label } = await labelHelper( + parent, + node, + 'icon-shape default' + ); + + const topLabel = node.pos === 't'; + + const height = iconSize + halfPadding * 2; + const width = iconSize + halfPadding * 2; + const { nodeBorder, mainBkg } = themeVariables; + const { stylesMap } = compileStyles(node); + + const x = -width / 2; + const y = -height / 2; + + const labelPadding = node.label ? 8 : 0; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + const fill = stylesMap.get('fill'); + options.stroke = fill ?? mainBkg; + + const iconNode = rc.path(createRoundedRectPathD(x, y, width, height, 5), options); + + const outerWidth = Math.max(width, bbox.width); + const outerHeight = height + bbox.height + labelPadding; + + const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, { + ...options, + fill: 'transparent', + stroke: 'none', + }); + + const iconShape = shapeSvg.insert(() => iconNode, ':first-child').attr('class', 'icon-shape2'); + const outerShape = shapeSvg.insert(() => outerNode); + + if (node.icon) { + const iconElem = shapeSvg.append('g'); + iconElem.html( + `${await getIconSVG(node.icon, { + height: iconSize, + width: iconSize, + fallbackPrefix: '', + })}` + ); + const iconBBox = iconElem.node()!.getBBox(); + const iconWidth = iconBBox.width; + const iconHeight = iconBBox.height; + const iconX = iconBBox.x; + const iconY = iconBBox.y; + iconElem.attr( + 'transform', + `translate(${-iconWidth / 2 - iconX},${ + topLabel + ? bbox.height / 2 + labelPadding / 2 - iconHeight / 2 - iconY + : -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY + })` + ); + iconElem.attr('style', `color: ${stylesMap.get('stroke') ?? nodeBorder};`); + } + + label.attr( + 'transform', + `translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${ + topLabel ? -outerHeight / 2 : outerHeight / 2 - bbox.height + })` + ); + + iconShape.attr( + 'transform', + `translate(${0},${ + topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2 + })` + ); + + updateNodeBounds(node, outerShape); + + node.intersect = function (point) { + log.info('iconSquare intersect', node, point); + if (!node.label) { + return intersect.rect(node, point); + } + const dx = node.x ?? 0; + const dy = node.y ?? 0; + const nodeHeight = node.height ?? 0; + let points = []; + if (topLabel) { + points = [ + { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 }, + { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 }, + { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + { x: dx + width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + { x: dx + width / 2, y: dy + nodeHeight / 2 }, + { x: dx - width / 2, y: dy + nodeHeight / 2 }, + { x: dx - width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + ]; + } else { + points = [ + { x: dx - width / 2, y: dy - nodeHeight / 2 }, + { x: dx + width / 2, y: dy - nodeHeight / 2 }, + { x: dx + width / 2, y: dy - nodeHeight / 2 + height }, + { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + height }, + { x: dx + bbox.width / 2 / 2, y: dy + nodeHeight / 2 }, + { x: dx - bbox.width / 2, y: dy + nodeHeight / 2 }, + { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + height }, + { x: dx - width / 2, y: dy - nodeHeight / 2 + height }, + ]; + } + + const pos = intersect.polygon(node, points, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts new file mode 100644 index 000000000..e3536b89e --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts @@ -0,0 +1,145 @@ +import rough from 'roughjs'; +import { log } from '../../../logger.js'; +import { getIconSVG } from '../../icons.js'; +import type { Node, ShapeRenderOptions } from '../../types.js'; +import intersect from '../intersect/index.js'; +import { createRoundedRectPathD } from './roundedRectPath.js'; +import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import { labelHelper, updateNodeBounds } from './util.js'; +import type { D3Selection } from '../../../types.js'; + +export async function iconSquare( + parent: D3Selection, + node: Node, + { config: { themeVariables, flowchart } }: ShapeRenderOptions +) { + const { labelStyles } = styles2String(node); + node.labelStyle = labelStyles; + const assetHeight = node.assetHeight ?? 48; + const assetWidth = node.assetWidth ?? 48; + const iconSize = Math.max(assetHeight, assetWidth); + const defaultWidth = flowchart?.wrappingWidth; + node.width = Math.max(iconSize, defaultWidth ?? 0); + const { shapeSvg, bbox, halfPadding, label } = await labelHelper( + parent, + node, + 'icon-shape default' + ); + + const topLabel = node.pos === 't'; + + const height = iconSize + halfPadding * 2; + const width = iconSize + halfPadding * 2; + const { nodeBorder, mainBkg } = themeVariables; + const { stylesMap } = compileStyles(node); + + const x = -width / 2; + const y = -height / 2; + + const labelPadding = node.label ? 8 : 0; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + const fill = stylesMap.get('fill'); + options.stroke = fill ?? mainBkg; + + const iconNode = rc.path(createRoundedRectPathD(x, y, width, height, 0.1), options); + + const outerWidth = Math.max(width, bbox.width); + const outerHeight = height + bbox.height + labelPadding; + + const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, { + ...options, + fill: 'transparent', + stroke: 'none', + }); + + const iconShape = shapeSvg.insert(() => iconNode, ':first-child'); + const outerShape = shapeSvg.insert(() => outerNode); + + if (node.icon) { + const iconElem = shapeSvg.append('g'); + iconElem.html( + `${await getIconSVG(node.icon, { + height: iconSize, + width: iconSize, + fallbackPrefix: '', + })}` + ); + const iconBBox = iconElem.node()!.getBBox(); + const iconWidth = iconBBox.width; + const iconHeight = iconBBox.height; + const iconX = iconBBox.x; + const iconY = iconBBox.y; + iconElem.attr( + 'transform', + `translate(${-iconWidth / 2 - iconX},${ + topLabel + ? bbox.height / 2 + labelPadding / 2 - iconHeight / 2 - iconY + : -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY + })` + ); + iconElem.attr('style', `color: ${stylesMap.get('stroke') ?? nodeBorder};`); + } + + label.attr( + 'transform', + `translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${ + topLabel ? -outerHeight / 2 : outerHeight / 2 - bbox.height + })` + ); + + iconShape.attr( + 'transform', + `translate(${0},${ + topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2 + })` + ); + + updateNodeBounds(node, outerShape); + + node.intersect = function (point) { + log.info('iconSquare intersect', node, point); + if (!node.label) { + return intersect.rect(node, point); + } + const dx = node.x ?? 0; + const dy = node.y ?? 0; + const nodeHeight = node.height ?? 0; + let points = []; + if (topLabel) { + points = [ + { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 }, + { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 }, + { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + { x: dx + width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + { x: dx + width / 2, y: dy + nodeHeight / 2 }, + { x: dx - width / 2, y: dy + nodeHeight / 2 }, + { x: dx - width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + ]; + } else { + points = [ + { x: dx - width / 2, y: dy - nodeHeight / 2 }, + { x: dx + width / 2, y: dy - nodeHeight / 2 }, + { x: dx + width / 2, y: dy - nodeHeight / 2 + height }, + { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + height }, + { x: dx + bbox.width / 2 / 2, y: dy + nodeHeight / 2 }, + { x: dx - bbox.width / 2, y: dy + nodeHeight / 2 }, + { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + height }, + { x: dx - width / 2, y: dy - nodeHeight / 2 + height }, + ]; + } + + const pos = intersect.polygon(node, points, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts new file mode 100644 index 000000000..5780ca1a6 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts @@ -0,0 +1,149 @@ +import rough from 'roughjs'; +import { log } from '../../../logger.js'; +import type { Node, ShapeRenderOptions } from '../../types.js'; +import intersect from '../intersect/index.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import { labelHelper, updateNodeBounds } from './util.js'; +import type { D3Selection } from '../../../types.js'; + +export async function imageSquare( + parent: D3Selection, + node: Node, + { config: { flowchart } }: ShapeRenderOptions +) { + const img = new Image(); + img.src = node?.img ?? ''; + await img.decode(); + + const imageNaturalWidth = Number(img.naturalWidth.toString().replace('px', '')); + const imageNaturalHeight = Number(img.naturalHeight.toString().replace('px', '')); + node.imageAspectRatio = imageNaturalWidth / imageNaturalHeight; + + const { labelStyles } = styles2String(node); + + node.labelStyle = labelStyles; + + const defaultWidth = flowchart?.wrappingWidth; + node.defaultWidth = flowchart?.wrappingWidth; + + const imageRawWidth = Math.max( + node.label ? (defaultWidth ?? 0) : 0, + node?.assetWidth ?? imageNaturalWidth + ); + + const imageWidth = + node.constraint === 'on' + ? node?.assetHeight + ? node.assetHeight * node.imageAspectRatio + : imageRawWidth + : imageRawWidth; + + const imageHeight = + node.constraint === 'on' + ? imageWidth / node.imageAspectRatio + : (node?.assetHeight ?? imageNaturalHeight); + node.width = Math.max(imageWidth, defaultWidth ?? 0); + const { shapeSvg, bbox, label } = await labelHelper(parent, node, 'image-shape default'); + + const topLabel = node.pos === 't'; + + const x = -imageWidth / 2; + const y = -imageHeight / 2; + + const labelPadding = node.label ? 8 : 0; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const imageNode = rc.rectangle(x, y, imageWidth, imageHeight, options); + + const outerWidth = Math.max(imageWidth, bbox.width); + const outerHeight = imageHeight + bbox.height + labelPadding; + + const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, { + ...options, + fill: 'none', + stroke: 'none', + }); + + const iconShape = shapeSvg.insert(() => imageNode, ':first-child'); + const outerShape = shapeSvg.insert(() => outerNode); + + if (node.img) { + const image = shapeSvg.append('image'); + + // Set the image attributes + image.attr('href', node.img); + image.attr('width', imageWidth); + image.attr('height', imageHeight); + image.attr('preserveAspectRatio', 'none'); + + image.attr( + 'transform', + `translate(${-imageWidth / 2},${topLabel ? outerHeight / 2 - imageHeight : -outerHeight / 2})` + ); + } + + label.attr( + 'transform', + `translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${ + topLabel + ? -imageHeight / 2 - bbox.height / 2 - labelPadding / 2 + : imageHeight / 2 - bbox.height / 2 + labelPadding / 2 + })` + ); + + iconShape.attr( + 'transform', + `translate(${0},${ + topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2 + })` + ); + + updateNodeBounds(node, outerShape); + + node.intersect = function (point) { + log.info('iconSquare intersect', node, point); + if (!node.label) { + return intersect.rect(node, point); + } + const dx = node.x ?? 0; + const dy = node.y ?? 0; + const nodeHeight = node.height ?? 0; + let points = []; + if (topLabel) { + points = [ + { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 }, + { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 }, + { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + { x: dx + imageWidth / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + { x: dx + imageWidth / 2, y: dy + nodeHeight / 2 }, + { x: dx - imageWidth / 2, y: dy + nodeHeight / 2 }, + { x: dx - imageWidth / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }, + ]; + } else { + points = [ + { x: dx - imageWidth / 2, y: dy - nodeHeight / 2 }, + { x: dx + imageWidth / 2, y: dy - nodeHeight / 2 }, + { x: dx + imageWidth / 2, y: dy - nodeHeight / 2 + imageHeight }, + { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + imageHeight }, + { x: dx + bbox.width / 2 / 2, y: dy + nodeHeight / 2 }, + { x: dx - bbox.width / 2, y: dy + nodeHeight / 2 }, + { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + imageHeight }, + { x: dx - imageWidth / 2, y: dy - nodeHeight / 2 + imageHeight }, + ]; + } + + const pos = intersect.polygon(node, points, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/insertPolygonShape.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/insertPolygonShape.ts new file mode 100644 index 000000000..874996444 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/insertPolygonShape.ts @@ -0,0 +1,21 @@ +import type { D3Selection } from '../../../types.js'; + +export function insertPolygonShape( + parent: D3Selection, + w: number, + h: number, + points: { x: number; y: number }[] +) { + return parent + .insert('polygon', ':first-child') + .attr( + 'points', + points + .map(function (d) { + return d.x + ',' + d.y; + }) + .join(' ') + ) + .attr('class', 'label-container') + .attr('transform', 'translate(' + -w / 2 + ',' + h / 2 + ')'); +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/invertedTrapezoid.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/invertedTrapezoid.ts new file mode 100644 index 000000000..49e0f908e --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/invertedTrapezoid.ts @@ -0,0 +1,78 @@ +import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import { insertPolygonShape } from './insertPolygonShape.js'; +import type { D3Selection } from '../../../types.js'; + +// export const createInvertedTrapezoidPathD = ( +// x: number, +// y: number, +// width: number, +// height: number +// ): string => { +// return [ +// `M${x + height / 6},${y}`, +// `L${x + width - height / 6},${y}`, +// `L${x + width + (2 * height) / 6},${y - height}`, +// `L${x - (2 * height) / 6},${y - height}`, +// 'Z', +// ].join(' '); +// }; + +export async function inv_trapezoid( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + + const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + + const points = [ + { x: 0, y: 0 }, + { x: w, y: 0 }, + { x: w + (3 * h) / 6, y: -h }, + { x: (-3 * h) / 6, y: -h }, + ]; + + let polygon: typeof shapeSvg | ReturnType; + const { cssStyles } = node; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + const pathData = createPathFromPoints(points); + // const pathData = createInvertedTrapezoidPathD(0, 0, w, h); + const roughNode = rc.path(pathData, options); + + polygon = shapeSvg + .insert(() => roughNode, ':first-child') + .attr('transform', `translate(${-w / 2}, ${h / 2})`); + + if (cssStyles) { + polygon.attr('style', cssStyles); + } + } else { + polygon = insertPolygonShape(shapeSvg, w, h, points); + } + + if (nodeStyles) { + polygon.attr('style', nodeStyles); + } + + node.width = w; + node.height = h; + + updateNodeBounds(node, polygon); + + node.intersect = function (point) { + return intersect.polygon(node, points, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/kanbanItem.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/kanbanItem.ts new file mode 100644 index 000000000..fba867a71 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/kanbanItem.ts @@ -0,0 +1,163 @@ +import { labelHelper, insertLabel, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node, KanbanNode, ShapeRenderOptions } from '../../types.js'; +import { createRoundedRectPathD } from './roundedRectPath.js'; +import { userNodeOverrides, styles2String } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; + +const colorFromPriority = (priority: NonNullable) => { + switch (priority) { + case 'Very High': + return 'red'; + case 'High': + return 'orange'; + case 'Medium': + return null; // no stroke + case 'Low': + return 'blue'; + case 'Very Low': + return 'lightblue'; + } +}; +export async function kanbanItem( + parent: D3Selection, + // Omit the 'shape' prop since otherwise, it causes a TypeScript circular dependency error + kanbanNode: Omit | Omit, + { config }: ShapeRenderOptions +) { + const { labelStyles, nodeStyles } = styles2String(kanbanNode); + kanbanNode.labelStyle = labelStyles || ''; + + const labelPaddingX = 10; + const orgWidth = kanbanNode.width; + kanbanNode.width = (kanbanNode.width ?? 200) - 10; + + const { + shapeSvg, + bbox, + label: labelElTitle, + } = await labelHelper(parent, kanbanNode, getNodeClasses(kanbanNode)); + const padding = kanbanNode.padding || 10; + + let ticketUrl = ''; + let link; + + if ('ticket' in kanbanNode && kanbanNode.ticket && config?.kanban?.ticketBaseUrl) { + ticketUrl = config?.kanban?.ticketBaseUrl.replace('#TICKET#', kanbanNode.ticket); + link = shapeSvg + .insert('svg:a', ':first-child') + .attr('class', 'kanban-ticket-link') + .attr('xlink:href', ticketUrl) + .attr('target', '_blank'); + } + + const options = { + useHtmlLabels: kanbanNode.useHtmlLabels, + labelStyle: kanbanNode.labelStyle || '', + width: kanbanNode.width, + img: kanbanNode.img, + padding: kanbanNode.padding || 8, + centerLabel: false, + }; + let labelEl, bbox2; + if (link) { + ({ label: labelEl, bbox: bbox2 } = await insertLabel( + link, + ('ticket' in kanbanNode && kanbanNode.ticket) || '', + options + )); + } else { + ({ label: labelEl, bbox: bbox2 } = await insertLabel( + shapeSvg, + ('ticket' in kanbanNode && kanbanNode.ticket) || '', + options + )); + } + const { label: labelElAssigned, bbox: bboxAssigned } = await insertLabel( + shapeSvg, + ('assigned' in kanbanNode && kanbanNode.assigned) || '', + options + ); + kanbanNode.width = orgWidth; + const labelPaddingY = 10; + const totalWidth = kanbanNode?.width || 0; + const heightAdj = Math.max(bbox2.height, bboxAssigned.height) / 2; + const totalHeight = + Math.max(bbox.height + labelPaddingY * 2, kanbanNode?.height || 0) + heightAdj; + const x = -totalWidth / 2; + const y = -totalHeight / 2; + labelElTitle.attr( + 'transform', + 'translate(' + (padding - totalWidth / 2) + ', ' + (-heightAdj - bbox.height / 2) + ')' + ); + labelEl.attr( + 'transform', + 'translate(' + (padding - totalWidth / 2) + ', ' + (-heightAdj + bbox.height / 2) + ')' + ); + labelElAssigned.attr( + 'transform', + 'translate(' + + (padding + totalWidth / 2 - bboxAssigned.width - 2 * labelPaddingX) + + ', ' + + (-heightAdj + bbox.height / 2) + + ')' + ); + + let rect; + + const { rx, ry } = kanbanNode; + const { cssStyles } = kanbanNode; + + if (kanbanNode.look === 'handDrawn') { + // @ts-ignore TODO: Fix rough typings + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(kanbanNode, {}); + + const roughNode = + rx || ry + ? rc.path(createRoundedRectPathD(x, y, totalWidth, totalHeight, rx || 0), options) + : rc.rectangle(x, y, totalWidth, totalHeight, options); + + rect = shapeSvg.insert(() => roughNode, ':first-child'); + rect.attr('class', 'basic label-container').attr('style', cssStyles ? cssStyles : null); + } else { + rect = shapeSvg.insert('rect', ':first-child'); + + rect + .attr('class', 'basic label-container __APA__') + .attr('style', nodeStyles) + .attr('rx', rx ?? 5) + .attr('ry', ry ?? 5) + .attr('x', x) + .attr('y', y) + .attr('width', totalWidth) + .attr('height', totalHeight); + + const priority = 'priority' in kanbanNode && kanbanNode.priority; + if (priority) { + const line = shapeSvg.append('line'); + const lineX = x + 2; + + const y1 = y + Math.floor((rx ?? 0) / 2); + const y2 = y + totalHeight - Math.floor((rx ?? 0) / 2); + line + .attr('x1', lineX) + .attr('y1', y1) + .attr('x2', lineX) + .attr('y2', y2) + + .attr('stroke-width', '4') + .attr('stroke', colorFromPriority(priority)); + } + } + + updateNodeBounds(kanbanNode, rect); + kanbanNode.height = totalHeight; + + kanbanNode.intersect = function (point) { + return intersect.rect(kanbanNode, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/labelRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/labelRect.ts new file mode 100644 index 000000000..de53da4f1 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/labelRect.ts @@ -0,0 +1,59 @@ +import type { Node, RectOptions } from '../../types.js'; +import { drawRect } from './drawRect.js'; +import { labelHelper, updateNodeBounds } from './util.js'; +import intersect from '../intersect/index.js'; +import type { D3Selection } from '../../../types.js'; + +export async function roundedRect( + parent: D3Selection, + node: Node +) { + const options = { + rx: 5, + ry: 5, + classes: '', + labelPaddingX: (node?.padding || 0) * 1, + labelPaddingY: (node?.padding || 0) * 1, + } as RectOptions; + + return drawRect(parent, node, options); +} + +export async function labelRect(parent: D3Selection, node: Node) { + const { shapeSvg, bbox, label } = await labelHelper(parent, node, 'label'); + + // log.trace('Classes = ', node.class); + // add the rect + const rect = shapeSvg.insert('rect', ':first-child'); + + // Hide the rect we are only after the label + const totalWidth = 0.1; + const totalHeight = 0.1; + rect.attr('width', totalWidth).attr('height', totalHeight); + shapeSvg.attr('class', 'label edgeLabel'); + label.attr( + 'transform', + `translate(${-(bbox.width / 2) - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) - (bbox.y - (bbox.top ?? 0))})` + ); + + // if (node.props) { + // const propKeys = new Set(Object.keys(node.props)); + // if (node.props.borders) { + // applyNodePropertyBorders(rect, node.borders, totalWidth, totalHeight); + // propKeys.delete('borders'); + // } + // propKeys.forEach((propKey) => { + // log.warn(`Unknown node property ${propKey}`); + // }); + // } + + updateNodeBounds(node, rect); + // node.width = 1; + // node.height = 1; + + node.intersect = function (point) { + return intersect.rect(node, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanLeft.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanLeft.ts new file mode 100644 index 000000000..de84b2a7f --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanLeft.ts @@ -0,0 +1,58 @@ +import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import { insertPolygonShape } from './insertPolygonShape.js'; +import type { D3Selection } from '../../../types.js'; + +export async function lean_left(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + const w = Math.max(bbox.width + (node.padding ?? 0), node?.width ?? 0); + const h = Math.max(bbox.height + (node.padding ?? 0), node?.height ?? 0); + const points = [ + { x: 0, y: 0 }, + { x: w + (3 * h) / 6, y: 0 }, + { x: w, y: -h }, + { x: -(3 * h) / 6, y: -h }, + ]; + + let polygon: typeof shapeSvg | ReturnType; + const { cssStyles } = node; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + const pathData = createPathFromPoints(points); + // const pathData = createLeanLeftPathD(0, 0, w, h); + const roughNode = rc.path(pathData, options); + + polygon = shapeSvg + .insert(() => roughNode, ':first-child') + .attr('transform', `translate(${-w / 2}, ${h / 2})`); + + if (cssStyles) { + polygon.attr('style', cssStyles); + } + } else { + polygon = insertPolygonShape(shapeSvg, w, h, points); + } + + if (nodeStyles) { + polygon.attr('style', nodeStyles); + } + + node.width = w; + node.height = h; + + updateNodeBounds(node, polygon); + + node.intersect = function (point) { + return intersect.polygon(node, points, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanRight.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanRight.ts new file mode 100644 index 000000000..0b4595bd4 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanRight.ts @@ -0,0 +1,57 @@ +import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import { insertPolygonShape } from './insertPolygonShape.js'; +import type { D3Selection } from '../../../types.js'; + +export async function lean_right(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + const w = Math.max(bbox.width + (node.padding ?? 0), node?.width ?? 0); + const h = Math.max(bbox.height + (node.padding ?? 0), node?.height ?? 0); + const points = [ + { x: (-3 * h) / 6, y: 0 }, + { x: w, y: 0 }, + { x: w + (3 * h) / 6, y: -h }, + { x: 0, y: -h }, + ]; + + let polygon: typeof shapeSvg | ReturnType; + const { cssStyles } = node; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + const pathData = createPathFromPoints(points); + const roughNode = rc.path(pathData, options); + + polygon = shapeSvg + .insert(() => roughNode, ':first-child') + .attr('transform', `translate(${-w / 2}, ${h / 2})`); + + if (cssStyles) { + polygon.attr('style', cssStyles); + } + } else { + polygon = insertPolygonShape(shapeSvg, w, h, points); + } + + if (nodeStyles) { + polygon.attr('style', nodeStyles); + } + + node.width = w; + node.height = h; + + updateNodeBounds(node, polygon); + + node.intersect = function (point) { + return intersect.polygon(node, points, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/lightningBolt.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/lightningBolt.ts new file mode 100644 index 000000000..b1e16f9ac --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/lightningBolt.ts @@ -0,0 +1,66 @@ +import { log } from '../../../logger.js'; +import { getNodeClasses, updateNodeBounds } from './util.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import intersect from '../intersect/index.js'; +import { createPathFromPoints } from './util.js'; +import type { D3Selection } from '../../../types.js'; + +export function lightningBolt(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.label = ''; + node.labelStyle = labelStyles; + const shapeSvg = parent + .insert('g') + .attr('class', getNodeClasses(node)) + .attr('id', node.domId ?? node.id); + const { cssStyles } = node; + const width = Math.max(35, node?.width ?? 0); + const height = Math.max(35, node?.height ?? 0); + const gap = 7; + + const points = [ + { x: width, y: 0 }, + { x: 0, y: height + gap / 2 }, + { x: width - 2 * gap, y: height + gap / 2 }, + { x: 0, y: 2 * height }, + { x: width, y: height - gap / 2 }, + { x: 2 * gap, y: height - gap / 2 }, + ]; + + // @ts-expect-error shapeSvg d3 class is incorrect? + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const linePath = createPathFromPoints(points); + const lineNode = rc.path(linePath, options); + + const lightningBolt = shapeSvg.insert(() => lineNode, ':first-child'); + + if (cssStyles && node.look !== 'handDrawn') { + lightningBolt.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + lightningBolt.selectAll('path').attr('style', nodeStyles); + } + + lightningBolt.attr('transform', `translate(-${width / 2},${-height})`); + + updateNodeBounds(node, lightningBolt); + + node.intersect = function (point) { + log.info('lightningBolt intersect', node, point); + const pos = intersect.polygon(node, points, point); + + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedCylinder.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedCylinder.ts new file mode 100644 index 000000000..6cd348649 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedCylinder.ts @@ -0,0 +1,139 @@ +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; +import { handleUndefinedAttr } from '../../../utils.js'; + +export const createCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number, + outerOffset: number +): string => { + return [ + `M${x},${y + ry}`, + `a${rx},${ry} 0,0,0 ${width},0`, + `a${rx},${ry} 0,0,0 ${-width},0`, + `l0,${height}`, + `a${rx},${ry} 0,0,0 ${width},0`, + `l0,${-height}`, + `M${x},${y + ry + outerOffset}`, + `a${rx},${ry} 0,0,0 ${width},0`, + ].join(' '); +}; +export const createOuterCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number, + outerOffset: number +): string => { + return [ + `M${x},${y + ry}`, + `M${x + width},${y + ry}`, + `a${rx},${ry} 0,0,0 ${-width},0`, + `l0,${height}`, + `a${rx},${ry} 0,0,0 ${width},0`, + `l0,${-height}`, + `M${x},${y + ry + outerOffset}`, + `a${rx},${ry} 0,0,0 ${width},0`, + ].join(' '); +}; +export const createInnerCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number +): string => { + return [`M${x - width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 ${width},0`].join(' '); +}; +export async function linedCylinder( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const w = Math.max(bbox.width + (node.padding ?? 0), node.width ?? 0); + const rx = w / 2; + const ry = rx / (2.5 + w / 50); + const h = Math.max(bbox.height + ry + (node.padding ?? 0), node.height ?? 0); + const outerOffset = h * 0.1; // 10% of height + + let cylinder: typeof shapeSvg | D3Selection; + const { cssStyles } = node; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry, outerOffset); + const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry); + const options = userNodeOverrides(node, {}); + + const outerNode = rc.path(outerPathData, options); + const innerLine = rc.path(innerPathData, options); + + const innerLineEl = shapeSvg.insert(() => innerLine, ':first-child'); + innerLineEl.attr('class', 'line'); + cylinder = shapeSvg.insert(() => outerNode, ':first-child'); + cylinder.attr('class', 'basic label-container'); + if (cssStyles) { + cylinder.attr('style', cssStyles); + } + } else { + const pathData = createCylinderPathD(0, 0, w, h, rx, ry, outerOffset); + cylinder = shapeSvg + .insert('path', ':first-child') + .attr('d', pathData) + .attr('class', 'basic label-container') + .attr('style', handleUndefinedAttr(cssStyles)) + .attr('style', nodeStyles); + } + + // find label and move it down + cylinder.attr('label-offset-y', ry); + cylinder.attr('transform', `translate(${-w / 2}, ${-(h / 2 + ry)})`); + + updateNodeBounds(node, cylinder); + + label.attr( + 'transform', + `translate(${-(bbox.width / 2) - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) + ry - (bbox.y - (bbox.top ?? 0))})` + ); + + node.intersect = function (point) { + const pos = intersect.rect(node, point); + const x = pos.x - (node.x ?? 0); + + if ( + rx != 0 && + (Math.abs(x) < (node.width ?? 0) / 2 || + (Math.abs(x) == (node.width ?? 0) / 2 && + Math.abs(pos.y - (node.y ?? 0)) > (node.height ?? 0) / 2 - ry)) + ) { + let y = ry * ry * (1 - (x * x) / (rx * rx)); + if (y > 0) { + y = Math.sqrt(y); + } + y = ry - y; + if (point.y - (node.y ?? 0) > 0) { + y = -y; + } + + pos.y += y; + } + + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedWaveEdgedRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedWaveEdgedRect.ts new file mode 100644 index 000000000..6f8123742 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedWaveEdgedRect.ts @@ -0,0 +1,83 @@ +import { + labelHelper, + updateNodeBounds, + getNodeClasses, + generateFullSineWavePoints, +} from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import rough from 'roughjs'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import type { D3Selection } from '../../../types.js'; + +export async function linedWaveEdgedRect( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + const waveAmplitude = h / 4; + const finalH = h + waveAmplitude; + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const points = [ + { x: -w / 2 - (w / 2) * 0.1, y: -finalH / 2 }, + { x: -w / 2 - (w / 2) * 0.1, y: finalH / 2 }, + ...generateFullSineWavePoints( + -w / 2 - (w / 2) * 0.1, + finalH / 2, + w / 2 + (w / 2) * 0.1, + finalH / 2, + waveAmplitude, + 0.8 + ), + { x: w / 2 + (w / 2) * 0.1, y: -finalH / 2 }, + { x: -w / 2 - (w / 2) * 0.1, y: -finalH / 2 }, + { x: -w / 2, y: -finalH / 2 }, + { x: -w / 2, y: (finalH / 2) * 1.1 }, + { x: -w / 2, y: -finalH / 2 }, + ]; + + const poly = rc.polygon( + points.map((p) => [p.x, p.y]), + options + ); + + const waveEdgeRect = shapeSvg.insert(() => poly, ':first-child'); + + waveEdgeRect.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + waveEdgeRect.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + waveEdgeRect.selectAll('path').attr('style', nodeStyles); + } + + waveEdgeRect.attr('transform', `translate(0,${-waveAmplitude / 2})`); + label.attr( + 'transform', + `translate(${-w / 2 + (node.padding ?? 0) + ((w / 2) * 0.1) / 2 - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) - waveAmplitude / 2 - (bbox.y - (bbox.top ?? 0))})` + ); + + updateNodeBounds(node, waveEdgeRect); + node.intersect = function (point) { + const pos = intersect.polygon(node, points, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiRect.ts new file mode 100644 index 000000000..a82929ec4 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiRect.ts @@ -0,0 +1,83 @@ +import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import intersect from '../intersect/index.js'; +import type { D3Selection } from '../../../types.js'; + +export async function multiRect(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + const rectOffset = 5; + const x = -w / 2; + const y = -h / 2; + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + const outerPathPoints = [ + { x: x - rectOffset, y: y + rectOffset }, + { x: x - rectOffset, y: y + h + rectOffset }, + { x: x + w - rectOffset, y: y + h + rectOffset }, + { x: x + w - rectOffset, y: y + h }, + { x: x + w, y: y + h }, + { x: x + w, y: y + h - rectOffset }, + { x: x + w + rectOffset, y: y + h - rectOffset }, + { x: x + w + rectOffset, y: y - rectOffset }, + { x: x + rectOffset, y: y - rectOffset }, + { x: x + rectOffset, y: y }, + { x, y }, + { x, y: y + rectOffset }, + ]; + + const innerPathPoints = [ + { x, y: y + rectOffset }, + { x: x + w - rectOffset, y: y + rectOffset }, + { x: x + w - rectOffset, y: y + h }, + { x: x + w, y: y + h }, + { x: x + w, y }, + { x, y }, + ]; + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const outerPath = createPathFromPoints(outerPathPoints); + const outerNode = rc.path(outerPath, options); + const innerPath = createPathFromPoints(innerPathPoints); + const innerNode = rc.path(innerPath, { ...options, fill: 'none' }); + + const multiRect = shapeSvg.insert(() => innerNode, ':first-child'); + multiRect.insert(() => outerNode, ':first-child'); + + multiRect.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + multiRect.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + multiRect.selectAll('path').attr('style', nodeStyles); + } + + label.attr( + 'transform', + `translate(${-(bbox.width / 2) - rectOffset - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) + rectOffset - (bbox.y - (bbox.top ?? 0))})` + ); + + updateNodeBounds(node, multiRect); + + node.intersect = function (point) { + const pos = intersect.polygon(node, outerPathPoints, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiWaveEdgedRectangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiWaveEdgedRectangle.ts new file mode 100644 index 000000000..db436879d --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiWaveEdgedRectangle.ts @@ -0,0 +1,108 @@ +import { + labelHelper, + updateNodeBounds, + getNodeClasses, + createPathFromPoints, + generateFullSineWavePoints, +} from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import rough from 'roughjs'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import type { D3Selection } from '../../../types.js'; + +export async function multiWaveEdgedRectangle( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + const waveAmplitude = h / 4; + const finalH = h + waveAmplitude; + const x = -w / 2; + const y = -finalH / 2; + const rectOffset = 5; + + const { cssStyles } = node; + + const wavePoints = generateFullSineWavePoints( + x - rectOffset, + y + finalH + rectOffset, + x + w - rectOffset, + y + finalH + rectOffset, + waveAmplitude, + 0.8 + ); + + const lastWavePoint = wavePoints?.[wavePoints.length - 1]; + + const outerPathPoints = [ + { x: x - rectOffset, y: y + rectOffset }, + { x: x - rectOffset, y: y + finalH + rectOffset }, + ...wavePoints, + { x: x + w - rectOffset, y: lastWavePoint.y - rectOffset }, + { x: x + w, y: lastWavePoint.y - rectOffset }, + { x: x + w, y: lastWavePoint.y - 2 * rectOffset }, + { x: x + w + rectOffset, y: lastWavePoint.y - 2 * rectOffset }, + { x: x + w + rectOffset, y: y - rectOffset }, + { x: x + rectOffset, y: y - rectOffset }, + { x: x + rectOffset, y: y }, + { x, y }, + { x, y: y + rectOffset }, + ]; + + const innerPathPoints = [ + { x, y: y + rectOffset }, + { x: x + w - rectOffset, y: y + rectOffset }, + { x: x + w - rectOffset, y: lastWavePoint.y - rectOffset }, + { x: x + w, y: lastWavePoint.y - rectOffset }, + { x: x + w, y }, + { x, y }, + ]; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const outerPath = createPathFromPoints(outerPathPoints); + const outerNode = rc.path(outerPath, options); + const innerPath = createPathFromPoints(innerPathPoints); + const innerNode = rc.path(innerPath, options); + + const shape = shapeSvg.insert(() => outerNode, ':first-child'); + shape.insert(() => innerNode); + + shape.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + shape.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + shape.selectAll('path').attr('style', nodeStyles); + } + + shape.attr('transform', `translate(0,${-waveAmplitude / 2})`); + + label.attr( + 'transform', + `translate(${-(bbox.width / 2) - rectOffset - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) + rectOffset - waveAmplitude / 2 - (bbox.y - (bbox.top ?? 0))})` + ); + + updateNodeBounds(node, shape); + + node.intersect = function (point) { + const pos = intersect.polygon(node, outerPathPoints, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts new file mode 100644 index 000000000..4a7f66a87 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts @@ -0,0 +1,60 @@ +import rough from 'roughjs'; +import type { Node, ShapeRenderOptions } from '../../types.js'; +import intersect from '../intersect/index.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import { getNodeClasses, labelHelper, updateNodeBounds } from './util.js'; +import type { D3Selection } from '../../../types.js'; +import { getConfig } from '../../../config.js'; + +export async function note( + parent: D3Selection, + node: Node, + { config: { themeVariables } }: ShapeRenderOptions +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const useHtmlLabels = node.useHtmlLabels || getConfig().flowchart?.htmlLabels !== false; + if (!useHtmlLabels) { + node.centerLabel = true; + } + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + const totalWidth = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const totalHeight = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + const x = -totalWidth / 2; + const y = -totalHeight / 2; + const { cssStyles } = node; + + // add the rect + // @ts-ignore TODO: Fix rough typings + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { + fill: themeVariables.noteBkgColor, + stroke: themeVariables.noteBorderColor, + }); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const noteShapeNode = rc.rectangle(x, y, totalWidth, totalHeight, options); + + const rect = shapeSvg.insert(() => noteShapeNode, ':first-child'); + rect.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + rect.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + rect.selectAll('path').attr('style', nodeStyles); + } + + updateNodeBounds(node, rect); + + node.intersect = function (point) { + return intersect.rect(node, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts new file mode 100644 index 000000000..eef958169 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts @@ -0,0 +1,76 @@ +import { log } from '../../../logger.js'; +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import { insertPolygonShape } from './insertPolygonShape.js'; +import type { D3Selection } from '../../../types.js'; + +export const createDecisionBoxPathD = (x: number, y: number, size: number): string => { + return [ + `M${x + size / 2},${y}`, + `L${x + size},${y - size / 2}`, + `L${x + size / 2},${y - size}`, + `L${x},${y - size / 2}`, + 'Z', + ].join(' '); +}; + +export async function question(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + + const w = bbox.width + node.padding; + const h = bbox.height + node.padding; + const s = w + h; + + const points = [ + { x: s / 2, y: 0 }, + { x: s, y: -s / 2 }, + { x: s / 2, y: -s }, + { x: 0, y: -s / 2 }, + ]; + + let polygon: typeof shapeSvg | ReturnType; + const { cssStyles } = node; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + const pathData = createDecisionBoxPathD(0, 0, s); + const roughNode = rc.path(pathData, options); + + polygon = shapeSvg + .insert(() => roughNode, ':first-child') + .attr('transform', `translate(${-s / 2}, ${s / 2})`); + + if (cssStyles) { + polygon.attr('style', cssStyles); + } + } else { + polygon = insertPolygonShape(shapeSvg, s, s, points); + } + + if (nodeStyles) { + polygon.attr('style', nodeStyles); + } + + updateNodeBounds(node, polygon); + + node.intersect = function (point) { + log.debug( + 'APA12 Intersect called SPLIT\npoint:', + point, + '\nnode:\n', + node, + '\nres:', + intersect.polygon(node, points, point) + ); + return intersect.polygon(node, points, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectLeftInvArrow.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectLeftInvArrow.ts new file mode 100644 index 000000000..1ad40c554 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectLeftInvArrow.ts @@ -0,0 +1,68 @@ +import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; + +export async function rect_left_inv_arrow( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + + const w = Math.max(bbox.width + (node.padding ?? 0), node?.width ?? 0); + const h = Math.max(bbox.height + (node.padding ?? 0), node?.height ?? 0); + + const x = -w / 2; + const y = -h / 2; + const notch = y / 2; + + const points = [ + { x: x + notch, y }, + { x: x, y: 0 }, + { x: x + notch, y: -y }, + { x: -x, y: -y }, + { x: -x, y }, + ]; + + const { cssStyles } = node; + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const pathData = createPathFromPoints(points); + const roughNode = rc.path(pathData, options); + + const polygon = shapeSvg.insert(() => roughNode, ':first-child'); + + polygon.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + polygon.selectAll('path').attr('style', cssStyles); + } + if (nodeStyles && node.look !== 'handDrawn') { + polygon.selectAll('path').attr('style', nodeStyles); + } + + polygon.attr('transform', `translate(${-notch / 2},0)`); + + label.attr( + 'transform', + `translate(${-notch / 2 - bbox.width / 2 - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) - (bbox.y - (bbox.top ?? 0))})` + ); + updateNodeBounds(node, polygon); + + node.intersect = function (point) { + return intersect.polygon(node, points, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectWithTitle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectWithTitle.ts new file mode 100644 index 000000000..bcaf2787a --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectWithTitle.ts @@ -0,0 +1,158 @@ +import type { Node } from '../../types.js'; +import { select } from 'd3'; +import { evaluate } from '../../../diagrams/common/common.js'; +import { updateNodeBounds } from './util.js'; +import createLabel from '../createLabel.js'; +import intersect from '../intersect/index.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; +import { createRoundedRectPathD } from './roundedRectPath.js'; +import { log } from '../../../logger.js'; +import type { D3Selection } from '../../../types.js'; + +export async function rectWithTitle( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + let classes; + if (!node.cssClasses) { + classes = 'node default'; + } else { + classes = 'node ' + node.cssClasses; + } + + // Add outer g element + const shapeSvg = parent + // @ts-ignore - d3 typings are not correct + .insert('g') + .attr('class', classes) + .attr('id', node.domId || node.id); + + // Create the title label and insert it after the rect + const g = shapeSvg.insert('g'); + + const label = shapeSvg.insert('g').attr('class', 'label').attr('style', nodeStyles); + + const description = node.description; + + const title = node.label; + + const text = label.node()!.appendChild(await createLabel(title, node.labelStyle, true, true)); + let bbox = { width: 0, height: 0 }; + if (evaluate(getConfig()?.flowchart?.htmlLabels)) { + const div = text.children[0]; + const dv = select(text); + bbox = div.getBoundingClientRect(); + dv.attr('width', bbox.width); + dv.attr('height', bbox.height); + } + log.info('Text 2', description); + const textRows = description || []; + const titleBox = text.getBBox(); + const descr = label + .node()! + .appendChild( + await createLabel( + textRows.join ? textRows.join('
') : textRows, + node.labelStyle, + true, + true + ) + ); + + //if (evaluate(getConfig()?.flowchart?.htmlLabels)) { + const div = descr.children[0]; + const dv = select(descr); + bbox = div.getBoundingClientRect(); + dv.attr('width', bbox.width); + dv.attr('height', bbox.height); + // } + + const halfPadding = (node.padding || 0) / 2; + select(descr).attr( + 'transform', + 'translate( ' + + (bbox.width > titleBox.width ? 0 : (titleBox.width - bbox.width) / 2) + + ', ' + + (titleBox.height + halfPadding + 5) + + ')' + ); + select(text).attr( + 'transform', + 'translate( ' + + (bbox.width < titleBox.width ? 0 : -(titleBox.width - bbox.width) / 2) + + ', ' + + 0 + + ')' + ); + // Get the size of the label + + // Bounding box for title and text + bbox = label.node()!.getBBox(); + + // Center the label + label.attr( + 'transform', + 'translate(' + -bbox.width / 2 + ', ' + (-bbox.height / 2 - halfPadding + 3) + ')' + ); + + const totalWidth = bbox.width + (node.padding || 0); + const totalHeight = bbox.height + (node.padding || 0); + const x = -bbox.width / 2 - halfPadding; + const y = -bbox.height / 2 - halfPadding; + let rect; + let innerLine; + if (node.look === 'handDrawn') { + // @ts-ignore No typings for rough + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + const roughNode = rc.path( + createRoundedRectPathD(x, y, totalWidth, totalHeight, node.rx || 0), + options + ); + + const roughLine = rc.line( + -bbox.width / 2 - halfPadding, + -bbox.height / 2 - halfPadding + titleBox.height + halfPadding, + bbox.width / 2 + halfPadding, + -bbox.height / 2 - halfPadding + titleBox.height + halfPadding, + options + ); + + innerLine = shapeSvg.insert(() => { + log.debug('Rough node insert CXC', roughNode); + return roughLine; + }, ':first-child'); + rect = shapeSvg.insert(() => { + log.debug('Rough node insert CXC', roughNode); + return roughNode; + }, ':first-child'); + } else { + rect = g.insert('rect', ':first-child'); + innerLine = g.insert('line'); + rect + .attr('class', 'outer title-state') + .attr('style', nodeStyles) + .attr('x', -bbox.width / 2 - halfPadding) + .attr('y', -bbox.height / 2 - halfPadding) + .attr('width', bbox.width + (node.padding || 0)) + .attr('height', bbox.height + (node.padding || 0)); + + innerLine + .attr('class', 'divider') + .attr('x1', -bbox.width / 2 - halfPadding) + .attr('x2', bbox.width / 2 + halfPadding) + .attr('y1', -bbox.height / 2 - halfPadding + titleBox.height + halfPadding) + .attr('y2', -bbox.height / 2 - halfPadding + titleBox.height + halfPadding); + } + updateNodeBounds(node, rect); + + node.intersect = function (point) { + return intersect.rect(node, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/requirementBox.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/requirementBox.ts new file mode 100644 index 000000000..eb50d09bd --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/requirementBox.ts @@ -0,0 +1,222 @@ +import { getNodeClasses, updateNodeBounds } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; +import { calculateTextWidth, decodeEntities } from '../../../utils.js'; +import { getConfig, sanitizeText } from '../../../diagram-api/diagramAPI.js'; +import { createText } from '../../createText.js'; +import { select } from 'd3'; +import type { Requirement, Element } from '../../../diagrams/requirement/types.js'; + +export async function requirementBox( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const requirementNode = node as unknown as Requirement; + const elementNode = node as unknown as Element; + const padding = 20; + const gap = 20; + const isRequirementNode = 'verifyMethod' in node; + const classes = getNodeClasses(node); + + // Add outer g element + const shapeSvg = parent + .insert('g') + .attr('class', classes) + .attr('id', node.domId ?? node.id); + + let typeHeight; + if (isRequirementNode) { + typeHeight = await addText( + shapeSvg, + `<<${requirementNode.type}>>`, + 0, + node.labelStyle + ); + } else { + typeHeight = await addText(shapeSvg, '<<Element>>', 0, node.labelStyle); + } + + let accumulativeHeight = typeHeight; + const nameHeight = await addText( + shapeSvg, + requirementNode.name, + accumulativeHeight, + node.labelStyle + '; font-weight: bold;' + ); + accumulativeHeight += nameHeight + gap; + + // Requirement + if (isRequirementNode) { + const idHeight = await addText( + shapeSvg, + `${requirementNode.requirementId ? `id: ${requirementNode.requirementId}` : ''}`, + accumulativeHeight, + node.labelStyle + ); + + accumulativeHeight += idHeight; + const textHeight = await addText( + shapeSvg, + `${requirementNode.text ? `Text: ${requirementNode.text}` : ''}`, + accumulativeHeight, + node.labelStyle + ); + accumulativeHeight += textHeight; + const riskHeight = await addText( + shapeSvg, + `${requirementNode.risk ? `Risk: ${requirementNode.risk}` : ''}`, + accumulativeHeight, + node.labelStyle + ); + accumulativeHeight += riskHeight; + await addText( + shapeSvg, + `${requirementNode.verifyMethod ? `Verification: ${requirementNode.verifyMethod}` : ''}`, + accumulativeHeight, + node.labelStyle + ); + } else { + // Element + const typeHeight = await addText( + shapeSvg, + `${elementNode.type ? `Type: ${elementNode.type}` : ''}`, + accumulativeHeight, + node.labelStyle + ); + accumulativeHeight += typeHeight; + await addText( + shapeSvg, + `${elementNode.docRef ? `Doc Ref: ${elementNode.docRef}` : ''}`, + accumulativeHeight, + node.labelStyle + ); + } + + const totalWidth = (shapeSvg.node()?.getBBox().width ?? 200) + padding; + const totalHeight = (shapeSvg.node()?.getBBox().height ?? 200) + padding; + const x = -totalWidth / 2; + const y = -totalHeight / 2; + + // Setup roughjs + // @ts-ignore TODO: Fix rough typings + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + // Create and center rectangle + const roughRect = rc.rectangle(x, y, totalWidth, totalHeight, options); + + const rect = shapeSvg.insert(() => roughRect, ':first-child'); + rect.attr('class', 'basic label-container').attr('style', nodeStyles); + + // Re-translate labels now that rect is centered + // eslint-disable-next-line @typescript-eslint/no-explicit-any + shapeSvg.selectAll('.label').each((_: any, i: number, nodes: any) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const text = select(nodes[i]); + + const transform = text.attr('transform'); + let translateX = 0; + let translateY = 0; + if (transform) { + const regex = RegExp(/translate\(([^,]+),([^)]+)\)/); + const translate = regex.exec(transform); + if (translate) { + translateX = parseFloat(translate[1]); + translateY = parseFloat(translate[2]); + } + } + + const newTranslateY = translateY - totalHeight / 2; + let newTranslateX = x + padding / 2; + + // Keep type and name labels centered. + if (i === 0 || i === 1) { + newTranslateX = translateX; + } + // Set the updated transform attribute + text.attr('transform', `translate(${newTranslateX}, ${newTranslateY + padding})`); + }); + + // Insert divider line if there is body text + if (accumulativeHeight > typeHeight + nameHeight + gap) { + const roughLine = rc.line( + x, + y + typeHeight + nameHeight + gap, + x + totalWidth, + y + typeHeight + nameHeight + gap, + options + ); + const dividerLine = shapeSvg.insert(() => roughLine); + dividerLine.attr('style', nodeStyles); + } + + updateNodeBounds(node, rect); + + node.intersect = function (point) { + return intersect.rect(node, point); + }; + + return shapeSvg; +} + +async function addText( + parentGroup: D3Selection, + inputText: string, + yOffset: number, + style = '' +) { + if (inputText === '') { + return 0; + } + const textEl = parentGroup.insert('g').attr('class', 'label').attr('style', style); + const config = getConfig(); + const useHtmlLabels = config.htmlLabels ?? true; + + const text = await createText( + textEl, + sanitizeText(decodeEntities(inputText)), + { + width: calculateTextWidth(inputText, config) + 50, // Add room for error when splitting text into multiple lines + classes: 'markdown-node-label', + useHtmlLabels, + style, + }, + config + ); + let bbox; + + if (!useHtmlLabels) { + const textChild = text.children[0]; + for (const child of textChild.children) { + child.textContent = child.textContent.replaceAll('>', '>').replaceAll('<', '<'); + if (style) { + child.setAttribute('style', style); + } + } + // Get the bounding box after the text update + bbox = text.getBBox(); + // Add extra height so it is similar to the html labels + bbox.height += 6; + } else { + const div = text.children[0]; + const dv = select(text); + + bbox = div.getBoundingClientRect(); + dv.attr('width', bbox.width); + dv.attr('height', bbox.height); + } + + // Center text and offset by yOffset + textEl.attr('transform', `translate(${-bbox.width / 2},${-bbox.height / 2 + yOffset})`); + return bbox.height; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRect.ts new file mode 100644 index 000000000..134bcdb6c --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRect.ts @@ -0,0 +1,18 @@ +import type { Node, RectOptions } from '../../types.js'; +import type { D3Selection } from '../../../types.js'; +import { drawRect } from './drawRect.js'; + +export async function roundedRect( + parent: D3Selection, + node: Node +) { + const options = { + rx: 5, + ry: 5, + classes: '', + labelPaddingX: (node?.padding || 0) * 1, + labelPaddingY: (node?.padding || 0) * 1, + } as RectOptions; + + return drawRect(parent, node, options); +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRectPath.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRectPath.ts new file mode 100644 index 000000000..031b935fd --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRectPath.ts @@ -0,0 +1,53 @@ +export const createRoundedRectPathD = ( + x: number, + y: number, + totalWidth: number, + totalHeight: number, + radius: number +) => + [ + 'M', + x + radius, + y, // Move to the first point + 'H', + x + totalWidth - radius, // Draw horizontal line to the beginning of the right corner + 'A', + radius, + radius, + 0, + 0, + 1, + x + totalWidth, + y + radius, // Draw arc to the right top corner + 'V', + y + totalHeight - radius, // Draw vertical line down to the beginning of the right bottom corner + 'A', + radius, + radius, + 0, + 0, + 1, + x + totalWidth - radius, + y + totalHeight, // Draw arc to the right bottom corner + 'H', + x + radius, // Draw horizontal line to the beginning of the left bottom corner + 'A', + radius, + radius, + 0, + 0, + 1, + x, + y + totalHeight - radius, // Draw arc to the left bottom corner + 'V', + y + radius, // Draw vertical line up to the beginning of the left top corner + 'A', + radius, + radius, + 0, + 0, + 1, + x + radius, + y, // Draw arc to the left top corner + 'Z', // Close the path + ].join(' '); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/shadedProcess.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/shadedProcess.ts new file mode 100644 index 000000000..835f55ee4 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/shadedProcess.ts @@ -0,0 +1,71 @@ +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; +import { handleUndefinedAttr } from '../../../utils.js'; + +export async function shadedProcess( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const halfPadding = node?.padding ?? 0; + const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + const x = -bbox.width / 2 - halfPadding; + const y = -bbox.height / 2 - halfPadding; + + const { cssStyles } = node; + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const points = [ + { x, y }, + { x: x + w + 8, y }, + { x: x + w + 8, y: y + h }, + { x: x - 8, y: y + h }, + { x: x - 8, y: y }, + { x, y }, + { x, y: y + h }, + ]; + + const roughNode = rc.polygon( + points.map((p) => [p.x, p.y]), + options + ); + + const rect = shapeSvg.insert(() => roughNode, ':first-child'); + + rect.attr('class', 'basic label-container').attr('style', handleUndefinedAttr(cssStyles)); + + if (nodeStyles && node.look !== 'handDrawn') { + rect.selectAll('path').attr('style', nodeStyles); + } + + if (cssStyles && node.look !== 'handDrawn') { + rect.selectAll('path').attr('style', nodeStyles); + } + + label.attr( + 'transform', + `translate(${-w / 2 + 4 + (node.padding ?? 0) - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) - (bbox.y - (bbox.top ?? 0))})` + ); + + updateNodeBounds(node, rect); + + node.intersect = function (point) { + return intersect.rect(node, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/slopedRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/slopedRect.ts new file mode 100644 index 000000000..d97e9fb6a --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/slopedRect.ts @@ -0,0 +1,63 @@ +import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; + +export async function slopedRect(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + const x = -w / 2; + const y = -h / 2; + + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const points = [ + { x, y }, + { x, y: y + h }, + { x: x + w, y: y + h }, + { x: x + w, y: y - h / 2 }, + ]; + + const pathData = createPathFromPoints(points); + const shapeNode = rc.path(pathData, options); + + const polygon = shapeSvg.insert(() => shapeNode, ':first-child'); + polygon.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + polygon.selectChildren('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + polygon.selectChildren('path').attr('style', nodeStyles); + } + + polygon.attr('transform', `translate(0, ${h / 4})`); + label.attr( + 'transform', + `translate(${-w / 2 + (node.padding ?? 0) - (bbox.x - (bbox.left ?? 0))}, ${-h / 4 + (node.padding ?? 0) - (bbox.y - (bbox.top ?? 0))})` + ); + + updateNodeBounds(node, polygon); + + node.intersect = function (point) { + const pos = intersect.polygon(node, points, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/squareRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/squareRect.ts new file mode 100644 index 000000000..af72a798f --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/squareRect.ts @@ -0,0 +1,14 @@ +import type { Node, RectOptions } from '../../types.js'; +import type { D3Selection } from '../../../types.js'; +import { drawRect } from './drawRect.js'; + +export async function squareRect(parent: D3Selection, node: Node) { + const options = { + rx: 0, + ry: 0, + classes: '', + labelPaddingX: (node?.padding || 0) * 2, + labelPaddingY: (node?.padding || 0) * 1, + } as RectOptions; + return drawRect(parent, node, options); +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stadium.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stadium.ts new file mode 100644 index 000000000..1b93aa1b3 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stadium.ts @@ -0,0 +1,96 @@ +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import { createRoundedRectPathD } from './roundedRectPath.js'; +import type { D3Selection } from '../../../types.js'; +import { handleUndefinedAttr } from '../../../utils.js'; + +export const createStadiumPathD = ( + x: number, + y: number, + totalWidth: number, + totalHeight: number +) => { + const radius = totalHeight / 2; + return [ + 'M', + x + radius, + y, // Move to the start of the top-left arc + 'H', + x + totalWidth - radius, // Draw horizontal line to the start of the top-right arc + 'A', + radius, + radius, + 0, + 0, + 1, + x + totalWidth, + y + radius, // Draw top-right arc + 'H', + x, // Draw horizontal line to the start of the bottom-right arc + 'A', + radius, + radius, + 0, + 0, + 1, + x + totalWidth - radius, + y + totalHeight, // Draw bottom-right arc + 'H', + x + radius, // Draw horizontal line to the start of the bottom-left arc + 'A', + radius, + radius, + 0, + 0, + 1, + x, + y + radius, // Draw bottom-left arc + 'Z', // Close the path + ].join(' '); +}; + +export async function stadium(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + + const h = bbox.height + node.padding; + const w = bbox.width + h / 4 + node.padding; + + let rect; + const { cssStyles } = node; + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + const pathData = createRoundedRectPathD(-w / 2, -h / 2, w, h, h / 2); + const roughNode = rc.path(pathData, options); + + rect = shapeSvg.insert(() => roughNode, ':first-child'); + rect.attr('class', 'basic label-container').attr('style', handleUndefinedAttr(cssStyles)); + } else { + rect = shapeSvg.insert('rect', ':first-child'); + + rect + .attr('class', 'basic label-container') + .attr('style', nodeStyles) + .attr('rx', h / 2) + .attr('ry', h / 2) + .attr('x', -w / 2) + .attr('y', -h / 2) + .attr('width', w) + .attr('height', h); + } + + updateNodeBounds(node, rect); + + node.intersect = function (point) { + return intersect.rect(node, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/state.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/state.ts new file mode 100644 index 000000000..821195e64 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/state.ts @@ -0,0 +1,12 @@ +import type { Node, RectOptions } from '../../types.js'; +import type { D3Selection } from '../../../types.js'; +import { drawRect } from './drawRect.js'; + +export async function state(parent: D3Selection, node: Node) { + const options = { + rx: 5, + ry: 5, + classes: 'flowchart-node', + } as RectOptions; + return drawRect(parent, node, options); +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateEnd.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateEnd.ts new file mode 100644 index 000000000..4cc2838ae --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateEnd.ts @@ -0,0 +1,62 @@ +import rough from 'roughjs'; +import type { Node, ShapeRenderOptions } from '../../types.js'; +import intersect from '../intersect/index.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import { updateNodeBounds } from './util.js'; +import type { D3Selection } from '../../../types.js'; + +export function stateEnd( + parent: D3Selection, + node: Node, + { config: { themeVariables } }: ShapeRenderOptions +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { cssStyles } = node; + const { lineColor, stateBorder, nodeBorder } = themeVariables; + const shapeSvg = parent + .insert('g') + .attr('class', 'node default') + .attr('id', node.domId || node.id); + + // @ts-ignore TODO: Fix rough typings + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const roughNode = rc.circle(0, 0, 14, { + ...options, + stroke: lineColor, + strokeWidth: 2, + }); + const innerFill = stateBorder ?? nodeBorder; + const roughInnerNode = rc.circle(0, 0, 5, { + ...options, + fill: innerFill, + stroke: innerFill, + strokeWidth: 2, + fillStyle: 'solid', + }); + const circle = shapeSvg.insert(() => roughNode, ':first-child'); + circle.insert(() => roughInnerNode); + + if (cssStyles) { + circle.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles) { + circle.selectAll('path').attr('style', nodeStyles); + } + + updateNodeBounds(node, circle); + + node.intersect = function (point) { + return intersect.circle(node, 7, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateStart.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateStart.ts new file mode 100644 index 000000000..07a0f8f92 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateStart.ts @@ -0,0 +1,41 @@ +import rough from 'roughjs'; +import type { Node, ShapeRenderOptions } from '../../types.js'; +import intersect from '../intersect/index.js'; +import { solidStateFill } from './handDrawnShapeStyles.js'; +import { updateNodeBounds } from './util.js'; +import type { D3Selection } from '../../../types.js'; + +export function stateStart( + parent: D3Selection, + node: Node, + { config: { themeVariables } }: ShapeRenderOptions +) { + const { lineColor } = themeVariables; + + const shapeSvg = parent + .insert('g') + .attr('class', 'node default') + .attr('id', node.domId || node.id); + + let circle: D3Selection | D3Selection; + if (node.look === 'handDrawn') { + // @ts-ignore TODO: Fix rough typings + const rc = rough.svg(shapeSvg); + const roughNode = rc.circle(0, 0, 14, solidStateFill(lineColor)); + circle = shapeSvg.insert(() => roughNode); + // center the circle around its coordinate + circle.attr('class', 'state-start').attr('r', 7).attr('width', 14).attr('height', 14); + } else { + circle = shapeSvg.insert('circle', ':first-child'); + // center the circle around its coordinate + circle.attr('class', 'state-start').attr('r', 7).attr('width', 14).attr('height', 14); + } + + updateNodeBounds(node, circle); + + node.intersect = function (point) { + return intersect.circle(node, 7, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts new file mode 100644 index 000000000..ab24af29c --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts @@ -0,0 +1,87 @@ +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import { insertPolygonShape } from './insertPolygonShape.js'; +import type { D3Selection } from '../../../types.js'; +import { handleUndefinedAttr } from '../../../utils.js'; + +export const createSubroutinePathD = ( + x: number, + y: number, + width: number, + height: number +): string => { + const offset = 8; + return [ + `M${x - offset},${y}`, + `H${x + width + offset}`, + `V${y + height}`, + `H${x - offset}`, + `V${y}`, + 'M', + x, + y, + 'H', + x + width, + 'V', + y + height, + 'H', + x, + 'Z', + ].join(' '); +}; + +export async function subroutine(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + const halfPadding = (node?.padding || 0) / 2; + const w = bbox.width + node.padding; + const h = bbox.height + node.padding; + const x = -bbox.width / 2 - halfPadding; + const y = -bbox.height / 2 - halfPadding; + + const points = [ + { x: 0, y: 0 }, + { x: w, y: 0 }, + { x: w, y: -h }, + { x: 0, y: -h }, + { x: 0, y: 0 }, + { x: -8, y: 0 }, + { x: w + 8, y: 0 }, + { x: w + 8, y: -h }, + { x: -8, y: -h }, + { x: -8, y: 0 }, + ]; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + const roughNode = rc.rectangle(x - 8, y, w + 16, h, options); + const l1 = rc.line(x, y, x, y + h, options); + const l2 = rc.line(x + w, y, x + w, y + h, options); + + shapeSvg.insert(() => l1, ':first-child'); + shapeSvg.insert(() => l2, ':first-child'); + const rect = shapeSvg.insert(() => roughNode, ':first-child'); + const { cssStyles } = node; + rect.attr('class', 'basic label-container').attr('style', handleUndefinedAttr(cssStyles)); + updateNodeBounds(node, rect); + } else { + const el = insertPolygonShape(shapeSvg, w, h, points); + if (nodeStyles) { + el.attr('style', nodeStyles); + } + updateNodeBounds(node, el); + } + + node.intersect = function (point) { + return intersect.polygon(node, points, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedRect.ts new file mode 100644 index 000000000..3ae068a00 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedRect.ts @@ -0,0 +1,70 @@ +import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import intersect from '../intersect/index.js'; +import type { D3Selection } from '../../../types.js'; + +export async function taggedRect(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + const x = -w / 2; + const y = -h / 2; + const tagWidth = 0.2 * h; + const tagHeight = 0.2 * h; + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + const rectPoints = [ + { x: x - tagWidth / 2, y }, + { x: x + w + tagWidth / 2, y }, + { x: x + w + tagWidth / 2, y: y + h }, + { x: x - tagWidth / 2, y: y + h }, + ]; + + const tagPoints = [ + { x: x + w - tagWidth / 2, y: y + h }, + { x: x + w + tagWidth / 2, y: y + h }, + { x: x + w + tagWidth / 2, y: y + h - tagHeight }, + ]; + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const rectPath = createPathFromPoints(rectPoints); + const rectNode = rc.path(rectPath, options); + + const tagPath = createPathFromPoints(tagPoints); + const tagNode = rc.path(tagPath, { ...options, fillStyle: 'solid' }); + + const taggedRect = shapeSvg.insert(() => tagNode, ':first-child'); + taggedRect.insert(() => rectNode, ':first-child'); + + taggedRect.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + taggedRect.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + taggedRect.selectAll('path').attr('style', nodeStyles); + } + + updateNodeBounds(node, taggedRect); + + node.intersect = function (point) { + const pos = intersect.polygon(node, rectPoints, point); + + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedWaveEdgedRectangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedWaveEdgedRectangle.ts new file mode 100644 index 000000000..1451bdacc --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedWaveEdgedRectangle.ts @@ -0,0 +1,105 @@ +import { + labelHelper, + updateNodeBounds, + getNodeClasses, + generateFullSineWavePoints, + createPathFromPoints, +} from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import rough from 'roughjs'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import type { D3Selection } from '../../../types.js'; + +export async function taggedWaveEdgedRectangle( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + const waveAmplitude = h / 4; + const tagWidth = 0.2 * w; + const tagHeight = 0.2 * h; + const finalH = h + waveAmplitude; + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const points = [ + { x: -w / 2 - (w / 2) * 0.1, y: finalH / 2 }, + ...generateFullSineWavePoints( + -w / 2 - (w / 2) * 0.1, + finalH / 2, + w / 2 + (w / 2) * 0.1, + finalH / 2, + waveAmplitude, + 0.8 + ), + + { x: w / 2 + (w / 2) * 0.1, y: -finalH / 2 }, + { x: -w / 2 - (w / 2) * 0.1, y: -finalH / 2 }, + ]; + + const x = -w / 2 + (w / 2) * 0.1; + const y = -finalH / 2 - tagHeight * 0.4; + + const tagPoints = [ + { x: x + w - tagWidth, y: (y + h) * 1.4 }, + { x: x + w, y: y + h - tagHeight }, + { x: x + w, y: (y + h) * 0.9 }, + ...generateFullSineWavePoints( + x + w, + (y + h) * 1.3, + x + w - tagWidth, + (y + h) * 1.5, + -h * 0.03, + 0.5 + ), + ]; + + const waveEdgeRectPath = createPathFromPoints(points); + const waveEdgeRectNode = rc.path(waveEdgeRectPath, options); + + const taggedWaveEdgeRectPath = createPathFromPoints(tagPoints); + const taggedWaveEdgeRectNode = rc.path(taggedWaveEdgeRectPath, { + ...options, + fillStyle: 'solid', + }); + + const waveEdgeRect = shapeSvg.insert(() => taggedWaveEdgeRectNode, ':first-child'); + waveEdgeRect.insert(() => waveEdgeRectNode, ':first-child'); + + waveEdgeRect.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + waveEdgeRect.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + waveEdgeRect.selectAll('path').attr('style', nodeStyles); + } + + waveEdgeRect.attr('transform', `translate(0,${-waveAmplitude / 2})`); + label.attr( + 'transform', + `translate(${-w / 2 + (node.padding ?? 0) - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) - waveAmplitude / 2 - (bbox.y - (bbox.top ?? 0))})` + ); + + updateNodeBounds(node, waveEdgeRect); + node.intersect = function (point) { + const pos = intersect.polygon(node, points, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/text.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/text.ts new file mode 100644 index 000000000..cf253fd17 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/text.ts @@ -0,0 +1,37 @@ +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String } from './handDrawnShapeStyles.js'; +import type { D3Selection } from '../../../types.js'; + +export async function text(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + + const totalWidth = Math.max(bbox.width + node.padding, node?.width || 0); + const totalHeight = Math.max(bbox.height + node.padding, node?.height || 0); + const x = -totalWidth / 2; + const y = -totalHeight / 2; + + const rect = shapeSvg.insert('rect', ':first-child'); + + rect + .attr('class', 'text') + .attr('style', nodeStyles) + .attr('rx', 0) + .attr('ry', 0) + .attr('x', x) + .attr('y', y) + .attr('width', totalWidth) + .attr('height', totalHeight); + + updateNodeBounds(node, rect); + + node.intersect = function (point) { + return intersect.rect(node, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/tiltedCylinder.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/tiltedCylinder.ts new file mode 100644 index 000000000..29f2c267f --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/tiltedCylinder.ts @@ -0,0 +1,142 @@ +import { labelHelper, getNodeClasses, updateNodeBounds } from './util.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import intersect from '../intersect/index.js'; +import type { D3Selection } from '../../../types.js'; +import { handleUndefinedAttr } from '../../../utils.js'; + +export const createCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number +): string => { + return `M${x},${y} + a${rx},${ry} 0,0,1 ${0},${-height} + l${width},${0} + a${rx},${ry} 0,0,1 ${0},${height} + M${width},${-height} + a${rx},${ry} 0,0,0 ${0},${height} + l${-width},${0}`; +}; + +export const createOuterCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number +): string => { + return [ + `M${x},${y}`, + `M${x + width},${y}`, + `a${rx},${ry} 0,0,0 ${0},${-height}`, + `l${-width},0`, + `a${rx},${ry} 0,0,0 ${0},${height}`, + `l${width},0`, + ].join(' '); +}; +export const createInnerCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number +): string => { + return [`M${x + width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 0,${height}`].join(' '); +}; + +export async function tiltedCylinder( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label, halfPadding } = await labelHelper( + parent, + node, + getNodeClasses(node) + ); + const labelPadding = node.look === 'neo' ? halfPadding * 2 : halfPadding; + const h = bbox.height + labelPadding; + const ry = h / 2; + const rx = ry / (2.5 + h / 50); + const w = bbox.width + rx + labelPadding; + const { cssStyles } = node; + + let cylinder: D3Selection | D3Selection; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry); + const innerPathData = createInnerCylinderPathD(0, 0, w, h, rx, ry); + const outerNode = rc.path(outerPathData, userNodeOverrides(node, {})); + const innerLine = rc.path(innerPathData, userNodeOverrides(node, { fill: 'none' })); + cylinder = shapeSvg.insert(() => innerLine, ':first-child'); + cylinder = shapeSvg.insert(() => outerNode, ':first-child'); + cylinder.attr('class', 'basic label-container'); + if (cssStyles) { + cylinder.attr('style', cssStyles); + } + } else { + const pathData = createCylinderPathD(0, 0, w, h, rx, ry); + cylinder = shapeSvg + .insert('path', ':first-child') + .attr('d', pathData) + .attr('class', 'basic label-container') + .attr('style', handleUndefinedAttr(cssStyles)) + .attr('style', nodeStyles); + cylinder.attr('class', 'basic label-container'); + + if (cssStyles) { + cylinder.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles) { + cylinder.selectAll('path').attr('style', nodeStyles); + } + } + + cylinder.attr('label-offset-x', rx); + cylinder.attr('transform', `translate(${-w / 2}, ${h / 2} )`); + + label.attr( + 'transform', + `translate(${-(bbox.width / 2) - rx - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) - (bbox.y - (bbox.top ?? 0))})` + ); + + updateNodeBounds(node, cylinder); + + node.intersect = function (point) { + const pos = intersect.rect(node, point); + const y = pos.y - (node.y ?? 0); + + if ( + ry != 0 && + (Math.abs(y) < (node.height ?? 0) / 2 || + (Math.abs(y) == (node.height ?? 0) / 2 && + Math.abs(pos.x - (node.x ?? 0)) > (node.width ?? 0) / 2 - rx)) + ) { + let x = rx * rx * (1 - (y * y) / (ry * ry)); + if (x != 0) { + x = Math.sqrt(Math.abs(x)); + } + x = rx - x; + if (point.x - (node.x ?? 0) > 0) { + x = -x; + } + + pos.x += x; + } + + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoid.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoid.ts new file mode 100644 index 000000000..d0228d55b --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoid.ts @@ -0,0 +1,73 @@ +import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import { insertPolygonShape } from './insertPolygonShape.js'; +import type { D3Selection } from '../../../types.js'; + +// export const createTrapezoidPathD = ( +// x: number, +// y: number, +// width: number, +// height: number +// ): string => { +// return [ +// `M${x - (2 * height) / 6},${y}`, +// `L${x + width + (2 * height) / 6},${y}`, +// `L${x + width - height / 6},${y - height}`, +// `L${x + height / 6},${y - height}`, +// 'Z', +// ].join(' '); +// }; + +export async function trapezoid(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + + const w = bbox.width + node.padding; + const h = bbox.height + node.padding; + const points = [ + { x: (-3 * h) / 6, y: 0 }, + { x: w + (3 * h) / 6, y: 0 }, + { x: w, y: -h }, + { x: 0, y: -h }, + ]; + + let polygon: typeof shapeSvg | ReturnType; + const { cssStyles } = node; + + if (node.look === 'handDrawn') { + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + const pathData = createPathFromPoints(points); + const roughNode = rc.path(pathData, options); + + polygon = shapeSvg + .insert(() => roughNode, ':first-child') + .attr('transform', `translate(${-w / 2}, ${h / 2})`); + + if (cssStyles) { + polygon.attr('style', cssStyles); + } + } else { + polygon = insertPolygonShape(shapeSvg, w, h, points); + } + + if (nodeStyles) { + polygon.attr('style', nodeStyles); + } + + node.width = w; + node.height = h; + + updateNodeBounds(node, polygon); + + node.intersect = function (point) { + return intersect.polygon(node, points, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoidalPentagon.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoidalPentagon.ts new file mode 100644 index 000000000..d4bfb03c0 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoidalPentagon.ts @@ -0,0 +1,61 @@ +import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; + +export async function trapezoidalPentagon( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + const minWidth = 60, + minHeight = 20; + const w = Math.max(minWidth, bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const h = Math.max(minHeight, bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + + const { cssStyles } = node; + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const points = [ + { x: (-w / 2) * 0.8, y: -h / 2 }, + { x: (w / 2) * 0.8, y: -h / 2 }, + { x: w / 2, y: (-h / 2) * 0.6 }, + { x: w / 2, y: h / 2 }, + { x: -w / 2, y: h / 2 }, + { x: -w / 2, y: (-h / 2) * 0.6 }, + ]; + + const pathData = createPathFromPoints(points); + const shapeNode = rc.path(pathData, options); + + const polygon = shapeSvg.insert(() => shapeNode, ':first-child'); + polygon.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + polygon.selectChildren('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + polygon.selectChildren('path').attr('style', nodeStyles); + } + + updateNodeBounds(node, polygon); + + node.intersect = function (point) { + const pos = intersect.polygon(node, points, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/triangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/triangle.ts new file mode 100644 index 000000000..d4bd3c347 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/triangle.ts @@ -0,0 +1,68 @@ +import { log } from '../../../logger.js'; +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import { createPathFromPoints } from './util.js'; +import { evaluate } from '../../../diagrams/common/common.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; +import type { D3Selection } from '../../../types.js'; + +export async function triangle(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const useHtmlLabels = evaluate(getConfig().flowchart?.htmlLabels); + + const w = bbox.width + (node.padding ?? 0); + const h = w + bbox.height; + + const tw = w + bbox.height; + const points = [ + { x: 0, y: 0 }, + { x: tw, y: 0 }, + { x: tw / 2, y: -h }, + ]; + + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + const pathData = createPathFromPoints(points); + const roughNode = rc.path(pathData, options); + + const polygon = shapeSvg + .insert(() => roughNode, ':first-child') + .attr('transform', `translate(${-h / 2}, ${h / 2})`); + + if (cssStyles && node.look !== 'handDrawn') { + polygon.selectChildren('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + polygon.selectChildren('path').attr('style', nodeStyles); + } + + node.width = w; + node.height = h; + + updateNodeBounds(node, polygon); + + label.attr( + 'transform', + `translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))}, ${h / 2 - (bbox.height + (node.padding ?? 0) / (useHtmlLabels ? 2 : 1) - (bbox.y - (bbox.top ?? 0)))})` + ); + + node.intersect = function (point) { + log.info('Triangle intersect', node, points, point); + return intersect.polygon(node, points, point); + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts new file mode 100644 index 000000000..52471ecc0 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.ts @@ -0,0 +1,282 @@ +import { createText } from '../../createText.js'; +import type { Node } from '../../types.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; +import { select } from 'd3'; +import defaultConfig from '../../../defaultConfig.js'; +import { evaluate, sanitizeText } from '../../../diagrams/common/common.js'; +import { decodeEntities, handleUndefinedAttr, parseFontSize } from '../../../utils.js'; +import type { D3Selection, Point } from '../../../types.js'; + +export const labelHelper = async ( + parent: D3Selection, + node: Node, + _classes?: string +) => { + let cssClasses; + const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig()?.htmlLabels); + if (!_classes) { + cssClasses = 'node default'; + } else { + cssClasses = _classes; + } + + // Add outer g element + const shapeSvg = parent + .insert('g') + .attr('class', cssClasses) + .attr('id', node.domId || node.id); + + // Create the label and insert it after the rect + const labelEl = shapeSvg + .insert('g') + .attr('class', 'label') + .attr('style', handleUndefinedAttr(node.labelStyle)); + + // Replace label with default value if undefined + let label; + if (node.label === undefined) { + label = ''; + } else { + label = typeof node.label === 'string' ? node.label : node.label[0]; + } + + const text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), { + useHtmlLabels, + width: node.width || getConfig().flowchart?.wrappingWidth, + // @ts-expect-error -- This is currently not used. Should this be `classes` instead? + cssClasses: 'markdown-node-label', + style: node.labelStyle, + addSvgBackground: !!node.icon || !!node.img, + }); + // Get the size of the label + let bbox = text.getBBox(); + const halfPadding = (node?.padding ?? 0) / 2; + + if (useHtmlLabels) { + const div = text.children[0]; + const dv = select(text); + + // if there are images, need to wait for them to load before getting the bounding box + const images = div.getElementsByTagName('img'); + if (images) { + const noImgText = label.replace(/]*>/g, '').trim() === ''; + + await Promise.all( + [...images].map( + (img) => + new Promise((res) => { + /** + * + */ + function setupImage() { + img.style.display = 'flex'; + img.style.flexDirection = 'column'; + + if (noImgText) { + // default size if no text + const bodyFontSize = getConfig().fontSize + ? getConfig().fontSize + : window.getComputedStyle(document.body).fontSize; + const enlargingFactor = 5; + const [parsedBodyFontSize = defaultConfig.fontSize] = parseFontSize(bodyFontSize); + const width = parsedBodyFontSize * enlargingFactor + 'px'; + img.style.minWidth = width; + img.style.maxWidth = width; + } else { + img.style.width = '100%'; + } + res(img); + } + setTimeout(() => { + if (img.complete) { + setupImage(); + } + }); + img.addEventListener('error', setupImage); + img.addEventListener('load', setupImage); + }) + ) + ); + } + + bbox = div.getBoundingClientRect(); + dv.attr('width', bbox.width); + dv.attr('height', bbox.height); + } + + // Center the label + if (useHtmlLabels) { + labelEl.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')'); + } else { + labelEl.attr('transform', 'translate(' + 0 + ', ' + -bbox.height / 2 + ')'); + } + if (node.centerLabel) { + labelEl.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')'); + } + labelEl.insert('rect', ':first-child'); + return { shapeSvg, bbox, halfPadding, label: labelEl }; +}; +export const insertLabel = async ( + parent: D3Selection, + label: string, + options: { + labelStyle?: string | undefined; + icon?: boolean | undefined; + img?: string | undefined; + useHtmlLabels?: boolean | undefined; + padding: number; + width?: number | undefined; + centerLabel?: boolean | undefined; + addSvgBackground?: boolean | undefined; + } +) => { + const useHtmlLabels = options.useHtmlLabels || evaluate(getConfig()?.flowchart?.htmlLabels); + + // Create the label and insert it after the rect + const labelEl = parent + .insert('g') + .attr('class', 'label') + .attr('style', options.labelStyle || ''); + + const text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), { + useHtmlLabels, + width: options.width || getConfig()?.flowchart?.wrappingWidth, + style: options.labelStyle, + addSvgBackground: !!options.icon || !!options.img, + }); + // Get the size of the label + let bbox = text.getBBox(); + const halfPadding = options.padding / 2; + + if (evaluate(getConfig()?.flowchart?.htmlLabels)) { + const div = text.children[0]; + const dv = select(text); + + bbox = div.getBoundingClientRect(); + dv.attr('width', bbox.width); + dv.attr('height', bbox.height); + } + + // Center the label + if (useHtmlLabels) { + labelEl.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')'); + } else { + labelEl.attr('transform', 'translate(' + 0 + ', ' + -bbox.height / 2 + ')'); + } + if (options.centerLabel) { + labelEl.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')'); + } + labelEl.insert('rect', ':first-child'); + return { shapeSvg: parent, bbox, halfPadding, label: labelEl }; +}; +export const updateNodeBounds = ( + node: Node, + // D3Selection is for the roughjs case, D3Selection is for the non-roughjs case + element: D3Selection | D3Selection +) => { + const bbox = element.node()!.getBBox(); + node.width = bbox.width; + node.height = bbox.height; +}; + +/** + * @param parent - Parent element to append the polygon to + * @param w - Width of the polygon + * @param h - Height of the polygon + * @param points - Array of points to create the polygon + */ +export function insertPolygonShape( + parent: D3Selection, + w: number, + h: number, + points: Point[] +) { + return parent + .insert('polygon', ':first-child') + .attr( + 'points', + points + .map(function (d) { + return d.x + ',' + d.y; + }) + .join(' ') + ) + .attr('class', 'label-container') + .attr('transform', 'translate(' + -w / 2 + ',' + h / 2 + ')'); +} + +export const getNodeClasses = (node: Node, extra?: string) => + (node.look === 'handDrawn' ? 'rough-node' : 'node') + ' ' + node.cssClasses + ' ' + (extra || ''); + +export function createPathFromPoints(points: Point[]) { + const pointStrings = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`); + pointStrings.push('Z'); + return pointStrings.join(' '); +} + +export function generateFullSineWavePoints( + x1: number, + y1: number, + x2: number, + y2: number, + amplitude: number, + numCycles: number +) { + const points = []; + const steps = 50; // Number of segments to create a smooth curve + const deltaX = x2 - x1; + const deltaY = y2 - y1; + const cycleLength = deltaX / numCycles; + + // Calculate frequency and phase shift + const frequency = (2 * Math.PI) / cycleLength; + const midY = y1 + deltaY / 2; + + for (let i = 0; i <= steps; i++) { + const t = i / steps; + const x = x1 + t * deltaX; + const y = midY + amplitude * Math.sin(frequency * (x - x1)); + + points.push({ x, y }); + } + + return points; +} + +/** + * @param centerX - x-coordinate of center of circle + * @param centerY - y-coordinate of center of circle + * @param radius - radius of circle + * @param numPoints - total points required + * @param startAngle - angle where arc will start + * @param endAngle - angle where arc will end + */ +export function generateCirclePoints( + centerX: number, + centerY: number, + radius: number, + numPoints: number, + startAngle: number, + endAngle: number +) { + const points = []; + + // Convert angles to radians + const startAngleRad = (startAngle * Math.PI) / 180; + const endAngleRad = (endAngle * Math.PI) / 180; + + // Calculate the angle range in radians + const angleRange = endAngleRad - startAngleRad; + + // Calculate the angle step + const angleStep = angleRange / (numPoints - 1); + + for (let i = 0; i < numPoints; i++) { + const angle = startAngleRad + i * angleStep; + const x = centerX + radius * Math.cos(angle); + const y = centerY + radius * Math.sin(angle); + points.push({ x: -x, y: -y }); + } + + return points; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveEdgedRectangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveEdgedRectangle.ts new file mode 100644 index 000000000..d2c1a525d --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveEdgedRectangle.ts @@ -0,0 +1,83 @@ +import { + labelHelper, + updateNodeBounds, + getNodeClasses, + generateFullSineWavePoints, + createPathFromPoints, +} from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import rough from 'roughjs'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import type { D3Selection } from '../../../types.js'; + +export async function waveEdgedRectangle( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + const waveAmplitude = h / 8; + const finalH = h + waveAmplitude; + const { cssStyles } = node; + + // To maintain minimum width + const minWidth = 70; + const widthDif = minWidth - w; + const extraW = widthDif > 0 ? widthDif / 2 : 0; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const points = [ + { x: -w / 2 - extraW, y: finalH / 2 }, + ...generateFullSineWavePoints( + -w / 2 - extraW, + finalH / 2, + w / 2 + extraW, + finalH / 2, + waveAmplitude, + 0.8 + ), + { x: w / 2 + extraW, y: -finalH / 2 }, + { x: -w / 2 - extraW, y: -finalH / 2 }, + ]; + + const waveEdgeRectPath = createPathFromPoints(points); + const waveEdgeRectNode = rc.path(waveEdgeRectPath, options); + + const waveEdgeRect = shapeSvg.insert(() => waveEdgeRectNode, ':first-child'); + + waveEdgeRect.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + waveEdgeRect.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + waveEdgeRect.selectAll('path').attr('style', nodeStyles); + } + + waveEdgeRect.attr('transform', `translate(0,${-waveAmplitude / 2})`); + label.attr( + 'transform', + `translate(${-w / 2 + (node.padding ?? 0) - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) - waveAmplitude - (bbox.y - (bbox.top ?? 0))})` + ); + + updateNodeBounds(node, waveEdgeRect); + node.intersect = function (point) { + const pos = intersect.polygon(node, points, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveRectangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveRectangle.ts new file mode 100644 index 000000000..4ee6dba47 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveRectangle.ts @@ -0,0 +1,84 @@ +import { + labelHelper, + updateNodeBounds, + getNodeClasses, + createPathFromPoints, + generateFullSineWavePoints, +} from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import type { D3Selection } from '../../../types.js'; + +export async function waveRectangle( + parent: D3Selection, + node: Node +) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); + + const minWidth = 100; // Minimum width + const minHeight = 50; // Minimum height + + const baseWidth = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const baseHeight = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + + const aspectRatio = baseWidth / baseHeight; + + let w = baseWidth; + let h = baseHeight; + + if (w > h * aspectRatio) { + h = w / aspectRatio; + } else { + w = h * aspectRatio; + } + + w = Math.max(w, minWidth); + h = Math.max(h, minHeight); + + const waveAmplitude = Math.min(h * 0.2, h / 4); + const finalH = h + waveAmplitude * 2; + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const points = [ + { x: -w / 2, y: finalH / 2 }, + ...generateFullSineWavePoints(-w / 2, finalH / 2, w / 2, finalH / 2, waveAmplitude, 1), + { x: w / 2, y: -finalH / 2 }, + ...generateFullSineWavePoints(w / 2, -finalH / 2, -w / 2, -finalH / 2, waveAmplitude, -1), + ]; + + const waveRectPath = createPathFromPoints(points); + const waveRectNode = rc.path(waveRectPath, options); + + const waveRect = shapeSvg.insert(() => waveRectNode, ':first-child'); + + waveRect.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + waveRect.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + waveRect.selectAll('path').attr('style', nodeStyles); + } + + updateNodeBounds(node, waveRect); + node.intersect = function (point) { + const pos = intersect.polygon(node, points, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/windowPane.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/windowPane.ts new file mode 100644 index 000000000..e67c92a06 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/windowPane.ts @@ -0,0 +1,67 @@ +import { labelHelper, getNodeClasses, updateNodeBounds } from './util.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import intersect from '../intersect/index.js'; +import type { D3Selection } from '../../../types.js'; + +export async function windowPane(parent: D3Selection, node: Node) { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0); + const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0); + const rectOffset = 5; + const x = -w / 2; + const y = -h / 2; + const { cssStyles } = node; + + // @ts-expect-error -- Passing a D3.Selection seems to work for some reason + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + + const outerPathPoints = [ + { x: x - rectOffset, y: y - rectOffset }, + { x: x - rectOffset, y: y + h }, + { x: x + w, y: y + h }, + { x: x + w, y: y - rectOffset }, + ]; + + const path = `M${x - rectOffset},${y - rectOffset} L${x + w},${y - rectOffset} L${x + w},${y + h} L${x - rectOffset},${y + h} L${x - rectOffset},${y - rectOffset} + M${x - rectOffset},${y} L${x + w},${y} + M${x},${y - rectOffset} L${x},${y + h}`; + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const no = rc.path(path, options); + + const windowPane = shapeSvg.insert(() => no, ':first-child'); + windowPane.attr('transform', `translate(${rectOffset / 2}, ${rectOffset / 2})`); + + windowPane.attr('class', 'basic label-container'); + + if (cssStyles && node.look !== 'handDrawn') { + windowPane.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + windowPane.selectAll('path').attr('style', nodeStyles); + } + + label.attr( + 'transform', + `translate(${-(bbox.width / 2) + rectOffset / 2 - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) + rectOffset / 2 - (bbox.y - (bbox.top ?? 0))})` + ); + + updateNodeBounds(node, windowPane); + + node.intersect = function (point) { + const pos = intersect.polygon(node, outerPathPoints, point); + return pos; + }; + + return shapeSvg; +} diff --git a/packages/mermaid/src/rendering-util/setupViewPortForSVG.ts b/packages/mermaid/src/rendering-util/setupViewPortForSVG.ts new file mode 100644 index 000000000..d3df5ddb7 --- /dev/null +++ b/packages/mermaid/src/rendering-util/setupViewPortForSVG.ts @@ -0,0 +1,40 @@ +import { configureSvgSize } from '../setupGraphViewbox.js'; +import type { SVG } from '../diagram-api/types.js'; +import { log } from '../logger.js'; + +export const setupViewPortForSVG = ( + svg: SVG, + padding: number, + cssDiagram: string, + useMaxWidth: boolean +) => { + // Initialize the SVG element and set the diagram class + svg.attr('class', cssDiagram); + + // Calculate the dimensions and position with padding + const { width, height, x, y } = calculateDimensionsWithPadding(svg, padding); + + // Configure the size and aspect ratio of the SVG + configureSvgSize(svg, height, width, useMaxWidth); + + // Update the viewBox to ensure all content is visible with padding + const viewBox = createViewBox(x, y, width, height, padding); + svg.attr('viewBox', viewBox); + + // Log the viewBox configuration for debugging + log.debug(`viewBox configured: ${viewBox} with padding: ${padding}`); +}; + +const calculateDimensionsWithPadding = (svg: SVG, padding: number) => { + const bounds = svg.node()?.getBBox() || { width: 0, height: 0, x: 0, y: 0 }; + return { + width: bounds.width + padding * 2, + height: bounds.height + padding * 2, + x: bounds.x, + y: bounds.y, + }; +}; + +const createViewBox = (x: number, y: number, width: number, height: number, padding: number) => { + return `${x - padding} ${y - padding} ${width} ${height}`; +}; diff --git a/packages/mermaid/src/rendering-util/types.d.ts b/packages/mermaid/src/rendering-util/types.d.ts deleted file mode 100644 index 6dabb476d..000000000 --- a/packages/mermaid/src/rendering-util/types.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type MarkdownWordType = 'normal' | 'strong' | 'emphasis'; -export interface MarkdownWord { - content: string; - type: MarkdownWordType; -} -export type MarkdownLine = MarkdownWord[]; -/** Returns `true` if the line fits a constraint (e.g. it's under 𝑛 chars) */ -export type CheckFitFunction = (text: MarkdownLine) => boolean; diff --git a/packages/mermaid/src/rendering-util/types.ts b/packages/mermaid/src/rendering-util/types.ts new file mode 100644 index 000000000..b11d2f314 --- /dev/null +++ b/packages/mermaid/src/rendering-util/types.ts @@ -0,0 +1,183 @@ +export type MarkdownWordType = 'normal' | 'strong' | 'em'; +import type { MermaidConfig } from '../config.type.js'; +import type { ClusterShapeID } from './rendering-elements/clusters.js'; +import type { ShapeID } from './rendering-elements/shapes.js'; +export interface MarkdownWord { + content: string; + type: MarkdownWordType; +} +export type MarkdownLine = MarkdownWord[]; +/** Returns `true` if the line fits a constraint (e.g. it's under 𝑛 chars) */ +export type CheckFitFunction = (text: MarkdownLine) => boolean; + +interface BaseNode { + id: string; + label?: string; + description?: string[]; + parentId?: string; + position?: string; // Keep, this is for notes 'left of', 'right of', etc. Move into nodeNode + cssStyles?: string[]; // Renamed from `styles` to `cssStyles` + cssCompiledStyles?: string[]; + cssClasses?: string; // Renamed from `classes` to `cssClasses` + // style?: string; //REMOVE ✅ + // class?: string; //REMOVE ✅ + // labelText?: string; //REMOVE, use `label` instead ✅ + // props?: Record; //REMOVE ✅ + // type: string; // REMOVE, replace with isGroup: boolean, default false ✅ + // borders?: string; //REMOVE ✅ + labelStyle?: string; // REMOVE - use cssStyles instead ✅ + + // Flowchart specific properties + labelType?: string; // REMOVE? Always use markdown string, need to check for KaTeX - âŗ wait with this one + + domId?: string; // When you create the node in the getData function you do not have the domId yet + // Rendering specific properties for both Flowchart and State Diagram nodes + dir?: string; // Only relevant for isGroup true, i.e. a sub-graph or composite state. + haveCallback?: boolean; + link?: string; + linkTarget?: string; + tooltip?: string; + padding?: number; //REMOVE?, use from LayoutData.config - Keep, this could be shape specific + isGroup: boolean; + width?: number; + height?: number; + // Specific properties for State Diagram nodes TODO remove and use generic properties + intersect?: (point: any) => any; + + // Non-generic properties + rx?: number; // Used for rounded corners in Rect, Ellipse, etc.Maybe it to specialized RectNode, EllipseNode, etc. + ry?: number; + + useHtmlLabels?: boolean; + centerLabel?: boolean; //keep for now. + //Candidate for removal, maybe rely on labelStyle or a specific property labelPosition: Top, Center, Bottom + + //Node style properties + backgroundColor?: string; + borderColor?: string; + borderStyle?: string; + borderWidth?: number; + labelTextColor?: string; + + // Flowchart specific properties + x?: number; + y?: number; + + look?: string; + icon?: string; + pos?: 't' | 'b'; + img?: string; + assetWidth?: number; + assetHeight?: number; + defaultWidth?: number; + imageAspectRatio?: number; + constraint?: 'on' | 'off'; +} + +/** + * Group/cluster nodes, e.g. nodes that contain other nodes. + */ +export interface ClusterNode extends BaseNode { + shape?: ClusterShapeID; + isGroup: true; +} + +export interface NonClusterNode extends BaseNode { + shape?: ShapeID; + isGroup: false; +} + +// Common properties for any node in the system +export type Node = ClusterNode | NonClusterNode; + +// Common properties for any edge in the system +export interface Edge { + id: string; + label?: string; + classes?: string; + style?: string[]; + animate?: boolean; + animation?: 'fast' | 'slow'; + // Properties common to both Flowchart and State Diagram edges + arrowhead?: string; + arrowheadStyle?: string; + arrowTypeEnd?: string; + arrowTypeStart?: string; + cssCompiledStyles?: string[]; + // Flowchart specific properties + defaultInterpolate?: string; + end?: string; + interpolate?: string; + labelType?: string; + length?: number; + start?: string; + stroke?: string; + text?: string; + type: string; + // Class Diagram specific properties + startLabelRight?: string; + endLabelLeft?: string; + // Rendering specific properties + curve?: string; + labelpos?: string; + labelStyle?: string[]; + minlen?: number; + pattern?: string; + thickness?: 'normal' | 'thick' | 'invisible' | 'dotted'; + look?: string; + isUserDefinedId?: boolean; +} + +export interface RectOptions { + rx: number; + ry: number; + labelPaddingX: number; + labelPaddingY: number; + classes: string; +} + +// Extending the Node interface for specific types if needed +export type ClassDiagramNode = Node & { + memberData: any; // Specific property for class diagram nodes +}; + +// Specific interfaces for layout and render data +export interface LayoutData { + nodes: Node[]; + edges: Edge[]; + config: MermaidConfig; + [key: string]: any; // Additional properties not yet defined +} + +export interface RenderData { + items: (Node | Edge)[]; + [key: string]: any; // Additional properties not yet defined +} + +// This refactored approach ensures that common properties are included in the base `Node` and `Edge` interfaces, with specific types extending these bases with additional properties as needed. This maintains flexibility while ensuring type safety and reducing redundancy. + +export type LayoutMethod = + | 'dagre' + | 'dagre-wrapper' + | 'elk' + | 'neato' + | 'dot' + | 'circo' + | 'fdp' + | 'osage' + | 'grid'; + +export interface ShapeRenderOptions { + config: MermaidConfig; + /** Some shapes render differently if a diagram has a direction `LR` */ + dir?: Node['dir']; +} + +export type KanbanNode = Node & { + // Kanban specif data + priority?: 'Very High' | 'High' | 'Medium' | 'Low' | 'Very Low'; + ticket?: string; + assigned?: string; + icon?: string; + level: number; +}; diff --git a/packages/mermaid/src/schemas/config.schema.yaml b/packages/mermaid/src/schemas/config.schema.yaml index d1bb8ad1b..c22d0aebc 100644 --- a/packages/mermaid/src/schemas/config.schema.yaml +++ b/packages/mermaid/src/schemas/config.schema.yaml @@ -46,12 +46,16 @@ required: - quadrantChart - xyChart - requirement + - architecture - mindmap + - kanban - gitGraph - c4 - sankey - packet - block + - look + - radar properties: theme: description: | @@ -60,8 +64,9 @@ properties: type: string enum: - default - - forest + - base - dark + - forest - neutral - 'null' # should this be a `null`-type? meta:enum: @@ -71,6 +76,24 @@ properties: tsType: any themeCSS: type: string + look: + description: | + Defines which main look to use for the diagram. + type: string + enum: + - classic + - handDrawn + default: 'classic' + handDrawnSeed: + description: | + Defines the seed to be used when using handDrawn look. This is important for the automated tests as they will always find differences without the seed. The default value is 0 which gives a random seed. + type: number + default: 0 + layout: + description: | + Defines which layout algorithm to use for rendering the diagram. + type: string + default: 'dagre' maxTextSize: description: The maximum allowed size of the users text diagram type: number @@ -81,6 +104,35 @@ properties: type: integer default: 500 minimum: 0 + elk: + type: object + properties: + mergeEdges: + description: | + Elk specific option that allows edges to share path where it convenient. It can make for pretty diagrams but can also make it harder to read the diagram. + type: boolean + default: false + nodePlacementStrategy: + description: | + Elk specific option affecting how nodes are placed. + type: string + enum: + - SIMPLE + - NETWORK_SIMPLEX + - LINEAR_SEGMENTS + - BRANDES_KOEPF + default: BRANDES_KOEPF + cycleBreakingStrategy: + description: | + This strategy decides how to find cycles in the graph and deciding which edges need adjustment to break loops. + type: string + enum: + - GREEDY + - DEPTH_FIRST + - INTERACTIVE + - MODEL_ORDER + - GREEDY_MODEL_ORDER + default: GREEDY_MODEL_ORDER darkMode: type: boolean default: false @@ -154,10 +206,7 @@ properties: secure: description: | This option controls which `currentConfig` keys are considered secure and - can only be changed via call to `mermaidAPI.initialize`. - Calls to `mermaidAPI.reinitialize` cannot make changes to the secure keys - in the current `currentConfig`. - + can only be changed via call to `mermaid.initialize`. This prevents malicious graph directives from overriding a site's default security. default: [ @@ -180,6 +229,13 @@ properties: fall back to legacy rendering for KaTeX. type: boolean default: false + forceLegacyMathML: + description: | + This option forces Mermaid to rely on KaTeX's own stylesheet for rendering MathML. Due to differences between OS + fonts and browser's MathML implementation, this option is recommended if consistent rendering is important. + If set to true, ignores legacyMathML. + type: boolean + default: false deterministicIds: description: | This option controls if the generated ids of nodes in the SVG are @@ -221,8 +277,12 @@ properties: $ref: '#/$defs/XYChartConfig' requirement: $ref: '#/$defs/RequirementDiagramConfig' + architecture: + $ref: '#/$defs/ArchitectureDiagramConfig' mindmap: $ref: '#/$defs/MindmapDiagramConfig' + kanban: + $ref: '#/$defs/KanbanDiagramConfig' gitGraph: $ref: '#/$defs/GitGraphDiagramConfig' c4: @@ -233,6 +293,8 @@ properties: $ref: '#/$defs/PacketDiagramConfig' block: $ref: '#/$defs/BlockDiagramConfig' + radar: + $ref: '#/$defs/RadarDiagramConfig' dompurifyConfig: title: DOM Purify Configuration description: Configuration options to pass to the `dompurify` library. @@ -868,6 +930,28 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) type: number default: 20 + ArchitectureDiagramConfig: + title: Architecture Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + description: The object containing configurations specific for architecture diagrams + type: object + unevaluatedProperties: false + required: + - useMaxWidth + - padding + - iconSize + - fontSize + properties: + padding: + type: number + default: 40 + iconSize: + type: number + default: 80 + fontSize: + type: number + default: 16 + MindmapDiagramConfig: title: Mindmap Diagram Config allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] @@ -886,6 +970,23 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) type: number default: 200 + KanbanDiagramConfig: + title: Kanban Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + description: The object containing configurations specific for kanban diagrams + type: object + unevaluatedProperties: false + properties: + padding: + type: number + default: 8 + sectionWidth: + type: number + default: 200 + ticketBaseUrl: + type: string + default: '' + PieDiagramConfig: title: Pie Diagram Config allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] @@ -1127,6 +1228,10 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) type: number default: 10 minimum: 0 + showDataLabel: + description: Should show the value corresponding to the bar within the bar + type: boolean + default: false showTitle: description: Should show the chart title type: boolean @@ -1202,6 +1307,14 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) type: integer default: 15 minimum: 0 + nodeSpacing: + type: integer + default: 140 + minimum: 0 + rankSpacing: + type: integer + default: 80 + minimum: 0 stroke: description: Stroke color of box edges and lines. type: string @@ -1251,6 +1364,16 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) noteMargin: type: number default: 10 + nodeSpacing: + type: integer + minimum: 0 + # should the default value be 50? + # see https://github.com/mermaid-js/mermaid/blob/7647ae317a7b2130e32777248d25a9c4d24b8f9f/packages/mermaid/src/diagrams/class/classRenderer-v2.ts#L258 + rankSpacing: + type: integer + minimum: 0 + # should the default value be 50? + # see https://github.com/mermaid-js/mermaid/blob/7647ae317a7b2130e32777248d25a9c4d24b8f9f/packages/mermaid/src/diagrams/class/classRenderer-v2.ts#L259 forkWidth: type: number default: 70 @@ -1340,6 +1463,9 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) htmlLabels: type: boolean default: false + hideEmptyMembersBox: + type: boolean + default: false JourneyDiagramConfig: title: Journey Diagram Config @@ -1362,6 +1488,9 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) - bottomMarginAdj - useMaxWidth - rightAngles + - titleColor + - titleFontFamily + - titleFontSize properties: diagramMarginX: $ref: '#/$defs/C4DiagramConfig/properties/diagramMarginX' @@ -1374,6 +1503,10 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) type: integer default: 150 minimum: 0 + maxLabelWidth: + description: Maximum width of actor labels + type: integer + default: 360 width: description: Width of actor boxes type: integer @@ -1462,6 +1595,18 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) items: type: string default: ['#fff'] + titleColor: + description: Color of the title text in Journey Diagrams + type: string + default: '' + titleFontFamily: + description: Font family to be used for the title text in Journey Diagrams + type: string + default: '"trebuchet ms", verdana, arial, sans-serif' + titleFontSize: + description: Font size to be used for the title text in Journey Diagrams + type: string + default: '4ex' TimelineDiagramConfig: # added by https://github.com/mermaid-js/mermaid/commit/0d5246fbc730bf15463d7183fe4400a1e2fc492c @@ -1944,7 +2089,21 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) description: | Defines how mermaid renders curves for flowcharts. type: string - enum: ['basis', 'linear', 'cardinal'] + enum: + [ + 'basis', + 'bumpX', + 'bumpY', + 'cardinal', + 'catmullRom', + 'linear', + 'monotoneX', + 'monotoneY', + 'natural', + 'step', + 'stepAfter', + 'stepBefore', + ] default: 'basis' padding: description: | @@ -1960,7 +2119,7 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) description: | Width of nodes where text is wrapped. - When using markdown strings the text ius wrapped automatically, this + When using markdown strings the text is wrapped automatically, this value sets the max width of a text before it continues on a new line. type: number default: 200 @@ -2089,6 +2248,60 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) minimum: 0 default: 8 + RadarDiagramConfig: + title: Radar Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + description: The object containing configurations specific for radar diagrams. + type: object + unevaluatedProperties: false + properties: + width: + description: The size of the radar diagram. + type: number + minimum: 1 + default: 600 + height: + description: The size of the radar diagram. + type: number + minimum: 1 + default: 600 + marginTop: + description: The margin from the top of the radar diagram. + type: number + minimum: 0 + default: 50 + marginRight: + description: The margin from the right of the radar diagram. + type: number + minimum: 0 + default: 50 + marginBottom: + description: The margin from the bottom of the radar diagram. + type: number + minimum: 0 + default: 50 + marginLeft: + description: The margin from the left of the radar diagram. + type: number + minimum: 0 + default: 50 + axisScaleFactor: + description: The scale factor of the axis. + type: number + minimum: 0 + default: 1 + axisLabelFactor: + description: The scale factor of the axis label. + type: number + minimum: 0 + default: 1.05 + curveTension: + description: The tension factor for the Catmull-Rom spline conversion to cubic BÊzier curves. + type: number + minimum: 0 + maximum: 1 + default: 0.17 + FontCalculator: title: Font Calculator description: | diff --git a/packages/mermaid/src/styles.spec.ts b/packages/mermaid/src/styles.spec.ts index 698b2beaf..8c5263edc 100644 --- a/packages/mermaid/src/styles.spec.ts +++ b/packages/mermaid/src/styles.spec.ts @@ -29,9 +29,10 @@ import timeline from './diagrams/timeline/styles.js'; import mindmap from './diagrams/mindmap/styles.js'; import packet from './diagrams/packet/styles.js'; import block from './diagrams/block/styles.js'; +import radar from './diagrams/radar/styles.js'; import themes from './themes/index.js'; -async function checkValidStylisCSSStyleSheet(stylisString: string) { +function checkValidStylisCSSStyleSheet(stylisString: string) { const cssString = serialize(compile(`#my-svg-id{${stylisString}}`), stringify); const errors = validate(cssString, 'this-file-was-created-by-tests.css') as Error[]; @@ -51,6 +52,7 @@ async function checkValidStylisCSSStyleSheet(stylisString: string) { if (unexpectedErrors.length > 0) { throw new Error( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `The given CSS string was invalid: ${errors}.\n\n` + 'Copy the below CSS into https://jigsaw.w3.org/css-validator/validator to help debug where the invalid CSS is:\n\n' + `Original CSS value was ${cssString}` @@ -75,7 +77,7 @@ describe('styles', () => { const styles = getStyles(diagramType, '', getConfig().themeVariables); - await checkValidStylisCSSStyleSheet(styles); + checkValidStylisCSSStyleSheet(styles); }); /** @@ -98,6 +100,7 @@ describe('styles', () => { block, timeline, packet, + radar, })) { test(`should return a valid style for diagram ${diagramId} and theme ${themeId}`, async () => { const { default: getStyles, addStylesForDiagram } = await import('./styles.js'); @@ -110,7 +113,7 @@ describe('styles', () => { themes[themeId].getThemeVariables() ); - await checkValidStylisCSSStyleSheet(styles); + checkValidStylisCSSStyleSheet(styles); }); } } diff --git a/packages/mermaid/src/styles.ts b/packages/mermaid/src/styles.ts index fde079450..2cb11f146 100644 --- a/packages/mermaid/src/styles.ts +++ b/packages/mermaid/src/styles.ts @@ -17,8 +17,8 @@ const getStyles = ( } & FlowChartStyleOptions ) => { let diagramStyles = ''; - if (type in themes && themes[type as keyof typeof themes]) { - diagramStyles = themes[type as keyof typeof themes](options); + if (type in themes && themes[type]) { + diagramStyles = themes[type](options); } else { log.warn(`No theme found for ${type}`); } @@ -27,7 +27,28 @@ const getStyles = ( font-size: ${options.fontSize}; fill: ${options.textColor} } - + @keyframes edge-animation-frame { + from { + stroke-dashoffset: 0; + } + } + @keyframes dash { + to { + stroke-dashoffset: 0; + } + } + & .edge-animation-slow { + stroke-dasharray: 9,5 !important; + stroke-dashoffset: 900; + animation: dash 50s linear infinite; + stroke-linecap: round; + } + & .edge-animation-fast { + stroke-dasharray: 9,5 !important; + stroke-dashoffset: 900; + animation: dash 20s linear infinite; + stroke-linecap: round; + } /* Classes common for multiple diagrams */ & .error-icon { @@ -39,7 +60,7 @@ const getStyles = ( } & .edge-thickness-normal { - stroke-width: 2px; + stroke-width: 1px; } & .edge-thickness-thick { stroke-width: 3.5px @@ -47,7 +68,10 @@ const getStyles = ( & .edge-pattern-solid { stroke-dasharray: 0; } - + & .edge-thickness-invisible { + stroke-width: 0; + fill: none; + } & .edge-pattern-dashed{ stroke-dasharray: 3; } @@ -67,6 +91,9 @@ const getStyles = ( font-family: ${options.fontFamily}; font-size: ${options.fontSize}; } + & p { + margin: 0 + } ${diagramStyles} diff --git a/packages/mermaid/src/tests/MockedD3.ts b/packages/mermaid/src/tests/MockedD3.ts index 2f00e4924..019aed124 100644 --- a/packages/mermaid/src/tests/MockedD3.ts +++ b/packages/mermaid/src/tests/MockedD3.ts @@ -51,7 +51,7 @@ export class MockedD3 { }); // NOTE: The d3 implementation allows for a selector ('beforeSelector' arg below). - // With this mocked implementation, we assume it will always refer to an node id + // With this mocked implementation, we assume it will always refer to a node id // and will always be of the form "#[id of the node to insert before]". // To keep this simple, any leading '#' is removed and the resulting string is the node id searched. insert = (type: string, beforeSelector?: string, id = this.id + '-inserted'): MockedD3 => { @@ -60,7 +60,7 @@ export class MockedD3 { if (beforeSelector === undefined) { this._children.push(newMock); } else { - const idOnly = beforeSelector[0] == '#' ? beforeSelector.substring(1) : beforeSelector; + const idOnly = beforeSelector.startsWith('#') ? beforeSelector.substring(1) : beforeSelector; const foundIndex = this._children.findIndex((child) => child.id === idOnly); if (foundIndex < 0) { this._children.push(newMock); @@ -104,7 +104,10 @@ export class MockedD3 { // This allows different tests to succeed -- some need a top level 'svg' and some need a 'svg' element to be the firstChild // Real implementation returns an HTML Element public node = vi.fn().mockImplementation(() => { + //create a top level svg element const topElem = this._containingHTMLdoc.createElement('svg'); + //@ts-ignore - this is a mock SVG element + topElem.getBBox = this.getBBox; const elem_svgChild = this._containingHTMLdoc.createElement('svg'); // another svg element topElem.appendChild(elem_svgChild); return topElem; diff --git a/packages/mermaid/src/themes/theme-base.js b/packages/mermaid/src/themes/theme-base.js index dde3b9ecf..73ffef070 100644 --- a/packages/mermaid/src/themes/theme-base.js +++ b/packages/mermaid/src/themes/theme-base.js @@ -1,9 +1,9 @@ -import { darken, lighten, adjust, invert, isDark, toRgba } from 'khroma'; -import { mkBorder } from './theme-helpers.js'; +import { adjust, darken, invert, isDark, lighten } from 'khroma'; import { oldAttributeBackgroundColorEven, oldAttributeBackgroundColorOdd, } from './erDiagram-oldHardcodedValues.js'; +import { mkBorder } from './theme-helpers.js'; class Theme { constructor() { @@ -110,6 +110,16 @@ class Theme { this.personBorder = this.personBorder || this.primaryBorderColor; this.personBkg = this.personBkg || this.mainBkg; + /* ER diagram */ + + if (this.darkMode) { + this.rowOdd = this.rowOdd || darken(this.mainBkg, 5) || '#ffffff'; + this.rowEven = this.rowEven || darken(this.mainBkg, 10); + } else { + this.rowOdd = this.rowOdd || lighten(this.mainBkg, 75) || '#ffffff'; + this.rowEven = this.rowEven || lighten(this.mainBkg, 5); + } + /* state colors */ this.transitionColor = this.transitionColor || this.lineColor; this.transitionLabelColor = this.transitionLabelColor || this.textColor; @@ -220,6 +230,27 @@ class Theme { this.pieOuterStrokeColor = this.pieOuterStrokeColor || 'black'; this.pieOpacity = this.pieOpacity || '0.7'; + /* radar */ + this.radar = { + axisColor: this.radar?.axisColor || this.lineColor, + axisStrokeWidth: this.radar?.axisStrokeWidth || 2, + axisLabelFontSize: this.radar?.axisLabelFontSize || 12, + curveOpacity: this.radar?.curveOpacity || 0.5, + curveStrokeWidth: this.radar?.curveStrokeWidth || 2, + graticuleColor: this.radar?.graticuleColor || '#DEDEDE', + graticuleStrokeWidth: this.radar?.graticuleStrokeWidth || 1, + graticuleOpacity: this.radar?.graticuleOpacity || 0.3, + legendBoxSize: this.radar?.legendBoxSize || 12, + legendFontSize: this.radar?.legendFontSize || 12, + }; + + /* architecture */ + this.archEdgeColor = this.archEdgeColor || '#777'; + this.archEdgeArrowColor = this.archEdgeArrowColor || '#777'; + this.archEdgeWidth = this.archEdgeWidth || '3'; + this.archGroupBorderColor = this.archGroupBorderColor || '#000'; + this.archGroupBorderWidth = this.archGroupBorderWidth || '2px'; + /* quadrant-graph */ this.quadrant1Fill = this.quadrant1Fill || this.primaryColor; this.quadrant2Fill = this.quadrant2Fill || adjust(this.primaryColor, { r: 5, g: 5, b: 5 }); diff --git a/packages/mermaid/src/themes/theme-dark.js b/packages/mermaid/src/themes/theme-dark.js index 02104a0ea..c452eea9f 100644 --- a/packages/mermaid/src/themes/theme-dark.js +++ b/packages/mermaid/src/themes/theme-dark.js @@ -6,7 +6,6 @@ class Theme { this.background = '#333'; this.primaryColor = '#1f2020'; this.secondaryColor = lighten(this.primaryColor, 16); - this.tertiaryColor = adjust(this.primaryColor, { h: -160 }); this.primaryBorderColor = invert(this.background); this.secondaryBorderColor = mkBorder(this.secondaryColor, this.darkMode); @@ -22,7 +21,7 @@ class Theme { this.mainContrastColor = 'lightgrey'; this.darkTextColor = lighten(invert('#323D47'), 10); this.lineColor = 'calculated'; - this.border1 = '#81B1DB'; + this.border1 = '#ccc'; this.border2 = rgba(255, 255, 255, 0.25); this.arrowheadColor = 'calculated'; this.fontFamily = '"trebuchet ms", verdana, arial, sans-serif'; @@ -85,6 +84,17 @@ class Theme { this.personBorder = this.primaryBorderColor; this.personBkg = this.mainBkg; + /* Architecture Diagram variables */ + this.archEdgeColor = 'calculated'; + this.archEdgeArrowColor = 'calculated'; + this.archEdgeWidth = '3'; + this.archGroupBorderColor = this.primaryBorderColor; + this.archGroupBorderWidth = '2px'; + + /* Entity Relationship variables */ + this.rowOdd = this.rowOdd || lighten(this.mainBkg, 5) || '#ffffff'; + this.rowEven = this.rowEven || darken(this.mainBkg, 10); + /* state colors */ this.labelColor = 'calculated'; @@ -133,6 +143,10 @@ class Theme { this.doneTaskBkgColor = this.mainContrastColor; this.taskTextDarkColor = this.darkTextColor; + /* Architecture Diagram variables */ + this.archEdgeColor = this.lineColor; + this.archEdgeArrowColor = this.lineColor; + /* state colors */ this.transitionColor = this.transitionColor || this.lineColor; this.transitionLabelColor = this.transitionLabelColor || this.textColor; @@ -277,6 +291,20 @@ class Theme { blockFillColor: this.background, }; + /* radar */ + this.radar = { + axisColor: this.radar?.axisColor || this.lineColor, + axisStrokeWidth: this.radar?.axisStrokeWidth || 2, + axisLabelFontSize: this.radar?.axisLabelFontSize || 12, + curveOpacity: this.radar?.curveOpacity || 0.5, + curveStrokeWidth: this.radar?.curveStrokeWidth || 2, + graticuleColor: this.radar?.graticuleColor || '#DEDEDE', + graticuleStrokeWidth: this.radar?.graticuleStrokeWidth || 1, + graticuleOpacity: this.radar?.graticuleOpacity || 0.3, + legendBoxSize: this.radar?.legendBoxSize || 12, + legendFontSize: this.radar?.legendFontSize || 12, + }; + /* class */ this.classText = this.primaryTextColor; @@ -333,6 +361,8 @@ class Theme { this.attributeBackgroundColorEven = this.attributeBackgroundColorEven || lighten(this.background, 2); /* -------------------------------------------------- */ + + this.nodeBorder = this.nodeBorder || '#999'; } calculate(overrides) { if (typeof overrides !== 'object') { diff --git a/packages/mermaid/src/themes/theme-default.js b/packages/mermaid/src/themes/theme-default.js index d95ccf59e..eba3ff101 100644 --- a/packages/mermaid/src/themes/theme-default.js +++ b/packages/mermaid/src/themes/theme-default.js @@ -34,7 +34,7 @@ class Theme { this.arrowheadColor = '#333333'; this.fontFamily = '"trebuchet ms", verdana, arial, sans-serif'; this.fontSize = '16px'; - this.labelBackground = '#e8e8e8'; + this.labelBackground = 'rgba(232,232,232, 0.8)'; this.textColor = '#333'; this.THEME_COLOR_LIMIT = 12; @@ -112,6 +112,17 @@ class Theme { this.personBorder = this.primaryBorderColor; this.personBkg = this.mainBkg; + /* Architecture Diagram variables */ + this.archEdgeColor = 'calculated'; + this.archEdgeArrowColor = 'calculated'; + this.archEdgeWidth = '3'; + this.archGroupBorderColor = this.primaryBorderColor; + this.archGroupBorderWidth = '2px'; + + /* Entity Relationship variables */ + this.rowOdd = 'calculated'; + this.rowEven = 'calculated'; + /* state colors */ this.labelColor = 'black'; this.errorBkgColor = '#552222'; @@ -194,6 +205,13 @@ class Theme { this.taskTextColor = this.taskTextLightColor; this.taskTextOutsideColor = this.taskTextDarkColor; + /* Architecture Diagram variables */ + this.archEdgeColor = this.lineColor; + this.archEdgeArrowColor = this.lineColor; + + /* Entity Relationship variables */ + this.rowOdd = this.rowOdd || lighten(this.primaryColor, 75) || '#ffffff'; + this.rowEven = this.rowEven || lighten(this.primaryColor, 1); /* state colors */ this.transitionColor = this.transitionColor || this.lineColor; this.transitionLabelColor = this.transitionLabelColor || this.textColor; @@ -273,6 +291,20 @@ class Theme { this.quadrantExternalBorderStrokeFill || this.primaryBorderColor; this.quadrantTitleFill = this.quadrantTitleFill || this.primaryTextColor; + /* radar */ + this.radar = { + axisColor: this.radar?.axisColor || this.lineColor, + axisStrokeWidth: this.radar?.axisStrokeWidth || 2, + axisLabelFontSize: this.radar?.axisLabelFontSize || 12, + curveOpacity: this.radar?.curveOpacity || 0.5, + curveStrokeWidth: this.radar?.curveStrokeWidth || 2, + graticuleColor: this.radar?.graticuleColor || '#DEDEDE', + graticuleStrokeWidth: this.radar?.graticuleStrokeWidth || 1, + graticuleOpacity: this.radar?.graticuleOpacity || 0.3, + legendBoxSize: this.radar?.legendBoxSize || 12, + legendFontSize: this.radar?.legendFontSize || 12, + }; + /* xychart */ this.xyChart = { backgroundColor: this.xyChart?.backgroundColor || this.background, @@ -362,6 +394,13 @@ class Theme { /* -------------------------------------------------- */ } calculate(overrides) { + // for all keys in this object, if it is 'calculated' then set it to undefined + Object.keys(this).forEach((k) => { + if (this[k] === 'calculated') { + this[k] = undefined; + } + }); + if (typeof overrides !== 'object') { // Calculate colors form base colors this.updateColors(); diff --git a/packages/mermaid/src/themes/theme-forest.js b/packages/mermaid/src/themes/theme-forest.js index 4bb7d2441..853b4d032 100644 --- a/packages/mermaid/src/themes/theme-forest.js +++ b/packages/mermaid/src/themes/theme-forest.js @@ -86,6 +86,13 @@ class Theme { this.personBorder = this.primaryBorderColor; this.personBkg = this.mainBkg; + /* Architecture Diagram variables */ + this.archEdgeColor = 'calculated'; + this.archEdgeArrowColor = 'calculated'; + this.archEdgeWidth = '3'; + this.archGroupBorderColor = this.primaryBorderColor; + this.archGroupBorderWidth = '2px'; + /* state colors */ this.labelColor = 'black'; @@ -162,6 +169,14 @@ class Theme { this.activeTaskBorderColor = this.taskBorderColor; this.activeTaskBkgColor = this.mainBkg; + /* Architecture Diagram variables */ + this.archEdgeColor = this.lineColor; + this.archEdgeArrowColor = this.lineColor; + + /* ER diagram */ + this.rowOdd = this.rowOdd || lighten(this.mainBkg, 75) || '#ffffff'; + this.rowEven = this.rowEven || lighten(this.mainBkg, 20); + /* state colors */ this.transitionColor = this.transitionColor || this.lineColor; this.transitionLabelColor = this.transitionLabelColor || this.textColor; @@ -250,6 +265,20 @@ class Theme { blockFillColor: this.mainBkg, }; + /* radar */ + this.radar = { + axisColor: this.radar?.axisColor || this.lineColor, + axisStrokeWidth: this.radar?.axisStrokeWidth || 2, + axisLabelFontSize: this.radar?.axisLabelFontSize || 12, + curveOpacity: this.radar?.curveOpacity || 0.5, + curveStrokeWidth: this.radar?.curveStrokeWidth || 2, + graticuleColor: this.radar?.graticuleColor || '#DEDEDE', + graticuleStrokeWidth: this.radar?.graticuleStrokeWidth || 1, + graticuleOpacity: this.radar?.graticuleOpacity || 0.3, + legendBoxSize: this.radar?.legendBoxSize || 12, + legendFontSize: this.radar?.legendFontSize || 12, + }; + /* xychart */ this.xyChart = { backgroundColor: this.xyChart?.backgroundColor || this.background, diff --git a/packages/mermaid/src/themes/theme-neutral.js b/packages/mermaid/src/themes/theme-neutral.js index 4134a985b..633a26849 100644 --- a/packages/mermaid/src/themes/theme-neutral.js +++ b/packages/mermaid/src/themes/theme-neutral.js @@ -98,6 +98,17 @@ class Theme { this.personBorder = this.primaryBorderColor; this.personBkg = this.mainBkg; + /* Architecture Diagram variables */ + this.archEdgeColor = 'calculated'; + this.archEdgeArrowColor = 'calculated'; + this.archEdgeWidth = '3'; + this.archGroupBorderColor = this.primaryBorderColor; + this.archGroupBorderWidth = '2px'; + + /* ER diagram */ + this.rowOdd = this.rowOdd || lighten(this.mainBkg, 75) || '#ffffff'; + this.rowEven = this.rowEven || '#f4f4f4'; + /* state colors */ this.labelColor = 'black'; @@ -156,8 +167,8 @@ class Theme { // Setup the label color for the set this.scaleLabelColor = this.scaleLabelColor || (this.darkMode ? 'black' : this.labelTextColor); - this['cScaleLabel0'] = this['cScaleLabel0'] || this.cScale1; - this['cScaleLabel2'] = this['cScaleLabel2'] || this.cScale1; + this.cScaleLabel0 = this.cScaleLabel0 || this.cScale1; + this.cScaleLabel2 = this.cScaleLabel2 || this.cScale1; for (let i = 0; i < this.THEME_COLOR_LIMIT; i++) { this['cScaleLabel' + i] = this['cScaleLabel' + i] || this.scaleLabelColor; } @@ -199,6 +210,10 @@ class Theme { this.todayLineColor = this.critBkgColor; + /* Architecture Diagram variables */ + this.archEdgeColor = this.lineColor; + this.archEdgeArrowColor = this.lineColor; + /* state colors */ this.transitionColor = this.transitionColor || '#000'; this.transitionLabelColor = this.transitionLabelColor || this.textColor; @@ -288,6 +303,20 @@ class Theme { '#EEE,#6BB8E4,#8ACB88,#C7ACD6,#E8DCC2,#FFB2A8,#FFF380,#7E8D91,#FFD8B1,#FAF3E0', }; + /* radar */ + this.radar = { + axisColor: this.radar?.axisColor || this.lineColor, + axisStrokeWidth: this.radar?.axisStrokeWidth || 2, + axisLabelFontSize: this.radar?.axisLabelFontSize || 12, + curveOpacity: this.radar?.curveOpacity || 0.5, + curveStrokeWidth: this.radar?.curveStrokeWidth || 2, + graticuleColor: this.radar?.graticuleColor || '#DEDEDE', + graticuleStrokeWidth: this.radar?.graticuleStrokeWidth || 1, + graticuleOpacity: this.radar?.graticuleOpacity || 0.3, + legendBoxSize: this.radar?.legendBoxSize || 12, + legendFontSize: this.radar?.legendFontSize || 12, + }; + /* requirement-diagram */ this.requirementBackground = this.requirementBackground || this.primaryColor; this.requirementBorderColor = this.requirementBorderColor || this.primaryBorderColor; diff --git a/packages/mermaid/src/types.ts b/packages/mermaid/src/types.ts index 487e089dc..fdccae677 100644 --- a/packages/mermaid/src/types.ts +++ b/packages/mermaid/src/types.ts @@ -1,3 +1,24 @@ +export interface NodeMetaData { + shape?: string; + label?: string; + icon?: string; + form?: string; + pos?: 't' | 'b'; + img?: string; + w?: string; + h?: string; + constraint?: 'on' | 'off'; + priority: 'Very High' | 'High' | 'Medium' | 'Low' | 'Very Low'; + assigned?: string; + ticket?: string; +} + +export interface EdgeMetaData { + animation?: 'fast' | 'slow'; + animate?: boolean; +} +import type { MermaidConfig } from './config.type.js'; + export interface Point { x: number; y: number; @@ -34,3 +55,57 @@ export interface EdgeData { } export type ArrayElement = A extends readonly (infer T)[] ? T : never; + +export interface ParseOptions { + /** + * If `true`, parse will return `false` instead of throwing error when the diagram is invalid. + * The `parseError` function will not be called. + */ + suppressErrors?: boolean; +} + +export interface ParseResult { + /** + * The diagram type, e.g. 'flowchart', 'sequence', etc. + */ + diagramType: string; + /** + * The config passed as YAML frontmatter or directives + */ + config: MermaidConfig; +} +// This makes it clear that we're working with a d3 selected element of some kind, even though it's hard to specify the exact type. +export type D3Element = any; + +/** + * Helper type for d3 selections. + */ +export type D3Selection = d3.Selection; + +export interface RenderResult { + /** + * The svg code for the rendered graph. + */ + svg: string; + /** + * The diagram type, e.g. 'flowchart', 'sequence', etc. + */ + diagramType: string; + /** + * Bind function to be called after the svg has been inserted into the DOM. + * This is necessary for adding event listeners to the elements in the svg. + * ```js + * const { svg, bindFunctions } = await mermaid.render('id1', 'graph TD;A-->B'); + * div.innerHTML = svg; + * bindFunctions?.(div); // To call bindFunctions only if it's present. + * ``` + */ + bindFunctions?: (element: Element) => void; +} + +/** + * Can be converted back to `T` by awaiting/`Awaited`. + * + * This is useful for function types that may be either synchronous or asynchronous. + */ +export type MaybePromise = T | Promise; diff --git a/packages/mermaid/src/utils.ts b/packages/mermaid/src/utils.ts index 06aca5ab2..6ed935cf6 100644 --- a/packages/mermaid/src/utils.ts +++ b/packages/mermaid/src/utils.ts @@ -1,5 +1,5 @@ import { sanitizeUrl } from '@braintree/sanitize-url'; -import type { CurveFactory } from 'd3'; +import type { BaseType, CurveFactory } from 'd3'; import { curveBasis, curveBasisClosed, @@ -32,8 +32,7 @@ import type { MermaidConfig } from './config.type.js'; import memoize from 'lodash-es/memoize.js'; import merge from 'lodash-es/merge.js'; import { directiveRegex } from './diagram-api/regexes.js'; -import type { D3Element } from './mermaidAPI.js'; -import type { Point, TextDimensionConfig, TextDimensions } from './types.js'; +import type { D3Element, Point, TextDimensionConfig, TextDimensions } from './types.js'; export const ZERO_WIDTH_SPACE = '\u200b'; @@ -178,11 +177,7 @@ export const detectDirective = function ( if (match.index === directiveRegex.lastIndex) { directiveRegex.lastIndex++; } - if ( - (match && !type) || - (type && match[1] && match[1].match(type)) || - (type && match[2] && match[2].match(type)) - ) { + if ((match && !type) || (type && match[1]?.match(type)) || (type && match[2]?.match(type))) { const type = match[1] ? match[1] : match[2]; const args = match[3] ? match[3].trim() : match[4] ? JSON.parse(match[4].trim()) : null; result.push({ type, args }); @@ -342,6 +337,9 @@ export const calculatePoint = (points: Point[], distanceToTraverse: number): Poi for (const point of points) { if (prevPoint) { const vectorDistance = distance(point, prevPoint); + if (vectorDistance === 0) { + return prevPoint; + } if (vectorDistance < remainingDistance) { remainingDistance -= vectorDistance; } else { @@ -572,7 +570,7 @@ export const wrapLabel: (label: string, maxWidth: number, config: WrapLabelConfi if (common.lineBreakRegex.test(label)) { return label; } - const words = label.split(' '); + const words = label.split(' ').filter(Boolean); const completedLines: string[] = []; let nextLine = ''; words.forEach((word, index) => { @@ -647,7 +645,7 @@ const breakString: ( * This calculates the text's height, taking into account the wrap breaks and both the statically * configured height, width, and the length of the text (in pixels). * - * If the wrapped text text has greater height, we extend the height, so it's value won't overflow. + * If the wrapped text has greater height, we extend the height, so it's value won't overflow. * * @param text - The text to measure * @param config - The config for fontSize, fontFamily, and fontWeight all impacting the @@ -778,7 +776,7 @@ export const entityDecode = function (html: string): string { // Escape HTML before decoding for HTML Entities html = escape(html).replace(/%26/g, '&').replace(/%23/g, '#').replace(/%3B/g, ';'); decoder.innerHTML = html; - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return unescape(decoder.textContent!); }; @@ -829,6 +827,7 @@ export const insertTitle = ( parent .append('text') .text(title) + .attr('text-anchor', 'middle') .attr('x', bounds.x + bounds.width / 2) .attr('y', -titleTopMargin) .attr('class', cssClass); @@ -929,3 +928,35 @@ export const decodeEntities = function (text: string): string { export const isString = (value: unknown): value is string => { return typeof value === 'string'; }; + +export const getEdgeId = ( + from: string, + to: string, + { + counter = 0, + prefix, + suffix, + }: { + counter?: number; + prefix?: string; + suffix?: string; + }, + id?: string +) => { + if (id) { + return id; + } + return `${prefix ? `${prefix}_` : ''}${from}_${to}_${counter}${suffix ? `_${suffix}` : ''}`; +}; + +/** + * D3's `selection.attr` method doesn't officially support `undefined`. + * + * However, it seems if you do pass `undefined`, it seems to be treated as `null` + * (e.g. it removes the attribute). + */ +export function handleUndefinedAttr( + attrValue: Parameters['attr']>[1] | undefined +) { + return attrValue ?? null; +} diff --git a/packages/mermaid/src/utils/base64.ts b/packages/mermaid/src/utils/base64.ts new file mode 100644 index 000000000..4a0f5b295 --- /dev/null +++ b/packages/mermaid/src/utils/base64.ts @@ -0,0 +1,6 @@ +export function toBase64(str: string) { + // ref: https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem + const utf8Bytes = new TextEncoder().encode(str); + const utf8Str = Array.from(utf8Bytes, (byte) => String.fromCodePoint(byte)).join(''); + return btoa(utf8Str); +} diff --git a/packages/mermaid/src/utils/lineWithOffset.ts b/packages/mermaid/src/utils/lineWithOffset.ts index af0cd3b46..800a5ffaf 100644 --- a/packages/mermaid/src/utils/lineWithOffset.ts +++ b/packages/mermaid/src/utils/lineWithOffset.ts @@ -9,7 +9,7 @@ const markerOffsets = { composition: 18, dependency: 6, lollipop: 13.5, - arrow_point: 5.3, + arrow_point: 4, } as const; /** @@ -45,20 +45,22 @@ export const getLineFunctionsWithOffset = ( edge: Pick ) => { return { - x: function (d: Point | [number, number], i: number, data: (Point | [number, number])[]) { + x: function ( + this: void, + d: Point | [number, number], + i: number, + data: (Point | [number, number])[] + ) { let offset = 0; + const DIRECTION = + pointTransformer(data[0]).x < pointTransformer(data[data.length - 1]).x ? 'left' : 'right'; if (i === 0 && Object.hasOwn(markerOffsets, edge.arrowTypeStart)) { - // Handle first point - // Calculate the angle and delta between the first two points const { angle, deltaX } = calculateDeltaAndAngle(data[0], data[1]); - // Calculate the offset based on the angle and the marker's dimensions offset = markerOffsets[edge.arrowTypeStart as keyof typeof markerOffsets] * Math.cos(angle) * (deltaX >= 0 ? 1 : -1); } else if (i === data.length - 1 && Object.hasOwn(markerOffsets, edge.arrowTypeEnd)) { - // Handle last point - // Calculate the angle and delta between the last two points const { angle, deltaX } = calculateDeltaAndAngle( data[data.length - 1], data[data.length - 2] @@ -68,11 +70,52 @@ export const getLineFunctionsWithOffset = ( Math.cos(angle) * (deltaX >= 0 ? 1 : -1); } + + const differenceToEnd = Math.abs( + pointTransformer(d).x - pointTransformer(data[data.length - 1]).x + ); + const differenceInYEnd = Math.abs( + pointTransformer(d).y - pointTransformer(data[data.length - 1]).y + ); + const differenceToStart = Math.abs(pointTransformer(d).x - pointTransformer(data[0]).x); + const differenceInYStart = Math.abs(pointTransformer(d).y - pointTransformer(data[0]).y); + const startMarkerHeight = markerOffsets[edge.arrowTypeStart as keyof typeof markerOffsets]; + const endMarkerHeight = markerOffsets[edge.arrowTypeEnd as keyof typeof markerOffsets]; + const extraRoom = 1; + + // Adjust the offset if the difference is smaller than the marker height + if ( + differenceToEnd < endMarkerHeight && + differenceToEnd > 0 && + differenceInYEnd < endMarkerHeight + ) { + let adjustment = endMarkerHeight + extraRoom - differenceToEnd; + adjustment *= DIRECTION === 'right' ? -1 : 1; + // Adjust the offset by the amount needed to fit the marker + offset -= adjustment; + } + + if ( + differenceToStart < startMarkerHeight && + differenceToStart > 0 && + differenceInYStart < startMarkerHeight + ) { + let adjustment = startMarkerHeight + extraRoom - differenceToStart; + adjustment *= DIRECTION === 'right' ? -1 : 1; + offset += adjustment; + } + return pointTransformer(d).x + offset; }, - y: function (d: Point | [number, number], i: number, data: (Point | [number, number])[]) { - // Same handling as X above + y: function ( + this: void, + d: Point | [number, number], + i: number, + data: (Point | [number, number])[] + ) { let offset = 0; + const DIRECTION = + pointTransformer(data[0]).y < pointTransformer(data[data.length - 1]).y ? 'down' : 'up'; if (i === 0 && Object.hasOwn(markerOffsets, edge.arrowTypeStart)) { const { angle, deltaY } = calculateDeltaAndAngle(data[0], data[1]); offset = @@ -89,6 +132,40 @@ export const getLineFunctionsWithOffset = ( Math.abs(Math.sin(angle)) * (deltaY >= 0 ? 1 : -1); } + + const differenceToEnd = Math.abs( + pointTransformer(d).y - pointTransformer(data[data.length - 1]).y + ); + const differenceInXEnd = Math.abs( + pointTransformer(d).x - pointTransformer(data[data.length - 1]).x + ); + const differenceToStart = Math.abs(pointTransformer(d).y - pointTransformer(data[0]).y); + const differenceInXStart = Math.abs(pointTransformer(d).x - pointTransformer(data[0]).x); + const startMarkerHeight = markerOffsets[edge.arrowTypeStart as keyof typeof markerOffsets]; + const endMarkerHeight = markerOffsets[edge.arrowTypeEnd as keyof typeof markerOffsets]; + const extraRoom = 1; + + // Adjust the offset if the difference is smaller than the marker height + if ( + differenceToEnd < endMarkerHeight && + differenceToEnd > 0 && + differenceInXEnd < endMarkerHeight + ) { + let adjustment = endMarkerHeight + extraRoom - differenceToEnd; + adjustment *= DIRECTION === 'up' ? -1 : 1; + // Adjust the offset by the amount needed to fit the marker + offset -= adjustment; + } + + if ( + differenceToStart < startMarkerHeight && + differenceToStart > 0 && + differenceInXStart < startMarkerHeight + ) { + let adjustment = startMarkerHeight + extraRoom - differenceToStart; + adjustment *= DIRECTION === 'up' ? -1 : 1; + offset += adjustment; + } return pointTransformer(d).y + offset; }, }; diff --git a/packages/mermaid/tsconfig.eslint.json b/packages/mermaid/tsconfig.eslint.json new file mode 100644 index 000000000..9df160d20 --- /dev/null +++ b/packages/mermaid/tsconfig.eslint.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": ["./tsconfig.json"], + "compilerOptions": { + "noEmit": true + }, + "include": [ + "./src/**/*.spec.js", + "./src/**/*.spec.ts", // test files + "./scripts", + "./.lintstagedrc.mjs" + ] +} diff --git a/packages/mermaid/tsconfig.json b/packages/mermaid/tsconfig.json index 78e3cf2de..447a5bb0d 100644 --- a/packages/mermaid/tsconfig.json +++ b/packages/mermaid/tsconfig.json @@ -5,5 +5,11 @@ "outDir": "./dist", "types": ["vitest/importMeta", "vitest/globals"] }, - "include": ["./src/**/*.ts", "./package.json"] + "include": [ + "./src/**/*.ts", + "./package.json", + "src/diagrams/gantt/ganttDb.js", + "src/diagrams/git/gitGraphRenderer.js", + "src/diagrams/class/classRenderer.js" + ] } diff --git a/packages/mermaid/typedoc.json b/packages/mermaid/typedoc.json index 971f6d562..5f1682f29 100644 --- a/packages/mermaid/typedoc.json +++ b/packages/mermaid/typedoc.json @@ -1,4 +1,5 @@ { + "$schema": "https://typedoc.org/schema.json", "plugin": ["typedoc-plugin-markdown"], "readme": "none", "githubPages": false, @@ -6,6 +7,5 @@ "gitRevision": "master", "out": "src/docs/config/setup", "entryPointStrategy": "expand", - "hideBreadcrumbs": true, - "hideInPageTOC": true + "hideBreadcrumbs": true } diff --git a/packages/parser/CHANGELOG.md b/packages/parser/CHANGELOG.md new file mode 100644 index 000000000..2dc2a3f36 --- /dev/null +++ b/packages/parser/CHANGELOG.md @@ -0,0 +1,37 @@ +# @mermaid-js/parser + +## 0.4.0 + +### Minor Changes + +- [#6381](https://github.com/mermaid-js/mermaid/pull/6381) [`95d73bc`](https://github.com/mermaid-js/mermaid/commit/95d73bc3f064dbf261a06483f94a7ef4d0bb52eb) Thanks [@thomascizeron](https://github.com/thomascizeron)! - Add Radar Chart + +## 0.3.0 + +### Minor Changes + +- [#5452](https://github.com/mermaid-js/mermaid/pull/5452) [`256a148`](https://github.com/mermaid-js/mermaid/commit/256a148bbf484fc7db6c19f94dd69d5d268ee048) Thanks [@NicolasNewman](https://github.com/NicolasNewman)! - New Diagram: Architecture + + Adds architecture diagrams which allows users to show relations between services. + +### Patch Changes + +- [#5793](https://github.com/mermaid-js/mermaid/pull/5793) [`7d8143b`](https://github.com/mermaid-js/mermaid/commit/7d8143b917ee3562149a0e0a821ed2d6f29cc05d) Thanks [@sidharthv96](https://github.com/sidharthv96)! - feat: Support - in architecture icons + +## 0.2.0 + +### Minor Changes + +- [#5664](https://github.com/mermaid-js/mermaid/pull/5664) [`5deaef4`](https://github.com/mermaid-js/mermaid/commit/5deaef456e74d796866431c26f69360e4e74dbff) Thanks [@Austin-Fulbright](https://github.com/Austin-Fulbright)! - chore: Migrate git graph to langium, use typescript for internals + +## 0.1.1 + +### Patch Changes + +- [#5746](https://github.com/mermaid-js/mermaid/pull/5746) [`83926c9`](https://github.com/mermaid-js/mermaid/commit/83926c9707b09c34e300888186250191ee8ae30a) Thanks [@sidharthv96](https://github.com/sidharthv96)! - test changeset + +## 0.1.0 + +### Minor Changes + +- [#5744](https://github.com/mermaid-js/mermaid/pull/5744) [`5013484`](https://github.com/mermaid-js/mermaid/commit/50134849246141ec400e33e08c12c10539b84de9) Thanks [@sidharthv96](https://github.com/sidharthv96)! - Release parser, test changesets diff --git a/packages/parser/langium-config.json b/packages/parser/langium-config.json index c750f049d..ad80350c2 100644 --- a/packages/parser/langium-config.json +++ b/packages/parser/langium-config.json @@ -15,6 +15,21 @@ "id": "pie", "grammar": "src/language/pie/pie.langium", "fileExtensions": [".mmd", ".mermaid"] + }, + { + "id": "architecture", + "grammar": "src/language/architecture/architecture.langium", + "fileExtensions": [".mmd", ".mermaid"] + }, + { + "id": "gitGraph", + "grammar": "src/language/gitGraph/gitGraph.langium", + "fileExtensions": [".mmd", ".mermaid"] + }, + { + "id": "radar", + "grammar": "src/language/radar/radar.langium", + "fileExtensions": [".mmd", ".mermaid"] } ], "mode": "production", diff --git a/packages/parser/package.json b/packages/parser/package.json index b937e37b9..dcb526bfc 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -1,6 +1,6 @@ { "name": "@mermaid-js/parser", - "version": "0.1.0-rc.1", + "version": "0.4.0", "description": "MermaidJS parser", "author": "Yokozuna59", "contributors": [ @@ -19,8 +19,7 @@ "scripts": { "clean": "rimraf dist src/language/generated", "langium:generate": "langium generate", - "langium:watch": "langium generate --watch", - "prepublishOnly": "pnpm -w run build" + "langium:watch": "langium generate --watch" }, "repository": { "type": "git", @@ -34,7 +33,7 @@ "ast" ], "dependencies": { - "langium": "3.0.0" + "langium": "3.3.1" }, "devDependencies": { "chevrotain": "^11.0.3" diff --git a/packages/parser/src/language/architecture/arch.langium b/packages/parser/src/language/architecture/arch.langium new file mode 100644 index 000000000..7b3a2fe22 --- /dev/null +++ b/packages/parser/src/language/architecture/arch.langium @@ -0,0 +1,2 @@ +terminal ARCH_ICON: /\([\w-:]+\)/; +terminal ARCH_TITLE: /\[[\w ]+\]/; \ No newline at end of file diff --git a/packages/parser/src/language/architecture/architecture.langium b/packages/parser/src/language/architecture/architecture.langium new file mode 100644 index 000000000..2e97372bd --- /dev/null +++ b/packages/parser/src/language/architecture/architecture.langium @@ -0,0 +1,52 @@ +grammar Architecture +import "../common/common"; +import "arch"; + +entry Architecture: + NEWLINE* + "architecture-beta" + ( + NEWLINE + | TitleAndAccessibilities + | Statement + )* +; + +fragment Statement: + groups+=Group + | services+=Service + | junctions+=Junction + | edges+=Edge +; + +fragment LeftPort: + ':'lhsDir=ARROW_DIRECTION +; + +fragment RightPort: + rhsDir=ARROW_DIRECTION':' +; + +fragment Arrow: + LeftPort lhsInto?=ARROW_INTO? ('--' | '-' title=ARCH_TITLE '-') rhsInto?=ARROW_INTO? RightPort +; + +Group: + 'group' id=ID icon=ARCH_ICON? title=ARCH_TITLE? ('in' in=ID)? EOL +; + +Service: + 'service' id=ID (iconText=STRING | icon=ARCH_ICON)? title=ARCH_TITLE? ('in' in=ID)? EOL +; + +Junction: + 'junction' id=ID ('in' in=ID)? EOL +; + +Edge: + lhsId=ID lhsGroup?=ARROW_GROUP? Arrow rhsId=ID rhsGroup?=ARROW_GROUP? EOL +; + +terminal ARROW_DIRECTION: 'L' | 'R' | 'T' | 'B'; +terminal ARROW_GROUP: /\{group\}/; +terminal ARROW_INTO: /<|>/; diff --git a/packages/parser/src/language/architecture/index.ts b/packages/parser/src/language/architecture/index.ts new file mode 100644 index 000000000..fd3c604b0 --- /dev/null +++ b/packages/parser/src/language/architecture/index.ts @@ -0,0 +1 @@ +export * from './module.js'; diff --git a/packages/parser/src/language/architecture/module.ts b/packages/parser/src/language/architecture/module.ts new file mode 100644 index 000000000..d4e730c2c --- /dev/null +++ b/packages/parser/src/language/architecture/module.ts @@ -0,0 +1,79 @@ +import type { + DefaultSharedCoreModuleContext, + LangiumCoreServices, + LangiumSharedCoreServices, + Module, + PartialLangiumCoreServices, +} from 'langium'; +import { + EmptyFileSystem, + createDefaultCoreModule, + createDefaultSharedCoreModule, + inject, +} from 'langium'; + +import { MermaidGeneratedSharedModule, ArchitectureGeneratedModule } from '../generated/module.js'; +import { ArchitectureTokenBuilder } from './tokenBuilder.js'; +import { ArchitectureValueConverter } from './valueConverter.js'; + +/** + * Declaration of `Architecture` services. + */ +interface ArchitectureAddedServices { + parser: { + TokenBuilder: ArchitectureTokenBuilder; + ValueConverter: ArchitectureValueConverter; + }; +} + +/** + * Union of Langium default services and `Architecture` services. + */ +export type ArchitectureServices = LangiumCoreServices & ArchitectureAddedServices; + +/** + * Dependency injection module that overrides Langium default services and + * contributes the declared `Architecture` services. + */ +export const ArchitectureModule: Module< + ArchitectureServices, + PartialLangiumCoreServices & ArchitectureAddedServices +> = { + parser: { + TokenBuilder: () => new ArchitectureTokenBuilder(), + ValueConverter: () => new ArchitectureValueConverter(), + }, +}; + +/** + * Create the full set of services required by Langium. + * + * First inject the shared services by merging two modules: + * - Langium default shared services + * - Services generated by langium-cli + * + * Then inject the language-specific services by merging three modules: + * - Langium default language-specific services + * - Services generated by langium-cli + * - Services specified in this file + * @param context - Optional module context with the LSP connection + * @returns An object wrapping the shared services and the language-specific services + */ +export function createArchitectureServices( + context: DefaultSharedCoreModuleContext = EmptyFileSystem +): { + shared: LangiumSharedCoreServices; + Architecture: ArchitectureServices; +} { + const shared: LangiumSharedCoreServices = inject( + createDefaultSharedCoreModule(context), + MermaidGeneratedSharedModule + ); + const Architecture: ArchitectureServices = inject( + createDefaultCoreModule({ shared }), + ArchitectureGeneratedModule, + ArchitectureModule + ); + shared.ServiceRegistry.register(Architecture); + return { shared, Architecture }; +} diff --git a/packages/parser/src/language/architecture/tokenBuilder.ts b/packages/parser/src/language/architecture/tokenBuilder.ts new file mode 100644 index 000000000..6a7c6a37a --- /dev/null +++ b/packages/parser/src/language/architecture/tokenBuilder.ts @@ -0,0 +1,7 @@ +import { AbstractMermaidTokenBuilder } from '../common/index.js'; + +export class ArchitectureTokenBuilder extends AbstractMermaidTokenBuilder { + public constructor() { + super(['architecture']); + } +} diff --git a/packages/parser/src/language/architecture/valueConverter.ts b/packages/parser/src/language/architecture/valueConverter.ts new file mode 100644 index 000000000..c9475657b --- /dev/null +++ b/packages/parser/src/language/architecture/valueConverter.ts @@ -0,0 +1,20 @@ +import type { CstNode, GrammarAST, ValueType } from 'langium'; + +import { AbstractMermaidValueConverter } from '../common/index.js'; + +export class ArchitectureValueConverter extends AbstractMermaidValueConverter { + protected runCustomConverter( + rule: GrammarAST.AbstractRule, + input: string, + _cstNode: CstNode + ): ValueType | undefined { + if (rule.name === 'ARCH_ICON') { + return input.replace(/[()]/g, '').trim(); + } else if (rule.name === 'ARCH_TEXT_ICON') { + return input.replace(/["()]/g, ''); + } else if (rule.name === 'ARCH_TITLE') { + return input.replace(/[[\]]/g, '').trim(); + } + return undefined; + } +} diff --git a/packages/parser/src/language/common/common.langium b/packages/parser/src/language/common/common.langium index 7989de193..b74ffc34d 100644 --- a/packages/parser/src/language/common/common.langium +++ b/packages/parser/src/language/common/common.langium @@ -1,22 +1,35 @@ -interface Common { - accDescr?: string; - accTitle?: string; - title?: string; -} - -fragment TitleAndAccessibilities: - ((accDescr=ACC_DESCR | accTitle=ACC_TITLE | title=TITLE) EOL)+ -; +// Base terminals and fragments for common language constructs +// Terminal Precedence: Lazy to Greedy +// When imported, the terminals are considered after the terminals in the importing grammar +// Note: Hence, to add a terminal greedier than the common terminals, import it separately after the common import fragment EOL returns string: NEWLINE+ | EOF ; -terminal NEWLINE: /\r?\n/; +fragment TitleAndAccessibilities: + ((accDescr=ACC_DESCR | accTitle=ACC_TITLE | title=TITLE) EOL)+ +; + +terminal BOOLEAN returns boolean: 'true' | 'false'; + terminal ACC_DESCR: /[\t ]*accDescr(?:[\t ]*:([^\n\r]*?(?=%%)|[^\n\r]*)|\s*{([^}]*)})/; terminal ACC_TITLE: /[\t ]*accTitle[\t ]*:(?:[^\n\r]*?(?=%%)|[^\n\r]*)/; terminal TITLE: /[\t ]*title(?:[\t ][^\n\r]*?(?=%%)|[\t ][^\n\r]*|)/; +terminal FLOAT returns number: /[0-9]+\.[0-9]+(?!\.)/; +terminal INT returns number: /0|[1-9][0-9]*(?!\.)/; +terminal NUMBER returns number: FLOAT | INT; + +terminal STRING returns string: /"([^"\\]|\\.)*"|'([^'\\]|\\.)*'/; + +// Alphanumerics with underscores and dashes +// Must start with an alphanumeric or an underscore +// Cant end with a dash +terminal ID returns string: /[\w]([-\w]*\w)?/; + +terminal NEWLINE: /\r?\n/; + hidden terminal WHITESPACE: /[\t ]+/; hidden terminal YAML: /---[\t ]*\r?\n(?:[\S\s]*?\r?\n)?---(?:\r?\n|(?!\S))/; hidden terminal DIRECTIVE: /[\t ]*%%{[\S\s]*?}%%(?:\r?\n|(?!\S))/; diff --git a/packages/parser/src/language/common/tokenBuilder.ts b/packages/parser/src/language/common/tokenBuilder.ts index f99763454..1511dd390 100644 --- a/packages/parser/src/language/common/tokenBuilder.ts +++ b/packages/parser/src/language/common/tokenBuilder.ts @@ -20,6 +20,7 @@ export abstract class AbstractMermaidTokenBuilder extends DefaultTokenBuilder { // to restrict users, they mustn't have any non-whitespace characters after the keyword. tokenTypes.forEach((tokenType: TokenType): void => { if (this.keywords.has(tokenType.name) && tokenType.PATTERN !== undefined) { + // eslint-disable-next-line @typescript-eslint/no-base-to-string tokenType.PATTERN = new RegExp(tokenType.PATTERN.toString() + '(?:(?=%%)|(?!\\S))'); } }); diff --git a/packages/parser/src/language/common/valueConverter.ts b/packages/parser/src/language/common/valueConverter.ts index 624cc67a5..740ef527f 100644 --- a/packages/parser/src/language/common/valueConverter.ts +++ b/packages/parser/src/language/common/valueConverter.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ import type { CstNode, GrammarAST, ValueType } from 'langium'; import { DefaultValueConverter } from 'langium'; diff --git a/packages/parser/src/language/gitGraph/gitGraph.langium b/packages/parser/src/language/gitGraph/gitGraph.langium new file mode 100644 index 000000000..5a4b0596c --- /dev/null +++ b/packages/parser/src/language/gitGraph/gitGraph.langium @@ -0,0 +1,56 @@ +grammar GitGraph +import "../common/common"; +import "reference"; + +entry GitGraph: + NEWLINE* + ('gitGraph' | 'gitGraph' ':' | 'gitGraph:' | ('gitGraph' Direction ':')) + ( + NEWLINE + | TitleAndAccessibilities + | statements+=Statement + )* +; + +Statement +: Commit +| Branch +| Merge +| Checkout +| CherryPicking +; + +Direction: + dir=('LR' | 'TB' | 'BT'); + +Commit: + 'commit' + ( + 'id:' id=STRING + |'msg:'? message=STRING + |'tag:' tags+=STRING + |'type:' type=('NORMAL' | 'REVERSE' | 'HIGHLIGHT') + )* EOL; +Branch: + 'branch' name=(REFERENCE|STRING) + ('order:' order=INT)? + EOL; + +Merge: + 'merge' branch=(REFERENCE|STRING) + ( + 'id:' id=STRING + |'tag:' tags+=STRING + |'type:' type=('NORMAL' | 'REVERSE' | 'HIGHLIGHT') + )* EOL; + +Checkout: + ('checkout'|'switch') branch=(REFERENCE|STRING) EOL; + +CherryPicking: + 'cherry-pick' + ( + 'id:' id=STRING + |'tag:' tags+=STRING + |'parent:' parent=STRING + )* EOL; diff --git a/packages/parser/src/language/gitGraph/index.ts b/packages/parser/src/language/gitGraph/index.ts new file mode 100644 index 000000000..fd3c604b0 --- /dev/null +++ b/packages/parser/src/language/gitGraph/index.ts @@ -0,0 +1 @@ +export * from './module.js'; diff --git a/packages/parser/src/language/gitGraph/module.ts b/packages/parser/src/language/gitGraph/module.ts new file mode 100644 index 000000000..e2d45c8fa --- /dev/null +++ b/packages/parser/src/language/gitGraph/module.ts @@ -0,0 +1,52 @@ +import type { + DefaultSharedCoreModuleContext, + LangiumCoreServices, + LangiumSharedCoreServices, + Module, + PartialLangiumCoreServices, +} from 'langium'; +import { + inject, + createDefaultCoreModule, + createDefaultSharedCoreModule, + EmptyFileSystem, +} from 'langium'; +import { CommonValueConverter } from '../common/valueConverter.js'; +import { MermaidGeneratedSharedModule, GitGraphGeneratedModule } from '../generated/module.js'; +import { GitGraphTokenBuilder } from './tokenBuilder.js'; + +interface GitGraphAddedServices { + parser: { + TokenBuilder: GitGraphTokenBuilder; + ValueConverter: CommonValueConverter; + }; +} + +export type GitGraphServices = LangiumCoreServices & GitGraphAddedServices; + +export const GitGraphModule: Module< + GitGraphServices, + PartialLangiumCoreServices & GitGraphAddedServices +> = { + parser: { + TokenBuilder: () => new GitGraphTokenBuilder(), + ValueConverter: () => new CommonValueConverter(), + }, +}; + +export function createGitGraphServices(context: DefaultSharedCoreModuleContext = EmptyFileSystem): { + shared: LangiumSharedCoreServices; + GitGraph: GitGraphServices; +} { + const shared: LangiumSharedCoreServices = inject( + createDefaultSharedCoreModule(context), + MermaidGeneratedSharedModule + ); + const GitGraph: GitGraphServices = inject( + createDefaultCoreModule({ shared }), + GitGraphGeneratedModule, + GitGraphModule + ); + shared.ServiceRegistry.register(GitGraph); + return { shared, GitGraph }; +} diff --git a/packages/parser/src/language/gitGraph/reference.langium b/packages/parser/src/language/gitGraph/reference.langium new file mode 100644 index 000000000..6e1af5863 --- /dev/null +++ b/packages/parser/src/language/gitGraph/reference.langium @@ -0,0 +1,4 @@ +// Alphanumerics with underscores, dashes, slashes, and dots +// Must start with an alphanumeric or an underscore +// Cant end with a dash, slash, or dot +terminal REFERENCE returns string: /\w([-\./\w]*[-\w])?/; \ No newline at end of file diff --git a/packages/parser/src/language/gitGraph/tokenBuilder.ts b/packages/parser/src/language/gitGraph/tokenBuilder.ts new file mode 100644 index 000000000..ccadf1a1f --- /dev/null +++ b/packages/parser/src/language/gitGraph/tokenBuilder.ts @@ -0,0 +1,7 @@ +import { AbstractMermaidTokenBuilder } from '../common/index.js'; + +export class GitGraphTokenBuilder extends AbstractMermaidTokenBuilder { + public constructor() { + super(['gitGraph']); + } +} diff --git a/packages/parser/src/language/index.ts b/packages/parser/src/language/index.ts index 9f1d92ba8..aa0c0f703 100644 --- a/packages/parser/src/language/index.ts +++ b/packages/parser/src/language/index.ts @@ -5,21 +5,39 @@ export { PacketBlock, Pie, PieSection, - isCommon, + Architecture, + GitGraph, + Radar, + Branch, + Commit, + Merge, + Statement, isInfo, isPacket, isPacketBlock, isPie, isPieSection, + isArchitecture, + isGitGraph, + isBranch, + isCommit, + isMerge, } from './generated/ast.js'; + export { InfoGeneratedModule, MermaidGeneratedSharedModule, PacketGeneratedModule, PieGeneratedModule, + ArchitectureGeneratedModule, + GitGraphGeneratedModule, + RadarGeneratedModule, } from './generated/module.js'; +export * from './gitGraph/index.js'; export * from './common/index.js'; export * from './info/index.js'; export * from './packet/index.js'; export * from './pie/index.js'; +export * from './architecture/index.js'; +export * from './radar/index.js'; diff --git a/packages/parser/src/language/packet/packet.langium b/packages/parser/src/language/packet/packet.langium index ad30f8df2..91d6501ed 100644 --- a/packages/parser/src/language/packet/packet.langium +++ b/packages/parser/src/language/packet/packet.langium @@ -5,15 +5,12 @@ entry Packet: NEWLINE* "packet-beta" ( - NEWLINE* TitleAndAccessibilities blocks+=PacketBlock* - | NEWLINE+ blocks+=PacketBlock+ - | NEWLINE* - ) + TitleAndAccessibilities + | blocks+=PacketBlock + | NEWLINE + )* ; PacketBlock: start=INT('-' end=INT)? ':' label=STRING EOL -; - -terminal INT returns number: /0|[1-9][0-9]*/; -terminal STRING: /"[^"]*"|'[^']*'/; +; \ No newline at end of file diff --git a/packages/parser/src/language/pie/pie.langium b/packages/parser/src/language/pie/pie.langium index 2bbf967e1..a80caa81f 100644 --- a/packages/parser/src/language/pie/pie.langium +++ b/packages/parser/src/language/pie/pie.langium @@ -5,15 +5,12 @@ entry Pie: NEWLINE* "pie" showData?="showData"? ( - NEWLINE* TitleAndAccessibilities sections+=PieSection* - | NEWLINE+ sections+=PieSection+ - | NEWLINE* - ) + TitleAndAccessibilities + | sections+=PieSection + | NEWLINE + )* ; PieSection: - label=PIE_SECTION_LABEL ":" value=PIE_SECTION_VALUE EOL + label=STRING ":" value=NUMBER EOL ; - -terminal PIE_SECTION_LABEL: /"[^"]+"/; -terminal PIE_SECTION_VALUE returns number: /(0|[1-9][0-9]*)(\.[0-9]+)?/; diff --git a/packages/parser/src/language/pie/valueConverter.ts b/packages/parser/src/language/pie/valueConverter.ts index b0ae18c0b..cc412d7a1 100644 --- a/packages/parser/src/language/pie/valueConverter.ts +++ b/packages/parser/src/language/pie/valueConverter.ts @@ -6,7 +6,6 @@ export class PieValueConverter extends AbstractMermaidValueConverter { protected runCustomConverter( rule: GrammarAST.AbstractRule, input: string, - // eslint-disable-next-line @typescript-eslint/no-unused-vars _cstNode: CstNode ): ValueType | undefined { if (rule.name !== 'PIE_SECTION_LABEL') { diff --git a/packages/parser/src/language/radar/index.ts b/packages/parser/src/language/radar/index.ts new file mode 100644 index 000000000..fd3c604b0 --- /dev/null +++ b/packages/parser/src/language/radar/index.ts @@ -0,0 +1 @@ +export * from './module.js'; diff --git a/packages/parser/src/language/radar/module.ts b/packages/parser/src/language/radar/module.ts new file mode 100644 index 000000000..de604724a --- /dev/null +++ b/packages/parser/src/language/radar/module.ts @@ -0,0 +1,73 @@ +import type { + DefaultSharedCoreModuleContext, + LangiumCoreServices, + LangiumSharedCoreServices, + Module, + PartialLangiumCoreServices, +} from 'langium'; +import { + EmptyFileSystem, + createDefaultCoreModule, + createDefaultSharedCoreModule, + inject, +} from 'langium'; +import { CommonValueConverter } from '../common/valueConverter.js'; +import { MermaidGeneratedSharedModule, RadarGeneratedModule } from '../generated/module.js'; +import { RadarTokenBuilder } from './tokenBuilder.js'; + +/** + * Declaration of `Radar` services. + */ +interface RadarAddedServices { + parser: { + TokenBuilder: RadarTokenBuilder; + ValueConverter: CommonValueConverter; + }; +} + +/** + * Union of Langium default services and `Radar` services. + */ +export type RadarServices = LangiumCoreServices & RadarAddedServices; + +/** + * Dependency injection module that overrides Langium default services and + * contributes the declared `Radar` services. + */ +export const RadarModule: Module = { + parser: { + TokenBuilder: () => new RadarTokenBuilder(), + ValueConverter: () => new CommonValueConverter(), + }, +}; + +/** + * Create the full set of services required by Langium. + * + * First inject the shared services by merging two modules: + * - Langium default shared services + * - Services generated by langium-cli + * + * Then inject the language-specific services by merging three modules: + * - Langium default language-specific services + * - Services generated by langium-cli + * - Services specified in this file + * @param context - Optional module context with the LSP connection + * @returns An object wrapping the shared services and the language-specific services + */ +export function createRadarServices(context: DefaultSharedCoreModuleContext = EmptyFileSystem): { + shared: LangiumSharedCoreServices; + Radar: RadarServices; +} { + const shared: LangiumSharedCoreServices = inject( + createDefaultSharedCoreModule(context), + MermaidGeneratedSharedModule + ); + const Radar: RadarServices = inject( + createDefaultCoreModule({ shared }), + RadarGeneratedModule, + RadarModule + ); + shared.ServiceRegistry.register(Radar); + return { shared, Radar }; +} diff --git a/packages/parser/src/language/radar/radar.langium b/packages/parser/src/language/radar/radar.langium new file mode 100644 index 000000000..8aa9cb0ff --- /dev/null +++ b/packages/parser/src/language/radar/radar.langium @@ -0,0 +1,55 @@ +grammar Radar +import "../common/common"; + +entry Radar: + NEWLINE* + ('radar-beta' | 'radar-beta:' | 'radar-beta' ':') + NEWLINE* + ( + TitleAndAccessibilities + | 'axis' axes+=Axis (',' axes+=Axis)* + | 'curve' curves+=Curve (',' curves+=Curve)* + | options+=Option (',' options+=Option)* + | NEWLINE + )* +; + +fragment Label: + '[' label=STRING ']' +; + +Axis: + name=ID (Label)? +; + +Curve: + name=ID (Label)? '{' Entries '}' +; + +fragment Entries: + NEWLINE* entries+=NumberEntry (',' NEWLINE* entries+=NumberEntry)* NEWLINE* | + NEWLINE* entries+=DetailedEntry (',' NEWLINE* entries+=DetailedEntry)* NEWLINE* +; + +interface Entry { + axis?: @Axis; + value: number; +} +DetailedEntry returns Entry: + axis=[Axis:ID] ':'? value=NUMBER +; +NumberEntry returns Entry: + value=NUMBER +; + +Option: + ( + name='showLegend' value=BOOLEAN + | name='ticks' value=NUMBER + | name='max' value=NUMBER + | name='min' value=NUMBER + | name='graticule' value=GRATICULE + ) +; + +terminal GRATICULE returns string: 'circle' | 'polygon'; \ No newline at end of file diff --git a/packages/parser/src/language/radar/tokenBuilder.ts b/packages/parser/src/language/radar/tokenBuilder.ts new file mode 100644 index 000000000..b016fb5d8 --- /dev/null +++ b/packages/parser/src/language/radar/tokenBuilder.ts @@ -0,0 +1,7 @@ +import { AbstractMermaidTokenBuilder } from '../common/index.js'; + +export class RadarTokenBuilder extends AbstractMermaidTokenBuilder { + public constructor() { + super(['radar-beta']); + } +} diff --git a/packages/parser/src/parse.ts b/packages/parser/src/parse.ts index 577a1cea6..020a86f7b 100644 --- a/packages/parser/src/parse.ts +++ b/packages/parser/src/parse.ts @@ -1,31 +1,50 @@ import type { LangiumParser, ParseResult } from 'langium'; -import type { Info, Packet, Pie } from './index.js'; +import type { Info, Packet, Pie, Architecture, GitGraph, Radar } from './index.js'; -export type DiagramAST = Info | Packet | Pie; +export type DiagramAST = Info | Packet | Pie | Architecture | GitGraph | Radar; const parsers: Record = {}; const initializers = { info: async () => { const { createInfoServices } = await import('./language/info/index.js'); const parser = createInfoServices().Info.parser.LangiumParser; - parsers['info'] = parser; + parsers.info = parser; }, packet: async () => { const { createPacketServices } = await import('./language/packet/index.js'); const parser = createPacketServices().Packet.parser.LangiumParser; - parsers['packet'] = parser; + parsers.packet = parser; }, pie: async () => { const { createPieServices } = await import('./language/pie/index.js'); const parser = createPieServices().Pie.parser.LangiumParser; - parsers['pie'] = parser; + parsers.pie = parser; + }, + architecture: async () => { + const { createArchitectureServices } = await import('./language/architecture/index.js'); + const parser = createArchitectureServices().Architecture.parser.LangiumParser; + parsers.architecture = parser; + }, + gitGraph: async () => { + const { createGitGraphServices } = await import('./language/gitGraph/index.js'); + const parser = createGitGraphServices().GitGraph.parser.LangiumParser; + parsers.gitGraph = parser; + }, + radar: async () => { + const { createRadarServices } = await import('./language/radar/index.js'); + const parser = createRadarServices().Radar.parser.LangiumParser; + parsers.radar = parser; }, } as const; export async function parse(diagramType: 'info', text: string): Promise; export async function parse(diagramType: 'packet', text: string): Promise; export async function parse(diagramType: 'pie', text: string): Promise; +export async function parse(diagramType: 'architecture', text: string): Promise; +export async function parse(diagramType: 'gitGraph', text: string): Promise; +export async function parse(diagramType: 'radar', text: string): Promise; + export async function parse( diagramType: keyof typeof initializers, text: string diff --git a/packages/parser/tests/architecture.test.ts b/packages/parser/tests/architecture.test.ts new file mode 100644 index 000000000..4dcce17d3 --- /dev/null +++ b/packages/parser/tests/architecture.test.ts @@ -0,0 +1,88 @@ +import { describe, expect, it } from 'vitest'; + +import { Architecture } from '../src/language/index.js'; +import { expectNoErrorsOrAlternatives, architectureParse as parse } from './test-util.js'; + +describe('architecture', () => { + describe('should handle architecture definition', () => { + it.each([ + `architecture-beta`, + ` architecture-beta `, + `\tarchitecture-beta\t`, + ` + \tarchitecture-beta + `, + ])('should handle regular architecture', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + }); + }); + + describe('should handle TitleAndAccessibilities', () => { + it.each([ + `architecture-beta title sample title`, + ` architecture-beta title sample title `, + `\tarchitecture-beta\ttitle sample title\t`, + `architecture-beta + \ttitle sample title + `, + ])('should handle regular architecture + title in same line', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + + const { title } = result.value; + expect(title).toBe('sample title'); + }); + + it.each([ + `architecture-beta + title sample title`, + `architecture-beta + title sample title + `, + ])('should handle regular architecture + title in next line', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + + const { title } = result.value; + expect(title).toBe('sample title'); + }); + + it('should handle regular architecture + title + accTitle + accDescr', () => { + const context = `architecture-beta + title sample title + accTitle: sample accTitle + accDescr: sample accDescr + `; + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + + const { title, accTitle, accDescr } = result.value; + expect(title).toBe('sample title'); + expect(accTitle).toBe('sample accTitle'); + expect(accDescr).toBe('sample accDescr'); + }); + + it('should handle regular architecture + title + accTitle + multi-line accDescr', () => { + const context = `architecture-beta + title sample title + accTitle: sample accTitle + accDescr { + sample accDescr + } + `; + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + + const { title, accTitle, accDescr } = result.value; + expect(title).toBe('sample title'); + expect(accTitle).toBe('sample accTitle'); + expect(accDescr).toBe('sample accDescr'); + }); + }); +}); diff --git a/packages/parser/tests/gitGraph.test.ts b/packages/parser/tests/gitGraph.test.ts new file mode 100644 index 000000000..f7f302236 --- /dev/null +++ b/packages/parser/tests/gitGraph.test.ts @@ -0,0 +1,213 @@ +import { describe, expect, it } from 'vitest'; +import type { Branch, Merge } from '../src/language/index.js'; +import { gitGraphParse as parse } from './test-util.js'; +import type { Commit } from '../src/language/index.js'; +import type { Checkout, CherryPicking } from '../src/language/generated/ast.js'; + +describe('Parsing Commit Statements', () => { + it('should parse a simple commit', () => { + const result = parse(`gitGraph\n commit\n`); + expect(result.value.statements[0].$type).toBe('Commit'); + }); + + it('should parse multiple commits', () => { + const result = parse(`gitGraph\n commit\n commit\n commit\n`); + expect(result.value.statements).toHaveLength(3); + }); + + it('should parse commits with all properties', () => { + const result = parse(`gitGraph\n commit id:"1" msg:"Fix bug" tag:"v1.2" type:NORMAL\n`); + const commit = result.value.statements[0] as Commit; + expect(commit.$type).toBe('Commit'); + expect(commit.id).toBe('1'); + expect(commit.message).toBe('Fix bug'); + expect(commit.tags).toEqual(['v1.2']); + expect(commit.type).toBe('NORMAL'); + }); + + it('should handle commit messages with special characters', () => { + const result = parse(`gitGraph\n commit msg:"Fix issue #123: Handle errors"\n`); + const commit = result.value.statements[0] as Commit; + expect(commit.message).toBe('Fix issue #123: Handle errors'); + }); + + it('should parse commits with only a message and no other properties', () => { + const result = parse(`gitGraph\n commit msg:"Initial release"\n`); + const commit = result.value.statements[0] as Commit; + expect(commit.message).toBe('Initial release'); + expect(commit.id).toBeUndefined(); + expect(commit.type).toBeUndefined(); + }); + + it('should ignore malformed properties and not break parsing', () => { + const result = parse(`gitGraph\n commit id:"2" msg:"Malformed commit" oops:"ignored"\n`); + const commit = result.value.statements[0] as Commit; + expect(commit.id).toBe('2'); + expect(commit.message).toBe('Malformed commit'); + expect(commit.hasOwnProperty('oops')).toBe(false); + }); + + it('should parse multiple commits with different types', () => { + const result = parse(`gitGraph\n commit type:NORMAL\n commit type:REVERSE\n`); + const commit1 = result.value.statements[0] as Commit; + const commit2 = result.value.statements[1] as Commit; + expect(commit1.type).toBe('NORMAL'); + expect(commit2.type).toBe('REVERSE'); + }); +}); + +describe('Parsing Branch Statements', () => { + it('should parse a branch with a simple name', () => { + const result = parse(`gitGraph\n commit\n commit\n branch master\n`); + const branch = result.value.statements[2] as Branch; + expect(branch.name).toBe('master'); + }); + + it('should parse a branch name starting with numbers', () => { + const result = parse(`gitGraph\n commit\n branch 1.0.1\n`); + const branch = result.value.statements[1] as Branch; + expect(branch.name).toBe('1.0.1'); + }); + + it('should parse a branch with an order property', () => { + const result = parse(`gitGraph\n commit\n branch feature order:1\n`); + const branch = result.value.statements[1] as Branch; + expect(branch.name).toBe('feature'); + expect(branch.order).toBe(1); + }); + + it('should handle branch names with special characters', () => { + const result = parse(`gitGraph\n branch feature/test-branch\n`); + const branch = result.value.statements[0] as Branch; + expect(branch.name).toBe('feature/test-branch'); + }); + + it('should parse branches with hyphens and underscores', () => { + const result = parse(`gitGraph\n branch my-feature_branch\n`); + const branch = result.value.statements[0] as Branch; + expect(branch.name).toBe('my-feature_branch'); + }); + + it('should correctly handle branch without order property', () => { + const result = parse(`gitGraph\n branch feature\n`); + const branch = result.value.statements[0] as Branch; + expect(branch.name).toBe('feature'); + expect(branch.order).toBeUndefined(); + }); +}); + +describe('Parsing Merge Statements', () => { + it('should parse a merge with a branch name', () => { + const result = parse(`gitGraph\n merge master\n`); + const merge = result.value.statements[0] as Merge; + expect(merge.branch).toBe('master'); + }); + + it('should handle merges with additional properties', () => { + const result = parse(`gitGraph\n merge feature id:"m1" tag:"release" type:HIGHLIGHT\n`); + const merge = result.value.statements[0] as Merge; + expect(merge.branch).toBe('feature'); + expect(merge.id).toBe('m1'); + expect(merge.tags).toEqual(['release']); + expect(merge.type).toBe('HIGHLIGHT'); + }); + + it('should parse merge without any properties', () => { + const result = parse(`gitGraph\n merge feature\n`); + const merge = result.value.statements[0] as Merge; + expect(merge.branch).toBe('feature'); + }); + + it('should ignore malformed properties in merge statements', () => { + const result = parse(`gitGraph\n merge feature random:"ignored"\n`); + const merge = result.value.statements[0] as Merge; + expect(merge.branch).toBe('feature'); + expect(merge.hasOwnProperty('random')).toBe(false); + }); +}); + +describe('Parsing Checkout Statements', () => { + it('should parse a checkout to a named branch', () => { + const result = parse( + `gitGraph\n commit id:"1"\n branch develop\n branch fun\n checkout develop\n` + ); + const checkout = result.value.statements[3] as Checkout; + expect(checkout.branch).toBe('develop'); + }); + + it('should parse checkout to branches with complex names', () => { + const result = parse(`gitGraph\n checkout hotfix-123\n`); + const checkout = result.value.statements[0] as Checkout; + expect(checkout.branch).toBe('hotfix-123'); + }); + + it('should parse checkouts with hyphens and numbers', () => { + const result = parse(`gitGraph\n checkout release-2021\n`); + const checkout = result.value.statements[0] as Checkout; + expect(checkout.branch).toBe('release-2021'); + }); +}); + +describe('Parsing CherryPicking Statements', () => { + it('should parse cherry-picking with a commit id', () => { + const result = parse(`gitGraph\n commit id:"123" commit id:"321" cherry-pick id:"123"\n`); + const cherryPick = result.value.statements[2] as CherryPicking; + expect(cherryPick.id).toBe('123'); + }); + + it('should parse cherry-picking with multiple properties', () => { + const result = parse(`gitGraph\n cherry-pick id:"123" tag:"urgent" parent:"100"\n`); + const cherryPick = result.value.statements[0] as CherryPicking; + expect(cherryPick.id).toBe('123'); + expect(cherryPick.tags).toEqual(['urgent']); + expect(cherryPick.parent).toBe('100'); + }); + + describe('Parsing with Accessibility Titles and Descriptions', () => { + it('should parse accessibility titles', () => { + const result = parse(`gitGraph\n accTitle: Accessible Graph\n commit\n`); + expect(result.value.accTitle).toBe('Accessible Graph'); + }); + + it('should parse multiline accessibility descriptions', () => { + const result = parse( + `gitGraph\n accDescr {\n Detailed description\n across multiple lines\n }\n commit\n` + ); + expect(result.value.accDescr).toBe('Detailed description\nacross multiple lines'); + }); + }); + + describe('Integration Tests', () => { + it('should correctly parse a complex graph with various elements', () => { + const result = parse(` + gitGraph TB: + accTitle: Complex Example + commit id:"init" type:NORMAL + branch feature + commit id:"feat1" msg:"Add feature" + checkout main + merge feature tag:"v1.0" + cherry-pick id:"feat1" tag:"critical fix" + `); + expect(result.value.accTitle).toBe('Complex Example'); + expect(result.value.statements[0].$type).toBe('Commit'); + expect(result.value.statements[1].$type).toBe('Branch'); + expect(result.value.statements[2].$type).toBe('Commit'); + expect(result.value.statements[3].$type).toBe('Checkout'); + expect(result.value.statements[4].$type).toBe('Merge'); + expect(result.value.statements[5].$type).toBe('CherryPicking'); + }); + }); + + describe('Error Handling for Invalid Syntax', () => { + it('should report errors for unknown properties in commit', () => { + const result = parse(`gitGraph\n commit unknown:"oops"\n`); + expect(result.parserErrors).not.toHaveLength(0); + }); + + it('should report errors for invalid branch order', () => { + const result = parse(`gitGraph\n branch feature order:xyz\n`); + expect(result.parserErrors).not.toHaveLength(0); + }); + }); +}); diff --git a/packages/parser/tests/packet.test.ts b/packages/parser/tests/packet.test.ts new file mode 100644 index 000000000..eb2ea303d --- /dev/null +++ b/packages/parser/tests/packet.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, it } from 'vitest'; + +import { Packet } from '../src/language/index.js'; +import { expectNoErrorsOrAlternatives, packetParse as parse } from './test-util.js'; + +describe('packet', () => { + it.each([ + `packet-beta`, + ` packet-beta `, + `\tpacket-beta\t`, + ` + \tpacket-beta + `, + ])('should handle regular packet', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Packet); + }); +}); diff --git a/packages/parser/tests/pie.test.ts b/packages/parser/tests/pie.test.ts index 43e9a374f..caa7cc528 100644 --- a/packages/parser/tests/pie.test.ts +++ b/packages/parser/tests/pie.test.ts @@ -4,226 +4,247 @@ import { Pie } from '../src/language/index.js'; import { expectNoErrorsOrAlternatives, pieParse as parse } from './test-util.js'; describe('pie', () => { - it.each([ - `pie`, - ` pie `, - `\tpie\t`, - ` + describe('should handle pie definition with or without showData', () => { + it.each([ + `pie`, + ` pie `, + `\tpie\t`, + ` \tpie `, - ])('should handle regular pie', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); - }); + ])('should handle regular pie', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); + }); - it.each([ - `pie showData`, - ` pie showData `, - `\tpie\tshowData\t`, - ` + it.each([ + `pie showData`, + ` pie showData `, + `\tpie\tshowData\t`, + ` pie\tshowData `, - ])('should handle regular showData', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + ])('should handle regular showData', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { showData } = result.value; - expect(showData).toBeTruthy(); + const { showData } = result.value; + expect(showData).toBeTruthy(); + }); }); + describe('should handle TitleAndAccessibilities', () => { + describe('should handle TitleAndAccessibilities without showData', () => { + it.each([ + `pie title sample title`, + ` pie title sample title `, + `\tpie\ttitle sample title\t`, + `pie + \ttitle sample title + `, + ])('should handle regular pie + title in same line', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - it.each([ - `pie title sample title`, - ` pie title sample title `, - `\tpie\ttitle sample title\t`, - `pie - \ttitle sample title - `, - ])('should handle regular pie + title in same line', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + const { title } = result.value; + expect(title).toBe('sample title'); + }); - const { title } = result.value; - expect(title).toBe('sample title'); - }); - - it.each([ - `pie - title sample title`, - `pie - title sample title - `, - `pie - title sample title`, - `pie - title sample title - `, - ])('should handle regular pie + title in different line', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); - - const { title } = result.value; - expect(title).toBe('sample title'); - }); - - it.each([ - `pie showData title sample title`, - `pie showData title sample title - `, - ])('should handle regular pie + showData + title', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); - - const { showData, title } = result.value; - expect(showData).toBeTruthy(); - expect(title).toBe('sample title'); - }); - - it.each([ - `pie showData - title sample title`, - `pie showData - title sample title - `, - `pie showData - title sample title`, - `pie showData - title sample title - `, - ])('should handle regular showData + title in different line', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); - - const { showData, title } = result.value; - expect(showData).toBeTruthy(); - expect(title).toBe('sample title'); - }); - - describe('sections', () => { - describe('normal', () => { it.each([ `pie + title sample title`, + `pie + title sample title + `, + `pie + title sample title`, + `pie + title sample title + `, + ])('should handle regular pie + title in different line', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); + + const { title } = result.value; + expect(title).toBe('sample title'); + }); + }); + + describe('should handle TitleAndAccessibilities with showData', () => { + it.each([ + `pie showData title sample title`, + `pie showData title sample title + `, + ])('should handle regular pie + showData + title', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); + + const { showData, title } = result.value; + expect(showData).toBeTruthy(); + expect(title).toBe('sample title'); + }); + + it.each([ + `pie showData + title sample title`, + `pie showData + title sample title + `, + `pie showData + title sample title`, + `pie showData + title sample title + `, + ])('should handle regular showData + title in different line', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); + + const { showData, title } = result.value; + expect(showData).toBeTruthy(); + expect(title).toBe('sample title'); + }); + }); + }); + + describe('should handle sections', () => { + it.each([ + `pie "GitHub":100 "GitLab":50`, - `pie + `pie "GitHub" : 100 "GitLab" : 50`, - `pie + `pie "GitHub"\t:\t100 "GitLab"\t:\t50`, - `pie + `pie \t"GitHub" \t : \t 100 \t"GitLab" \t : \t 50 `, - ])('should handle regular sections', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + ])('should handle regular sections', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { sections } = result.value; - expect(sections[0].label).toBe('GitHub'); - expect(sections[0].value).toBe(100); + const { sections } = result.value; + expect(sections[0].label).toBe('GitHub'); + expect(sections[0].value).toBe(100); - expect(sections[1].label).toBe('GitLab'); - expect(sections[1].value).toBe(50); - }); + expect(sections[1].label).toBe('GitLab'); + expect(sections[1].value).toBe(50); + }); - it('should handle sections with showData', () => { - const context = `pie showData + it('should handle sections with showData', () => { + const context = `pie showData "GitHub": 100 "GitLab": 50`; - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { showData, sections } = result.value; - expect(showData).toBeTruthy(); + const { showData, sections } = result.value; + expect(showData).toBeTruthy(); - expect(sections[0].label).toBe('GitHub'); - expect(sections[0].value).toBe(100); + expect(sections[0].label).toBe('GitHub'); + expect(sections[0].value).toBe(100); - expect(sections[1].label).toBe('GitLab'); - expect(sections[1].value).toBe(50); - }); + expect(sections[1].label).toBe('GitLab'); + expect(sections[1].value).toBe(50); + }); - it('should handle sections with title', () => { - const context = `pie title sample wow + it('should handle sections with title', () => { + const context = `pie title sample wow "GitHub": 100 "GitLab": 50`; - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { title, sections } = result.value; - expect(title).toBe('sample wow'); + const { title, sections } = result.value; + expect(title).toBe('sample wow'); - expect(sections[0].label).toBe('GitHub'); - expect(sections[0].value).toBe(100); + expect(sections[0].label).toBe('GitHub'); + expect(sections[0].value).toBe(100); - expect(sections[1].label).toBe('GitLab'); - expect(sections[1].value).toBe(50); - }); + expect(sections[1].label).toBe('GitLab'); + expect(sections[1].value).toBe(50); + }); - it('should handle sections with accTitle', () => { - const context = `pie accTitle: sample wow + it('should handle value with positive decimal', () => { + const context = `pie + "ash": 60.67 + "bat": 40`; + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); + + const { sections } = result.value; + expect(sections[0].label).toBe('ash'); + expect(sections[0].value).toBe(60.67); + + expect(sections[1].label).toBe('bat'); + expect(sections[1].value).toBe(40); + }); + + it('should handle sections with accTitle', () => { + const context = `pie accTitle: sample wow "GitHub": 100 "GitLab": 50`; - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { accTitle, sections } = result.value; - expect(accTitle).toBe('sample wow'); + const { accTitle, sections } = result.value; + expect(accTitle).toBe('sample wow'); - expect(sections[0].label).toBe('GitHub'); - expect(sections[0].value).toBe(100); + expect(sections[0].label).toBe('GitHub'); + expect(sections[0].value).toBe(100); - expect(sections[1].label).toBe('GitLab'); - expect(sections[1].value).toBe(50); - }); + expect(sections[1].label).toBe('GitLab'); + expect(sections[1].value).toBe(50); + }); - it('should handle sections with single line accDescr', () => { - const context = `pie accDescr: sample wow + it('should handle sections with single line accDescr', () => { + const context = `pie accDescr: sample wow "GitHub": 100 "GitLab": 50`; - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { accDescr, sections } = result.value; - expect(accDescr).toBe('sample wow'); + const { accDescr, sections } = result.value; + expect(accDescr).toBe('sample wow'); - expect(sections[0].label).toBe('GitHub'); - expect(sections[0].value).toBe(100); + expect(sections[0].label).toBe('GitHub'); + expect(sections[0].value).toBe(100); - expect(sections[1].label).toBe('GitLab'); - expect(sections[1].value).toBe(50); - }); + expect(sections[1].label).toBe('GitLab'); + expect(sections[1].value).toBe(50); + }); - it('should handle sections with multi line accDescr', () => { - const context = `pie accDescr { + it('should handle sections with multi line accDescr', () => { + const context = `pie accDescr { sample wow } "GitHub": 100 "GitLab": 50`; - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { accDescr, sections } = result.value; - expect(accDescr).toBe('sample wow'); + const { accDescr, sections } = result.value; + expect(accDescr).toBe('sample wow'); - expect(sections[0].label).toBe('GitHub'); - expect(sections[0].value).toBe(100); + expect(sections[0].label).toBe('GitHub'); + expect(sections[0].value).toBe(100); - expect(sections[1].label).toBe('GitLab'); - expect(sections[1].value).toBe(50); - }); + expect(sections[1].label).toBe('GitLab'); + expect(sections[1].value).toBe(50); }); }); }); diff --git a/packages/parser/tests/radar.test.ts b/packages/parser/tests/radar.test.ts new file mode 100644 index 000000000..5d483d53c --- /dev/null +++ b/packages/parser/tests/radar.test.ts @@ -0,0 +1,343 @@ +import { describe, expect, it } from 'vitest'; + +import { Radar } from '../src/language/index.js'; +import { expectNoErrorsOrAlternatives, radarParse as parse } from './test-util.js'; + +const mutateGlobalSpacing = (context: string) => { + return [ + context, + ` ${context} `, + `\t${context}\t`, + ` + \t${context} + `, + ]; +}; + +describe('radar', () => { + it.each([ + ...mutateGlobalSpacing('radar-beta'), + ...mutateGlobalSpacing('radar-beta:'), + ...mutateGlobalSpacing('radar-beta :'), + ])('should handle regular radar', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + }); + + describe('should handle title, accDescr, and accTitle', () => { + it.each([ + ...mutateGlobalSpacing(' title My Title'), + ...mutateGlobalSpacing('\n title My Title'), + ])('should handle title', (context: string) => { + const result = parse(`radar-beta${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { title } = result.value; + expect(title).toBe('My Title'); + }); + + it.each([ + ...mutateGlobalSpacing(' accDescr: My Accessible Description'), + ...mutateGlobalSpacing('\n accDescr: My Accessible Description'), + ])('should handle accDescr', (context: string) => { + const result = parse(`radar-beta${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { accDescr } = result.value; + expect(accDescr).toBe('My Accessible Description'); + }); + + it.each([ + ...mutateGlobalSpacing(' accTitle: My Accessible Title'), + ...mutateGlobalSpacing('\n accTitle: My Accessible Title'), + ])('should handle accTitle', (context: string) => { + const result = parse(`radar-beta${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { accTitle } = result.value; + expect(accTitle).toBe('My Accessible Title'); + }); + + it.each([ + ...mutateGlobalSpacing( + ' title My Title\n accDescr: My Accessible Description\n accTitle: My Accessible Title' + ), + ...mutateGlobalSpacing( + '\n title My Title\n accDescr: My Accessible Description\n accTitle: My Accessible Title' + ), + ])('should handle title + accDescr + accTitle', (context: string) => { + const result = parse(`radar-beta${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { title, accDescr, accTitle } = result.value; + expect(title).toBe('My Title'); + expect(accDescr).toBe('My Accessible Description'); + expect(accTitle).toBe('My Accessible Title'); + }); + }); + + describe('should handle axis', () => { + it.each([`axis my-axis`, `axis my-axis["My Axis Label"]`])( + 'should handle one axis', + (context: string) => { + const result = parse(`radar-beta\n${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { axes } = result.value; + expect(axes).toHaveLength(1); + expect(axes[0].$type).toBe('Axis'); + expect(axes[0].name).toBe('my-axis'); + } + ); + + it.each([ + `axis my-axis["My Axis Label"] + axis my-axis2`, + `axis my-axis, my-axis2`, + `axis my-axis["My Axis Label"], my-axis2`, + `axis my-axis, my-axis2["My Second Axis Label"]`, + ])('should handle multiple axes', (context: string) => { + const result = parse(`radar-beta\n${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { axes } = result.value; + expect(axes).toHaveLength(2); + expect(axes.every((axis) => axis.$type === 'Axis')).toBe(true); + expect(axes[0].name).toBe('my-axis'); + expect(axes[1].name).toBe('my-axis2'); + }); + + it.each([ + `axis my-axis["My Axis Label"] + axis my-axis2["My Second Axis Label"]`, + `axis my-axis ["My Axis Label"], my-axis2\t["My Second Axis Label"]`, + ])('should handle axis labels', (context: string) => { + const result = parse(`radar-beta\n${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { axes } = result.value; + expect(axes).toHaveLength(2); + expect(axes[0].name).toBe('my-axis'); + expect(axes[0].label).toBe('My Axis Label'); + expect(axes[1].name).toBe('my-axis2'); + expect(axes[1].label).toBe('My Second Axis Label'); + }); + + it('should not allow empty axis names', () => { + const result = parse(`radar-beta + axis`); + expect(result.parserErrors).not.toHaveLength(0); + }); + + it('should not allow non-comma separated axis names', () => { + const result = parse(`radar-beta + axis my-axis my-axis2`); + expect(result.parserErrors).not.toHaveLength(0); + }); + }); + + describe('should handle curves', () => { + it.each([ + `radar-beta + curve my-curve`, + `radar-beta + curve my-curve["My Curve Label"]`, + ])('should not allow curves without axes', (context: string) => { + const result = parse(`radar-beta${context}`); + expect(result.parserErrors).not.toHaveLength(0); + }); + + it.each([ + `radar-beta + axis my-axis + curve my-curve`, + `radar-beta + axis my-axis + curve my-curve["My Curve Label"]`, + ])('should not allow curves without entries', (context: string) => { + const result = parse(`radar-beta${context}`); + expect(result.parserErrors).not.toHaveLength(0); + }); + + it.each([ + `curve my-curve { 1 }`, + `curve my-curve { + 1 + }`, + `curve my-curve { + + 1 + + }`, + ])('should handle one curve with one entry', (context: string) => { + const result = parse(`radar-beta\naxis my-axis\n${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { curves } = result.value; + expect(curves).toHaveLength(1); + expect(curves[0].$type).toBe('Curve'); + expect(curves[0].name).toBe('my-curve'); + expect(curves[0].entries).toHaveLength(1); + expect(curves[0].entries[0].$type).toBe('Entry'); + expect(curves[0].entries[0].value).toBe(1); + }); + + it.each([ + `curve my-curve { my-axis 1 }`, + `curve my-curve { my-axis : 1 }`, + `curve my-curve { + my-axis: 1 + }`, + ])('should handle one curve with one detailed entry', (context: string) => { + const result = parse(`radar-beta\naxis my-axis\n${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { curves } = result.value; + expect(curves).toHaveLength(1); + expect(curves[0].$type).toBe('Curve'); + expect(curves[0].name).toBe('my-curve'); + expect(curves[0].entries).toHaveLength(1); + expect(curves[0].entries[0].$type).toBe('Entry'); + expect(curves[0].entries[0].value).toBe(1); + expect(curves[0].entries[0]?.axis?.$refText).toBe('my-axis'); + }); + + it.each([ + `curve my-curve { ax1 1, ax2 2 }`, + `curve my-curve { + ax1 1, + ax2 2 + }`, + `curve my-curve["My Curve Label"] { + ax1: 1, ax2: 2 + }`, + ])('should handle one curve with multiple detailed entries', (context: string) => { + const result = parse(`radar-beta\naxis ax1, ax1\n${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { curves } = result.value; + expect(curves).toHaveLength(1); + expect(curves[0].$type).toBe('Curve'); + expect(curves[0].name).toBe('my-curve'); + expect(curves[0].entries).toHaveLength(2); + expect(curves[0].entries[0].$type).toBe('Entry'); + expect(curves[0].entries[0].value).toBe(1); + expect(curves[0].entries[0]?.axis?.$refText).toBe('ax1'); + expect(curves[0].entries[1].$type).toBe('Entry'); + expect(curves[0].entries[1].value).toBe(2); + expect(curves[0].entries[1]?.axis?.$refText).toBe('ax2'); + }); + + it.each([ + `curve c1 { ax1 1, ax2 2 } + curve c2 { ax1 3, ax2 4 }`, + `curve c1 { + ax1 1, + ax2 2 + } + curve c2 { + ax1 3, + ax2 4 + }`, + `curve c1{ 1, 2 }, c2{ 3, 4 }`, + ])('should handle multiple curves', (context: string) => { + const result = parse(`radar-beta\naxis ax1, ax1\n${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { curves } = result.value; + expect(curves).toHaveLength(2); + expect(curves.every((curve) => curve.$type === 'Curve')).toBe(true); + expect(curves[0].name).toBe('c1'); + expect(curves[1].name).toBe('c2'); + }); + + it('should not allow empty curve names', () => { + const result = parse(`radar-beta + axis my-axis + curve`); + expect(result.parserErrors).not.toHaveLength(0); + }); + + it('should not allow number and detailed entries in the same curve', () => { + const result = parse(`radar-beta + axis ax1, ax2 + curve my-curve { 1, ax1 2 }`); + expect(result.parserErrors).not.toHaveLength(0); + }); + + it('should not allow non-comma separated entries', () => { + const result = parse(`radar-beta + axis ax1, ax2 + curve my-curve { ax1 1 ax2 2 }`); + expect(result.parserErrors).not.toHaveLength(0); + }); + }); + + describe('should handle options', () => { + it.each([`ticks 5`, `min 50`, `max 50`])( + `should handle number option %s`, + (context: string) => { + const result = parse(`radar-beta + axis ax1, ax2 + curve c1 { ax1 1, ax2 2 } + ${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { options } = result.value; + expect(options).toBeDefined(); + const option = options.find((option) => option.name === context.split(' ')[0]); + expect(option).toBeDefined(); + expect(option?.value).toBe(Number(context.split(' ')[1])); + } + ); + + it.each([`graticule circle`, `graticule polygon`])( + `should handle string option %s`, + (context: string) => { + const result = parse(`radar-beta + axis ax1, ax2 + curve c1 { ax1 1, ax2 2 } + ${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { options } = result.value; + expect(options).toBeDefined(); + const option = options.find((option) => option.name === context.split(' ')[0]); + expect(option).toBeDefined(); + expect(option?.value).toBe(context.split(' ')[1]); + } + ); + + it.each([`showLegend true`, `showLegend false`])( + `should handle boolean option %s`, + (context: string) => { + const result = parse(`radar-beta + axis ax1, ax2 + curve c1 { ax1 1, ax2 2 } + ${context}`); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Radar); + + const { options } = result.value; + expect(options).toBeDefined(); + const option = options.find((option) => option.name === context.split(' ')[0]); + expect(option).toBeDefined(); + expect(option?.value).toBe(context.split(' ')[1] === 'true'); + } + ); + }); +}); diff --git a/packages/parser/tests/test-util.ts b/packages/parser/tests/test-util.ts index 9bdec348a..7a6050016 100644 --- a/packages/parser/tests/test-util.ts +++ b/packages/parser/tests/test-util.ts @@ -1,7 +1,27 @@ import type { LangiumParser, ParseResult } from 'langium'; import { expect, vi } from 'vitest'; -import type { Info, InfoServices, Pie, PieServices } from '../src/language/index.js'; -import { createInfoServices, createPieServices } from '../src/language/index.js'; +import type { + Architecture, + ArchitectureServices, + Info, + InfoServices, + Pie, + PieServices, + Radar, + RadarServices, + Packet, + PacketServices, + GitGraph, + GitGraphServices, +} from '../src/language/index.js'; +import { + createArchitectureServices, + createInfoServices, + createPieServices, + createRadarServices, + createPacketServices, + createGitGraphServices, +} from '../src/language/index.js'; const consoleMock = vi.spyOn(console, 'log').mockImplementation(() => undefined); @@ -30,6 +50,17 @@ export function createInfoTestServices() { } export const infoParse = createInfoTestServices().parse; +const architectureServices: ArchitectureServices = createArchitectureServices().Architecture; +const architectureParser: LangiumParser = architectureServices.parser.LangiumParser; +export function createArchitectureTestServices() { + const parse = (input: string) => { + return architectureParser.parse(input); + }; + + return { services: architectureServices, parse }; +} +export const architectureParse = createArchitectureTestServices().parse; + const pieServices: PieServices = createPieServices().Pie; const pieParser: LangiumParser = pieServices.parser.LangiumParser; export function createPieTestServices() { @@ -40,3 +71,36 @@ export function createPieTestServices() { return { services: pieServices, parse }; } export const pieParse = createPieTestServices().parse; + +const packetServices: PacketServices = createPacketServices().Packet; +const packetParser: LangiumParser = packetServices.parser.LangiumParser; +export function createPacketTestServices() { + const parse = (input: string) => { + return packetParser.parse(input); + }; + + return { services: packetServices, parse }; +} +export const packetParse = createPacketTestServices().parse; + +const radarServices: RadarServices = createRadarServices().Radar; +const radarParser: LangiumParser = radarServices.parser.LangiumParser; +export function createRadarTestServices() { + const parse = (input: string) => { + return radarParser.parse(input); + }; + + return { services: radarServices, parse }; +} +export const radarParse = createRadarTestServices().parse; + +const gitGraphServices: GitGraphServices = createGitGraphServices().GitGraph; +const gitGraphParser: LangiumParser = gitGraphServices.parser.LangiumParser; +export function createGitGraphTestServices() { + const parse = (input: string) => { + return gitGraphParser.parse(input); + }; + + return { services: gitGraphServices, parse }; +} +export const gitGraphParse = createGitGraphTestServices().parse; diff --git a/packages/parser/tsconfig.json b/packages/parser/tsconfig.json index 7e830e229..4822488c9 100644 --- a/packages/parser/tsconfig.json +++ b/packages/parser/tsconfig.json @@ -4,7 +4,6 @@ "rootDir": ".", "outDir": "./dist", "allowJs": false, - "preserveSymlinks": false, "strictPropertyInitialization": false }, "include": ["./src/**/*.ts", "./tests/**/*.ts"], diff --git a/patches/cytoscape@3.28.1.patch b/patches/cytoscape@3.28.1.patch deleted file mode 100644 index d92163a31..000000000 --- a/patches/cytoscape@3.28.1.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/package.json b/package.json -index f2f77fa79c99382b079f4051ed51eafe8d2379c8..0bfddf55394e86f3a386eb7ab681369d410bae07 100644 ---- a/package.json -+++ b/package.json -@@ -30,7 +30,15 @@ - "engines": { - "node": ">=0.10" - }, -+ "exports": { -+ ".": { -+ "import": "./dist/cytoscape.umd.js", -+ "default": "./dist/cytoscape.cjs.js" -+ }, -+ "./*": "./*" -+ }, - "main": "dist/cytoscape.cjs.js", -+ "module": "dist/cytoscape.umd.js", - "unpkg": "dist/cytoscape.min.js", - "jsdelivr": "dist/cytoscape.min.js", - "scripts": { diff --git a/patches/roughjs.patch b/patches/roughjs.patch new file mode 100644 index 000000000..7a17084fe --- /dev/null +++ b/patches/roughjs.patch @@ -0,0 +1,10 @@ +diff --git a/bin/rough.d.ts b/bin/rough.d.ts +index 810db1fb34496a5b9f7c0734a7ad8be8605f5534..3624d5b6288a3d2b7d397dfcfffce60558f18cf9 100644 +--- a/bin/rough.d.ts ++++ b/bin/rough.d.ts +@@ -8,4 +8,4 @@ declare const _default: { + generator(config?: Config): RoughGenerator; + newSeed(): number; + }; +-export default _default; ++export = _default; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1f077122..b51d86bfd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,147 +1,159 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false patchedDependencies: - cytoscape@3.28.1: - hash: claipxynndhyqyu2csninuoh5e - path: patches/cytoscape@3.28.1.patch + roughjs: + hash: 3543d47108cb41b68ec6a671c0e1f9d0cfe2ce524fea5b0992511ae84c3c6b64 + path: patches/roughjs.patch importers: .: devDependencies: '@applitools/eyes-cypress': - specifier: ^3.42.3 - version: 3.43.1(typescript@5.4.5) + specifier: ^3.44.9 + version: 3.50.2(encoding@0.1.13)(typescript@5.7.3) + '@argos-ci/cypress': + specifier: ^4.0.3 + version: 4.0.3(cypress@14.0.3) + '@changesets/changelog-github': + specifier: ^0.5.1 + version: 0.5.1(encoding@0.1.13) + '@changesets/cli': + specifier: ^2.27.12 + version: 2.28.1 '@cspell/eslint-plugin': - specifier: ^8.6.0 - version: 8.7.0(eslint@8.57.0) + specifier: ^8.18.1 + version: 8.18.1(eslint@9.24.0(jiti@2.4.2)) '@cypress/code-coverage': - specifier: ^3.12.30 - version: 3.12.34(@babel/core@7.24.4)(@babel/preset-env@7.24.4)(babel-loader@9.1.3)(cypress@13.7.3)(webpack@5.91.0) + specifier: ^3.12.49 + version: 3.13.4(@babel/core@7.26.9)(@babel/preset-env@7.26.9(@babel/core@7.26.9))(babel-loader@9.2.1(@babel/core@7.26.9)(webpack@5.95.0(esbuild@0.25.0)))(cypress@14.0.3)(webpack@5.95.0(esbuild@0.25.0)) + '@eslint/js': + specifier: ^9.24.0 + version: 9.24.0 '@rollup/plugin-typescript': - specifier: ^11.1.6 - version: 11.1.6(typescript@5.4.5) + specifier: ^12.1.2 + version: 12.1.2(rollup@4.34.8)(tslib@2.8.1)(typescript@5.7.3) '@types/cors': specifier: ^2.8.17 version: 2.8.17 - '@types/eslint': - specifier: ^8.56.6 - version: 8.56.9 '@types/express': - specifier: ^4.17.21 - version: 4.17.21 + specifier: ^5.0.0 + version: 5.0.0 '@types/js-yaml': specifier: ^4.0.9 version: 4.0.9 '@types/jsdom': - specifier: ^21.1.6 - version: 21.1.6 + specifier: ^21.1.7 + version: 21.1.7 '@types/lodash': - specifier: ^4.17.0 - version: 4.17.0 + specifier: ^4.17.15 + version: 4.17.15 '@types/mdast': + specifier: ^4.0.4 + version: 4.0.4 + '@types/node': + specifier: ^22.13.5 + version: 22.13.5 + '@types/rollup-plugin-visualizer': + specifier: ^5.0.3 + version: 5.0.3(rollup@4.34.8) + '@vitest/coverage-v8': + specifier: ^3.0.6 + version: 3.0.6(vitest@3.0.6) + '@vitest/spy': + specifier: ^3.0.6 + version: 3.0.6 + '@vitest/ui': + specifier: ^3.0.6 + version: 3.0.6(vitest@3.0.6) + ajv: + specifier: ^8.17.1 + version: 8.17.1 + chokidar: specifier: ^4.0.3 version: 4.0.3 - '@types/node': - specifier: ^20.11.30 - version: 20.12.7 - '@types/rollup-plugin-visualizer': - specifier: ^4.2.4 - version: 4.2.4 - '@typescript-eslint/eslint-plugin': - specifier: ^7.3.1 - version: 7.6.0(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/parser': - specifier: ^7.3.1 - version: 7.6.0(eslint@8.57.0)(typescript@5.4.5) - '@vitest/coverage-v8': - specifier: ^1.4.0 - version: 1.5.0(vitest@1.5.0) - '@vitest/spy': - specifier: ^1.4.0 - version: 1.5.0 - '@vitest/ui': - specifier: ^1.4.0 - version: 1.5.0(vitest@1.5.0) - ajv: - specifier: ^8.12.0 - version: 8.12.0 - chokidar: - specifier: ^3.6.0 - version: 3.6.0 concurrently: - specifier: ^8.2.2 - version: 8.2.2 + specifier: ^9.1.2 + version: 9.1.2 cors: specifier: ^2.8.5 version: 2.8.5 + cpy-cli: + specifier: ^5.0.0 + version: 5.0.0 cross-env: specifier: ^7.0.3 version: 7.0.3 cspell: - specifier: ^8.6.0 - version: 8.7.0 + specifier: ^8.6.1 + version: 8.17.4 cypress: - specifier: ^13.7.1 - version: 13.7.3 + specifier: ^14.0.3 + version: 14.0.3 cypress-image-snapshot: specifier: ^4.0.1 - version: 4.0.1(cypress@13.7.3)(jest@29.7.0) + version: 4.0.1(cypress@14.0.3)(jest@29.7.0(@types/node@22.13.5)) + cypress-split: + specifier: ^1.24.14 + version: 1.24.14(@babel/core@7.26.9) esbuild: - specifier: ^0.20.2 - version: 0.20.2 + specifier: ^0.25.0 + version: 0.25.0 eslint: - specifier: ^8.57.0 - version: 8.57.0 + specifier: ^9.24.0 + version: 9.24.0(jiti@2.4.2) eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) + specifier: ^10.1.1 + version: 10.1.1(eslint@9.24.0(jiti@2.4.2)) eslint-plugin-cypress: - specifier: ^2.15.1 - version: 2.15.1(eslint@8.57.0) + specifier: ^4.2.1 + version: 4.2.1(eslint@9.24.0(jiti@2.4.2)) eslint-plugin-html: - specifier: ^8.0.0 - version: 8.1.0 + specifier: ^8.1.2 + version: 8.1.2 eslint-plugin-jest: - specifier: ^27.9.0 - version: 27.9.0(@typescript-eslint/eslint-plugin@7.6.0)(eslint@8.57.0)(jest@29.7.0)(typescript@5.4.5) + specifier: ^28.11.0 + version: 28.11.0(@typescript-eslint/eslint-plugin@8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(jest@29.7.0(@types/node@22.13.5))(typescript@5.7.3) eslint-plugin-jsdoc: - specifier: ^48.2.1 - version: 48.2.3(eslint@8.57.0) + specifier: ^50.6.9 + version: 50.6.9(eslint@9.24.0(jiti@2.4.2)) eslint-plugin-json: - specifier: ^3.1.0 - version: 3.1.0 - eslint-plugin-lodash: - specifier: ^7.4.0 - version: 7.4.0(eslint@8.57.0) - eslint-plugin-markdown: specifier: ^4.0.1 - version: 4.0.1(eslint@8.57.0) + version: 4.0.1 + eslint-plugin-lodash: + specifier: ^8.0.0 + version: 8.0.0(eslint@9.24.0(jiti@2.4.2)) + eslint-plugin-markdown: + specifier: ^5.1.0 + version: 5.1.0(eslint@9.24.0(jiti@2.4.2)) eslint-plugin-no-only-tests: - specifier: ^3.1.0 - version: 3.1.0 + specifier: ^3.3.0 + version: 3.3.0 eslint-plugin-tsdoc: - specifier: ^0.2.17 - version: 0.2.17 + specifier: ^0.4.0 + version: 0.4.0 eslint-plugin-unicorn: - specifier: ^51.0.1 - version: 51.0.1(eslint@8.57.0) + specifier: ^58.0.0 + version: 58.0.0(eslint@9.24.0(jiti@2.4.2)) express: - specifier: ^4.19.1 - version: 4.19.2 + specifier: ^5.1.0 + version: 5.1.0 + globals: + specifier: ^16.0.0 + version: 16.0.0 globby: - specifier: ^14.0.1 - version: 14.0.1 + specifier: ^14.0.2 + version: 14.1.0 husky: - specifier: ^9.0.11 - version: 9.0.11 + specifier: ^9.1.7 + version: 9.1.7 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.12.7) + version: 29.7.0(@types/node@22.13.5) jison: specifier: ^0.4.18 version: 0.4.18 @@ -149,71 +161,83 @@ importers: specifier: ^4.1.0 version: 4.1.0 jsdom: - specifier: ^24.0.0 - version: 24.0.0 + specifier: ^26.0.0 + version: 26.0.0 langium-cli: - specifier: 3.0.1 - version: 3.0.1 + specifier: 3.3.0 + version: 3.3.0 lint-staged: - specifier: ^15.2.2 - version: 15.2.2 + specifier: ^15.2.11 + version: 15.4.3 markdown-table: - specifier: ^3.0.3 - version: 3.0.3 + specifier: ^3.0.4 + version: 3.0.4 nyc: - specifier: ^15.1.0 - version: 15.1.0 + specifier: ^17.1.0 + version: 17.1.0 path-browserify: specifier: ^1.0.1 version: 1.0.1 - pnpm: - specifier: ^8.15.5 - version: 8.15.7 prettier: - specifier: ^3.2.5 - version: 3.2.5 + specifier: ^3.5.2 + version: 3.5.2 prettier-plugin-jsdoc: - specifier: ^1.3.0 - version: 1.3.0(prettier@3.2.5) + specifier: ^1.3.2 + version: 1.3.2(prettier@3.5.2) rimraf: - specifier: ^5.0.5 - version: 5.0.5 + specifier: ^6.0.1 + version: 6.0.1 rollup-plugin-visualizer: - specifier: ^5.12.0 - version: 5.12.0 + specifier: ^5.14.0 + version: 5.14.0(rollup@4.34.8) start-server-and-test: - specifier: ^2.0.3 - version: 2.0.3 + specifier: ^2.0.10 + version: 2.0.10 + tslib: + specifier: ^2.8.1 + version: 2.8.1 tsx: - specifier: ^4.7.1 - version: 4.7.2 + specifier: ^4.7.3 + version: 4.19.3 typescript: - specifier: ^5.4.3 - version: 5.4.5 + specifier: ~5.7.3 + version: 5.7.3 + typescript-eslint: + specifier: ^8.29.1 + version: 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) vite: - specifier: ^5.2.3 - version: 5.2.8(@types/node@20.12.7) + specifier: ^6.1.1 + version: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) vite-plugin-istanbul: - specifier: ^6.0.0 - version: 6.0.0(vite@5.2.8) + specifier: ^7.0.0 + version: 7.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0)) vitest: - specifier: ^1.4.0 - version: 1.5.0(@types/node@20.12.7)(@vitest/ui@1.5.0)(jsdom@24.0.0) + specifier: ^3.0.6 + version: 3.0.6(@types/debug@4.1.12)(@types/node@22.13.5)(@vitest/ui@3.0.6)(jiti@2.4.2)(jsdom@26.0.0)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) packages/mermaid: dependencies: '@braintree/sanitize-url': - specifier: ^7.0.1 - version: 7.0.1 + specifier: ^7.0.4 + version: 7.1.0 + '@iconify/utils': + specifier: ^2.1.33 + version: 2.3.0 '@mermaid-js/parser': specifier: workspace:^ version: link:../parser + '@types/d3': + specifier: ^7.4.3 + version: 7.4.3 cytoscape: - specifier: ^3.28.1 - version: 3.28.1(patch_hash=claipxynndhyqyu2csninuoh5e) + specifier: ^3.29.3 + version: 3.31.0 cytoscape-cose-bilkent: specifier: ^4.1.0 - version: 4.1.0(cytoscape@3.28.1) + version: 4.1.0(cytoscape@3.31.0) + cytoscape-fcose: + specifier: ^2.2.0 + version: 2.2.0(cytoscape@3.31.0) d3: specifier: ^7.9.0 version: 7.9.0 @@ -221,69 +245,69 @@ importers: specifier: ^0.12.3 version: 0.12.3 dagre-d3-es: - specifier: 7.0.10 - version: 7.0.10 + specifier: 7.0.11 + version: 7.0.11 dayjs: - specifier: ^1.11.10 - version: 1.11.10 + specifier: ^1.11.13 + version: 1.11.13 dompurify: - specifier: ^3.0.11 - version: 3.1.0 - elkjs: - specifier: ^0.9.2 - version: 0.9.2 + specifier: ^3.2.5 + version: 3.2.5 katex: specifier: ^0.16.9 - version: 0.16.10 + version: 0.16.11 khroma: specifier: ^2.1.0 version: 2.1.0 lodash-es: specifier: ^4.17.21 version: 4.17.21 - mdast-util-from-markdown: - specifier: ^2.0.0 - version: 2.0.0 + marked: + specifier: ^15.0.7 + version: 15.0.7 + roughjs: + specifier: ^4.6.6 + version: 4.6.6(patch_hash=3543d47108cb41b68ec6a671c0e1f9d0cfe2ce524fea5b0992511ae84c3c6b64) stylis: - specifier: ^4.3.1 - version: 4.3.1 + specifier: ^4.3.6 + version: 4.3.6 ts-dedent: specifier: ^2.2.0 version: 2.2.0 uuid: - specifier: ^9.0.1 - version: 9.0.1 + specifier: ^11.1.0 + version: 11.1.0 devDependencies: '@adobe/jsonschema2md': - specifier: ^8.0.0 + specifier: ^8.0.2 version: 8.0.2 + '@iconify/types': + specifier: ^2.0.0 + version: 2.0.0 '@types/cytoscape': - specifier: ^3.19.16 - version: 3.21.0 - '@types/d3': - specifier: ^7.4.3 - version: 7.4.3 + specifier: ^3.21.9 + version: 3.21.9 + '@types/cytoscape-fcose': + specifier: ^2.2.4 + version: 2.2.4 '@types/d3-sankey': specifier: ^0.12.4 version: 0.12.4 '@types/d3-scale': - specifier: ^4.0.8 - version: 4.0.8 + specifier: ^4.0.9 + version: 4.0.9 '@types/d3-scale-chromatic': - specifier: ^3.0.3 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 '@types/d3-selection': - specifier: ^3.0.10 - version: 3.0.10 + specifier: ^3.0.11 + version: 3.0.11 '@types/d3-shape': - specifier: ^3.1.6 - version: 3.1.6 - '@types/dompurify': - specifier: ^3.0.5 - version: 3.0.5 + specifier: ^3.1.7 + version: 3.1.7 '@types/jsdom': - specifier: ^21.1.6 - version: 21.1.6 + specifier: ^21.1.7 + version: 21.1.7 '@types/katex': specifier: ^0.16.7 version: 0.16.7 @@ -291,41 +315,29 @@ importers: specifier: ^4.17.12 version: 4.17.12 '@types/micromatch': - specifier: ^4.0.6 - version: 4.0.7 - '@types/prettier': - specifier: ^3.0.0 - version: 3.0.0 + specifier: ^4.0.9 + version: 4.0.9 '@types/stylis': - specifier: ^4.2.5 - version: 4.2.5 + specifier: ^4.2.7 + version: 4.2.7 '@types/uuid': - specifier: ^9.0.8 - version: 9.0.8 - '@typescript-eslint/eslint-plugin': - specifier: ^7.3.1 - version: 7.6.0(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/parser': - specifier: ^7.3.1 - version: 7.6.0(eslint@8.57.0)(typescript@5.4.5) + specifier: ^10.0.0 + version: 10.0.0 ajv: - specifier: ^8.12.0 - version: 8.12.0 + specifier: ^8.17.1 + version: 8.17.1 chokidar: - specifier: ^3.6.0 - version: 3.6.0 + specifier: ^4.0.3 + version: 4.0.3 concurrently: - specifier: ^8.2.2 - version: 8.2.2 - cpy-cli: - specifier: ^5.0.0 - version: 5.0.0 + specifier: ^9.1.2 + version: 9.1.2 csstree-validator: - specifier: ^3.0.0 - version: 3.0.0 + specifier: ^4.0.1 + version: 4.0.1 globby: - specifier: ^14.0.1 - version: 14.0.1 + specifier: ^14.0.2 + version: 14.1.0 jison: specifier: ^0.4.18 version: 0.4.18 @@ -333,20 +345,20 @@ importers: specifier: ^3.7.7 version: 3.7.7 jsdom: - specifier: ^24.0.0 - version: 24.0.0 + specifier: ^26.0.0 + version: 26.0.0 json-schema-to-typescript: - specifier: ^13.1.2 - version: 13.1.2 + specifier: ^15.0.4 + version: 15.0.4 micromatch: - specifier: ^4.0.5 - version: 4.0.5 + specifier: ^4.0.8 + version: 4.0.8 path-browserify: specifier: ^1.0.1 version: 1.0.1 prettier: - specifier: ^3.2.5 - version: 3.2.5 + specifier: ^3.5.2 + version: 3.5.2 remark: specifier: ^15.0.1 version: 15.0.1 @@ -354,26 +366,26 @@ importers: specifier: ^5.0.0 version: 5.0.0 remark-gfm: - specifier: ^4.0.0 - version: 4.0.0 + specifier: ^4.0.1 + version: 4.0.1 rimraf: - specifier: ^5.0.5 - version: 5.0.5 + specifier: ^6.0.1 + version: 6.0.1 start-server-and-test: - specifier: ^2.0.3 - version: 2.0.3 + specifier: ^2.0.10 + version: 2.0.10 type-fest: - specifier: ^4.13.1 - version: 4.15.0 + specifier: ^4.35.0 + version: 4.35.0 typedoc: - specifier: ^0.25.12 - version: 0.25.13(typescript@5.4.5) + specifier: ^0.27.8 + version: 0.27.8(typescript@5.7.3) typedoc-plugin-markdown: - specifier: ^3.17.1 - version: 3.17.1(typedoc@0.25.13) + specifier: ^4.4.2 + version: 4.4.2(typedoc@0.27.8(typescript@5.7.3)) typescript: - specifier: ^5.4.3 - version: 5.4.5 + specifier: ~5.7.3 + version: 5.7.3 unist-util-flatmap: specifier: ^1.0.0 version: 1.0.0 @@ -381,17 +393,17 @@ importers: specifier: ^5.0.0 version: 5.0.0 vitepress: - specifier: ^1.0.1 - version: 1.1.0(@algolia/client-search@4.23.3)(@types/node@20.12.7)(postcss@8.4.38)(search-insights@2.13.0)(typescript@5.4.5) + specifier: ^1.0.2 + version: 1.6.3(@algolia/client-search@5.20.3)(@types/node@22.13.5)(axios@1.8.4)(postcss@8.5.3)(search-insights@2.17.2)(terser@5.39.0)(typescript@5.7.3) vitepress-plugin-search: specifier: 1.0.4-alpha.22 - version: 1.0.4-alpha.22(flexsearch@0.7.43)(vitepress@1.1.0)(vue@3.4.21) + version: 1.0.4-alpha.22(flexsearch@0.7.43)(vitepress@1.6.3(@algolia/client-search@5.20.3)(@types/node@22.13.5)(axios@1.8.4)(postcss@8.5.3)(search-insights@2.17.2)(terser@5.39.0)(typescript@5.7.3))(vue@3.5.13(typescript@5.7.3)) packages/mermaid-example-diagram: dependencies: '@braintree/sanitize-url': - specifier: ^7.0.0 - version: 7.0.1 + specifier: ^7.0.4 + version: 7.1.0 d3: specifier: ^7.9.0 version: 7.9.0 @@ -400,45 +412,36 @@ importers: version: 2.1.0 devDependencies: concurrently: - specifier: ^8.2.2 - version: 8.2.2 + specifier: ^9.1.2 + version: 9.1.2 mermaid: specifier: workspace:* version: link:../mermaid rimraf: - specifier: ^5.0.5 - version: 5.0.5 + specifier: ^6.0.1 + version: 6.0.1 - packages/mermaid-flowchart-elk: + packages/mermaid-layout-elk: dependencies: d3: specifier: ^7.9.0 version: 7.9.0 - dagre-d3-es: - specifier: 7.0.10 - version: 7.0.10 elkjs: - specifier: ^0.9.2 - version: 0.9.2 - khroma: - specifier: ^2.1.0 - version: 2.1.0 + specifier: ^0.9.3 + version: 0.9.3 devDependencies: - concurrently: - specifier: ^8.2.2 - version: 8.2.2 + '@types/d3': + specifier: ^7.4.3 + version: 7.4.3 mermaid: specifier: workspace:^ version: link:../mermaid - rimraf: - specifier: ^5.0.5 - version: 5.0.5 packages/mermaid-zenuml: dependencies: '@zenuml/core': - specifier: ^3.19.2 - version: 3.21.2(typescript@5.4.5) + specifier: ^3.23.28 + version: 3.27.12(typescript@5.7.3) devDependencies: mermaid: specifier: workspace:^ @@ -447,69 +450,69 @@ importers: packages/mermaid/src/docs: dependencies: '@mdi/font': - specifier: ^7.0.0 + specifier: ^7.4.47 version: 7.4.47 '@vueuse/core': - specifier: ^10.9.0 - version: 10.9.0(vue@3.4.21) + specifier: ^13.1.0 + version: 13.1.0(vue@3.5.13(typescript@5.7.3)) font-awesome: specifier: ^4.7.0 version: 4.7.0 jiti: - specifier: ^1.21.0 - version: 1.21.0 + specifier: ^2.4.2 + version: 2.4.2 mermaid: specifier: workspace:^ version: link:../.. vue: - specifier: ^3.4.21 - version: 3.4.21(typescript@5.4.5) + specifier: ^3.4.38 + version: 3.5.13(typescript@5.7.3) devDependencies: '@iconify-json/carbon': - specifier: ^1.1.31 - version: 1.1.31 + specifier: ^1.1.37 + version: 1.2.1 '@unocss/reset': - specifier: ^0.59.0 - version: 0.59.2 + specifier: ^66.0.0 + version: 66.0.0 '@vite-pwa/vitepress': - specifier: ^0.4.0 - version: 0.4.0(vite-plugin-pwa@0.19.8) + specifier: ^1.0.0 + version: 1.0.0(vite-plugin-pwa@1.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0)) '@vitejs/plugin-vue': - specifier: ^5.0.0 - version: 5.0.4(vite@5.2.8)(vue@3.4.21) + specifier: ^5.0.5 + version: 5.2.1(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) fast-glob: - specifier: ^3.3.2 - version: 3.3.2 + specifier: ^3.3.3 + version: 3.3.3 https-localhost: specifier: ^4.7.1 version: 4.7.1 pathe: - specifier: ^1.1.2 - version: 1.1.2 + specifier: ^2.0.3 + version: 2.0.3 unocss: - specifier: ^0.59.0 - version: 0.59.2(postcss@8.4.38)(rollup@2.79.1)(vite@5.2.8) + specifier: ^66.0.0 + version: 66.0.0(postcss@8.5.3)(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) unplugin-vue-components: - specifier: ^0.26.0 - version: 0.26.0(rollup@2.79.1)(vue@3.4.21) + specifier: ^28.4.0 + version: 28.4.0(@babel/parser@7.26.9)(vue@3.5.13(typescript@5.7.3)) vite: - specifier: ^5.0.0 - version: 5.2.8(@types/node@20.12.7) + specifier: ^6.1.1 + version: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) vite-plugin-pwa: - specifier: ^0.19.7 - version: 0.19.8(vite@5.2.8)(workbox-build@7.0.0)(workbox-window@7.0.0) + specifier: ^1.0.0 + version: 1.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0) vitepress: - specifier: 1.1.0 - version: 1.1.0(@algolia/client-search@4.23.3)(@types/node@20.12.7)(postcss@8.4.38)(search-insights@2.13.0)(typescript@5.4.5) + specifier: 1.6.3 + version: 1.6.3(@algolia/client-search@5.20.3)(@types/node@22.13.5)(axios@1.8.4)(postcss@8.5.3)(search-insights@2.17.2)(terser@5.39.0)(typescript@5.7.3) workbox-window: - specifier: ^7.0.0 - version: 7.0.0 + specifier: ^7.3.0 + version: 7.3.0 packages/parser: dependencies: langium: - specifier: 3.0.0 - version: 3.0.0 + specifier: 3.3.1 + version: 3.3.1 devDependencies: chevrotain: specifier: ^11.0.3 @@ -526,2298 +529,1302 @@ importers: devDependencies: webpack: specifier: ^5.91.0 - version: 5.91.0(esbuild@0.20.2)(webpack-cli@4.10.0) + version: 5.95.0(esbuild@0.25.0)(webpack-cli@4.10.0) webpack-cli: specifier: ^4.10.0 - version: 4.10.0(webpack-dev-server@4.15.2)(webpack@5.91.0) + version: 4.10.0(webpack-dev-server@4.15.2)(webpack@5.95.0) webpack-dev-server: specifier: ^4.15.2 - version: 4.15.2(webpack-cli@4.10.0)(webpack@5.91.0) + version: 4.15.2(webpack-cli@4.10.0)(webpack@5.95.0) packages: - /@aashutoshrathi/word-wrap@1.2.6: - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - dev: true + '@actions/core@1.11.1': + resolution: {integrity: sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==} - /@adobe/jsonschema2md@8.0.2: + '@actions/exec@1.1.1': + resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==} + + '@actions/http-client@2.2.3': + resolution: {integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==} + + '@actions/io@1.1.3': + resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==} + + '@adobe/jsonschema2md@8.0.2': resolution: {integrity: sha512-g90Rtz1Xghp9HTfbtBH2Pf5IpuUY1Ry9Wps5NNuNmxucbtmnCY4/1KXmtwe0yKxnknPF7nt5/Y8TOekMh450tQ==} engines: {node: ^18.0.0 || >= 20.0.0} hasBin: true - dependencies: - '@types/json-schema': 7.0.15 - '@types/mdast': 4.0.3 - es2015-i18n-tag: 1.6.1 - ferrum: 1.9.4 - fs-extra: 11.2.0 - github-slugger: 2.0.0 - js-yaml: 4.1.0 - json-schema: 0.4.0 - mdast-builder: 1.1.1 - mdast-util-to-string: 4.0.0 - readdirp: 3.6.0 - remark-gfm: 4.0.0 - remark-parse: 11.0.0 - remark-stringify: 11.0.0 - unified: 11.0.4 - unist-util-inspect: 8.0.0 - yargs: 17.7.2 - transitivePeerDependencies: - - supports-color - dev: true - /@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.23.3)(algoliasearch@4.23.3)(search-insights@2.13.0): - resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==} - dependencies: - '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@4.23.3)(algoliasearch@4.23.3)(search-insights@2.13.0) - '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.23.3)(algoliasearch@4.23.3) - transitivePeerDependencies: - - '@algolia/client-search' - - algoliasearch - - search-insights - dev: true + '@algolia/autocomplete-core@1.17.7': + resolution: {integrity: sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==} - /@algolia/autocomplete-plugin-algolia-insights@1.9.3(@algolia/client-search@4.23.3)(algoliasearch@4.23.3)(search-insights@2.13.0): - resolution: {integrity: sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==} + '@algolia/autocomplete-plugin-algolia-insights@1.17.7': + resolution: {integrity: sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==} peerDependencies: search-insights: '>= 1 < 3' - dependencies: - '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.23.3)(algoliasearch@4.23.3) - search-insights: 2.13.0 - transitivePeerDependencies: - - '@algolia/client-search' - - algoliasearch - dev: true - /@algolia/autocomplete-preset-algolia@1.9.3(@algolia/client-search@4.23.3)(algoliasearch@4.23.3): - resolution: {integrity: sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==} + '@algolia/autocomplete-preset-algolia@1.17.7': + resolution: {integrity: sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==} peerDependencies: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' - dependencies: - '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.23.3)(algoliasearch@4.23.3) - '@algolia/client-search': 4.23.3 - algoliasearch: 4.23.3 - dev: true - /@algolia/autocomplete-shared@1.9.3(@algolia/client-search@4.23.3)(algoliasearch@4.23.3): - resolution: {integrity: sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==} + '@algolia/autocomplete-shared@1.17.7': + resolution: {integrity: sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==} peerDependencies: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' - dependencies: - '@algolia/client-search': 4.23.3 - algoliasearch: 4.23.3 - dev: true - /@algolia/cache-browser-local-storage@4.23.3: - resolution: {integrity: sha512-vRHXYCpPlTDE7i6UOy2xE03zHF2C8MEFjPN2v7fRbqVpcOvAUQK81x3Kc21xyb5aSIpYCjWCZbYZuz8Glyzyyg==} - dependencies: - '@algolia/cache-common': 4.23.3 - dev: true + '@algolia/client-abtesting@5.20.3': + resolution: {integrity: sha512-wPOzHYSsW+H97JkBLmnlOdJSpbb9mIiuNPycUCV5DgzSkJFaI/OFxXfZXAh1gqxK+hf0miKue1C9bltjWljrNA==} + engines: {node: '>= 14.0.0'} - /@algolia/cache-common@4.23.3: - resolution: {integrity: sha512-h9XcNI6lxYStaw32pHpB1TMm0RuxphF+Ik4o7tcQiodEdpKK+wKufY6QXtba7t3k8eseirEMVB83uFFF3Nu54A==} - dev: true + '@algolia/client-analytics@5.20.3': + resolution: {integrity: sha512-XE3iduH9lA7iTQacDGofBQyIyIgaX8qbTRRdj1bOCmfzc9b98CoiMwhNwdTifmmMewmN0EhVF3hP8KjKWwX7Yw==} + engines: {node: '>= 14.0.0'} - /@algolia/cache-in-memory@4.23.3: - resolution: {integrity: sha512-yvpbuUXg/+0rbcagxNT7un0eo3czx2Uf0y4eiR4z4SD7SiptwYTpbuS0IHxcLHG3lq22ukx1T6Kjtk/rT+mqNg==} - dependencies: - '@algolia/cache-common': 4.23.3 - dev: true + '@algolia/client-common@5.20.3': + resolution: {integrity: sha512-IYRd/A/R3BXeaQVT2805lZEdWo54v39Lqa7ABOxIYnUvX2vvOMW1AyzCuT0U7Q+uPdD4UW48zksUKRixShcWxA==} + engines: {node: '>= 14.0.0'} - /@algolia/client-account@4.23.3: - resolution: {integrity: sha512-hpa6S5d7iQmretHHF40QGq6hz0anWEHGlULcTIT9tbUssWUriN9AUXIFQ8Ei4w9azD0hc1rUok9/DeQQobhQMA==} - dependencies: - '@algolia/client-common': 4.23.3 - '@algolia/client-search': 4.23.3 - '@algolia/transporter': 4.23.3 - dev: true + '@algolia/client-insights@5.20.3': + resolution: {integrity: sha512-QGc/bmDUBgzB71rDL6kihI2e1Mx6G6PxYO5Ks84iL3tDcIel1aFuxtRF14P8saGgdIe1B6I6QkpkeIddZ6vWQw==} + engines: {node: '>= 14.0.0'} - /@algolia/client-analytics@4.23.3: - resolution: {integrity: sha512-LBsEARGS9cj8VkTAVEZphjxTjMVCci+zIIiRhpFun9jGDUlS1XmhCW7CTrnaWeIuCQS/2iPyRqSy1nXPjcBLRA==} - dependencies: - '@algolia/client-common': 4.23.3 - '@algolia/client-search': 4.23.3 - '@algolia/requester-common': 4.23.3 - '@algolia/transporter': 4.23.3 - dev: true + '@algolia/client-personalization@5.20.3': + resolution: {integrity: sha512-zuM31VNPDJ1LBIwKbYGz/7+CSm+M8EhlljDamTg8AnDilnCpKjBebWZR5Tftv/FdWSro4tnYGOIz1AURQgZ+tQ==} + engines: {node: '>= 14.0.0'} - /@algolia/client-common@4.23.3: - resolution: {integrity: sha512-l6EiPxdAlg8CYhroqS5ybfIczsGUIAC47slLPOMDeKSVXYG1n0qGiz4RjAHLw2aD0xzh2EXZ7aRguPfz7UKDKw==} - dependencies: - '@algolia/requester-common': 4.23.3 - '@algolia/transporter': 4.23.3 - dev: true + '@algolia/client-query-suggestions@5.20.3': + resolution: {integrity: sha512-Nn872PuOI8qzi1bxMMhJ0t2AzVBqN01jbymBQOkypvZHrrjZPso3iTpuuLLo9gi3yc/08vaaWTAwJfPhxPwJUw==} + engines: {node: '>= 14.0.0'} - /@algolia/client-personalization@4.23.3: - resolution: {integrity: sha512-3E3yF3Ocr1tB/xOZiuC3doHQBQ2zu2MPTYZ0d4lpfWads2WTKG7ZzmGnsHmm63RflvDeLK/UVx7j2b3QuwKQ2g==} - dependencies: - '@algolia/client-common': 4.23.3 - '@algolia/requester-common': 4.23.3 - '@algolia/transporter': 4.23.3 - dev: true + '@algolia/client-search@5.20.3': + resolution: {integrity: sha512-9+Fm1ahV8/2goSIPIqZnVitV5yHW5E5xTdKy33xnqGd45A9yVv5tTkudWzEXsbfBB47j9Xb3uYPZjAvV5RHbKA==} + engines: {node: '>= 14.0.0'} - /@algolia/client-search@4.23.3: - resolution: {integrity: sha512-P4VAKFHqU0wx9O+q29Q8YVuaowaZ5EM77rxfmGnkHUJggh28useXQdopokgwMeYw2XUht49WX5RcTQ40rZIabw==} - dependencies: - '@algolia/client-common': 4.23.3 - '@algolia/requester-common': 4.23.3 - '@algolia/transporter': 4.23.3 - dev: true + '@algolia/ingestion@1.20.3': + resolution: {integrity: sha512-5GHNTiZ3saLjTNyr6WkP5hzDg2eFFAYWomvPcm9eHWskjzXt8R0IOiW9kkTS6I6hXBwN5H9Zna5mZDSqqJdg+g==} + engines: {node: '>= 14.0.0'} - /@algolia/logger-common@4.23.3: - resolution: {integrity: sha512-y9kBtmJwiZ9ZZ+1Ek66P0M68mHQzKRxkW5kAAXYN/rdzgDN0d2COsViEFufxJ0pb45K4FRcfC7+33YB4BLrZ+g==} - dev: true + '@algolia/monitoring@1.20.3': + resolution: {integrity: sha512-KUWQbTPoRjP37ivXSQ1+lWMfaifCCMzTnEcEnXwAmherS5Tp7us6BAqQDMGOD4E7xyaS2I8pto6WlOzxH+CxmA==} + engines: {node: '>= 14.0.0'} - /@algolia/logger-console@4.23.3: - resolution: {integrity: sha512-8xoiseoWDKuCVnWP8jHthgaeobDLolh00KJAdMe9XPrWPuf1by732jSpgy2BlsLTaT9m32pHI8CRfrOqQzHv3A==} - dependencies: - '@algolia/logger-common': 4.23.3 - dev: true + '@algolia/recommend@5.20.3': + resolution: {integrity: sha512-oo/gG77xTTTclkrdFem0Kmx5+iSRFiwuRRdxZETDjwzCI7svutdbwBgV/Vy4D4QpYaX4nhY/P43k84uEowCE4Q==} + engines: {node: '>= 14.0.0'} - /@algolia/recommend@4.23.3: - resolution: {integrity: sha512-9fK4nXZF0bFkdcLBRDexsnGzVmu4TSYZqxdpgBW2tEyfuSSY54D4qSRkLmNkrrz4YFvdh2GM1gA8vSsnZPR73w==} - dependencies: - '@algolia/cache-browser-local-storage': 4.23.3 - '@algolia/cache-common': 4.23.3 - '@algolia/cache-in-memory': 4.23.3 - '@algolia/client-common': 4.23.3 - '@algolia/client-search': 4.23.3 - '@algolia/logger-common': 4.23.3 - '@algolia/logger-console': 4.23.3 - '@algolia/requester-browser-xhr': 4.23.3 - '@algolia/requester-common': 4.23.3 - '@algolia/requester-node-http': 4.23.3 - '@algolia/transporter': 4.23.3 - dev: true + '@algolia/requester-browser-xhr@5.20.3': + resolution: {integrity: sha512-BkkW7otbiI/Er1AiEPZs1h7lxbtSO9p09jFhv3/iT8/0Yz0CY79VJ9iq+Wv1+dq/l0OxnMpBy8mozrieGA3mXQ==} + engines: {node: '>= 14.0.0'} - /@algolia/requester-browser-xhr@4.23.3: - resolution: {integrity: sha512-jDWGIQ96BhXbmONAQsasIpTYWslyjkiGu0Quydjlowe+ciqySpiDUrJHERIRfELE5+wFc7hc1Q5hqjGoV7yghw==} - dependencies: - '@algolia/requester-common': 4.23.3 - dev: true + '@algolia/requester-fetch@5.20.3': + resolution: {integrity: sha512-eAVlXz7UNzTsA1EDr+p0nlIH7WFxo7k3NMxYe8p38DH8YVWLgm2MgOVFUMNg9HCi6ZNOi/A2w/id2ZZ4sKgUOw==} + engines: {node: '>= 14.0.0'} - /@algolia/requester-common@4.23.3: - resolution: {integrity: sha512-xloIdr/bedtYEGcXCiF2muajyvRhwop4cMZo+K2qzNht0CMzlRkm8YsDdj5IaBhshqfgmBb3rTg4sL4/PpvLYw==} - dev: true + '@algolia/requester-node-http@5.20.3': + resolution: {integrity: sha512-FqR3pQPfHfQyX1wgcdK6iyqu86yP76MZd4Pzj1y/YLMj9rRmRCY0E0AffKr//nrOFEwv6uY8BQY4fd9/6b0ZCg==} + engines: {node: '>= 14.0.0'} - /@algolia/requester-node-http@4.23.3: - resolution: {integrity: sha512-zgu++8Uj03IWDEJM3fuNl34s746JnZOWn1Uz5taV1dFyJhVM/kTNw9Ik7YJWiUNHJQXcaD8IXD1eCb0nq/aByA==} - dependencies: - '@algolia/requester-common': 4.23.3 - dev: true - - /@algolia/transporter@4.23.3: - resolution: {integrity: sha512-Wjl5gttqnf/gQKJA+dafnD0Y6Yw97yvfY8R9h0dQltX1GXTgNs1zWgvtWW0tHl1EgMdhAyw189uWiZMnL3QebQ==} - dependencies: - '@algolia/cache-common': 4.23.3 - '@algolia/logger-common': 4.23.3 - '@algolia/requester-common': 4.23.3 - dev: true - - /@alloc/quick-lru@5.2.0: + '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} - dev: false - /@ampproject/remapping@2.3.0: + '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - /@antfu/install-pkg@0.1.1: - resolution: {integrity: sha512-LyB/8+bSfa0DFGC06zpCEfs89/XoWZwws5ygEa5D+Xsm3OfI+aXQ86VgVG7Acyef+rSZ5HE7J8rrxzrQeM3PjQ==} - dependencies: - execa: 5.1.1 - find-up: 5.0.0 - dev: true + '@antfu/install-pkg@1.0.0': + resolution: {integrity: sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw==} - /@antfu/utils@0.7.6: - resolution: {integrity: sha512-pvFiLP2BeOKA/ZOS6jxx4XhKzdVLHDhGlFEaZ2flWWYf2xOqVniqpk38I04DFRyz+L0ASggl7SkItTc+ZLju4w==} - dev: true + '@antfu/utils@8.1.1': + resolution: {integrity: sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==} - /@antfu/utils@0.7.7: - resolution: {integrity: sha512-gFPqTG7otEJ8uP6wrhDv6mqwGWYZKNvAcCq6u9hOj0c+IKCEsY4L1oC9trPq2SaWIzAfHvqfBDxF591JkMf+kg==} - dev: true - - /@apideck/better-ajv-errors@0.3.6(ajv@8.12.0): + '@apideck/better-ajv-errors@0.3.6': resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==} engines: {node: '>=10'} peerDependencies: ajv: '>=8' - dependencies: - ajv: 8.12.0 - json-schema: 0.4.0 - jsonpointer: 5.0.1 - leven: 3.1.0 - dev: true - /@applitools/core-base@1.10.1: - resolution: {integrity: sha512-s4q72eyPLaV1D5xXH1He72y/yCdSihL4oNs6vRe+IxP2CSDH8b42B+8Ps2nAPMNxatp7nzpHq/jRfXHv24Z1ZQ==} + '@apidevtools/json-schema-ref-parser@11.9.1': + resolution: {integrity: sha512-OvyhwtYaWSTfo8NfibmFlgl+pIMaBOmN0OwZ3CPaGscEK3B8FCVDuQ7zgxY8seU/1kfSvNWnyB0DtKJyNLxX7g==} + engines: {node: '>= 16'} + + '@applitools/core-base@1.22.1': + resolution: {integrity: sha512-5pHJgSjD6sGpWGrNzQsHasqkO8ROQ65z1F/dE+pITFfanreyoSrr8FLwwjQMiLq/Ggryt69PoAPXd7/N8vf0vg==} engines: {node: '>=12.13.0'} - dependencies: - '@applitools/image': 1.1.9 - '@applitools/logger': 2.0.14 - '@applitools/req': 1.6.5 - '@applitools/utils': 1.7.0 - abort-controller: 3.0.0 - throat: 6.0.2 - transitivePeerDependencies: - - supports-color - dev: true - /@applitools/core@4.11.1(typescript@5.4.5): - resolution: {integrity: sha512-j+LbBn6e7KMONzacFNI+VxEJjBB+3TxxntJrhzBJE9hUzhLuXYR8+oVcpJf0FHyfwruUEF9Fsi+A2K++d3uG5g==} + '@applitools/core@4.31.2': + resolution: {integrity: sha512-Na/VOO1ab3Ne+BIbX8JQWflFPj5OkhOgTia9xoXq7B4z3BoVY/37eXl3wzbVn0uQJqVuvwhe2MfCwnQ7dI2eaA==} engines: {node: '>=12.13.0'} hasBin: true - dependencies: - '@applitools/core-base': 1.10.1 - '@applitools/dom-capture': 11.2.6 - '@applitools/dom-snapshot': 4.9.2 - '@applitools/driver': 1.16.5 - '@applitools/ec-client': 1.7.32(typescript@5.4.5) - '@applitools/logger': 2.0.14 - '@applitools/nml-client': 1.7.5 - '@applitools/req': 1.6.5 - '@applitools/screenshoter': 3.8.27 - '@applitools/snippets': 2.4.25 - '@applitools/socket': 1.1.14 - '@applitools/spec-driver-webdriver': 1.1.3(webdriver@7.31.1) - '@applitools/ufg-client': 1.10.2 - '@applitools/utils': 1.7.0 - '@types/ws': 8.5.5 - abort-controller: 3.0.0 - chalk: 4.1.2 - node-fetch: 2.6.7(encoding@0.1.13) - semver: 7.5.4 - webdriver: 7.31.1(typescript@5.4.5) - ws: 8.13.0 - yargs: 17.7.2 - transitivePeerDependencies: - - bufferutil - - encoding - - supports-color - - typescript - - utf-8-validate - dev: true - /@applitools/css-tree@1.1.2: - resolution: {integrity: sha512-+DBY7Rf/PorHniPYNNG9rDbQcjuXvrVTx3vXXMz7h4m8h8wjUDq5afIUQ9QSTj3H8awXKHRg1o9XJl5yA6cxOg==} + '@applitools/css-tree@1.1.4': + resolution: {integrity: sha512-rH3aq/dkTweEUgS/MKuthD79CZDqpQVJlqmxqVxLZVAzbeFxYdTG/gnfG0zj6YJ025jzcPH2ktdW16Rl3QLutg==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - dependencies: - mdn-data: 2.1.0 - source-map-js: 1.0.1 - dev: true - /@applitools/dom-capture@11.2.6: - resolution: {integrity: sha512-USNpYDaj+L8GcPX0pJFHbDpaHc/IFWJVvFiGrOWylgPPinBWtco52mj7lv5urSX9rVyxEF41awszA2BOFOIV3Q==} + '@applitools/dom-capture@11.5.4': + resolution: {integrity: sha512-3n2wLLsXpGGiYrSkHnwgFsTXZntvw5MXtt6n0Kbpyi3mqBgdZ3yPt/9tJ+pQZDX/xe9mNXUVClHXmWmVCrGPCA==} engines: {node: '>=12.13.0'} - dependencies: - '@applitools/dom-shared': 1.0.13 - '@applitools/functional-commons': 1.6.0 - dev: true - /@applitools/dom-shared@1.0.13: - resolution: {integrity: sha512-FcZKhdnPcV42IT9tPK80Tlzs6Xxsv11hgfgMqKscOOtgZ02xK9d8w1tuSMRO9VFDzCLaEFe/QSLk8/FgrDMy7w==} + '@applitools/dom-shared@1.0.16': + resolution: {integrity: sha512-P0JA5mq1f8rIi/xbh2+gCsEvv1CGenf0sGrC2UxXjmaFRpgoVS9BfpNg5aZyFJ9OPoi4qRMi9LCGsFiqZNNcTQ==} engines: {node: '>=12.13.0'} - dev: true - /@applitools/dom-snapshot@4.9.2: - resolution: {integrity: sha512-edAoScuJvrwbj6MSy7WCph1+eK9SMB+8UAAcbGRK1kTlvsRSYJ4fjMyw6A6tEhVKeRY/u6Byn0LELY2YmQukLQ==} + '@applitools/dom-snapshot@4.11.15': + resolution: {integrity: sha512-JsJ/2vTOywsxcwUMe9inGkHTBpMrnI09bCB7SJGRlbM4au4JAtMsyF5WnrbvrMlxr/kbe/BsJUDndswlkM9Duw==} engines: {node: '>=12.13.0'} - dependencies: - '@applitools/css-tree': 1.1.2 - '@applitools/dom-shared': 1.0.13 - '@applitools/functional-commons': 1.6.0 - pako: 1.0.11 - dev: true - /@applitools/driver@1.16.5: - resolution: {integrity: sha512-/KfxNXRKX02Ru8h55R402H2pOfwQv0XSLvg83T8rJJ6SuAAGsnT+a2orvHmj2tfb7hkEBoe1AuXdRZPdQVZLYg==} + '@applitools/driver@1.20.4': + resolution: {integrity: sha512-Lm1x6Bw66nqu7xtzRQoC3+DQb1PjZiC1DiyXi7L0YzR2c/JhQCyZ1uWWb8NrrLKctwv3SgohXZMaV90TIpAdQw==} engines: {node: '>=12.13.0'} - dependencies: - '@applitools/logger': 2.0.14 - '@applitools/snippets': 2.4.25 - '@applitools/utils': 1.7.0 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - dev: true - /@applitools/ec-client@1.7.32(typescript@5.4.5): - resolution: {integrity: sha512-jwjrcpuQLAEManS3V5bCB6BMgl4+/SL95uRwM8yIRQpHw0+l0w6yTuqOAmrygPHTKphHNjDurDia0lmt30IrQA==} + '@applitools/ec-client@1.10.4': + resolution: {integrity: sha512-2+cs6jHG4HjG3UsswgIQOnjvMg7h/Ms7eerN5vkSXg0UE3/eqWaPz0VBv9+ihOHQOZwJX4BDBR791ZTsMG3XGw==} engines: {node: '>=12.13.0'} hasBin: true - dependencies: - '@applitools/core-base': 1.10.1 - '@applitools/driver': 1.16.5 - '@applitools/logger': 2.0.14 - '@applitools/req': 1.6.5 - '@applitools/socket': 1.1.14 - '@applitools/spec-driver-webdriver': 1.1.3(webdriver@7.31.1) - '@applitools/tunnel-client': 1.4.1 - '@applitools/utils': 1.7.0 - abort-controller: 3.0.0 - webdriver: 7.31.1(typescript@5.4.5) - yargs: 17.7.2 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - /@applitools/eg-frpc@1.0.5: + '@applitools/eg-frpc@1.0.5': resolution: {integrity: sha512-9qUNiCK3R3VKxIAaLr5HO5QnUx6TioLFkJ2JcpU1ZqefApt1X2bdfS7eA4TGDXDWv/a0OIl2Lddzuo5/h3vbTw==} engines: {node: '>=12.13.0'} - dev: true - /@applitools/eg-socks5-proxy-server@0.5.6: + '@applitools/eg-socks5-proxy-server@0.5.6': resolution: {integrity: sha512-SjjDBFeiKspX3nHKOoSQ+l4JUiJK3xJiWAEaR8b+GuMvnGFLnrvAECHhuXXG00+LwBJM8WKmfxEe17nvZe+nhg==} engines: {node: '>=12'} - dependencies: - binary: 0.3.0 - is-localhost-ip: 2.0.0 - dev: true - /@applitools/execution-grid-tunnel@2.1.10: - resolution: {integrity: sha512-d/haRUUehvfRQXu/idhxaWnJY0zThsjuGRz0wPTElQtLoYP2s5zmkrB0ahTqkLc9FsYdTrYKhFYWpp6R6yp17Q==} + '@applitools/execution-grid-tunnel@3.0.8': + resolution: {integrity: sha512-4S6NcpxELH4NXketD3g6VUhWDUCuwAm4F1sCZdZLpPWOSMu5QwQDYUoe6/4t5KuktTQ4K7N90NmTzQrxiFtDKA==} + engines: {node: '>=14.0.0'} + hasBin: true + + '@applitools/eyes-cypress@3.50.2': + resolution: {integrity: sha512-K8OIylLfkcNfbkM1VJ+ouudOFtGZaNKVxSVllP7BPKskYPWBjbHE3hSOsmvzYiY6SjdPmbBGLlgO2enrbuC/0w==} engines: {node: '>=12.13.0'} hasBin: true - dependencies: - '@applitools/eg-frpc': 1.0.5 - '@applitools/eg-socks5-proxy-server': 0.5.6 - '@applitools/logger': 1.1.53 - dotenv: 16.4.5 - encoding: 0.1.13 - fastify: 3.29.5 - fastify-plugin: 3.0.1 - find-process: 1.4.7 - ini: 3.0.1 - node-cleanup: 2.1.2 - node-fetch: 2.6.7(encoding@0.1.13) - p-retry: 4.6.2 - teen_process: 1.16.0 - transitivePeerDependencies: - - supports-color - dev: true - /@applitools/eyes-cypress@3.43.1(typescript@5.4.5): - resolution: {integrity: sha512-qq7vKsMRiZj1s21G9s1umma9NfDAeproqjygKcrEwMQ7+dGTpPrBbttC25S+Ge50a4PmIoZ6yao4FxKviC3J+Q==} + '@applitools/eyes@1.32.1': + resolution: {integrity: sha512-O6nKRmPTUSgt6yUlbRY8JEJOcq5Ch/yckLipgRRxBbqsL+l9f7JzZ2VCxTuwPkhjQ0tnsitWbz9QeRge5EN6yw==} engines: {node: '>=12.13.0'} hasBin: true - dependencies: - '@applitools/core': 4.11.1(typescript@5.4.5) - '@applitools/eyes': 1.17.1(typescript@5.4.5) - '@applitools/functional-commons': 1.6.0 - '@applitools/logger': 2.0.14 - '@applitools/utils': 1.7.0 - boxen: 5.1.2 - chalk: 3.0.0 - semver: 7.5.4 - uuid: 8.3.2 - ws: 8.5.0 - transitivePeerDependencies: - - bufferutil - - encoding - - supports-color - - typescript - - utf-8-validate - dev: true - /@applitools/eyes@1.17.1(typescript@5.4.5): - resolution: {integrity: sha512-kgDgILH4yuKBEve4J93Y9XXqF2GPfoEPbrSM3lJY4JUvTFl2q6czfAVtZO7HfQkTFuW4Q/YK2wZg/sTGCWznnQ==} - engines: {node: '>=12.13.0'} - dependencies: - '@applitools/core': 4.11.1(typescript@5.4.5) - '@applitools/logger': 2.0.14 - '@applitools/utils': 1.7.0 - transitivePeerDependencies: - - bufferutil - - encoding - - supports-color - - typescript - - utf-8-validate - dev: true - - /@applitools/functional-commons@1.6.0: + '@applitools/functional-commons@1.6.0': resolution: {integrity: sha512-fwiF0CbeYHDEOTD/NKaFgaI8LvRcGYG2GaJJiRwcedKko16sQ8F3TK5wXfj2Ytjf+8gjwHwsEEX550z3yvDWxA==} engines: {node: '>=8.0.0'} - dev: true - /@applitools/image@1.1.9: - resolution: {integrity: sha512-R86re+yofXSBamTuzSLwFB57fzaf7aiKvyx675uw8e/XfqQy3vhGbp8Bh23lUZX9y7ngf2ldrpnQ7nQrvmtJuA==} + '@applitools/image@1.1.16': + resolution: {integrity: sha512-vwTDcyzW7OT/PQfVFc1v2aSb48G4I4fzqmRa83wKI3YKt4HzuYYkzFS9OcoN8pSdQ5Kt8+if5gSfSxnYDhtZbw==} engines: {node: '>=12.13.0'} - dependencies: - '@applitools/utils': 1.7.0 - bmpimagejs: 1.0.4 - jpeg-js: 0.4.4 - omggif: 1.0.10 - png-async: 0.9.4 - dev: true - /@applitools/logger@1.1.53: + '@applitools/logger@1.1.53': resolution: {integrity: sha512-4mlzYxc0MgM3WIxEwKqIjn9W7G7kMtQc2bFRxozViKOXypTfr72j8iODs88wcetP0GsXtplhZQ5/6aZN5WY9ug==} engines: {node: '>=12.13.0'} - dependencies: - '@applitools/utils': 1.3.36 - chalk: 4.1.2 - debug: 4.3.3 - transitivePeerDependencies: - - supports-color - dev: true - /@applitools/logger@2.0.14: - resolution: {integrity: sha512-oq/RPjs/3BjR3EdLohHhzzVufBYEMMhOUmZlCnvgmCJIhUsa3ceq8Ta2E99TUzSny9xkl962JoRDfLQg/vS+Ww==} + '@applitools/logger@2.1.0': + resolution: {integrity: sha512-/7wYHRyte8ZoUNGis3lVeEjBdRHda2AcykOr4+3RM2TB8APO4qIPjDSEE5TDramUKzjKC+K4BSUAL39pn8w13w==} engines: {node: '>=12.13.0'} - dependencies: - '@applitools/utils': 1.7.0 - chalk: 4.1.2 - debug: 4.3.4(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - dev: true - /@applitools/nml-client@1.7.5: - resolution: {integrity: sha512-VeZy/aik9a9PMSE2NNq2LYgwu7FEj/hkGgwVv4M13jdH8/e+RI+fnjEVcky7hE6F1AjsY3HRHvbIrnUBDmF0/g==} + '@applitools/nml-client@1.8.24': + resolution: {integrity: sha512-BV6qONX/2FmFr2j2vRAK3F4irRvVwzYfoklpNataRSSK5ZW6Q+XVSI2uHjD1vVce4Haq7ECeVUkUFMpff1zkjw==} engines: {node: '>=12.13.0'} - dependencies: - '@applitools/logger': 2.0.14 - '@applitools/req': 1.6.5 - '@applitools/utils': 1.7.0 - transitivePeerDependencies: - - supports-color - dev: true - /@applitools/req@1.6.5: - resolution: {integrity: sha512-EV6SNrABc/MEknQ5hSEUm0TgNlcOQXLM5W7VV2nObuVOMu35XL4BuVJH9Wivg4WiV6O1ZJ2rvpZ9ju0x4DHFsQ==} + '@applitools/req@1.7.7': + resolution: {integrity: sha512-kqEu6TKdPe++53/QDOVWmqYqd2jZ0zoZ/FPPsPKvcHzIY4DFx0W/BhLl0KYXFYWKdE1slnkyyQfCqhKOP0umWw==} engines: {node: '>=16.13.0'} - dependencies: - '@applitools/utils': 1.7.0 - abort-controller: 3.0.0 - http-proxy-agent: 5.0.0 - https-proxy-agent: 5.0.1 - node-fetch: 3.3.1 - transitivePeerDependencies: - - supports-color - dev: true - /@applitools/screenshoter@3.8.27: - resolution: {integrity: sha512-YIByICLMOmfc7gDXIzT9Qc/lVeqzXKjkOu47aKncEmKy2pcOUkMDmbVdhlP+M7pRIaaoPOmsC0CQpdteTGFi/g==} + '@applitools/screenshoter@3.10.5': + resolution: {integrity: sha512-eeWae+HSUd/+J8pU0B7QdINR21sF/NHKEXW9duyOHd+GiGNsZxoWJGq1lVXxVx5QKfyrc87Gbbt3b5O+WOyIYg==} engines: {node: '>=12.13.0'} - dependencies: - '@applitools/image': 1.1.9 - '@applitools/logger': 2.0.14 - '@applitools/snippets': 2.4.25 - '@applitools/utils': 1.7.0 - transitivePeerDependencies: - - supports-color - dev: true - /@applitools/snippets@2.4.25: - resolution: {integrity: sha512-vnU9qq1IGkNpvh7Qy0m196t1u3mpx7NNUeHyJRVnJ53Ok4sb9s/KKrkrU9xYkKYY+T3AEvoN0Rp5LVVrKBHGQw==} + '@applitools/snippets@2.6.4': + resolution: {integrity: sha512-J9X2uqtt1LQNJsQy9X+1smXKlalKpLJpNRAIvepqGZaVOwG5eKxF7chMZSiztv2jVbZCJj7DRLZdfEueB7xjcA==} engines: {node: '>=12.13.0'} - dev: true - /@applitools/socket@1.1.14: - resolution: {integrity: sha512-o43hNnD/PN5T5MFR3cZ5OC+b5PpkV/PeTk8z844sNtGyziS9GEpO0vYfG2XLq/mZg0YQurrXtYupUMndV+0wDg==} + '@applitools/socket@1.2.1': + resolution: {integrity: sha512-OGMVkfOQBrJviVc1K4+kZMExMBTAMA5ZtF7DGrn7pqJQTAVTI7VL9ZXUELwiburMJS6ILNXOcBvi4z9l9adCig==} engines: {node: '>=12.13.0'} - dependencies: - '@applitools/logger': 2.0.14 - '@applitools/utils': 1.7.0 - transitivePeerDependencies: - - supports-color - dev: true - /@applitools/spec-driver-webdriver@1.1.3(webdriver@7.31.1): - resolution: {integrity: sha512-L9uhnKdX5Ts/FBS7J1Xq/SV9qQ6codgssKDPVwOytvQEhtJnohGRdnAIgRDdLANPq7j4JCV0SyeCNyYeljwErw==} + '@applitools/spec-driver-webdriver@1.1.25': + resolution: {integrity: sha512-grS0B/ityKqjCac2vJSVpvFnLyyRp5KODXxOQBjmPUGDeOd/aPrw+vdXdbEJOvMZV0oyOMenFLTJ6kT2WxgPMw==} engines: {node: '>=12.13.0'} peerDependencies: webdriver: '>=6.0.0' - dependencies: - '@applitools/driver': 1.16.5 - '@applitools/utils': 1.7.0 - http-proxy-agent: 5.0.0 - https-proxy-agent: 5.0.1 - webdriver: 7.31.1(typescript@5.4.5) - transitivePeerDependencies: - - supports-color - dev: true - /@applitools/tunnel-client@1.4.1: - resolution: {integrity: sha512-/oGPWwk+p6qu/u3IUNXA7ZG1jkC9myg3Jv3yu014+i8Ltd9dp+OcUCH8Q4kN/W8RFBjLcRvahpbzWNd0cnYWQA==} + '@applitools/tunnel-client@1.6.2': + resolution: {integrity: sha512-TZrb3ctsGnA2Pd4vF2GrOyzJJf5cX16LtJmrgKL+OfdMNJLKTPZ8PrUXElpjUcaYdjdE8bXpF+afmsWfwymqiQ==} engines: {node: '>=12.13.0'} hasBin: true - dependencies: - '@applitools/execution-grid-tunnel': 2.1.10 - '@applitools/logger': 2.0.14 - '@applitools/req': 1.6.5 - '@applitools/socket': 1.1.14 - '@applitools/utils': 1.7.0 - abort-controller: 3.0.0 - yargs: 17.7.2 - transitivePeerDependencies: - - supports-color - dev: true - /@applitools/ufg-client@1.10.2: - resolution: {integrity: sha512-2F2nSZwxnMF+zZ5wiQuOJhyAbD/s4Wui8zHet2YL69ZZkhDMtMwYLtU/6VtUd9ZrzSYtBX32KE2ynfWraZ+zbg==} + '@applitools/ufg-client@1.16.4': + resolution: {integrity: sha512-TTZEH3QW0EoTmgayrF8i+p3BXbqN/yfYDCQOrwwNPlGAvMNbPgfHYhZKiAOi4ecY5MwMLMxkOqTQ0MKS41wN7w==} engines: {node: '>=12.13.0'} - dependencies: - '@applitools/css-tree': 1.1.2 - '@applitools/image': 1.1.9 - '@applitools/logger': 2.0.14 - '@applitools/req': 1.6.5 - '@applitools/utils': 1.7.0 - '@xmldom/xmldom': 0.8.10 - abort-controller: 3.0.0 - throat: 6.0.2 - transitivePeerDependencies: - - supports-color - dev: true - /@applitools/utils@1.3.36: + '@applitools/utils@1.3.36': resolution: {integrity: sha512-eROEssh7wIW+V87PvLiHI2hUPxqoBxXFMRx3+z5qOZqXUPSR1Uz7EMFwxZcDDR7T6C3O3UDckB2aVB5fJAg5JA==} engines: {node: '>=12.13.0'} - dev: true - /@applitools/utils@1.7.0: - resolution: {integrity: sha512-CvBxdfPZ3ss1hOD8Yr9y2SzVfqLKBA/0N3gfQd5qafMrBhI0wuCycQmiclpAQNEVNkbhqn8/t6dOeeYgapjyDw==} + '@applitools/utils@1.7.7': + resolution: {integrity: sha512-4YQc/FGYmA4Jx8vRNRI6YOE8oa7tOWhCik3b1OV3RQ6OkAY5EpVRF8ruiFpX+9BIjZ2V5AdVpsJacYOIiCHNMg==} engines: {node: '>=12.13.0'} - dev: true - /@babel/code-frame@7.23.5: - resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} + '@argos-ci/api-client@0.8.1': + resolution: {integrity: sha512-3IHv7ANSPNO6OwWgwULlHbP9/tFV9kQDu6+nL9jysfPkGj0GgtrOsyBb+iU931c7wSMo1OD+XNujCnRzDD968w==} + engines: {node: '>=18.0.0'} + + '@argos-ci/browser@4.1.1': + resolution: {integrity: sha512-UyKdnprGftUjWQkb0jqJ0zGHJmcWBzdko8zRy4y+4efukVX4jjC/Px2HvWW8aqwjoR4aplouMZuzhmOkq2SCsA==} + engines: {node: '>=18.0.0'} + + '@argos-ci/core@3.1.1': + resolution: {integrity: sha512-7iE3o1XGxlfHC5AF05pzT0OxuO387sryrZt3gKGj/e+6R20DXz7J49yI8++nQ2cuT+wLhcJp8+X0ox+SGMYHmw==} + engines: {node: '>=18.0.0'} + + '@argos-ci/cypress@4.0.3': + resolution: {integrity: sha512-JGP48zPwbUGU5ziLP4Okv6mTuLPiEPvQ954BoH78ySlNpDGxyw68yeY4jxz8QpYe+P7vvKmuZiUFPAXTFu8XiQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + cypress: ^12.0.0 || ^13.0.0 || ^14.0.0 + + '@argos-ci/util@2.3.1': + resolution: {integrity: sha512-kE61HU2480fbAnimmA4x9HK45ZJvkoqLdW5GxT5uvwhkclQykVd2S6WfGFUr3JokTXfZ5LZEEfoWgtGA316KSQ==} + engines: {node: '>=18.0.0'} + + '@asamuzakjp/css-color@2.8.3': + resolution: {integrity: sha512-GIc76d9UI1hCvOATjZPyHFmE5qhRccp3/zGfMPapK3jBi+yocEzp6BBB0UnfRYP9NP4FANqUZYb0hnfs3TM3hw==} + + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.24.2 - chalk: 2.4.2 - dev: true - /@babel/code-frame@7.24.2: - resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} + '@babel/compat-data@7.26.8': + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.24.2 - picocolors: 1.0.0 - dev: true - /@babel/compat-data@7.24.4: - resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} + '@babel/core@7.26.9': + resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} engines: {node: '>=6.9.0'} - dev: true - /@babel/core@7.24.4: - resolution: {integrity: sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==} + '@babel/generator@7.26.9': + resolution: {integrity: sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==} engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.4 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) - '@babel/helpers': 7.24.4 - '@babel/parser': 7.24.4 - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.1 - '@babel/types': 7.24.0 - convert-source-map: 2.0.0 - debug: 4.3.4(supports-color@8.1.1) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/generator@7.24.4: - resolution: {integrity: sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==} + '@babel/helper-annotate-as-pure@7.25.9': + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - dev: true - /@babel/helper-annotate-as-pure@7.22.5: - resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + '@babel/helper-compilation-targets@7.26.5': + resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - /@babel/helper-builder-binary-assignment-operator-visitor@7.22.15: - resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-compilation-targets@7.23.6: - resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/helper-validator-option': 7.23.5 - browserslist: 4.23.0 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-create-class-features-plugin@7.24.4(@babel/core@7.24.4): - resolution: {integrity: sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==} + '@babel/helper-create-class-features-plugin@7.26.9': + resolution: {integrity: sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.4) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - semver: 6.3.1 - dev: true - /@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.24.4): - resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} + '@babel/helper-create-regexp-features-plugin@7.26.3': + resolution: {integrity: sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - regexpu-core: 5.3.2 - semver: 6.3.1 - dev: true - /@babel/helper-define-polyfill-provider@0.6.1(@babel/core@7.24.4): - resolution: {integrity: sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==} + '@babel/helper-define-polyfill-provider@0.6.3': + resolution: {integrity: sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.0 - debug: 4.3.4(supports-color@8.1.1) - lodash.debounce: 4.0.8 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/helper-environment-visitor@7.22.20: - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + '@babel/helper-member-expression-to-functions@7.25.9': + resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} engines: {node: '>=6.9.0'} - dev: true - /@babel/helper-function-name@7.23.0: - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.0 - dev: true - /@babel/helper-hoist-variables@7.22.5: - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-member-expression-to-functions@7.23.0: - resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-module-imports@7.24.3: - resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-module-transforms@7.23.3(@babel/core@7.24.4): - resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 - dev: true - /@babel/helper-optimise-call-expression@7.22.5: - resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} + '@babel/helper-optimise-call-expression@7.25.9': + resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - /@babel/helper-plugin-utils@7.24.0: - resolution: {integrity: sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==} + '@babel/helper-plugin-utils@7.25.7': + resolution: {integrity: sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==} engines: {node: '>=6.9.0'} - dev: true - /@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.24.4): - resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} + '@babel/helper-plugin-utils@7.26.5': + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.25.9': + resolution: {integrity: sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-wrap-function': 7.22.20 - dev: true - /@babel/helper-replace-supers@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==} + '@babel/helper-replace-supers@7.26.5': + resolution: {integrity: sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - dev: true - /@babel/helper-simple-access@7.22.5: - resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-skip-transparent-expression-wrappers@7.22.5: - resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-split-export-declaration@7.22.6: - resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-string-parser@7.23.4: - resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': + resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier@7.22.20: - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-option@7.23.5: - resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - dev: true - /@babel/helper-wrap-function@7.22.20: - resolution: {integrity: sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==} + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-function-name': 7.23.0 - '@babel/template': 7.24.0 - '@babel/types': 7.24.0 - dev: true - /@babel/helpers@7.24.4: - resolution: {integrity: sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==} + '@babel/helper-wrap-function@7.25.9': + resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.1 - '@babel/types': 7.24.0 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/highlight@7.24.2: - resolution: {integrity: sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==} + '@babel/helpers@7.26.9': + resolution: {integrity: sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.0.0 - dev: true - /@babel/parser@7.24.0: - resolution: {integrity: sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==} + '@babel/parser@7.26.9': + resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} engines: {node: '>=6.0.0'} hasBin: true - dependencies: - '@babel/types': 7.24.0 - /@babel/parser@7.24.1: - resolution: {integrity: sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.24.0 - - /@babel/parser@7.24.4: - resolution: {integrity: sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.24.0 - - /@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.4(@babel/core@7.24.4): - resolution: {integrity: sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA==} + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9': + resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==} + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9': + resolution: {integrity: sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==} + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9': + resolution: {integrity: sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9': + resolution: {integrity: sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.24.1(@babel/core@7.24.4) - dev: true - /@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==} + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9': + resolution: {integrity: sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.4): + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - dev: true - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.4): + '@babel/plugin-syntax-async-generators@7.8.4': resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.4): + '@babel/plugin-syntax-bigint@7.8.3': resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.4): + '@babel/plugin-syntax-class-properties@7.12.13': resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.24.4): + '@babel/plugin-syntax-class-static-block@7.14.5': resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.24.4): - resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.24.4): - resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-syntax-import-assertions@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==} + '@babel/plugin-syntax-import-assertions@7.26.0': + resolution: {integrity: sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-import-attributes@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==} + '@babel/plugin-syntax-import-attributes@7.25.7': + resolution: {integrity: sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.4): + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.4): + '@babel/plugin-syntax-json-strings@7.8.3': resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==} + '@babel/plugin-syntax-jsx@7.25.7': + resolution: {integrity: sha512-ruZOnKO+ajVL/MVx+PwNBPOkrnXTXoWMtte1MBpegfCArhqOe3Bj52avVj1huLLxNKYKXYaSxZ2F+woK1ekXfw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.4): + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.4): + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.4): + '@babel/plugin-syntax-numeric-separator@7.10.4': resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.4): + '@babel/plugin-syntax-object-rest-spread@7.8.3': resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.4): + '@babel/plugin-syntax-optional-catch-binding@7.8.3': resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.4): + '@babel/plugin-syntax-optional-chaining@7.8.3': resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.24.4): + '@babel/plugin-syntax-private-property-in-object@7.14.5': resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.4): + '@babel/plugin-syntax-top-level-await@7.14.5': resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==} + '@babel/plugin-syntax-typescript@7.25.7': + resolution: {integrity: sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.24.4): + '@babel/plugin-syntax-unicode-sets-regex@7.18.6': resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-arrow-functions@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==} + '@babel/plugin-transform-arrow-functions@7.25.9': + resolution: {integrity: sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-async-generator-functions@7.24.3(@babel/core@7.24.4): - resolution: {integrity: sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==} + '@babel/plugin-transform-async-generator-functions@7.26.8': + resolution: {integrity: sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.4) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.4) - dev: true - /@babel/plugin-transform-async-to-generator@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==} + '@babel/plugin-transform-async-to-generator@7.25.9': + resolution: {integrity: sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.4) - dev: true - /@babel/plugin-transform-block-scoped-functions@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==} + '@babel/plugin-transform-block-scoped-functions@7.26.5': + resolution: {integrity: sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-block-scoping@7.24.4(@babel/core@7.24.4): - resolution: {integrity: sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g==} + '@babel/plugin-transform-block-scoping@7.25.9': + resolution: {integrity: sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-class-properties@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==} + '@babel/plugin-transform-class-properties@7.25.9': + resolution: {integrity: sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-class-features-plugin': 7.24.4(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-class-static-block@7.24.4(@babel/core@7.24.4): - resolution: {integrity: sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==} + '@babel/plugin-transform-class-static-block@7.26.0': + resolution: {integrity: sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-class-features-plugin': 7.24.4(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.4) - dev: true - /@babel/plugin-transform-classes@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==} + '@babel/plugin-transform-classes@7.25.9': + resolution: {integrity: sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.4) - '@babel/helper-split-export-declaration': 7.22.6 - globals: 11.12.0 - dev: true - /@babel/plugin-transform-computed-properties@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==} + '@babel/plugin-transform-computed-properties@7.25.9': + resolution: {integrity: sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/template': 7.24.0 - dev: true - /@babel/plugin-transform-destructuring@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==} + '@babel/plugin-transform-destructuring@7.25.9': + resolution: {integrity: sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-dotall-regex@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==} + '@babel/plugin-transform-dotall-regex@7.25.9': + resolution: {integrity: sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-duplicate-keys@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==} + '@babel/plugin-transform-duplicate-keys@7.25.9': + resolution: {integrity: sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-dynamic-import@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.4) - dev: true - - /@babel/plugin-transform-exponentiation-operator@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-export-namespace-from@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.4) - dev: true - - /@babel/plugin-transform-for-of@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - dev: true - - /@babel/plugin-transform-function-name@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-json-strings@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.4) - dev: true - - /@babel/plugin-transform-literals@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-logical-assignment-operators@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.4) - dev: true - - /@babel/plugin-transform-member-expression-literals@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-modules-amd@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-modules-commonjs@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-simple-access': 7.22.5 - dev: true - - /@babel/plugin-transform-modules-systemjs@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-validator-identifier': 7.22.20 - dev: true - - /@babel/plugin-transform-modules-umd@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.24.4): - resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9': + resolution: {integrity: sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-new-target@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==} + '@babel/plugin-transform-dynamic-import@7.25.9': + resolution: {integrity: sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-nullish-coalescing-operator@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==} + '@babel/plugin-transform-exponentiation-operator@7.26.3': + resolution: {integrity: sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.4) - dev: true - /@babel/plugin-transform-numeric-separator@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==} + '@babel/plugin-transform-export-namespace-from@7.25.9': + resolution: {integrity: sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.4) - dev: true - /@babel/plugin-transform-object-rest-spread@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA==} + '@babel/plugin-transform-for-of@7.26.9': + resolution: {integrity: sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-transform-parameters': 7.24.1(@babel/core@7.24.4) - dev: true - /@babel/plugin-transform-object-super@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==} + '@babel/plugin-transform-function-name@7.25.9': + resolution: {integrity: sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.4) - dev: true - /@babel/plugin-transform-optional-catch-binding@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==} + '@babel/plugin-transform-json-strings@7.25.9': + resolution: {integrity: sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.4) - dev: true - /@babel/plugin-transform-optional-chaining@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==} + '@babel/plugin-transform-literals@7.25.9': + resolution: {integrity: sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.4) - dev: true - /@babel/plugin-transform-parameters@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==} + '@babel/plugin-transform-logical-assignment-operators@7.25.9': + resolution: {integrity: sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-private-methods@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==} + '@babel/plugin-transform-member-expression-literals@7.25.9': + resolution: {integrity: sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-class-features-plugin': 7.24.4(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-private-property-in-object@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==} + '@babel/plugin-transform-modules-amd@7.25.9': + resolution: {integrity: sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.24.4(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.4) - dev: true - /@babel/plugin-transform-property-literals@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==} + '@babel/plugin-transform-modules-commonjs@7.26.3': + resolution: {integrity: sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-regenerator@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==} + '@babel/plugin-transform-modules-systemjs@7.25.9': + resolution: {integrity: sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - regenerator-transform: 0.15.2 - dev: true - /@babel/plugin-transform-reserved-words@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==} + '@babel/plugin-transform-modules-umd@7.25.9': + resolution: {integrity: sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/plugin-transform-shorthand-properties@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-spread@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - dev: true - - /@babel/plugin-transform-sticky-regex@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-template-literals@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-typeof-symbol@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-typescript@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-liYSESjX2fZ7JyBFkYG78nfvHlMKE6IpNdTVnxmlYUR+j5ZLsitFbaAE+eJSK2zPPkNWNw4mXL51rQ8WrvdK0w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.24.4(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.4) - dev: true - - /@babel/plugin-transform-unicode-escapes@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-unicode-property-regex@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-unicode-regex@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - dev: true - - /@babel/plugin-transform-unicode-sets-regex@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==} + '@babel/plugin-transform-named-capturing-groups-regex@7.25.9': + resolution: {integrity: sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.4) - '@babel/helper-plugin-utils': 7.24.0 - dev: true - /@babel/preset-env@7.24.4(@babel/core@7.24.4): - resolution: {integrity: sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A==} + '@babel/plugin-transform-new-target@7.25.9': + resolution: {integrity: sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/core': 7.24.4 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.24.4(@babel/core@7.24.4) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.4) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.4) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.4) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.4) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-import-assertions': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-syntax-import-attributes': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.4) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.4) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.4) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.4) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.4) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.24.4) - '@babel/plugin-transform-arrow-functions': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-async-generator-functions': 7.24.3(@babel/core@7.24.4) - '@babel/plugin-transform-async-to-generator': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-block-scoped-functions': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-block-scoping': 7.24.4(@babel/core@7.24.4) - '@babel/plugin-transform-class-properties': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-class-static-block': 7.24.4(@babel/core@7.24.4) - '@babel/plugin-transform-classes': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-computed-properties': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-destructuring': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-dotall-regex': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-duplicate-keys': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-dynamic-import': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-exponentiation-operator': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-export-namespace-from': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-for-of': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-function-name': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-json-strings': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-literals': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-logical-assignment-operators': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-member-expression-literals': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-modules-amd': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-modules-systemjs': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-modules-umd': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.24.4) - '@babel/plugin-transform-new-target': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-nullish-coalescing-operator': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-numeric-separator': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-object-rest-spread': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-object-super': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-optional-catch-binding': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-optional-chaining': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-parameters': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-private-methods': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-private-property-in-object': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-property-literals': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-regenerator': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-reserved-words': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-shorthand-properties': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-spread': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-sticky-regex': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-template-literals': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-typeof-symbol': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-unicode-escapes': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-unicode-property-regex': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-unicode-regex': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-unicode-sets-regex': 7.24.1(@babel/core@7.24.4) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.24.4) - babel-plugin-polyfill-corejs2: 0.4.10(@babel/core@7.24.4) - babel-plugin-polyfill-corejs3: 0.10.4(@babel/core@7.24.4) - babel-plugin-polyfill-regenerator: 0.6.1(@babel/core@7.24.4) - core-js-compat: 3.36.1 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.24.4): + '@babel/plugin-transform-nullish-coalescing-operator@7.26.6': + resolution: {integrity: sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-numeric-separator@7.25.9': + resolution: {integrity: sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.25.9': + resolution: {integrity: sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-super@7.25.9': + resolution: {integrity: sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.25.9': + resolution: {integrity: sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.25.9': + resolution: {integrity: sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.25.9': + resolution: {integrity: sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.25.9': + resolution: {integrity: sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.25.9': + resolution: {integrity: sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-property-literals@7.25.9': + resolution: {integrity: sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.25.9': + resolution: {integrity: sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regexp-modifiers@7.26.0': + resolution: {integrity: sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.25.9': + resolution: {integrity: sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.25.9': + resolution: {integrity: sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-spread@7.25.9': + resolution: {integrity: sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-sticky-regex@7.25.9': + resolution: {integrity: sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.26.8': + resolution: {integrity: sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typeof-symbol@7.26.7': + resolution: {integrity: sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-escapes@7.25.9': + resolution: {integrity: sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-property-regex@7.25.9': + resolution: {integrity: sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.25.9': + resolution: {integrity: sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-sets-regex@7.25.9': + resolution: {integrity: sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/preset-env@7.26.9': + resolution: {integrity: sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-modules@0.1.6-no-external-plugins': resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} peerDependencies: '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/types': 7.24.0 - esutils: 2.0.3 - dev: true - /@babel/preset-typescript@7.24.1(@babel/core@7.24.4): - resolution: {integrity: sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==} + '@babel/runtime@7.26.9': + resolution: {integrity: sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==} engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-plugin-utils': 7.24.0 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-transform-typescript': 7.24.1(@babel/core@7.24.4) - dev: true - /@babel/regjsgen@0.8.0: - resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - dev: true - - /@babel/runtime@7.24.0: - resolution: {integrity: sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==} + '@babel/template@7.26.9': + resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.1 - dev: true - /@babel/runtime@7.24.4: - resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==} + '@babel/traverse@7.26.9': + resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==} engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.1 - dev: true - /@babel/template@7.24.0: - resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} + '@babel/types@7.26.9': + resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/parser': 7.24.4 - '@babel/types': 7.24.0 - dev: true - /@babel/traverse@7.24.1: - resolution: {integrity: sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.4 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.24.4 - '@babel/types': 7.24.0 - debug: 4.3.4(supports-color@8.1.1) - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.24.0: - resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.23.4 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 - - /@bcherny/json-schema-ref-parser@10.0.5-fork: - resolution: {integrity: sha512-E/jKbPoca1tfUPj3iSbitDZTGnq6FUFjkH6L8U2oDwSuwK1WhnnVtCG7oFOTg/DDnyoXbQYUiUiGOibHqaGVnw==} - engines: {node: '>= 16'} - dependencies: - '@jsdevtools/ono': 7.1.3 - '@types/json-schema': 7.0.15 - call-me-maybe: 1.0.2 - js-yaml: 4.1.0 - dev: true - - /@bcoe/v8-coverage@0.2.3: + '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - dev: true - /@braintree/sanitize-url@7.0.1: - resolution: {integrity: sha512-URg8UM6lfC9ZYqFipItRSxYJdgpU5d2Z4KnjsJ+rj6tgAmGme7E+PQNCiud8g0HDaZKMovu2qjfa0f5Ge0Vlsg==} - dev: false + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} - /@chevrotain/cst-dts-gen@11.0.3: + '@braintree/sanitize-url@7.1.0': + resolution: {integrity: sha512-o+UlMLt49RvtCASlOMW0AkHnabN9wR9rwCCherxO0yG4Npy34GkvrAqdXQvrhNs+jh+gkK8gB8Lf05qL/O7KWg==} + + '@changesets/apply-release-plan@7.0.10': + resolution: {integrity: sha512-wNyeIJ3yDsVspYvHnEz1xQDq18D9ifed3lI+wxRQRK4pArUcuHgCTrHv0QRnnwjhVCQACxZ+CBih3wgOct6UXw==} + + '@changesets/assemble-release-plan@6.0.6': + resolution: {integrity: sha512-Frkj8hWJ1FRZiY3kzVCKzS0N5mMwWKwmv9vpam7vt8rZjLL1JMthdh6pSDVSPumHPshTTkKZ0VtNbE0cJHZZUg==} + + '@changesets/changelog-git@0.2.1': + resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} + + '@changesets/changelog-github@0.5.1': + resolution: {integrity: sha512-BVuHtF+hrhUScSoHnJwTELB4/INQxVFc+P/Qdt20BLiBFIHFJDDUaGsZw+8fQeJTRP5hJZrzpt3oZWh0G19rAQ==} + + '@changesets/cli@2.28.1': + resolution: {integrity: sha512-PiIyGRmSc6JddQJe/W1hRPjiN4VrMvb2VfQ6Uydy2punBioQrsxppyG5WafinKcW1mT0jOe/wU4k9Zy5ff21AA==} + hasBin: true + + '@changesets/config@3.1.1': + resolution: {integrity: sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==} + + '@changesets/errors@0.2.0': + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} + + '@changesets/get-dependents-graph@2.1.3': + resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} + + '@changesets/get-github-info@0.6.0': + resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} + + '@changesets/get-release-plan@4.0.8': + resolution: {integrity: sha512-MM4mq2+DQU1ZT7nqxnpveDMTkMBLnwNX44cX7NSxlXmr7f8hO6/S2MXNiXG54uf/0nYnefv0cfy4Czf/ZL/EKQ==} + + '@changesets/get-version-range-type@0.4.0': + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} + + '@changesets/git@3.0.2': + resolution: {integrity: sha512-r1/Kju9Y8OxRRdvna+nxpQIsMsRQn9dhhAZt94FLDeu0Hij2hnOozW8iqnHBgvu+KdnJppCveQwK4odwfw/aWQ==} + + '@changesets/logger@0.1.1': + resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} + + '@changesets/parse@0.4.1': + resolution: {integrity: sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==} + + '@changesets/pre@2.0.2': + resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} + + '@changesets/read@0.6.3': + resolution: {integrity: sha512-9H4p/OuJ3jXEUTjaVGdQEhBdqoT2cO5Ts95JTFsQyawmKzpL8FnIeJSyhTDPW1MBRDnwZlHFEM9SpPwJDY5wIg==} + + '@changesets/should-skip-package@0.1.2': + resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} + + '@changesets/types@4.1.0': + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} + + '@changesets/types@6.1.0': + resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} + + '@changesets/write@0.4.0': + resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} + + '@chevrotain/cst-dts-gen@11.0.3': resolution: {integrity: sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==} - dependencies: - '@chevrotain/gast': 11.0.3 - '@chevrotain/types': 11.0.3 - lodash-es: 4.17.21 - /@chevrotain/gast@11.0.3: + '@chevrotain/gast@11.0.3': resolution: {integrity: sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==} - dependencies: - '@chevrotain/types': 11.0.3 - lodash-es: 4.17.21 - /@chevrotain/regexp-to-ast@11.0.3: + '@chevrotain/regexp-to-ast@11.0.3': resolution: {integrity: sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==} - /@chevrotain/types@11.0.3: + '@chevrotain/types@11.0.3': resolution: {integrity: sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==} - /@chevrotain/utils@11.0.3: + '@chevrotain/utils@11.0.3': resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==} - /@colors/colors@1.5.0: + '@colors/colors@1.5.0': resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} - requiresBuild: true - dev: true - optional: true - /@cspell/cspell-bundled-dicts@8.7.0: - resolution: {integrity: sha512-B5YQI7Dd9m0JHTmHgs7PiyP4BWXzl8ixpK+HGOwhxzh7GyfFt1Eo/gxMxBDX/9SaewEzeb2OjRpRKEFtEsto3A==} + '@cspell/cspell-bundled-dicts@8.17.4': + resolution: {integrity: sha512-oPNQU3Uwc0OnvAmC8Vs7DSCRBhGRbZvO8J57JEnJ6YMNyCJZpKq050OzbAWmNdjjZ7yRLJ+LOcxhzdFg2Qn4Yw==} engines: {node: '>=18'} - dependencies: - '@cspell/dict-ada': 4.0.2 - '@cspell/dict-aws': 4.0.1 - '@cspell/dict-bash': 4.1.3 - '@cspell/dict-companies': 3.0.31 - '@cspell/dict-cpp': 5.1.3 - '@cspell/dict-cryptocurrencies': 5.0.0 - '@cspell/dict-csharp': 4.0.2 - '@cspell/dict-css': 4.0.12 - '@cspell/dict-dart': 2.0.3 - '@cspell/dict-django': 4.1.0 - '@cspell/dict-docker': 1.1.7 - '@cspell/dict-dotnet': 5.0.0 - '@cspell/dict-elixir': 4.0.3 - '@cspell/dict-en-common-misspellings': 2.0.0 - '@cspell/dict-en-gb': 1.1.33 - '@cspell/dict-en_us': 4.3.18 - '@cspell/dict-filetypes': 3.0.3 - '@cspell/dict-fonts': 4.0.0 - '@cspell/dict-fsharp': 1.0.1 - '@cspell/dict-fullstack': 3.1.5 - '@cspell/dict-gaming-terms': 1.0.5 - '@cspell/dict-git': 3.0.0 - '@cspell/dict-golang': 6.0.5 - '@cspell/dict-haskell': 4.0.1 - '@cspell/dict-html': 4.0.5 - '@cspell/dict-html-symbol-entities': 4.0.0 - '@cspell/dict-java': 5.0.6 - '@cspell/dict-julia': 1.0.1 - '@cspell/dict-k8s': 1.0.2 - '@cspell/dict-latex': 4.0.0 - '@cspell/dict-lorem-ipsum': 4.0.0 - '@cspell/dict-lua': 4.0.3 - '@cspell/dict-makefile': 1.0.0 - '@cspell/dict-monkeyc': 1.0.6 - '@cspell/dict-node': 4.0.3 - '@cspell/dict-npm': 5.0.15 - '@cspell/dict-php': 4.0.6 - '@cspell/dict-powershell': 5.0.3 - '@cspell/dict-public-licenses': 2.0.6 - '@cspell/dict-python': 4.1.11 - '@cspell/dict-r': 2.0.1 - '@cspell/dict-ruby': 5.0.2 - '@cspell/dict-rust': 4.0.2 - '@cspell/dict-scala': 5.0.0 - '@cspell/dict-software-terms': 3.3.18 - '@cspell/dict-sql': 2.1.3 - '@cspell/dict-svelte': 1.0.2 - '@cspell/dict-swift': 2.0.1 - '@cspell/dict-terraform': 1.0.0 - '@cspell/dict-typescript': 3.1.3 - '@cspell/dict-vue': 3.0.0 - dev: true - /@cspell/cspell-json-reporter@8.7.0: - resolution: {integrity: sha512-LTQPEvXvCqnc+ok9WXpSISZyt4/nGse9fVEM430g0BpGzKpt3RMx49B8uasvvnanzCuikaW9+wFLmwgvraERhA==} + '@cspell/cspell-bundled-dicts@8.18.1': + resolution: {integrity: sha512-gxciVVfQqCVXYH0p2Q5D7x7/SgaW3Wv5UjRwO+TCme0P2lVLl/IcfjkujZX+6UQkT7X4QRglXo1QN141UcCRCQ==} engines: {node: '>=18'} - dependencies: - '@cspell/cspell-types': 8.7.0 - dev: true - /@cspell/cspell-pipe@8.7.0: - resolution: {integrity: sha512-ePqddIQ4arqPQgOkC146SkZxvZb9/jL7xIM5Igy2n3tiWTC5ijrX/mbHpPZ1VGcFck+1M0cJUuyhuJk+vMj3rg==} + '@cspell/cspell-json-reporter@8.17.4': + resolution: {integrity: sha512-O7V2hMt6zPt2Eu5LSxFyD/dcZRUOASeY+8oE1O2xanfJUMOG1EldCt8LERSmU829RQ4VF4H2Z9TbeQzx+4G21w==} engines: {node: '>=18'} - dev: true - /@cspell/cspell-resolver@8.7.0: - resolution: {integrity: sha512-grZwDFYqcBYQDaz4AkUtdyqc4UUH2J3/7yWVkBbYDPE+FQHa9ofFXzXxyjs56GJlPfi9ULpe5/Wz6uVLg8rQkQ==} + '@cspell/cspell-pipe@8.17.4': + resolution: {integrity: sha512-0KzqYetKMT9c3Pt77yRla2/zLDitpztEQ/VPYAbW5DCW+btRe5pAb6VQ7U6HKA2HoM2rhlLTWOBh4jauRFtgxA==} engines: {node: '>=18'} - dependencies: - global-directory: 4.0.1 - dev: true - /@cspell/cspell-service-bus@8.7.0: - resolution: {integrity: sha512-KW48iu0nTDzbedixc7iB7K7mlAZQ7QeMLuM/akxigOlvtOdVJrRa9Pfn44lwejts1ANb/IXil3GH8YylkVi76Q==} + '@cspell/cspell-pipe@8.18.1': + resolution: {integrity: sha512-QHndTQPkR1c02pvvQ7UKFtLjCXgY0OcX8zjTLrCkynmcQxJFjAZAh9cJ7NMOAxab+ciSnkaVf4KWaRSEG17z8Q==} engines: {node: '>=18'} - dev: true - /@cspell/cspell-types@8.7.0: - resolution: {integrity: sha512-Rb+LCE5I9JEb/LE8nSViVSF8z1CWv/z4mPBIG37VMa7aUx2gAQa6gJekNfpY9YZiMzx4Tv3gDujN80ytks4pGA==} + '@cspell/cspell-resolver@8.17.4': + resolution: {integrity: sha512-1Z3yZRuhnyGCheD2nt/ZswV+ulXBOfnKCoyfkUKNAR5ALkrqv6bjXXwZrpEi2cIK1km4/59ybT72+r2Ry9dGUw==} engines: {node: '>=18'} - dev: true - /@cspell/dict-ada@4.0.2: - resolution: {integrity: sha512-0kENOWQeHjUlfyId/aCM/mKXtkEgV0Zu2RhUXCBr4hHo9F9vph+Uu8Ww2b0i5a4ZixoIkudGA+eJvyxrG1jUpA==} - dev: true + '@cspell/cspell-resolver@8.18.1': + resolution: {integrity: sha512-T2sUBv0p9Hnfyg1xT1u3ESKuIWaaIDo0I8idh5DSlTpHgLjdIeAwasmFjEJ28qZv8OKSGawcSQKgJbStfbZASQ==} + engines: {node: '>=18'} - /@cspell/dict-aws@4.0.1: - resolution: {integrity: sha512-NXO+kTPQGqaaJKa4kO92NAXoqS+i99dQzf3/L1BxxWVSBS3/k1f3uhmqIh7Crb/n22W793lOm0D9x952BFga3Q==} - dev: true + '@cspell/cspell-service-bus@8.17.4': + resolution: {integrity: sha512-S8fENifriBW8KdDIvOnsP9gdEyCp1zrs4GT15vmDvm6uoevj2mfmdCj4/EbM1KbmmNAh1tlidAgn2OWdtyW7Lg==} + engines: {node: '>=18'} - /@cspell/dict-bash@4.1.3: - resolution: {integrity: sha512-tOdI3QVJDbQSwPjUkOiQFhYcu2eedmX/PtEpVWg0aFps/r6AyjUQINtTgpqMYnYuq8O1QUIQqnpx21aovcgZCw==} - dev: true + '@cspell/cspell-service-bus@8.18.1': + resolution: {integrity: sha512-PwWl7EyhGIu4wHEhvBJb6xVlqMtFwQk0qLDArBvugL6nA+MX9NfG/w7PTgS7tCkFjVF1ku2sDzDLTDWwEk+MLw==} + engines: {node: '>=18'} - /@cspell/dict-companies@3.0.31: - resolution: {integrity: sha512-hKVpV/lcGKP4/DpEPS8P4osPvFH/YVLJaDn9cBIOH6/HSmL5LbFgJNKpMGaYRbhm2FEX56MKE3yn/MNeNYuesQ==} - dev: true + '@cspell/cspell-types@8.17.4': + resolution: {integrity: sha512-1K6tXEMXSaoUXhH3TiaCyh3Nh8ZE0wPej0+wa5HAMtdcY1B3FGvHZ9DltkgZxbzs3bGNXIySFE5ITqULbhweBA==} + engines: {node: '>=18'} - /@cspell/dict-cpp@5.1.3: - resolution: {integrity: sha512-sqnriXRAInZH9W75C+APBh6dtben9filPqVbIsiRMUXGg+s02ekz0z6LbS7kXeJ5mD2qXoMLBrv13qH2eIwutQ==} - dev: true + '@cspell/cspell-types@8.18.1': + resolution: {integrity: sha512-d/nMG+qnMbI/1JPm+lD0KcKpgtEHMRsHxkdtGyNCDgvHL/JOGaSHc5ERS3IUgBW0Dfya/3z9wPdaMcHEzt7YCQ==} + engines: {node: '>=18'} - /@cspell/dict-cryptocurrencies@5.0.0: - resolution: {integrity: sha512-Z4ARIw5+bvmShL+4ZrhDzGhnc9znaAGHOEMaB/GURdS/jdoreEDY34wdN0NtdLHDO5KO7GduZnZyqGdRoiSmYA==} - dev: true + '@cspell/dict-ada@4.1.0': + resolution: {integrity: sha512-7SvmhmX170gyPd+uHXrfmqJBY5qLcCX8kTGURPVeGxmt8XNXT75uu9rnZO+jwrfuU2EimNoArdVy5GZRGljGNg==} - /@cspell/dict-csharp@4.0.2: - resolution: {integrity: sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g==} - dev: true + '@cspell/dict-al@1.1.0': + resolution: {integrity: sha512-PtNI1KLmYkELYltbzuoztBxfi11jcE9HXBHCpID2lou/J4VMYKJPNqe4ZjVzSI9NYbMnMnyG3gkbhIdx66VSXg==} - /@cspell/dict-css@4.0.12: - resolution: {integrity: sha512-vGBgPM92MkHQF5/2jsWcnaahOZ+C6OE/fPvd5ScBP72oFY9tn5GLuomcyO0z8vWCr2e0nUSX1OGimPtcQAlvSw==} - dev: true + '@cspell/dict-aws@4.0.9': + resolution: {integrity: sha512-bDYdnnJGwSkIZ4gzrauu7qzOs/ZAY/FnU4k11LgdMI8BhwMfsbsy2EI1iS+sD/BI5ZnNT9kU5YR3WADeNOmhRg==} - /@cspell/dict-dart@2.0.3: - resolution: {integrity: sha512-cLkwo1KT5CJY5N5RJVHks2genFkNCl/WLfj+0fFjqNR+tk3tBI1LY7ldr9piCtSFSm4x9pO1x6IV3kRUY1lLiw==} - dev: true + '@cspell/dict-bash@4.2.0': + resolution: {integrity: sha512-HOyOS+4AbCArZHs/wMxX/apRkjxg6NDWdt0jF9i9XkvJQUltMwEhyA2TWYjQ0kssBsnof+9amax2lhiZnh3kCg==} - /@cspell/dict-data-science@1.0.11: - resolution: {integrity: sha512-TaHAZRVe0Zlcc3C23StZqqbzC0NrodRwoSAc8dis+5qLeLLnOCtagYQeROQvDlcDg3X/VVEO9Whh4W/z4PAmYQ==} - dev: true + '@cspell/dict-companies@3.1.14': + resolution: {integrity: sha512-iqo1Ce4L7h0l0GFSicm2wCLtfuymwkvgFGhmu9UHyuIcTbdFkDErH+m6lH3Ed+QuskJlpQ9dM7puMIGqUlVERw==} - /@cspell/dict-django@4.1.0: - resolution: {integrity: sha512-bKJ4gPyrf+1c78Z0Oc4trEB9MuhcB+Yg+uTTWsvhY6O2ncFYbB/LbEZfqhfmmuK/XJJixXfI1laF2zicyf+l0w==} - dev: true + '@cspell/dict-cpp@6.0.3': + resolution: {integrity: sha512-OFrVXdxCeGKnon36Pe3yFjBuY4kzzEwWFf3vDz+cJTodZDkjFkBifQeTtt5YfimgF8cfAJZXkBCsxjipAgmAiw==} - /@cspell/dict-docker@1.1.7: - resolution: {integrity: sha512-XlXHAr822euV36GGsl2J1CkBIVg3fZ6879ZOg5dxTIssuhUOCiV2BuzKZmt6aIFmcdPmR14+9i9Xq+3zuxeX0A==} - dev: true + '@cspell/dict-cpp@6.0.7': + resolution: {integrity: sha512-mk0AUx6au1BJQBTT2Uq9L+y43E0Cy0Vcm6TrK3Toi2iuBLWOnDR/xRE4nZADBsi6WnWoiyl3/QqA1gW2zPkGvQ==} - /@cspell/dict-dotnet@5.0.0: - resolution: {integrity: sha512-EOwGd533v47aP5QYV8GlSSKkmM9Eq8P3G/eBzSpH3Nl2+IneDOYOBLEUraHuiCtnOkNsz0xtZHArYhAB2bHWAw==} - dev: true + '@cspell/dict-cryptocurrencies@5.0.4': + resolution: {integrity: sha512-6iFu7Abu+4Mgqq08YhTKHfH59mpMpGTwdzDB2Y8bbgiwnGFCeoiSkVkgLn1Kel2++hYcZ8vsAW/MJS9oXxuMag==} - /@cspell/dict-elixir@4.0.3: - resolution: {integrity: sha512-g+uKLWvOp9IEZvrIvBPTr/oaO6619uH/wyqypqvwpmnmpjcfi8+/hqZH8YNKt15oviK8k4CkINIqNhyndG9d9Q==} - dev: true + '@cspell/dict-csharp@4.0.6': + resolution: {integrity: sha512-w/+YsqOknjQXmIlWDRmkW+BHBPJZ/XDrfJhZRQnp0wzpPOGml7W0q1iae65P2AFRtTdPKYmvSz7AL5ZRkCnSIw==} - /@cspell/dict-en-common-misspellings@2.0.0: - resolution: {integrity: sha512-NOg8dlv37/YqLkCfBs5OXeJm/Wcfb/CzeOmOZJ2ZXRuxwsNuolb4TREUce0yAXRqMhawahY5TSDRJJBgKjBOdw==} - dev: true + '@cspell/dict-css@4.0.17': + resolution: {integrity: sha512-2EisRLHk6X/PdicybwlajLGKF5aJf4xnX2uuG5lexuYKt05xV/J/OiBADmi8q9obhxf1nesrMQbqAt+6CsHo/w==} - /@cspell/dict-en-gb@1.1.33: + '@cspell/dict-dart@2.3.0': + resolution: {integrity: sha512-1aY90lAicek8vYczGPDKr70pQSTQHwMFLbmWKTAI6iavmb1fisJBS1oTmMOKE4ximDf86MvVN6Ucwx3u/8HqLg==} + + '@cspell/dict-data-science@2.0.7': + resolution: {integrity: sha512-XhAkK+nSW6zmrnWzusmZ1BpYLc62AWYHZc2p17u4nE2Z9XG5DleG55PCZxXQTKz90pmwlhFM9AfpkJsYaBWATA==} + + '@cspell/dict-data-science@2.0.8': + resolution: {integrity: sha512-uyAtT+32PfM29wRBeAkUSbkytqI8bNszNfAz2sGPtZBRmsZTYugKMEO9eDjAIE/pnT9CmbjNuoiXhk+Ss4fCOg==} + + '@cspell/dict-django@4.1.4': + resolution: {integrity: sha512-fX38eUoPvytZ/2GA+g4bbdUtCMGNFSLbdJJPKX2vbewIQGfgSFJKY56vvcHJKAvw7FopjvgyS/98Ta9WN1gckg==} + + '@cspell/dict-docker@1.1.12': + resolution: {integrity: sha512-6d25ZPBnYZaT9D9An/x6g/4mk542R8bR3ipnby3QFCxnfdd6xaWiTcwDPsCgwN2aQZIQ1jX/fil9KmBEqIK/qA==} + + '@cspell/dict-dotnet@5.0.9': + resolution: {integrity: sha512-JGD6RJW5sHtO5lfiJl11a5DpPN6eKSz5M1YBa1I76j4dDOIqgZB6rQexlDlK1DH9B06X4GdDQwdBfnpAB0r2uQ==} + + '@cspell/dict-elixir@4.0.7': + resolution: {integrity: sha512-MAUqlMw73mgtSdxvbAvyRlvc3bYnrDqXQrx5K9SwW8F7fRYf9V4vWYFULh+UWwwkqkhX9w03ZqFYRTdkFku6uA==} + + '@cspell/dict-en-common-misspellings@2.0.10': + resolution: {integrity: sha512-80mXJLtr0tVEtzowrI7ycVae/ULAYImZUlr0kUTpa8i57AUk7Zy3pYBs44EYIKW7ZC9AHu4Qjjfq4vriAtyTDQ==} + + '@cspell/dict-en-common-misspellings@2.0.9': + resolution: {integrity: sha512-O/jAr1VNtuyCFckbTmpeEf43ZFWVD9cJFvWaA6rO2IVmLirJViHWJUyBZOuQcesSplzEIw80MAYmnK06/MDWXQ==} + + '@cspell/dict-en-gb@1.1.33': resolution: {integrity: sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==} - dev: true - /@cspell/dict-en_us@4.3.18: - resolution: {integrity: sha512-D8jGT7Zi3+e8zIpT0NqGKvvzehcvUETFlOA0NxcRStkw7H7mgouHxKFU+u7t3tvCoGNwh2gwjCqZQlK8ZXwQHw==} - dev: true + '@cspell/dict-en_us@4.3.31': + resolution: {integrity: sha512-MDc+1B0aFwQONS0JZ6w7ks2KFGkUcaNTFJ8kI6GHvFRmEl3zP5NJDwFEXFsoEdLDb86j2myauSWMJXR3JFuwbA==} - /@cspell/dict-filetypes@3.0.3: - resolution: {integrity: sha512-J9UP+qwwBLfOQ8Qg9tAsKtSY/WWmjj21uj6zXTI9hRLD1eG1uUOLcfVovAmtmVqUWziPSKMr87F6SXI3xmJXgw==} - dev: true + '@cspell/dict-en_us@4.4.0': + resolution: {integrity: sha512-TEfVT2NwvI9k1/ECjuC7GbULxenjJAbTLWMri1eMRk3mRGtqg5j0XzvvNRFuJWq8X48MdGVjsD+ZVI/VR94+eQ==} - /@cspell/dict-fonts@4.0.0: - resolution: {integrity: sha512-t9V4GeN/m517UZn63kZPUYP3OQg5f0OBLSd3Md5CU3eH1IFogSvTzHHnz4Wqqbv8NNRiBZ3HfdY/pqREZ6br3Q==} - dev: true + '@cspell/dict-filetypes@3.0.11': + resolution: {integrity: sha512-bBtCHZLo7MiSRUqx5KEiPdGOmXIlDGY+L7SJEtRWZENpAKE+96rT7hj+TUUYWBbCzheqHr0OXZJFEKDgsG/uZg==} - /@cspell/dict-fsharp@1.0.1: - resolution: {integrity: sha512-23xyPcD+j+NnqOjRHgW3IU7Li912SX9wmeefcY0QxukbAxJ/vAN4rBpjSwwYZeQPAn3fxdfdNZs03fg+UM+4yQ==} - dev: true + '@cspell/dict-flutter@1.1.0': + resolution: {integrity: sha512-3zDeS7zc2p8tr9YH9tfbOEYfopKY/srNsAa+kE3rfBTtQERAZeOhe5yxrnTPoufctXLyuUtcGMUTpxr3dO0iaA==} - /@cspell/dict-fullstack@3.1.5: - resolution: {integrity: sha512-6ppvo1dkXUZ3fbYn/wwzERxCa76RtDDl5Afzv2lijLoijGGUw5yYdLBKJnx8PJBGNLh829X352ftE7BElG4leA==} - dev: true + '@cspell/dict-fonts@4.0.4': + resolution: {integrity: sha512-cHFho4hjojBcHl6qxidl9CvUb492IuSk7xIf2G2wJzcHwGaCFa2o3gRcxmIg1j62guetAeDDFELizDaJlVRIOg==} - /@cspell/dict-gaming-terms@1.0.5: - resolution: {integrity: sha512-C3riccZDD3d9caJQQs1+MPfrUrQ+0KHdlj9iUR1QD92FgTOF6UxoBpvHUUZ9YSezslcmpFQK4xQQ5FUGS7uWfw==} - dev: true + '@cspell/dict-fsharp@1.1.0': + resolution: {integrity: sha512-oguWmHhGzgbgbEIBKtgKPrFSVAFtvGHaQS0oj+vacZqMObwkapcTGu7iwf4V3Bc2T3caf0QE6f6rQfIJFIAVsw==} - /@cspell/dict-git@3.0.0: - resolution: {integrity: sha512-simGS/lIiXbEaqJu9E2VPoYW1OTC2xrwPPXNXFMa2uo/50av56qOuaxDrZ5eH1LidFXwoc8HROCHYeKoNrDLSw==} - dev: true + '@cspell/dict-fullstack@3.2.4': + resolution: {integrity: sha512-JRRvaOLBZ13BO9sP395W+06tyO1Jy/87aFlKe9xQiCWMiwpCo2kGq0xBGq0PDWe253lYLs+GKrNmLU0fSxrObg==} - /@cspell/dict-golang@6.0.5: - resolution: {integrity: sha512-w4mEqGz4/wV+BBljLxduFNkMrd3rstBNDXmoX5kD4UTzIb4Sy0QybWCtg2iVT+R0KWiRRA56QKOvBsgXiddksA==} - dev: true + '@cspell/dict-fullstack@3.2.6': + resolution: {integrity: sha512-cSaq9rz5RIU9j+0jcF2vnKPTQjxGXclntmoNp4XB7yFX2621PxJcekGjwf/lN5heJwVxGLL9toR0CBlGKwQBgA==} - /@cspell/dict-haskell@4.0.1: - resolution: {integrity: sha512-uRrl65mGrOmwT7NxspB4xKXFUenNC7IikmpRZW8Uzqbqcu7ZRCUfstuVH7T1rmjRgRkjcIjE4PC11luDou4wEQ==} - dev: true + '@cspell/dict-gaming-terms@1.1.0': + resolution: {integrity: sha512-46AnDs9XkgJ2f1Sqol1WgfJ8gOqp60fojpc9Wxch7x+BA63g4JfMV5/M5x0sI0TLlLY8EBSglcr8wQF/7C80AQ==} - /@cspell/dict-html-symbol-entities@4.0.0: - resolution: {integrity: sha512-HGRu+48ErJjoweR5IbcixxETRewrBb0uxQBd6xFGcxbEYCX8CnQFTAmKI5xNaIt2PKaZiJH3ijodGSqbKdsxhw==} - dev: true + '@cspell/dict-git@3.0.4': + resolution: {integrity: sha512-C44M+m56rYn6QCsLbiKiedyPTMZxlDdEYAsPwwlL5bhMDDzXZ3Ic8OCQIhMbiunhCOJJT+er4URmOmM+sllnjg==} - /@cspell/dict-html@4.0.5: - resolution: {integrity: sha512-p0brEnRybzSSWi8sGbuVEf7jSTDmXPx7XhQUb5bgG6b54uj+Z0Qf0V2n8b/LWwIPJNd1GygaO9l8k3HTCy1h4w==} - dev: true + '@cspell/dict-golang@6.0.18': + resolution: {integrity: sha512-Mt+7NwfodDwUk7423DdaQa0YaA+4UoV3XSxQwZioqjpFBCuxfvvv4l80MxCTAAbK6duGj0uHbGTwpv8fyKYPKg==} - /@cspell/dict-java@5.0.6: - resolution: {integrity: sha512-kdE4AHHHrixyZ5p6zyms1SLoYpaJarPxrz8Tveo6gddszBVVwIUZ+JkQE1bWNLK740GWzIXdkznpUfw1hP9nXw==} - dev: true + '@cspell/dict-golang@6.0.20': + resolution: {integrity: sha512-b7nd9XXs+apMMzNSWorjirQsbmlwcTC0ViQJU8u+XNose3z0y7oNeEpbTPTVoN1+1sO9aOHuFwfwoOMFCDS14Q==} - /@cspell/dict-julia@1.0.1: - resolution: {integrity: sha512-4JsCLCRhhLMLiaHpmR7zHFjj1qOauzDI5ZzCNQS31TUMfsOo26jAKDfo0jljFAKgw5M2fEG7sKr8IlPpQAYrmQ==} - dev: true + '@cspell/dict-google@1.0.8': + resolution: {integrity: sha512-BnMHgcEeaLyloPmBs8phCqprI+4r2Jb8rni011A8hE+7FNk7FmLE3kiwxLFrcZnnb7eqM0agW4zUaNoB0P+z8A==} - /@cspell/dict-k8s@1.0.2: - resolution: {integrity: sha512-tLT7gZpNPnGa+IIFvK9SP1LrSpPpJ94a/DulzAPOb1Q2UBFwdpFd82UWhio0RNShduvKG/WiMZf/wGl98pn+VQ==} - dev: true + '@cspell/dict-haskell@4.0.5': + resolution: {integrity: sha512-s4BG/4tlj2pPM9Ha7IZYMhUujXDnI0Eq1+38UTTCpatYLbQqDwRFf2KNPLRqkroU+a44yTUAe0rkkKbwy4yRtQ==} - /@cspell/dict-latex@4.0.0: - resolution: {integrity: sha512-LPY4y6D5oI7D3d+5JMJHK/wxYTQa2lJMSNxps2JtuF8hbAnBQb3igoWEjEbIbRRH1XBM0X8dQqemnjQNCiAtxQ==} - dev: true + '@cspell/dict-html-symbol-entities@4.0.3': + resolution: {integrity: sha512-aABXX7dMLNFdSE8aY844X4+hvfK7977sOWgZXo4MTGAmOzR8524fjbJPswIBK7GaD3+SgFZ2yP2o0CFvXDGF+A==} - /@cspell/dict-lorem-ipsum@4.0.0: - resolution: {integrity: sha512-1l3yjfNvMzZPibW8A7mQU4kTozwVZVw0AvFEdy+NcqtbxH+TvbSkNMqROOFWrkD2PjnKG0+Ea0tHI2Pi6Gchnw==} - dev: true + '@cspell/dict-html@4.0.11': + resolution: {integrity: sha512-QR3b/PB972SRQ2xICR1Nw/M44IJ6rjypwzA4jn+GH8ydjAX9acFNfc+hLZVyNe0FqsE90Gw3evLCOIF0vy1vQw==} - /@cspell/dict-lua@4.0.3: - resolution: {integrity: sha512-lDHKjsrrbqPaea13+G9s0rtXjMO06gPXPYRjRYawbNmo4E/e3XFfVzeci3OQDQNDmf2cPOwt9Ef5lu2lDmwfJg==} - dev: true + '@cspell/dict-java@5.0.11': + resolution: {integrity: sha512-T4t/1JqeH33Raa/QK/eQe26FE17eUCtWu+JsYcTLkQTci2dk1DfcIKo8YVHvZXBnuM43ATns9Xs0s+AlqDeH7w==} - /@cspell/dict-makefile@1.0.0: - resolution: {integrity: sha512-3W9tHPcSbJa6s0bcqWo6VisEDTSN5zOtDbnPabF7rbyjRpNo0uHXHRJQF8gAbFzoTzBBhgkTmrfSiuyQm7vBUQ==} - dev: true + '@cspell/dict-julia@1.1.0': + resolution: {integrity: sha512-CPUiesiXwy3HRoBR3joUseTZ9giFPCydSKu2rkh6I2nVjXnl5vFHzOMLXpbF4HQ1tH2CNfnDbUndxD+I+7eL9w==} - /@cspell/dict-monkeyc@1.0.6: - resolution: {integrity: sha512-oO8ZDu/FtZ55aq9Mb67HtaCnsLn59xvhO/t2mLLTHAp667hJFxpp7bCtr2zOrR1NELzFXmKln/2lw/PvxMSvrA==} - dev: true + '@cspell/dict-k8s@1.0.10': + resolution: {integrity: sha512-313haTrX9prep1yWO7N6Xw4D6tvUJ0Xsx+YhCP+5YrrcIKoEw5Rtlg8R4PPzLqe6zibw6aJ+Eqq+y76Vx5BZkw==} - /@cspell/dict-node@4.0.3: - resolution: {integrity: sha512-sFlUNI5kOogy49KtPg8SMQYirDGIAoKBO3+cDLIwD4MLdsWy1q0upc7pzGht3mrjuyMiPRUV14Bb0rkVLrxOhg==} - dev: true + '@cspell/dict-kotlin@1.1.0': + resolution: {integrity: sha512-vySaVw6atY7LdwvstQowSbdxjXG6jDhjkWVWSjg1XsUckyzH1JRHXe9VahZz1i7dpoFEUOWQrhIe5B9482UyJQ==} - /@cspell/dict-npm@5.0.15: - resolution: {integrity: sha512-sX0X5YWNW54F4baW7b5JJB6705OCBIZtUqjOghlJNORS5No7QY1IX1zc5FxNNu4gsaCZITAmfMi4ityXEsEThA==} - dev: true + '@cspell/dict-latex@4.0.3': + resolution: {integrity: sha512-2KXBt9fSpymYHxHfvhUpjUFyzrmN4c4P8mwIzweLyvqntBT3k0YGZJSriOdjfUjwSygrfEwiuPI1EMrvgrOMJw==} - /@cspell/dict-php@4.0.6: - resolution: {integrity: sha512-ySAXisf7twoVFZqBV2o/DKiCLIDTHNqfnj0EfH9OoOUR7HL3rb6zJkm0viLUFDO2G/8SyIi6YrN/6KX+Scjjjg==} - dev: true + '@cspell/dict-lorem-ipsum@4.0.4': + resolution: {integrity: sha512-+4f7vtY4dp2b9N5fn0za/UR0kwFq2zDtA62JCbWHbpjvO9wukkbl4rZg4YudHbBgkl73HRnXFgCiwNhdIA1JPw==} - /@cspell/dict-powershell@5.0.3: - resolution: {integrity: sha512-lEdzrcyau6mgzu1ie98GjOEegwVHvoaWtzQnm1ie4DyZgMr+N6D0Iyj1lzvtmt0snvsDFa5F2bsYzf3IMKcpcA==} - dev: true + '@cspell/dict-lua@4.0.7': + resolution: {integrity: sha512-Wbr7YSQw+cLHhTYTKV6cAljgMgcY+EUAxVIZW3ljKswEe4OLxnVJ7lPqZF5JKjlXdgCjbPSimsHqyAbC5pQN/Q==} - /@cspell/dict-public-licenses@2.0.6: - resolution: {integrity: sha512-bHqpSpJvLCUcWxj1ov/Ki8WjmESpYwRpQlqfdchekOTc93Huhvjm/RXVN1R4fVf4Hspyem1QVkCGqAmjJMj6sw==} - dev: true + '@cspell/dict-makefile@1.0.4': + resolution: {integrity: sha512-E4hG/c0ekPqUBvlkrVvzSoAA+SsDA9bLi4xSV3AXHTVru7Y2bVVGMPtpfF+fI3zTkww/jwinprcU1LSohI3ylw==} - /@cspell/dict-python@4.1.11: - resolution: {integrity: sha512-XG+v3PumfzUW38huSbfT15Vqt3ihNb462ulfXifpQllPok5OWynhszCLCRQjQReV+dgz784ST4ggRxW452/kVg==} - dependencies: - '@cspell/dict-data-science': 1.0.11 - dev: true + '@cspell/dict-markdown@2.0.9': + resolution: {integrity: sha512-j2e6Eg18BlTb1mMP1DkyRFMM/FLS7qiZjltpURzDckB57zDZbUyskOFdl4VX7jItZZEeY0fe22bSPOycgS1Z5A==} + peerDependencies: + '@cspell/dict-css': ^4.0.17 + '@cspell/dict-html': ^4.0.11 + '@cspell/dict-html-symbol-entities': ^4.0.3 + '@cspell/dict-typescript': ^3.2.0 - /@cspell/dict-r@2.0.1: - resolution: {integrity: sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA==} - dev: true + '@cspell/dict-monkeyc@1.0.10': + resolution: {integrity: sha512-7RTGyKsTIIVqzbvOtAu6Z/lwwxjGRtY5RkKPlXKHEoEAgIXwfDxb5EkVwzGQwQr8hF/D3HrdYbRT8MFBfsueZw==} - /@cspell/dict-ruby@5.0.2: - resolution: {integrity: sha512-cIh8KTjpldzFzKGgrqUX4bFyav5lC52hXDKo4LbRuMVncs3zg4hcSf4HtURY+f2AfEZzN6ZKzXafQpThq3dl2g==} - dev: true + '@cspell/dict-node@5.0.6': + resolution: {integrity: sha512-CEbhPCpxGvRNByGolSBTrXXW2rJA4bGqZuTx1KKO85mwR6aadeOmUE7xf/8jiCkXSy+qvr9aJeh+jlfXcsrziQ==} - /@cspell/dict-rust@4.0.2: - resolution: {integrity: sha512-RhziKDrklzOntxAbY3AvNR58wnFGIo3YS8+dNeLY36GFuWOvXDHFStYw5Pod4f/VXbO/+1tXtywCC4zWfB2p1w==} - dev: true + '@cspell/dict-npm@5.1.26': + resolution: {integrity: sha512-JU0/9P4nLPPC3Py+sF42tUKm9J4KAvwXaJubp2a4QwhCPzFVlOJTP2tTseFlLbdZn23d61pt0hZ+Jhyy7N76Mg==} - /@cspell/dict-scala@5.0.0: - resolution: {integrity: sha512-ph0twaRoV+ylui022clEO1dZ35QbeEQaKTaV2sPOsdwIokABPIiK09oWwGK9qg7jRGQwVaRPEq0Vp+IG1GpqSQ==} - dev: true + '@cspell/dict-npm@5.1.34': + resolution: {integrity: sha512-UrUYqRQX864Cx9QJkg7eEIxmjYGqcje+x1j7bzl+a3jCKwT6jm+p0off6VEOf3EReHP0dWUSYO3Q0+pLL/N+FQ==} - /@cspell/dict-software-terms@3.3.18: - resolution: {integrity: sha512-LJZGGMGqS8KzgXJrSMs3T+6GoqHG9z8Bc+rqLzLzbtoR3FbsMasE9U8oP2PmS3q7jJLFjQkzmg508DrcuZuo2g==} - dev: true + '@cspell/dict-php@4.0.14': + resolution: {integrity: sha512-7zur8pyncYZglxNmqsRycOZ6inpDoVd4yFfz1pQRe5xaRWMiK3Km4n0/X/1YMWhh3e3Sl/fQg5Axb2hlN68t1g==} - /@cspell/dict-sql@2.1.3: - resolution: {integrity: sha512-SEyTNKJrjqD6PAzZ9WpdSu6P7wgdNtGV2RV8Kpuw1x6bV+YsSptuClYG+JSdRExBTE6LwIe1bTklejUp3ZP8TQ==} - dev: true + '@cspell/dict-powershell@5.0.14': + resolution: {integrity: sha512-ktjjvtkIUIYmj/SoGBYbr3/+CsRGNXGpvVANrY0wlm/IoGlGywhoTUDYN0IsGwI2b8Vktx3DZmQkfb3Wo38jBA==} - /@cspell/dict-svelte@1.0.2: - resolution: {integrity: sha512-rPJmnn/GsDs0btNvrRBciOhngKV98yZ9SHmg8qI6HLS8hZKvcXc0LMsf9LLuMK1TmS2+WQFAan6qeqg6bBxL2Q==} - dev: true + '@cspell/dict-public-licenses@2.0.13': + resolution: {integrity: sha512-1Wdp/XH1ieim7CadXYE7YLnUlW0pULEjVl9WEeziZw3EKCAw8ZI8Ih44m4bEa5VNBLnuP5TfqC4iDautAleQzQ==} - /@cspell/dict-swift@2.0.1: - resolution: {integrity: sha512-gxrCMUOndOk7xZFmXNtkCEeroZRnS2VbeaIPiymGRHj5H+qfTAzAKxtv7jJbVA3YYvEzWcVE2oKDP4wcbhIERw==} - dev: true + '@cspell/dict-python@4.2.15': + resolution: {integrity: sha512-VNXhj0Eh+hdHN89MgyaoSAexBQKmYtJaMhucbMI7XmBs4pf8fuFFN3xugk51/A4TZJr8+RImdFFsGMOw+I4bDA==} - /@cspell/dict-terraform@1.0.0: - resolution: {integrity: sha512-Ak+vy4HP/bOgzf06BAMC30+ZvL9mzv21xLM2XtfnBLTDJGdxlk/nK0U6QT8VfFLqJ0ZZSpyOxGsUebWDCTr/zQ==} - dev: true + '@cspell/dict-python@4.2.17': + resolution: {integrity: sha512-xqMKfVc8d7yDaOChFdL2uWAN3Mw9qObB/Zr6t5w1OHbi23gWs7V1lI9d0mXAoqSK6N3mosbum4OIq/FleQDnlw==} - /@cspell/dict-typescript@3.1.3: - resolution: {integrity: sha512-TdD789OWwOImH/IMyz/QRA6LJz7ScI/qbn1YOkcAW3AROvgbc0oKAxzp08+Xu8tj4GROrJ9UqZdh0t9xQCPkPg==} - dev: true + '@cspell/dict-r@2.1.0': + resolution: {integrity: sha512-k2512wgGG0lTpTYH9w5Wwco+lAMf3Vz7mhqV8+OnalIE7muA0RSuD9tWBjiqLcX8zPvEJr4LdgxVju8Gk3OKyA==} - /@cspell/dict-vue@3.0.0: - resolution: {integrity: sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A==} - dev: true + '@cspell/dict-ruby@5.0.7': + resolution: {integrity: sha512-4/d0hcoPzi5Alk0FmcyqlzFW9lQnZh9j07MJzPcyVO62nYJJAGKaPZL2o4qHeCS/od/ctJC5AHRdoUm0ktsw6Q==} - /@cspell/dynamic-import@8.7.0: - resolution: {integrity: sha512-xlEPdiHVDu+4xYkvwjL9MgklxOi9XB+Pr1H9s3Ww9WEq+q6BA3xOHxLIU/k8mhqFTMZGFZRCsdy/EwMu6SyRhQ==} + '@cspell/dict-ruby@5.0.8': + resolution: {integrity: sha512-ixuTneU0aH1cPQRbWJvtvOntMFfeQR2KxT8LuAv5jBKqQWIHSxzGlp+zX3SVyoeR0kOWiu64/O5Yn836A5yMcQ==} + + '@cspell/dict-rust@4.0.11': + resolution: {integrity: sha512-OGWDEEzm8HlkSmtD8fV3pEcO2XBpzG2XYjgMCJCRwb2gRKvR+XIm6Dlhs04N/K2kU+iH8bvrqNpM8fS/BFl0uw==} + + '@cspell/dict-scala@5.0.7': + resolution: {integrity: sha512-yatpSDW/GwulzO3t7hB5peoWwzo+Y3qTc0pO24Jf6f88jsEeKmDeKkfgPbYuCgbE4jisGR4vs4+jfQZDIYmXPA==} + + '@cspell/dict-shell@1.1.0': + resolution: {integrity: sha512-D/xHXX7T37BJxNRf5JJHsvziFDvh23IF/KvkZXNSh8VqcRdod3BAz9VGHZf6VDqcZXr1VRqIYR3mQ8DSvs3AVQ==} + + '@cspell/dict-software-terms@4.2.5': + resolution: {integrity: sha512-CaRzkWti3AgcXoxuRcMijaNG7YUk/MH1rHjB8VX34v3UdCxXXeqvRyElRKnxhFeVLB/robb2UdShqh/CpskxRg==} + + '@cspell/dict-software-terms@5.0.5': + resolution: {integrity: sha512-ZjAOa8FI8/JrxaRqKT3eS7AQXFjU174xxQoKYMkmdwSyNIj7WUCAg10UeLqeMjFVv36zIO0Hm0dD2+Bvn18SLA==} + + '@cspell/dict-sql@2.2.0': + resolution: {integrity: sha512-MUop+d1AHSzXpBvQgQkCiok8Ejzb+nrzyG16E8TvKL2MQeDwnIvMe3bv90eukP6E1HWb+V/MA/4pnq0pcJWKqQ==} + + '@cspell/dict-svelte@1.0.6': + resolution: {integrity: sha512-8LAJHSBdwHCoKCSy72PXXzz7ulGROD0rP1CQ0StOqXOOlTUeSFaJJlxNYjlONgd2c62XBQiN2wgLhtPN+1Zv7Q==} + + '@cspell/dict-swift@2.0.5': + resolution: {integrity: sha512-3lGzDCwUmnrfckv3Q4eVSW3sK3cHqqHlPprFJZD4nAqt23ot7fic5ALR7J4joHpvDz36nHX34TgcbZNNZOC/JA==} + + '@cspell/dict-terraform@1.1.0': + resolution: {integrity: sha512-G55pcUUxeXAhejstmD35B47SkFd4uqCQimc+CMgq8Nx0dr03guL2iMsz8faRWQGkCnGimX8S91rbOhDv9p/heg==} + + '@cspell/dict-terraform@1.1.1': + resolution: {integrity: sha512-07KFDwCU7EnKl4hOZLsLKlj6Zceq/IsQ3LRWUyIjvGFfZHdoGtFdCp3ZPVgnFaAcd/DKv+WVkrOzUBSYqHopQQ==} + + '@cspell/dict-typescript@3.2.0': + resolution: {integrity: sha512-Pk3zNePLT8qg51l0M4g1ISowYAEGxTuNfZlgkU5SvHa9Cu7x/BWoyYq9Fvc3kAyoisCjRPyvWF4uRYrPitPDFw==} + + '@cspell/dict-vue@3.0.4': + resolution: {integrity: sha512-0dPtI0lwHcAgSiQFx8CzvqjdoXROcH+1LyqgROCpBgppommWpVhbQ0eubnKotFEXgpUCONVkeZJ6Ql8NbTEu+w==} + + '@cspell/dynamic-import@8.17.4': + resolution: {integrity: sha512-rUwFOVPnfEGzhzCRnE4esTTMgWtTORXfa5FJJR8653KwcvD6HJQfPTYepBG6n6Bmu3TssMa4ktq+ZJk4o1BF9A==} engines: {node: '>=18.0'} - dependencies: - import-meta-resolve: 4.0.0 - dev: true - /@cspell/eslint-plugin@8.7.0(eslint@8.57.0): - resolution: {integrity: sha512-ZITI9ybL5vsOukUzMyyBc5eKndEag7Pe4Z19br2w92xyNCZtHeAoDzp1eo1OeRilT7zBXCdXEDzvvNiNAHhg9A==} + '@cspell/dynamic-import@8.18.1': + resolution: {integrity: sha512-VJHfS/Iv0Rx7wn1pjPmwgsaw6r72N5Cx2gL0slWk8Cogc8YiK7/6jsGnsvxJZVkHntJoiT8PrkIvhNKb3awD3g==} + engines: {node: '>=18.0'} + + '@cspell/eslint-plugin@8.18.1': + resolution: {integrity: sha512-Knlp6M5zGKkjZSFPhsLZoARS8vbSiePK6AkNXujmlxM91KyHJsAEJiyAVnR5qwhYcsOkcngmO+pmLir+WjHlAw==} engines: {node: '>=18'} peerDependencies: eslint: ^7 || ^8 || ^9 - dependencies: - '@cspell/cspell-types': 8.7.0 - cspell-lib: 8.7.0 - eslint: 8.57.0 - estree-walker: 3.0.3 - synckit: 0.9.0 - dev: true - /@cspell/strong-weak-map@8.7.0: - resolution: {integrity: sha512-0bo0WwDr2lzGoCP7vbpWbDpPyuOrHKK+218txnUpx6Pn1EDBLfcDQsiZED5B6zlpwgbGi6y3vc0rWtJbjKvwzg==} + '@cspell/filetypes@8.17.4': + resolution: {integrity: sha512-zzYm0hr+lvctsy/65hjI0vsQJj2CAwSOTnVk+5ubJCkCaWH/rayI/SaVZA0Xynf08B/x0r/36nPH0lO2iMJ4aw==} engines: {node: '>=18'} - dev: true - /@cypress/code-coverage@3.12.34(@babel/core@7.24.4)(@babel/preset-env@7.24.4)(babel-loader@9.1.3)(cypress@13.7.3)(webpack@5.91.0): - resolution: {integrity: sha512-5z2I9SfjWYViX6+kj92Ha078ZwJEZ30R/j6cQJiZgY6fYMJVD3o3mffyXPOytB85PIfBURtWdlyWsSLBaj41Mw==} + '@cspell/filetypes@8.18.1': + resolution: {integrity: sha512-vTOb2itP0pjrccvt8wcKiTGyw0pFMTPI85H12T6n8ZhqXTktPgQH2gEf/SU/5tkPNnBKr4GJ+FdU5hJ27HzgXQ==} + engines: {node: '>=18'} + + '@cspell/strong-weak-map@8.17.4': + resolution: {integrity: sha512-Io4ffbMI9hQz+9CLe/oU1Om0H3SqAlvFTaS7ZQOg7joyJSXuGBsCcCg03uTRKWD+NoaxPNUlZOkucUBGil6djw==} + engines: {node: '>=18'} + + '@cspell/strong-weak-map@8.18.1': + resolution: {integrity: sha512-gsgv+5ZQD4aHNHDdfNGoafVYkqRynyYgaodt9Dp/3o0YKYcxGf2jrX8SJ35MfZ61qln0n7P4Djrg+bFV2zNH5w==} + engines: {node: '>=18'} + + '@cspell/url@8.17.4': + resolution: {integrity: sha512-vWLySh0ARsI0+TdvA8W6btdeeQbSjBhDE8kwGlzIrOCLIfkeO9Bu++mkc1To1/uogkS2T5icmA24D0rL8ZqjNw==} + engines: {node: '>=18.0'} + + '@cspell/url@8.18.1': + resolution: {integrity: sha512-FRJbLYDC9ucpTOzbF6MohP2u5X3NU5L0RoVuoYCynqm/QOI38XP6WOEaI4H58CAn857bOIKZk0LZRPTGzi6Qlg==} + engines: {node: '>=18.0'} + + '@csstools/color-helpers@5.0.1': + resolution: {integrity: sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.1': + resolution: {integrity: sha512-rL7kaUnTkL9K+Cvo2pnCieqNpTKgQzy5f+N+5Iuko9HAoasP+xgprVh7KN/MaJVvVL1l0EzQq2MoqBHKSrDrag==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.4 + '@csstools/css-tokenizer': ^3.0.3 + + '@csstools/css-color-parser@3.0.7': + resolution: {integrity: sha512-nkMp2mTICw32uE5NN+EsJ4f5N+IGFeCFu4bGpiKgb2Pq/7J/MpyLBeQ5ry4KKtRFZaYs6sTmcMYrSRIyj5DFKA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.4 + '@csstools/css-tokenizer': ^3.0.3 + + '@csstools/css-parser-algorithms@3.0.4': + resolution: {integrity: sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.3 + + '@csstools/css-tokenizer@3.0.3': + resolution: {integrity: sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==} + engines: {node: '>=18'} + + '@cypress/code-coverage@3.13.4': + resolution: {integrity: sha512-4Bne95y/Vkye9tfctyiKjYHirA/0LZq7Z5MiCrrT2mlyWfaOSnPeUHG84BdxuycgVOLzMFxqvc+uNQO5lupvTg==} peerDependencies: '@babel/core': ^7.0.1 '@babel/preset-env': ^7.0.0 babel-loader: ^8.3 || ^9 cypress: '*' webpack: ^4 || ^5 - dependencies: - '@babel/core': 7.24.4 - '@babel/preset-env': 7.24.4(@babel/core@7.24.4) - '@cypress/webpack-preprocessor': 6.0.1(@babel/core@7.24.4)(@babel/preset-env@7.24.4)(babel-loader@9.1.3)(webpack@5.91.0) - babel-loader: 9.1.3(@babel/core@7.24.4)(webpack@5.91.0) - chalk: 4.1.2 - cypress: 13.7.3 - dayjs: 1.11.10 - debug: 4.3.4(supports-color@8.1.1) - execa: 4.1.0 - globby: 11.1.0 - istanbul-lib-coverage: 3.2.2 - js-yaml: 4.1.0 - nyc: 15.1.0 - webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@4.10.0) - transitivePeerDependencies: - - supports-color - dev: true - /@cypress/request@3.0.1: - resolution: {integrity: sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==} + '@cypress/request@3.0.7': + resolution: {integrity: sha512-LzxlLEMbBOPYB85uXrDqvD4MgcenjRBLIns3zyhx7vTPj/0u2eQhzXvPiGcaJrV38Q9dbkExWp6cOHPJ+EtFYg==} engines: {node: '>= 6'} - 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 - http-signature: 1.3.6 - is-typedarray: 1.0.0 - isstream: 0.1.2 - json-stringify-safe: 5.0.1 - mime-types: 2.1.35 - performance-now: 2.1.0 - qs: 6.10.4 - safe-buffer: 5.2.1 - tough-cookie: 4.1.3 - tunnel-agent: 0.6.0 - uuid: 8.3.2 - dev: true - /@cypress/webpack-preprocessor@6.0.1(@babel/core@7.24.4)(@babel/preset-env@7.24.4)(babel-loader@9.1.3)(webpack@5.91.0): - resolution: {integrity: sha512-WVNeFVSnFKxE3WZNRIriduTgqJRpevaiJIPlfqYTTzfXRD7X1Pv4woDE+G4caPV9bJqVKmVFiwzrXMRNeJxpxA==} + '@cypress/webpack-preprocessor@6.0.2': + resolution: {integrity: sha512-0+1+4iy4W9PE6R5ywBNKAZoFp8Sf//w3UJ+CKTqkcAjA29b+dtsD0iFT70DsYE0BMqUM1PO7HXFGbXllQ+bRAA==} peerDependencies: '@babel/core': ^7.0.1 '@babel/preset-env': ^7.0.0 babel-loader: ^8.3 || ^9 webpack: ^4 || ^5 - dependencies: - '@babel/core': 7.24.4 - '@babel/preset-env': 7.24.4(@babel/core@7.24.4) - babel-loader: 9.1.3(@babel/core@7.24.4)(webpack@5.91.0) - bluebird: 3.7.1 - debug: 4.3.4(supports-color@8.1.1) - lodash: 4.17.21 - webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@4.10.0) - transitivePeerDependencies: - - supports-color - dev: true - /@cypress/xvfb@1.2.4(supports-color@8.1.1): + '@cypress/xvfb@1.2.4': resolution: {integrity: sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==} - dependencies: - debug: 3.2.7(supports-color@8.1.1) - lodash.once: 4.1.1 - transitivePeerDependencies: - - supports-color - dev: true - /@discoveryjs/json-ext@0.5.7: + '@dependents/detective-less@5.0.0': + resolution: {integrity: sha512-D/9dozteKcutI5OdxJd8rU+fL6XgaaRg60sPPJWkT33OCiRfkCu5wO5B/yXTaaL2e6EB0lcCBGe5E0XscZCvvQ==} + engines: {node: '>=18'} + + '@discoveryjs/json-ext@0.5.7': resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} - dev: true - /@docsearch/css@3.6.0: - resolution: {integrity: sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==} - dev: true + '@docsearch/css@3.8.2': + resolution: {integrity: sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==} - /@docsearch/js@3.6.0(@algolia/client-search@4.23.3)(search-insights@2.13.0): - resolution: {integrity: sha512-QujhqINEElrkIfKwyyyTfbsfMAYCkylInLYMRqHy7PHc8xTBQCow73tlo/Kc7oIwBrCLf0P3YhjlOeV4v8hevQ==} - dependencies: - '@docsearch/react': 3.6.0(@algolia/client-search@4.23.3)(search-insights@2.13.0) - preact: 10.20.2 - transitivePeerDependencies: - - '@algolia/client-search' - - '@types/react' - - react - - react-dom - - search-insights - dev: true + '@docsearch/js@3.8.2': + resolution: {integrity: sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==} - /@docsearch/react@3.6.0(@algolia/client-search@4.23.3)(search-insights@2.13.0): - resolution: {integrity: sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==} + '@docsearch/react@3.8.2': + resolution: {integrity: sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' react: '>= 16.8.0 < 19.0.0' @@ -2832,643 +1839,699 @@ packages: optional: true search-insights: optional: true - dependencies: - '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.23.3)(algoliasearch@4.23.3)(search-insights@2.13.0) - '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.23.3)(algoliasearch@4.23.3) - '@docsearch/css': 3.6.0 - algoliasearch: 4.23.3 - search-insights: 2.13.0 - transitivePeerDependencies: - - '@algolia/client-search' - dev: true - /@es-joy/jsdoccomment@0.42.0: - resolution: {integrity: sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw==} + '@emnapi/runtime@1.3.1': + resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} + + '@es-joy/jsdoccomment@0.49.0': + resolution: {integrity: sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==} engines: {node: '>=16'} - dependencies: - comment-parser: 1.4.1 - esquery: 1.5.0 - jsdoc-type-pratt-parser: 4.0.0 - dev: true - /@esbuild/aix-ppc64@0.19.12: - resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} cpu: [ppc64] os: [aix] - requiresBuild: true - dev: true - optional: true - /@esbuild/aix-ppc64@0.20.2: - resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} - engines: {node: '>=12'} + '@esbuild/aix-ppc64@0.24.2': + resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} + engines: {node: '>=18'} cpu: [ppc64] os: [aix] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm64@0.19.12: - resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} + '@esbuild/aix-ppc64@0.25.0': + resolution: {integrity: sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} cpu: [arm64] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm64@0.20.2: - resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} - engines: {node: '>=12'} + '@esbuild/android-arm64@0.24.2': + resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} + engines: {node: '>=18'} cpu: [arm64] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm@0.19.12: - resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} + '@esbuild/android-arm64@0.25.0': + resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} cpu: [arm] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm@0.20.2: - resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} - engines: {node: '>=12'} + '@esbuild/android-arm@0.24.2': + resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} + engines: {node: '>=18'} cpu: [arm] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-x64@0.19.12: - resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} + '@esbuild/android-arm@0.25.0': + resolution: {integrity: sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} cpu: [x64] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-x64@0.20.2: - resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} - engines: {node: '>=12'} + '@esbuild/android-x64@0.24.2': + resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} + engines: {node: '>=18'} cpu: [x64] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-arm64@0.19.12: - resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} + '@esbuild/android-x64@0.25.0': + resolution: {integrity: sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-arm64@0.20.2: - resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} - engines: {node: '>=12'} + '@esbuild/darwin-arm64@0.24.2': + resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-x64@0.19.12: - resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} + '@esbuild/darwin-arm64@0.25.0': + resolution: {integrity: sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-x64@0.20.2: - resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} - engines: {node: '>=12'} + '@esbuild/darwin-x64@0.24.2': + resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-arm64@0.19.12: - resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} + '@esbuild/darwin-x64@0.25.0': + resolution: {integrity: sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-arm64@0.20.2: - resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} - engines: {node: '>=12'} + '@esbuild/freebsd-arm64@0.24.2': + resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-x64@0.19.12: - resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} + '@esbuild/freebsd-arm64@0.25.0': + resolution: {integrity: sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-x64@0.20.2: - resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} - engines: {node: '>=12'} + '@esbuild/freebsd-x64@0.24.2': + resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm64@0.19.12: - resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} + '@esbuild/freebsd-x64@0.25.0': + resolution: {integrity: sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} cpu: [arm64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm64@0.20.2: - resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} - engines: {node: '>=12'} + '@esbuild/linux-arm64@0.24.2': + resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm@0.19.12: - resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} + '@esbuild/linux-arm64@0.25.0': + resolution: {integrity: sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} cpu: [arm] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm@0.20.2: - resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} - engines: {node: '>=12'} + '@esbuild/linux-arm@0.24.2': + resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} + engines: {node: '>=18'} cpu: [arm] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ia32@0.19.12: - resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} + '@esbuild/linux-arm@0.25.0': + resolution: {integrity: sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ia32@0.20.2: - resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} - engines: {node: '>=12'} + '@esbuild/linux-ia32@0.24.2': + resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-loong64@0.19.12: - resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} + '@esbuild/linux-ia32@0.25.0': + resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-loong64@0.20.2: - resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} - engines: {node: '>=12'} + '@esbuild/linux-loong64@0.24.2': + resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-mips64el@0.19.12: - resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} + '@esbuild/linux-loong64@0.25.0': + resolution: {integrity: sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-mips64el@0.20.2: - resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} - engines: {node: '>=12'} + '@esbuild/linux-mips64el@0.24.2': + resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ppc64@0.19.12: - resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} + '@esbuild/linux-mips64el@0.25.0': + resolution: {integrity: sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ppc64@0.20.2: - resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} - engines: {node: '>=12'} + '@esbuild/linux-ppc64@0.24.2': + resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-riscv64@0.19.12: - resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} + '@esbuild/linux-ppc64@0.25.0': + resolution: {integrity: sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-riscv64@0.20.2: - resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} - engines: {node: '>=12'} + '@esbuild/linux-riscv64@0.24.2': + resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-s390x@0.19.12: - resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} + '@esbuild/linux-riscv64@0.25.0': + resolution: {integrity: sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} cpu: [s390x] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-s390x@0.20.2: - resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} - engines: {node: '>=12'} + '@esbuild/linux-s390x@0.24.2': + resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-x64@0.19.12: - resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} + '@esbuild/linux-s390x@0.25.0': + resolution: {integrity: sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-x64@0.20.2: - resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} - engines: {node: '>=12'} + '@esbuild/linux-x64@0.24.2': + resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} + engines: {node: '>=18'} cpu: [x64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/netbsd-x64@0.19.12: - resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} + '@esbuild/linux-x64@0.25.0': + resolution: {integrity: sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.24.2': + resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-arm64@0.25.0': + resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/netbsd-x64@0.20.2: - resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} - engines: {node: '>=12'} + '@esbuild/netbsd-x64@0.24.2': + resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} + engines: {node: '>=18'} cpu: [x64] os: [netbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/openbsd-x64@0.19.12: - resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} + '@esbuild/netbsd-x64@0.25.0': + resolution: {integrity: sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.24.2': + resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-arm64@0.25.0': + resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/openbsd-x64@0.20.2: - resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} - engines: {node: '>=12'} + '@esbuild/openbsd-x64@0.24.2': + resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} + engines: {node: '>=18'} cpu: [x64] os: [openbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/sunos-x64@0.19.12: - resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} + '@esbuild/openbsd-x64@0.25.0': + resolution: {integrity: sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] - requiresBuild: true - dev: true - optional: true - /@esbuild/sunos-x64@0.20.2: - resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} - engines: {node: '>=12'} + '@esbuild/sunos-x64@0.24.2': + resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} + engines: {node: '>=18'} cpu: [x64] os: [sunos] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-arm64@0.19.12: - resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} + '@esbuild/sunos-x64@0.25.0': + resolution: {integrity: sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-arm64@0.20.2: - resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} - engines: {node: '>=12'} + '@esbuild/win32-arm64@0.24.2': + resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-ia32@0.19.12: - resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} + '@esbuild/win32-arm64@0.25.0': + resolution: {integrity: sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} cpu: [ia32] os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-ia32@0.20.2: - resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} - engines: {node: '>=12'} + '@esbuild/win32-ia32@0.24.2': + resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-x64@0.19.12: - resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} + '@esbuild/win32-ia32@0.25.0': + resolution: {integrity: sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} cpu: [x64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-x64@0.20.2: - resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} - engines: {node: '>=12'} + '@esbuild/win32-x64@0.24.2': + resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} + engines: {node: '>=18'} cpu: [x64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + '@esbuild/win32-x64@0.25.0': + resolution: {integrity: sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.5.1': + resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - dev: true - /@eslint-community/regexpp@4.10.0: - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4(supports-color@8.1.1) - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true + '@eslint/config-array@0.20.0': + resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} + 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} - dev: true + '@eslint/config-helpers@0.2.1': + resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /@fastify/ajv-compiler@1.1.0: - resolution: {integrity: sha512-gvCOUNpXsWrIQ3A4aXCLIdblL0tDq42BG/2Xw7oxbil9h11uow10ztS2GuFazNBfjbrsZ5nl+nPl5jDSjj5TSg==} - dependencies: - ajv: 6.12.6 - dev: true + '@eslint/core@0.12.0': + resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /@fastify/error@2.0.0: - resolution: {integrity: sha512-wI3fpfDT0t7p8E6dA2eTECzzOd+bZsZCJ2Hcv+Onn2b7ZwK3RwD27uW2QDaMtQhAfWQQP+WNK7nKf0twLsBf9w==} - dev: true + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /@floating-ui/core@1.6.0: - resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} - dependencies: - '@floating-ui/utils': 0.2.1 - dev: false + '@eslint/js@9.24.0': + resolution: {integrity: sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /@floating-ui/dom@1.6.3: - resolution: {integrity: sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==} - dependencies: - '@floating-ui/core': 1.6.0 - '@floating-ui/utils': 0.2.1 - dev: false + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /@floating-ui/utils@0.2.1: - resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} - dev: false + '@eslint/plugin-kit@0.2.7': + resolution: {integrity: sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /@floating-ui/vue@0.2.1(vue@3.4.21): - resolution: {integrity: sha512-HE+EIeakID7wI6vUwF0yMpaW48bNaPj8QtnQaRMkaQFhQReVBA4bY6fmJ3J7X+dqVgDbMhyfCG0fBJfdQMdWxQ==} - peerDependencies: - '@vue/composition-api': ^1.0.0-rc.1 - vue: ^2.0.0 || >=3.0.0 - peerDependenciesMeta: - '@vue/composition-api': - optional: true - dependencies: - '@floating-ui/dom': 1.6.3 - vue: 3.4.21(typescript@5.4.5) - vue-demi: 0.13.11(vue@3.4.21) - dev: false + '@fastify/ajv-compiler@3.6.0': + resolution: {integrity: sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==} - /@hapi/hoek@9.3.0: + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + + '@fastify/error@3.4.1': + resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==} + + '@fastify/fast-json-stringify-compiler@4.3.0': + resolution: {integrity: sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==} + + '@fastify/merge-json-schemas@0.1.1': + resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==} + + '@floating-ui/core@1.6.9': + resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==} + + '@floating-ui/dom@1.6.13': + resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==} + + '@floating-ui/utils@0.2.9': + resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} + + '@floating-ui/vue@1.1.6': + resolution: {integrity: sha512-XFlUzGHGv12zbgHNk5FN2mUB7ROul3oG2ENdTpWdE+qMFxyNxWSRmsoyhiEnpmabNm6WnUvR1OvJfUfN4ojC1A==} + + '@gerrit0/mini-shiki@1.27.2': + resolution: {integrity: sha512-GeWyHz8ao2gBiUW4OJnQDxXQnFgZQwwQk05t/CVVgNBN7/rK8XZ7xY6YhLVv9tH3VppWWmr9DCl3MwemB/i+Og==} + + '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} - dev: true - /@hapi/topo@5.1.0: + '@hapi/topo@5.1.0': resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} - dependencies: - '@hapi/hoek': 9.3.0 - dev: true - /@headlessui-float/vue@0.11.4(vue@3.4.21): - resolution: {integrity: sha512-hNGQTT3trknSB78ZI3usvnJACLyEUmacvk5Q8JQizJ8k+8GYLvhKklGIhJVO1E3litEzW6yyjPgfg6aEJ+1p6g==} + '@headlessui-float/vue@0.14.4': + resolution: {integrity: sha512-MSyWCxUTueeex+veRCf++q4KM/fa4HOe9HDttzGrtgVDBULkGduFK6ItJh7EHJp2U/dY7qpyDUqp2KCHpCEplw==} peerDependencies: + '@headlessui/vue': ^1.0.0 vue: ^3.0.0 - dependencies: - '@floating-ui/core': 1.6.0 - '@floating-ui/dom': 1.6.3 - '@floating-ui/vue': 0.2.1(vue@3.4.21) - vue: 3.4.21(typescript@5.4.5) - transitivePeerDependencies: - - '@vue/composition-api' - dev: false - /@headlessui/tailwindcss@0.2.0(tailwindcss@3.4.3): - resolution: {integrity: sha512-fpL830Fln1SykOCboExsWr3JIVeQKieLJ3XytLe/tt1A0XzqUthOftDmjcCYLW62w7mQI7wXcoPXr3tZ9QfGxw==} + '@headlessui/tailwindcss@0.2.2': + resolution: {integrity: sha512-xNe42KjdyA4kfUKLLPGzME9zkH7Q3rOZ5huFihWNWOQFxnItxPB3/67yBI8/qBfY8nwBRx5GHn4VprsoluVMGw==} engines: {node: '>=10'} peerDependencies: - tailwindcss: ^3.0 - dependencies: - tailwindcss: 3.4.3 - dev: false + tailwindcss: ^3.0 || ^4.0 - /@headlessui/vue@1.7.19(vue@3.4.21): - resolution: {integrity: sha512-VFjKPybogux/5/QYGSq4zgG/x3RcxId15W8uguAJAjPBxelI23dwjOjTx/mIiMkM/Hd3rzFxcf2aIp56eEWRcA==} + '@headlessui/vue@1.7.23': + resolution: {integrity: sha512-JzdCNqurrtuu0YW6QaDtR2PIYCKPUWq28csDyMvN4zmGccmE7lz40Is6hc3LA4HFeCI7sekZ/PQMTNmn9I/4Wg==} engines: {node: '>=10'} peerDependencies: vue: ^3.2.0 - dependencies: - '@tanstack/vue-virtual': 3.2.1(vue@3.4.21) - vue: 3.4.21(typescript@5.4.5) - dev: false - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4(supports-color@8.1.1) - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} - /@humanwhocodes/module-importer@1.0.1: + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - dev: true - /@humanwhocodes/object-schema@2.0.2: - resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} - dev: true + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} - /@iconify-json/carbon@1.1.31: - resolution: {integrity: sha512-CAvECFfiwGyZmlcuM2JLMRDEN3VsIEZv6lml7Xf+3giQ5oXloADm0b5wiVPFZmONKM5jXERmx+E7YSvAtFJIbw==} - dependencies: - '@iconify/types': 2.0.0 - dev: true + '@humanwhocodes/retry@0.4.2': + resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} + engines: {node: '>=18.18'} - /@iconify/types@2.0.0: + '@iconify-json/carbon@1.2.1': + resolution: {integrity: sha512-dIMY6OOY9LnwR3kOqAtfz4phGFG+KNfESEwSL6muCprBelSlSPpRXtdqvEEO/qWhkf5AJ9hWrOV3Egi5Z2IuKA==} + + '@iconify-json/simple-icons@1.2.25': + resolution: {integrity: sha512-2E1/gOCO97rF6usfhhiXxwzCb+UhdEsxW3lW1Sew+xZY0COY6dp82Z/r1rUt2fWKneWjuoGcNeJHHXQyG8mIuw==} + + '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} - dev: true - /@iconify/utils@2.1.22: - resolution: {integrity: sha512-6UHVzTVXmvO8uS6xFF+L/QTSpTzA/JZxtgU+KYGFyDYMEObZ1bu/b5l+zNJjHy+0leWjHI+C0pXlzGvv3oXZMA==} - dependencies: - '@antfu/install-pkg': 0.1.1 - '@antfu/utils': 0.7.7 - '@iconify/types': 2.0.0 - debug: 4.3.4(supports-color@8.1.1) - kolorist: 1.8.0 - local-pkg: 0.5.0 - mlly: 1.6.1 - transitivePeerDependencies: - - supports-color - dev: true + '@iconify/utils@2.3.0': + resolution: {integrity: sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==} - /@isaacs/cliui@8.0.2: + '@img/sharp-darwin-arm64@0.33.5': + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.33.5': + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.0.4': + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.0.4': + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.0.4': + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.0.5': + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.0.4': + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.0.4': + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.33.5': + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.33.5': + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-s390x@0.33.5': + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.33.5': + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.33.5': + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.33.5': + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.33.5': + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-ia32@0.33.5': + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.33.5': + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - /@istanbuljs/load-nyc-config@1.1.0: + '@istanbuljs/load-nyc-config@1.1.0': resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} engines: {node: '>=8'} - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - dev: true - /@istanbuljs/schema@0.1.3: + '@istanbuljs/schema@0.1.3': resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} - dev: true - /@jest/console@29.7.0: + '@jest/console@29.7.0': resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 20.12.7 - chalk: 4.1.2 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - dev: true - /@jest/core@29.7.0: + '@jest/core@29.7.0': resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -3476,93 +2539,28 @@ packages: peerDependenciesMeta: node-notifier: optional: true - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.12.7 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.12.7) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.5 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - dev: true - /@jest/environment@29.7.0: + '@jest/environment@29.7.0': resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.12.7 - jest-mock: 29.7.0 - dev: true - /@jest/expect-utils@29.7.0: + '@jest/expect-utils@29.7.0': resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.6.3 - dev: true - /@jest/expect@29.7.0: + '@jest/expect@29.7.0': resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - expect: 29.7.0 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - dev: true - /@jest/fake-timers@29.7.0: + '@jest/fake-timers@29.7.0': resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.12.7 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - dev: true - /@jest/globals@29.7.0: + '@jest/globals@29.7.0': resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/types': 29.6.3 - jest-mock: 29.7.0 - transitivePeerDependencies: - - supports-color - dev: true - /@jest/reporters@29.7.0: + '@jest/reporters@29.7.0': resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -3570,197 +2568,101 @@ packages: peerDependenciesMeta: node-notifier: optional: true - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.12.7 - chalk: 4.1.2 - collect-v8-coverage: 1.0.2 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.2 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.7 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - jest-worker: 29.7.0 - slash: 3.0.0 - string-length: 4.0.2 - strip-ansi: 6.0.1 - v8-to-istanbul: 9.2.0 - transitivePeerDependencies: - - supports-color - dev: true - /@jest/schemas@29.6.3: + '@jest/schemas@29.6.3': resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@sinclair/typebox': 0.27.8 - dev: true - /@jest/source-map@29.6.3: + '@jest/source-map@29.6.3': resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - callsites: 3.1.0 - graceful-fs: 4.2.11 - dev: true - /@jest/test-result@29.7.0: + '@jest/test-result@29.7.0': resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.7.0 - '@jest/types': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - collect-v8-coverage: 1.0.2 - dev: true - /@jest/test-sequencer@29.7.0: + '@jest/test-sequencer@29.7.0': resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.7.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - slash: 3.0.0 - dev: true - /@jest/transform@29.7.0: + '@jest/transform@29.7.0': resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.24.4 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - micromatch: 4.0.5 - pirates: 4.0.6 - slash: 3.0.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - dev: true - /@jest/types@29.6.3: + '@jest/types@29.6.3': resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 20.12.7 - '@types/yargs': 17.0.32 - chalk: 4.1.2 - dev: true - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.25 - /@jridgewell/resolve-uri@3.1.2: + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - /@jridgewell/set-array@1.2.1: + '@jridgewell/set-array@1.2.1': resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - /@jridgewell/source-map@0.3.6: + '@jridgewell/source-map@0.3.6': resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - /@jridgewell/trace-mapping@0.3.25: + '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - /@jsdevtools/ono@7.1.3: + '@jsdevtools/ono@7.1.3': resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} - dev: true - /@leichtgewicht/ip-codec@2.0.4: - resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==} - dev: true + '@leichtgewicht/ip-codec@2.0.5': + resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} - /@mdi/font@7.4.47: + '@manypkg/find-root@1.1.0': + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + + '@manypkg/get-packages@1.1.3': + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + + '@mdi/font@7.4.47': resolution: {integrity: sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==} - dev: false - /@microsoft/tsdoc-config@0.16.2: - resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - ajv: 6.12.6 - jju: 1.4.0 - resolve: 1.19.0 - dev: true + '@microsoft/tsdoc-config@0.17.1': + resolution: {integrity: sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw==} - /@microsoft/tsdoc@0.14.2: - resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} - dev: true + '@microsoft/tsdoc@0.15.1': + resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==} - /@nodelib/fs.scandir@2.1.5: + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - /@nodelib/fs.stat@2.0.5: + '@nodelib/fs.stat@2.0.5': resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} - /@nodelib/fs.walk@1.2.8: + '@nodelib/fs.walk@1.2.8': resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - /@pkgjs/parseargs@0.11.0: + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - requiresBuild: true - optional: true - /@pkgr/core@0.1.1: + '@pkgr/core@0.1.1': resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - dev: true - /@polka/url@1.0.0-next.25: - resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} - dev: true + '@pkgr/core@0.2.1': + resolution: {integrity: sha512-VzgHzGblFmUeBmmrk55zPyrQIArQN4vujc9shWytaPdB3P7qhi0cpaiKIr7tlCmFv2lYUwnLospIqjL9ZSAhhg==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - /@rollup/plugin-babel@5.3.1(@babel/core@7.24.4)(rollup@2.79.1): + '@polka/url@1.0.0-next.28': + resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} + + '@rollup/plugin-babel@5.3.1': resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} engines: {node: '>= 10.0.0'} peerDependencies: @@ -3770,40 +2672,32 @@ packages: peerDependenciesMeta: '@types/babel__core': optional: true - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-module-imports': 7.24.3 - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) - rollup: 2.79.1 - dev: true - /@rollup/plugin-node-resolve@11.2.1(rollup@2.79.1): - resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==} - engines: {node: '>= 10.0.0'} + '@rollup/plugin-node-resolve@15.3.1': + resolution: {integrity: sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==} + engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^1.20.0||^2.0.0 - dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) - '@types/resolve': 1.17.1 - builtin-modules: 3.3.0 - deepmerge: 4.3.1 - is-module: 1.0.0 - resolve: 1.22.8 - rollup: 2.79.1 - dev: true + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true - /@rollup/plugin-replace@2.4.2(rollup@2.79.1): + '@rollup/plugin-replace@2.4.2': resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==} peerDependencies: rollup: ^1.20.0 || ^2.0.0 - dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) - magic-string: 0.25.9 - rollup: 2.79.1 - dev: true - /@rollup/plugin-typescript@11.1.6(typescript@5.4.5): - resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==} + '@rollup/plugin-terser@0.4.4': + resolution: {integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-typescript@12.1.2': + resolution: {integrity: sha512-cdtSp154H5sv637uMr1a8OTWB0L1SWDSm1rDGiyfcGcvQ6cuTs4MDk2BVEBGysUWago4OJN4EQZqOTl/QY3Jgg==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^2.14.0||^3.0.0||^4.0.0 @@ -3814,1528 +2708,844 @@ packages: optional: true tslib: optional: true - dependencies: - '@rollup/pluginutils': 5.1.0(rollup@2.79.1) - resolve: 1.22.8 - typescript: 5.4.5 - dev: true - /@rollup/pluginutils@3.1.0(rollup@2.79.1): + '@rollup/pluginutils@3.1.0': resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} engines: {node: '>= 8.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0 - dependencies: - '@types/estree': 0.0.39 - estree-walker: 1.0.1 - picomatch: 2.3.1 - rollup: 2.79.1 - dev: true - /@rollup/pluginutils@5.1.0(rollup@2.79.1): - resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + '@rollup/pluginutils@5.1.4': + resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 peerDependenciesMeta: rollup: optional: true - dependencies: - '@types/estree': 1.0.5 - estree-walker: 2.0.2 - picomatch: 2.3.1 - rollup: 2.79.1 - dev: true - /@rollup/rollup-android-arm-eabi@4.14.2: - resolution: {integrity: sha512-ahxSgCkAEk+P/AVO0vYr7DxOD3CwAQrT0Go9BJyGQ9Ef0QxVOfjDZMiF4Y2s3mLyPrjonchIMH/tbWHucJMykQ==} + '@rollup/rollup-android-arm-eabi@4.34.8': + resolution: {integrity: sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==} cpu: [arm] os: [android] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-android-arm64@4.14.2: - resolution: {integrity: sha512-lAarIdxZWbFSHFSDao9+I/F5jDaKyCqAPMq5HqnfpBw8dKDiCaaqM0lq5h1pQTLeIqueeay4PieGR5jGZMWprw==} + '@rollup/rollup-android-arm64@4.34.8': + resolution: {integrity: sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==} cpu: [arm64] os: [android] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-darwin-arm64@4.14.2: - resolution: {integrity: sha512-SWsr8zEUk82KSqquIMgZEg2GE5mCSfr9sE/thDROkX6pb3QQWPp8Vw8zOq2GyxZ2t0XoSIUlvHDkrf5Gmf7x3Q==} + '@rollup/rollup-darwin-arm64@4.34.8': + resolution: {integrity: sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==} cpu: [arm64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-darwin-x64@4.14.2: - resolution: {integrity: sha512-o/HAIrQq0jIxJAhgtIvV5FWviYK4WB0WwV91SLUnsliw1lSAoLsmgEEgRWzDguAFeUEUUoIWXiJrPqU7vGiVkA==} + '@rollup/rollup-darwin-x64@4.34.8': + resolution: {integrity: sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==} cpu: [x64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-linux-arm-gnueabihf@4.14.2: - resolution: {integrity: sha512-nwlJ65UY9eGq91cBi6VyDfArUJSKOYt5dJQBq8xyLhvS23qO+4Nr/RreibFHjP6t+5ap2ohZrUJcHv5zk5ju/g==} + '@rollup/rollup-freebsd-arm64@4.34.8': + resolution: {integrity: sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.34.8': + resolution: {integrity: sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.34.8': + resolution: {integrity: sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==} cpu: [arm] os: [linux] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-linux-arm64-gnu@4.14.2: - resolution: {integrity: sha512-Pg5TxxO2IVlMj79+c/9G0LREC9SY3HM+pfAwX7zj5/cAuwrbfj2Wv9JbMHIdPCfQpYsI4g9mE+2Bw/3aeSs2rQ==} + '@rollup/rollup-linux-arm-musleabihf@4.34.8': + resolution: {integrity: sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.34.8': + resolution: {integrity: sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==} cpu: [arm64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-linux-arm64-musl@4.14.2: - resolution: {integrity: sha512-cAOTjGNm84gc6tS02D1EXtG7tDRsVSDTBVXOLbj31DkwfZwgTPYZ6aafSU7rD/4R2a34JOwlF9fQayuTSkoclA==} + '@rollup/rollup-linux-arm64-musl@4.34.8': + resolution: {integrity: sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==} cpu: [arm64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-linux-powerpc64le-gnu@4.14.2: - resolution: {integrity: sha512-4RyT6v1kXb7C0fn6zV33rvaX05P0zHoNzaXI/5oFHklfKm602j+N4mn2YvoezQViRLPnxP8M1NaY4s/5kXO5cw==} + '@rollup/rollup-linux-loongarch64-gnu@4.34.8': + resolution: {integrity: sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': + resolution: {integrity: sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==} cpu: [ppc64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-linux-riscv64-gnu@4.14.2: - resolution: {integrity: sha512-KNUH6jC/vRGAKSorySTyc/yRYlCwN/5pnMjXylfBniwtJx5O7X17KG/0efj8XM3TZU7raYRXJFFReOzNmL1n1w==} + '@rollup/rollup-linux-riscv64-gnu@4.34.8': + resolution: {integrity: sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==} cpu: [riscv64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-linux-s390x-gnu@4.14.2: - resolution: {integrity: sha512-xPV4y73IBEXToNPa3h5lbgXOi/v0NcvKxU0xejiFw6DtIYQqOTMhZ2DN18/HrrP0PmiL3rGtRG9gz1QE8vFKXQ==} + '@rollup/rollup-linux-s390x-gnu@4.34.8': + resolution: {integrity: sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==} cpu: [s390x] os: [linux] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-linux-x64-gnu@4.14.2: - resolution: {integrity: sha512-QBhtr07iFGmF9egrPOWyO5wciwgtzKkYPNLVCFZTmr4TWmY0oY2Dm/bmhHjKRwZoGiaKdNcKhFtUMBKvlchH+Q==} + '@rollup/rollup-linux-x64-gnu@4.34.8': + resolution: {integrity: sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==} cpu: [x64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-linux-x64-musl@4.14.2: - resolution: {integrity: sha512-8zfsQRQGH23O6qazZSFY5jP5gt4cFvRuKTpuBsC1ZnSWxV8ZKQpPqOZIUtdfMOugCcBvFGRa1pDC/tkf19EgBw==} + '@rollup/rollup-linux-x64-musl@4.34.8': + resolution: {integrity: sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==} cpu: [x64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-win32-arm64-msvc@4.14.2: - resolution: {integrity: sha512-H4s8UjgkPnlChl6JF5empNvFHp77Jx+Wfy2EtmYPe9G22XV+PMuCinZVHurNe8ggtwoaohxARJZbaH/3xjB/FA==} + '@rollup/rollup-win32-arm64-msvc@4.34.8': + resolution: {integrity: sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==} cpu: [arm64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-win32-ia32-msvc@4.14.2: - resolution: {integrity: sha512-djqpAjm/i8erWYF0K6UY4kRO3X5+T4TypIqw60Q8MTqSBaQNpNXDhxdjpZ3ikgb+wn99svA7jxcXpiyg9MUsdw==} + '@rollup/rollup-win32-ia32-msvc@4.34.8': + resolution: {integrity: sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==} cpu: [ia32] os: [win32] - requiresBuild: true - dev: true - optional: true - /@rollup/rollup-win32-x64-msvc@4.14.2: - resolution: {integrity: sha512-teAqzLT0yTYZa8ZP7zhFKEx4cotS8Tkk5XiqNMJhD4CpaWB1BHARE4Qy+RzwnXvSAYv+Q3jAqCVBS+PS+Yee8Q==} + '@rollup/rollup-win32-x64-msvc@4.34.8': + resolution: {integrity: sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==} cpu: [x64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@shikijs/core@1.3.0: - resolution: {integrity: sha512-7fedsBfuILDTBmrYZNFI8B6ATTxhQAasUHllHmjvSZPnoq4bULWoTpHwmuQvZ8Aq03/tAa2IGo6RXqWtHdWaCA==} - dev: true + '@shikijs/core@2.5.0': + resolution: {integrity: sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==} - /@shikijs/transformers@1.3.0: - resolution: {integrity: sha512-3mlpg2I9CjhjE96dEWQOGeCWoPcyTov3s4aAsHmgvnTHa8MBknEnCQy8/xivJPSpD+olqOqIEoHnLfbNJK29AA==} - dependencies: - shiki: 1.3.0 - dev: true + '@shikijs/engine-javascript@2.5.0': + resolution: {integrity: sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==} - /@sideway/address@4.1.5: + '@shikijs/engine-oniguruma@1.29.2': + resolution: {integrity: sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==} + + '@shikijs/engine-oniguruma@2.5.0': + resolution: {integrity: sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==} + + '@shikijs/langs@2.5.0': + resolution: {integrity: sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==} + + '@shikijs/themes@2.5.0': + resolution: {integrity: sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==} + + '@shikijs/transformers@2.5.0': + resolution: {integrity: sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==} + + '@shikijs/types@1.29.2': + resolution: {integrity: sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==} + + '@shikijs/types@2.5.0': + resolution: {integrity: sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + + '@sideway/address@4.1.5': resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} - dependencies: - '@hapi/hoek': 9.3.0 - dev: true - /@sideway/formula@3.0.1: + '@sideway/formula@3.0.1': resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} - dev: true - /@sideway/pinpoint@2.0.0: + '@sideway/pinpoint@2.0.0': resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} - dev: true - /@sinclair/typebox@0.27.8: + '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - dev: true - /@sindresorhus/is@4.6.0: + '@sindresorhus/is@4.6.0': resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} - dev: true - /@sindresorhus/merge-streams@2.3.0: + '@sindresorhus/merge-streams@2.3.0': resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} engines: {node: '>=18'} - dev: true - /@sinonjs/commons@3.0.1: + '@sinonjs/commons@3.0.1': resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - dependencies: - type-detect: 4.0.8 - dev: true - /@sinonjs/fake-timers@10.3.0: + '@sinonjs/fake-timers@10.3.0': resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - dependencies: - '@sinonjs/commons': 3.0.1 - dev: true - /@surma/rollup-plugin-off-main-thread@2.2.3: + '@surma/rollup-plugin-off-main-thread@2.2.3': resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} - dependencies: - ejs: 3.1.10 - json5: 2.2.3 - magic-string: 0.25.9 - string.prototype.matchall: 4.0.11 - dev: true - /@szmarczak/http-timer@4.0.6: + '@szmarczak/http-timer@4.0.6': resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} engines: {node: '>=10'} - dependencies: - defer-to-connect: 2.0.1 - dev: true - /@tanstack/virtual-core@3.2.1: - resolution: {integrity: sha512-nO0d4vRzsmpBQCJYyClNHPPoUMI4nXNfrm6IcCRL33ncWMoNVpURh9YebEHPw8KrtsP2VSJIHE4gf4XFGk1OGg==} - dev: false + '@tanstack/virtual-core@3.13.0': + resolution: {integrity: sha512-NBKJP3OIdmZY3COJdWkSonr50FMVIi+aj5ZJ7hI/DTpEKg2RMfo/KvP8A3B/zOSpMgIe52B5E2yn7rryULzA6g==} - /@tanstack/vue-virtual@3.2.1(vue@3.4.21): - resolution: {integrity: sha512-NWJL8zJ4kwCkUzWd2jLKN9NTxj9RjYyaJwtA16j9urfbnMIdKe2g2HNymq0jGj+fmX/9nd58d6h78LrZ7I/J+A==} + '@tanstack/vue-virtual@3.13.0': + resolution: {integrity: sha512-EPgcTc41KGJAK2N2Ux2PeUnG3cPpdkldTib05nwq+0zdS2Ihpbq8BsWXz/eXPyNc5noDBh1GBgAe36yMYiW6WA==} peerDependencies: vue: ^2.7.0 || ^3.0.0 - dependencies: - '@tanstack/virtual-core': 3.2.1 - vue: 3.4.21(typescript@5.4.5) - dev: false - /@tootallnate/once@2.0.0: + '@tootallnate/once@2.0.0': resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} - dev: true - /@types/assert@1.5.10: - resolution: {integrity: sha512-qEO+AUgYab7GVbeDDgUNCU3o0aZUoIMpNAe+w5LDbRxfxQX7vQAdDgwj1AroX+i8KaV56FWg0srXlSZROnsrIQ==} - dev: false + '@types/assert@1.5.11': + resolution: {integrity: sha512-FjS1mxq2dlGr9N4z72/DO+XmyRS3ZZIoVn998MEopAN/OmyN28F4yumRL5pOw2z+hbFLuWGYuF2rrw5p11xM5A==} - /@types/babel__core@7.20.5: + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - dependencies: - '@babel/parser': 7.24.4 - '@babel/types': 7.24.0 - '@types/babel__generator': 7.6.8 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.5 - dev: true - /@types/babel__generator@7.6.8: + '@types/babel__generator@7.6.8': resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} - dependencies: - '@babel/types': 7.24.0 - dev: true - /@types/babel__template@7.4.4: + '@types/babel__template@7.4.4': resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - dependencies: - '@babel/parser': 7.24.4 - '@babel/types': 7.24.0 - dev: true - /@types/babel__traverse@7.20.5: - resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} - dependencies: - '@babel/types': 7.24.0 - dev: true + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} - /@types/body-parser@1.19.5: + '@types/body-parser@1.19.5': resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} - dependencies: - '@types/connect': 3.4.38 - '@types/node': 20.12.7 - dev: true - /@types/bonjour@3.5.10: - resolution: {integrity: sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==} - dependencies: - '@types/node': 20.12.7 - dev: true + '@types/bonjour@3.5.13': + resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} - /@types/braces@3.0.4: + '@types/braces@3.0.4': resolution: {integrity: sha512-0WR3b8eaISjEW7RpZnclONaLFDf7buaowRHdqLp4vLj54AsSAYWfh3DRbfiYJY9XDxMgx1B4sE1Afw2PGpuHOA==} - dev: true - /@types/cacheable-request@6.0.3: + '@types/cacheable-request@6.0.3': resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} - dependencies: - '@types/http-cache-semantics': 4.0.4 - '@types/keyv': 3.1.4 - '@types/node': 20.12.7 - '@types/responselike': 1.0.3 - dev: true - /@types/connect-history-api-fallback@1.5.0: - resolution: {integrity: sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==} - dependencies: - '@types/express-serve-static-core': 4.17.43 - '@types/node': 20.12.7 - dev: true + '@types/connect-history-api-fallback@1.5.4': + resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} - /@types/connect@3.4.38: + '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - dependencies: - '@types/node': 20.12.7 - dev: true - /@types/cors@2.8.17: + '@types/cors@2.8.17': resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} - dependencies: - '@types/node': 20.12.7 - dev: true - /@types/cytoscape@3.21.0: - resolution: {integrity: sha512-RN5SPiyVDpUP+LoOlxxlOYAMzkE7iuv3gA1jt3Hx2qTwArpZVPPdO+SI0hUj49OAn4QABR7JK9Gi0hibzGE0Aw==} - dev: true + '@types/cytoscape-fcose@2.2.4': + resolution: {integrity: sha512-QwWtnT8HI9h+DHhG5krGc1ZY0Ex+cn85MvX96ZNAjSxuXiZDnjIZW/ypVkvvubTjIY4rSdkJY1D/Nsn8NDpmAw==} - /@types/d3-array@3.2.1: + '@types/cytoscape@3.21.9': + resolution: {integrity: sha512-JyrG4tllI6jvuISPjHK9j2Xv/LTbnLekLke5otGStjFluIyA9JjgnvgZrSBsp8cEDpiTjwgZUZwpPv8TSBcoLw==} + + '@types/d3-array@3.2.1': resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} - dev: true - /@types/d3-axis@3.0.6: + '@types/d3-axis@3.0.6': resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==} - dependencies: - '@types/d3-selection': 3.0.10 - dev: true - /@types/d3-brush@3.0.6: + '@types/d3-brush@3.0.6': resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==} - dependencies: - '@types/d3-selection': 3.0.10 - dev: true - /@types/d3-chord@3.0.6: + '@types/d3-chord@3.0.6': resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==} - dev: true - /@types/d3-color@3.1.3: + '@types/d3-color@3.1.3': resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} - dev: true - /@types/d3-contour@3.0.6: + '@types/d3-contour@3.0.6': resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==} - dependencies: - '@types/d3-array': 3.2.1 - '@types/geojson': 7946.0.14 - dev: true - /@types/d3-delaunay@6.0.4: + '@types/d3-delaunay@6.0.4': resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==} - dev: true - /@types/d3-dispatch@3.0.6: + '@types/d3-dispatch@3.0.6': resolution: {integrity: sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==} - dev: true - /@types/d3-drag@3.0.7: + '@types/d3-drag@3.0.7': resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==} - dependencies: - '@types/d3-selection': 3.0.10 - dev: true - /@types/d3-dsv@3.0.7: + '@types/d3-dsv@3.0.7': resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==} - dev: true - /@types/d3-ease@3.0.2: + '@types/d3-ease@3.0.2': resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} - dev: true - /@types/d3-fetch@3.0.7: + '@types/d3-fetch@3.0.7': resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==} - dependencies: - '@types/d3-dsv': 3.0.7 - dev: true - /@types/d3-force@3.0.9: - resolution: {integrity: sha512-IKtvyFdb4Q0LWna6ymywQsEYjK/94SGhPrMfEr1TIc5OBeziTi+1jcCvttts8e0UWZIxpasjnQk9MNk/3iS+kA==} - dev: true + '@types/d3-force@3.0.10': + resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==} - /@types/d3-format@3.0.4: + '@types/d3-format@3.0.4': resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==} - dev: true - /@types/d3-geo@3.1.0: + '@types/d3-geo@3.1.0': resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} - dependencies: - '@types/geojson': 7946.0.14 - dev: true - /@types/d3-hierarchy@3.1.6: - resolution: {integrity: sha512-qlmD/8aMk5xGorUvTUWHCiumvgaUXYldYjNVOWtYoTYY/L+WwIEAmJxUmTgr9LoGNG0PPAOmqMDJVDPc7DOpPw==} - dev: true + '@types/d3-hierarchy@3.1.7': + resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==} - /@types/d3-interpolate@3.0.4: + '@types/d3-interpolate@3.0.4': resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} - dependencies: - '@types/d3-color': 3.1.3 - dev: true - /@types/d3-path@1.0.11: + '@types/d3-path@1.0.11': resolution: {integrity: sha512-4pQMp8ldf7UaB/gR8Fvvy69psNHkTpD/pVw3vmEi8iZAB9EPMBruB1JvHO4BIq9QkUUd2lV1F5YXpMNj7JPBpw==} - dev: true - /@types/d3-path@3.1.0: + '@types/d3-path@3.1.0': resolution: {integrity: sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==} - dev: true - /@types/d3-polygon@3.0.2: + '@types/d3-polygon@3.0.2': resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==} - dev: true - /@types/d3-quadtree@3.0.6: + '@types/d3-quadtree@3.0.6': resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==} - dev: true - /@types/d3-random@3.0.3: + '@types/d3-random@3.0.3': resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==} - dev: true - /@types/d3-sankey@0.12.4: + '@types/d3-sankey@0.12.4': resolution: {integrity: sha512-YTicQNwioitIlvuvlfW2GfO6sKxpohzg2cSQttlXAPjFwoBuN+XpGLhUN3kLutG/dI3GCLC+DUorqiJt7Naetw==} - dependencies: - '@types/d3-shape': 1.3.12 - dev: true - /@types/d3-scale-chromatic@3.0.3: - resolution: {integrity: sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==} - dev: true + '@types/d3-scale-chromatic@3.1.0': + resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} - /@types/d3-scale@4.0.8: - resolution: {integrity: sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==} - dependencies: - '@types/d3-time': 3.0.3 - dev: true + '@types/d3-scale@4.0.9': + resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==} - /@types/d3-selection@3.0.10: - resolution: {integrity: sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg==} - dev: true + '@types/d3-selection@3.0.11': + resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} - /@types/d3-shape@1.3.12: + '@types/d3-shape@1.3.12': resolution: {integrity: sha512-8oMzcd4+poSLGgV0R1Q1rOlx/xdmozS4Xab7np0eamFFUYq71AU9pOCJEFnkXW2aI/oXdVYJzw6pssbSut7Z9Q==} - dependencies: - '@types/d3-path': 1.0.11 - dev: true - /@types/d3-shape@3.1.6: - resolution: {integrity: sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==} - dependencies: - '@types/d3-path': 3.1.0 - dev: true + '@types/d3-shape@3.1.7': + resolution: {integrity: sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==} - /@types/d3-time-format@4.0.3: + '@types/d3-time-format@4.0.3': resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} - dev: true - /@types/d3-time@3.0.3: + '@types/d3-time@3.0.3': resolution: {integrity: sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==} - dev: true - /@types/d3-timer@3.0.2: + '@types/d3-timer@3.0.2': resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} - dev: true - /@types/d3-transition@3.0.8: - resolution: {integrity: sha512-ew63aJfQ/ms7QQ4X7pk5NxQ9fZH/z+i24ZfJ6tJSfqxJMrYLiK01EAs2/Rtw/JreGUsS3pLPNV644qXFGnoZNQ==} - dependencies: - '@types/d3-selection': 3.0.10 - dev: true + '@types/d3-transition@3.0.9': + resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==} - /@types/d3-zoom@3.0.8: + '@types/d3-zoom@3.0.8': resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} - dependencies: - '@types/d3-interpolate': 3.0.4 - '@types/d3-selection': 3.0.10 - dev: true - /@types/d3@7.4.3: + '@types/d3@7.4.3': resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==} - dependencies: - '@types/d3-array': 3.2.1 - '@types/d3-axis': 3.0.6 - '@types/d3-brush': 3.0.6 - '@types/d3-chord': 3.0.6 - '@types/d3-color': 3.1.3 - '@types/d3-contour': 3.0.6 - '@types/d3-delaunay': 6.0.4 - '@types/d3-dispatch': 3.0.6 - '@types/d3-drag': 3.0.7 - '@types/d3-dsv': 3.0.7 - '@types/d3-ease': 3.0.2 - '@types/d3-fetch': 3.0.7 - '@types/d3-force': 3.0.9 - '@types/d3-format': 3.0.4 - '@types/d3-geo': 3.1.0 - '@types/d3-hierarchy': 3.1.6 - '@types/d3-interpolate': 3.0.4 - '@types/d3-path': 3.1.0 - '@types/d3-polygon': 3.0.2 - '@types/d3-quadtree': 3.0.6 - '@types/d3-random': 3.0.3 - '@types/d3-scale': 4.0.8 - '@types/d3-scale-chromatic': 3.0.3 - '@types/d3-selection': 3.0.10 - '@types/d3-shape': 3.1.6 - '@types/d3-time': 3.0.3 - '@types/d3-time-format': 4.0.3 - '@types/d3-timer': 3.0.2 - '@types/d3-transition': 3.0.8 - '@types/d3-zoom': 3.0.8 - dev: true - /@types/debug@4.1.12: + '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} - dependencies: - '@types/ms': 0.7.34 - /@types/dompurify@3.0.5: - resolution: {integrity: sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==} - dependencies: - '@types/trusted-types': 2.0.7 - dev: true - - /@types/eslint-scope@3.7.7: - resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - dependencies: - '@types/eslint': 8.56.9 - '@types/estree': 1.0.5 - dev: true - - /@types/eslint@8.56.9: - resolution: {integrity: sha512-W4W3KcqzjJ0sHg2vAq9vfml6OhsJ53TcUjUqfzzZf/EChUtwspszj/S0pzMxnfRcO55/iGq47dscXw71Fxc4Zg==} - dependencies: - '@types/estree': 1.0.5 - '@types/json-schema': 7.0.15 - dev: true - - /@types/estree@0.0.39: + '@types/estree@0.0.39': resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} - dev: true - /@types/estree@1.0.5: - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - dev: true + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - /@types/express-serve-static-core@4.17.43: - resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==} - dependencies: - '@types/node': 20.12.7 - '@types/qs': 6.9.12 - '@types/range-parser': 1.2.7 - '@types/send': 0.17.4 - dev: true + '@types/express-serve-static-core@4.19.6': + resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} - /@types/express@4.17.21: + '@types/express-serve-static-core@5.0.0': + resolution: {integrity: sha512-AbXMTZGt40T+KON9/Fdxx0B2WK5hsgxcfXJLr5bFpZ7b4JCex2WyQPTEKdXqfHiY5nKKBScZ7yCoO6Pvgxfvnw==} + + '@types/express@4.17.21': resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} - dependencies: - '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.17.43 - '@types/qs': 6.9.12 - '@types/serve-static': 1.15.5 - dev: true - /@types/flexsearch@0.7.3: - resolution: {integrity: sha512-HXwADeHEP4exXkCIwy2n1+i0f1ilP1ETQOH5KDOugjkTFZPntWo0Gr8stZOaebkxsdx+k0X/K6obU/+it07ocg==} - dev: true + '@types/express@5.0.0': + resolution: {integrity: sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==} - /@types/geojson@7946.0.14: + '@types/flexsearch@0.7.6': + resolution: {integrity: sha512-H5IXcRn96/gaDmo+rDl2aJuIJsob8dgOXDqf8K0t8rWZd1AFNaaspmRsElESiU+EWE33qfbFPgI0OC/B1g9FCA==} + + '@types/geojson@7946.0.14': resolution: {integrity: sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==} - dev: true - /@types/glob@7.2.0: - resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} - dependencies: - '@types/minimatch': 5.1.2 - '@types/node': 20.12.7 - dev: true - - /@types/glob@8.1.0: + '@types/glob@8.1.0': resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==} - dependencies: - '@types/minimatch': 5.1.2 - '@types/node': 20.12.7 - dev: true - /@types/graceful-fs@4.1.9: + '@types/graceful-fs@4.1.9': resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} - dependencies: - '@types/node': 20.12.7 - dev: true - /@types/http-cache-semantics@4.0.4: + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/http-cache-semantics@4.0.4': resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} - dev: true - /@types/http-errors@2.0.4: + '@types/http-errors@2.0.4': resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - dev: true - /@types/http-proxy@1.17.11: - resolution: {integrity: sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==} - dependencies: - '@types/node': 20.12.7 - dev: true + '@types/http-proxy@1.17.15': + resolution: {integrity: sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==} - /@types/istanbul-lib-coverage@2.0.6: + '@types/istanbul-lib-coverage@2.0.6': resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} - dev: true - /@types/istanbul-lib-report@3.0.3: + '@types/istanbul-lib-report@3.0.3': resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} - dependencies: - '@types/istanbul-lib-coverage': 2.0.6 - dev: true - /@types/istanbul-reports@3.0.4: + '@types/istanbul-reports@3.0.4': resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - dependencies: - '@types/istanbul-lib-report': 3.0.3 - dev: true - /@types/js-yaml@4.0.9: + '@types/js-yaml@4.0.9': resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} - dev: true - /@types/jsdom@21.1.6: - resolution: {integrity: sha512-/7kkMsC+/kMs7gAYmmBR9P0vGTnOoLhQhyhQJSlXGI5bzTHp6xdo0TtKWQAsz6pmSAeVqKSbqeyP6hytqr9FDw==} - dependencies: - '@types/node': 20.11.30 - '@types/tough-cookie': 4.0.5 - parse5: 7.1.2 - dev: true + '@types/jsdom@21.1.7': + resolution: {integrity: sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==} - /@types/json-schema@7.0.15: + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: true - /@types/katex@0.16.7: + '@types/katex@0.16.7': resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==} - dev: true - /@types/keyv@3.1.4: + '@types/keyv@3.1.4': resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} - dependencies: - '@types/node': 20.12.7 - dev: true - /@types/linkify-it@3.0.5: - resolution: {integrity: sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==} - dev: true + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} - /@types/lodash-es@4.17.12: + '@types/lodash-es@4.17.12': resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} - dependencies: - '@types/lodash': 4.17.0 - dev: true - /@types/lodash@4.17.0: - resolution: {integrity: sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==} - dev: true + '@types/lodash@4.17.10': + resolution: {integrity: sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==} - /@types/markdown-it@12.2.3: + '@types/lodash@4.17.15': + resolution: {integrity: sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==} + + '@types/markdown-it@12.2.3': resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==} - dependencies: - '@types/linkify-it': 3.0.5 - '@types/mdurl': 1.0.5 - dev: true - /@types/markdown-it@13.0.7: - resolution: {integrity: sha512-U/CBi2YUUcTHBt5tjO2r5QV/x0Po6nsYwQU4Y04fBS6vfoImaiZ6f8bi3CjTCxBPQSO1LMyUqkByzi8AidyxfA==} - dependencies: - '@types/linkify-it': 3.0.5 - '@types/mdurl': 1.0.5 - dev: true + '@types/markdown-it@14.1.2': + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} - /@types/mdast@3.0.15: + '@types/mdast@3.0.15': resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} - dependencies: - '@types/unist': 2.0.10 - dev: true - /@types/mdast@4.0.3: - resolution: {integrity: sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==} - dependencies: - '@types/unist': 2.0.10 + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - /@types/mdurl@1.0.5: - resolution: {integrity: sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==} - dev: true + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} - /@types/micromatch@4.0.7: - resolution: {integrity: sha512-C/FMQ8HJAZhTsDpl4wDKZdMeeW5USjgzOczUwTGbRc1ZopPgOhIEnxY2ZgUrsuyy4DwK1JVOJZKFakv3TbCKiA==} - dependencies: - '@types/braces': 3.0.4 - dev: true + '@types/micromatch@4.0.9': + resolution: {integrity: sha512-7V+8ncr22h4UoYRLnLXSpTxjQrNUXtWHGeMPRJt1nULXI57G9bIcpyrHlmrQ7QK24EyyuXvYcSSWAM8GA9nqCg==} - /@types/mime@1.3.5: + '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - dev: true - /@types/mime@3.0.4: - resolution: {integrity: sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==} - dev: true - - /@types/minimatch@5.1.2: + '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - dev: true - /@types/ms@0.7.34: + '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} - /@types/node@18.19.31: - resolution: {integrity: sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==} - dependencies: - undici-types: 5.26.5 - dev: true + '@types/node-forge@1.3.11': + resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} - /@types/node@20.11.30: - resolution: {integrity: sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==} - dependencies: - undici-types: 5.26.5 - dev: true + '@types/node@12.20.55': + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - /@types/node@20.12.7: - resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} - dependencies: - undici-types: 5.26.5 - dev: true + '@types/node@18.19.76': + resolution: {integrity: sha512-yvR7Q9LdPz2vGpmpJX5LolrgRdWvB67MJKDPSgIIzpFbaf9a1j/f5DnLp5VDyHGMR0QZHlTr1afsD87QCXFHKw==} - /@types/normalize-package-data@2.4.1: - resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} - dev: true + '@types/node@22.13.5': + resolution: {integrity: sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==} - /@types/prettier@2.7.3: - resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} - dev: true + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - /@types/prettier@3.0.0: - resolution: {integrity: sha512-mFMBfMOz8QxhYVbuINtswBp9VL2b4Y0QqYHwqLz3YbgtfAcat2Dl6Y1o4e22S/OVE6Ebl9m7wWiMT2lSbAs1wA==} - deprecated: This is a stub types definition. prettier provides its own type definitions, so you do not need this installed. - dependencies: - prettier: 3.2.5 - dev: true + '@types/qs@6.9.16': + resolution: {integrity: sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==} - /@types/qs@6.9.12: - resolution: {integrity: sha512-bZcOkJ6uWrL0Qb2NAWKa7TBU+mJHPzhx9jjLL1KHF+XpzEcR7EXHvjbHlGtR/IsP1vyPrehuS6XqkmaePy//mg==} - dev: true - - /@types/ramda@0.28.25: + '@types/ramda@0.28.25': resolution: {integrity: sha512-HrQNqQAGcITpn9HAJFamDxm7iZeeXiP/95pN5OMbNniDjzCCeOHbBKNGmUy8NRi0fhYS+/cXeo91MFC+06gbow==} - dependencies: - ts-toolbelt: 6.15.5 - dev: false - /@types/range-parser@1.2.7: + '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - dev: true - /@types/resolve@1.17.1: - resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} - dependencies: - '@types/node': 20.12.7 - dev: true + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - /@types/responselike@1.0.3: + '@types/responselike@1.0.3': resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} - dependencies: - '@types/node': 20.12.7 - dev: true - /@types/retry@0.12.0: + '@types/retry@0.12.0': resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} - dev: true - /@types/rollup-plugin-visualizer@4.2.4: - resolution: {integrity: sha512-BW4Q6D1Qy5gno5qHWrnMDC2dOe/TAKXvqCpckOggCCu+XpS+ZZJJ1lq1+K3bvYccoO3Y7f5kglbFAgYGqCgULg==} - dependencies: - rollup: 2.79.1 - dev: true + '@types/rollup-plugin-visualizer@5.0.3': + resolution: {integrity: sha512-eqlnKXp1TvvlUVPd+cBrTfD4v7TyshgoCT3ao490fkJdR6M8CPjZLc+MFBmXZjCRXk30yKAyZ2n381fXafAQOg==} + deprecated: This is a stub types definition. rollup-plugin-visualizer provides its own type definitions, so you do not need this installed. - /@types/semver@7.5.8: - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - dev: true - - /@types/send@0.17.4: + '@types/send@0.17.4': resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} - dependencies: - '@types/mime': 1.3.5 - '@types/node': 20.12.7 - dev: true - /@types/serve-index@1.9.1: - resolution: {integrity: sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==} - dependencies: - '@types/express': 4.17.21 - dev: true + '@types/serve-index@1.9.4': + resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} - /@types/serve-static@1.15.5: - resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==} - dependencies: - '@types/http-errors': 2.0.4 - '@types/mime': 3.0.4 - '@types/node': 20.12.7 - dev: true + '@types/serve-static@1.15.7': + resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} - /@types/sinonjs__fake-timers@8.1.1: + '@types/sinonjs__fake-timers@8.1.1': resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==} - dev: true - /@types/sizzle@2.3.8: - resolution: {integrity: sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==} - dev: true + '@types/sizzle@2.3.9': + resolution: {integrity: sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==} - /@types/sockjs@0.3.33: - resolution: {integrity: sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==} - dependencies: - '@types/node': 20.12.7 - dev: true + '@types/sockjs@0.3.36': + resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} - /@types/stack-utils@2.0.3: + '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} - dev: true - /@types/stylis@4.2.5: - resolution: {integrity: sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==} - dev: true + '@types/stylis@4.2.7': + resolution: {integrity: sha512-VgDNokpBoKF+wrdvhAAfS55OMQpL6QRglwTwNC3kIgBrzZxA4WsFj+2eLfEA/uMUDzBcEhYmjSbwQakn/i3ajA==} - /@types/tough-cookie@4.0.5: + '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - dev: true - /@types/trusted-types@2.0.3: - resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==} - dev: true - - /@types/trusted-types@2.0.7: + '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - dev: true - /@types/unist@2.0.10: - resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} - /@types/unist@3.0.2: - resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - /@types/uuid@9.0.8: - resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} - dev: true + '@types/uuid@10.0.0': + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} - /@types/web-bluetooth@0.0.20: + '@types/web-bluetooth@0.0.20': resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} - /@types/ws@8.5.5: + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} + + '@types/ws@8.5.12': + resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==} + + '@types/ws@8.5.5': resolution: {integrity: sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==} - dependencies: - '@types/node': 20.12.7 - dev: true - /@types/yargs-parser@21.0.3: + '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - dev: true - /@types/yargs@17.0.32: - resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} - dependencies: - '@types/yargs-parser': 21.0.3 - dev: true + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} - /@types/yauzl@2.10.3: + '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - requiresBuild: true - dependencies: - '@types/node': 20.12.7 - dev: true - optional: true - /@typescript-eslint/eslint-plugin@7.6.0(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/eslint-plugin@8.29.1': + resolution: {integrity: sha512-ba0rr4Wfvg23vERs3eB+P3lfj2E+2g3lhWcCVukUuhtcdUx5lSIFZlGFEBHKr+3zizDa/TvZTptdNHVZWAkSBg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.6.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.6.0 - '@typescript-eslint/type-utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.6.0 - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.4.5) - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' - /@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/parser@8.29.1': + resolution: {integrity: sha512-zczrHVEqEaTwh12gWBIJWj8nx+ayDcCJs06yoNMY0kwjMWDM6+kppljY+BxWI06d2Ja+h4+WdufDcwMnnMEWmg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 7.6.0 - '@typescript-eslint/types': 7.6.0 - '@typescript-eslint/typescript-estree': 7.6.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.6.0 - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' - /@typescript-eslint/scope-manager@5.62.0: - resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - dev: true + '@typescript-eslint/scope-manager@8.24.1': + resolution: {integrity: sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /@typescript-eslint/scope-manager@7.6.0: - resolution: {integrity: sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.6.0 - '@typescript-eslint/visitor-keys': 7.6.0 - dev: true + '@typescript-eslint/scope-manager@8.29.1': + resolution: {integrity: sha512-2nggXGX5F3YrsGN08pw4XpMLO1Rgtnn4AzTegC2MDesv6q3QaTU5yU7IbS1tf1IwCR0Hv/1EFygLn9ms6LIpDA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /@typescript-eslint/type-utils@7.6.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/type-utils@8.29.1': + resolution: {integrity: sha512-DkDUSDwZVCYN71xA4wzySqqcZsHKic53A4BLqmrWFFpOpNSoxX233lwGu/2135ymTCR04PoKiEEEvN1gFYg4Tw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 7.6.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.4.5) - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' - /@typescript-eslint/types@5.62.0: - resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@typescript-eslint/types@7.6.0: - resolution: {integrity: sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==} + '@typescript-eslint/types@7.18.0': + resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} engines: {node: ^18.18.0 || >=20.0.0} - dev: true - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.4.5): - resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.4(supports-color@8.1.1) - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.6.0 - tsutils: 3.21.0(typescript@5.4.5) - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true + '@typescript-eslint/types@8.24.1': + resolution: {integrity: sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /@typescript-eslint/typescript-estree@7.6.0(typescript@5.4.5): - resolution: {integrity: sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==} + '@typescript-eslint/types@8.29.1': + resolution: {integrity: sha512-VT7T1PuJF1hpYC3AGm2rCgJBjHL3nc+A/bhOp9sGMKfi5v0WufsX/sHCFBfNTx2F+zA6qBc/PD0/kLRLjdt8mQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@7.18.0': + resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true - dependencies: - '@typescript-eslint/types': 7.6.0 - '@typescript-eslint/visitor-keys': 7.6.0 - debug: 4.3.4(supports-color@8.1.1) - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.4 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.4.5) - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - dev: true - /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/typescript-estree@8.24.1': + resolution: {integrity: sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5) - eslint: 8.57.0 - eslint-scope: 5.1.1 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true + typescript: '>=4.8.4 <5.8.0' - /@typescript-eslint/utils@7.6.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==} + '@typescript-eslint/typescript-estree@8.29.1': + resolution: {integrity: sha512-l1enRoSaUkQxOQnbi0KPUtqeZkSiFlqrx9/3ns2rEDhGKfTa+88RmXqedC1zmVTOWrLc2e6DEJrTA51C9iLH5g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/utils@8.24.1': + resolution: {integrity: sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.8.0' + + '@typescript-eslint/utils@8.29.1': + resolution: {integrity: sha512-QAkFEbytSaB8wnmB+DflhUPz6CLbFWE2SnSCrRMEa+KnXIzDYbpsn++1HGvnfAsUY44doDXmvRkO5shlM/3UfA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/visitor-keys@7.18.0': + resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/visitor-keys@8.24.1': + resolution: {integrity: sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/visitor-keys@8.29.1': + resolution: {integrity: sha512-RGLh5CRaUEf02viP5c1Vh1cMGffQscyHe7HPAzGpfmfflFg1wUz2rYxd+OZqwpeypYvZ8UxSxuIpF++fmOzEcg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + '@unocss/astro@66.0.0': + resolution: {integrity: sha512-GBhXT6JPqXjDXoJZTXhySk83NgOt0UigChqrUUdG4x7Z+DVYkDBION8vZUJjw0OdIaxNQ4euGWu4GDsMF6gQQg==} peerDependencies: - eslint: ^8.56.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 7.6.0 - '@typescript-eslint/types': 7.6.0 - '@typescript-eslint/typescript-estree': 7.6.0(typescript@5.4.5) - eslint: 8.57.0 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys@5.62.0: - resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@7.6.0: - resolution: {integrity: sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.6.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true - - /@unocss/astro@0.59.2(rollup@2.79.1)(vite@5.2.8): - resolution: {integrity: sha512-vchGjdGxwDELAWJX6Ql5FCg+eDsJmT4Pn752h4oCy6cZHq/0i4p+CovT/Rb8AkfCpCW+DtdjKRRhfAnmKjJquQ==} - peerDependencies: - vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 peerDependenciesMeta: vite: optional: true - dependencies: - '@unocss/core': 0.59.2 - '@unocss/reset': 0.59.2 - '@unocss/vite': 0.59.2(rollup@2.79.1)(vite@5.2.8) - vite: 5.2.8(@types/node@20.12.7) - transitivePeerDependencies: - - rollup - dev: true - /@unocss/cli@0.59.2(rollup@2.79.1): - resolution: {integrity: sha512-B7DjC49obmf9LXDxlAcy+K4ItYYgjHUALv+PVzPRcFml2H1DqSSWmOAHmbr12a81MWXXRlS1s7Z24LKqX6vFKg==} + '@unocss/cli@66.0.0': + resolution: {integrity: sha512-KVQiskoOjVkLVpNaG6WpLa4grPplrZROYZJVIUYSTqZyZRFNSvjttHcsCwpoWUEUdEombPtVZl8FrXePjY5IiQ==} engines: {node: '>=14'} hasBin: true - dependencies: - '@ampproject/remapping': 2.3.0 - '@rollup/pluginutils': 5.1.0(rollup@2.79.1) - '@unocss/config': 0.59.2 - '@unocss/core': 0.59.2 - '@unocss/preset-uno': 0.59.2 - cac: 6.7.14 - chokidar: 3.6.0 - colorette: 2.0.20 - consola: 3.2.3 - fast-glob: 3.3.2 - magic-string: 0.30.9 - pathe: 1.1.2 - perfect-debounce: 1.0.0 - transitivePeerDependencies: - - rollup - dev: true - /@unocss/config@0.59.2: - resolution: {integrity: sha512-KknR9kcid1w/8IuujZ8msE5pU930GD5e2v84H9Ftcv308yfuj+j/0zQ/ORtG8qMx+97p7uFy3xspzI2yoRYRpQ==} + '@unocss/config@66.0.0': + resolution: {integrity: sha512-nFRGop/guBa4jLkrgXjaRDm5JPz4x3YpP10m5IQkHpHwlnHUVn1L9smyPl04ohYWhYn9ZcAHgR28Ih2jwta8hw==} engines: {node: '>=14'} - dependencies: - '@unocss/core': 0.59.2 - unconfig: 0.3.12 - dev: true - /@unocss/core@0.59.2: - resolution: {integrity: sha512-0NtauY7v5bG0UIcvIABWnD2ssD5b9UcFkyw4iRIsT9NvR0e7QqGIOvZEg5XN0j25o50GtxlotMmTAAiaazHZ0Q==} - dev: true + '@unocss/core@66.0.0': + resolution: {integrity: sha512-PdVbSMHNDDkr++9nkqzsZRAkaU84gxMTEgYbqI7dt2p1DXp/5tomVtmMsr2/whXGYKRiUc0xZ3p4Pzraz8TcXA==} - /@unocss/extractor-arbitrary-variants@0.59.2: - resolution: {integrity: sha512-v+1cdybFmi7sRUG8/B2vSVaBi/CgViithbiwjTjzeKETA5Cw/pWgk1Rf/MDu4jfux4MZ0+mLULm20HSUg0oXdg==} - dependencies: - '@unocss/core': 0.59.2 - dev: true + '@unocss/extractor-arbitrary-variants@66.0.0': + resolution: {integrity: sha512-vlkOIOuwBfaFBJcN6o7+obXjigjOlzVFN/jT6pG1WXbQDTRZ021jeF3i9INdb9D/0cQHSeDvNgi1TJ5oUxfiow==} - /@unocss/inspector@0.59.2: - resolution: {integrity: sha512-9BbtPrxYZVazODkNM5pZJ0j0XXIxdWxwG7PigyqJCBJbtUyM35jEZRQPNKAeGAlcnxoZE6UAJneG1M+BgFZt/w==} - dependencies: - '@unocss/core': 0.59.2 - '@unocss/rule-utils': 0.59.2 - gzip-size: 6.0.0 - sirv: 2.0.4 - dev: true + '@unocss/inspector@66.0.0': + resolution: {integrity: sha512-mkIxieVm0kMOKw+E4ABpIerihYMdjgq9A92RD5h2+W/ebpxTEw5lTTK1xcMLiAlmOrVYMQKjpgPeu3vQmDyGZQ==} - /@unocss/postcss@0.59.2(postcss@8.4.38): - resolution: {integrity: sha512-9pRixhnL9B1sdhzY7zlhnBXc8nVNwDCT4nMQRgSdWNvT76dImVv1N3609veIrCfLEHQJi52Juo//trSNLjUzZQ==} + '@unocss/postcss@66.0.0': + resolution: {integrity: sha512-6bi+ujzh8I1PJwtmHX71LH8z/H9+vPxeYD4XgFihyU1k4Y6MVhjr7giGjLX4yP27IP+NsVyotD22V7by/dBVEA==} engines: {node: '>=14'} peerDependencies: postcss: ^8.4.21 - dependencies: - '@unocss/config': 0.59.2 - '@unocss/core': 0.59.2 - '@unocss/rule-utils': 0.59.2 - css-tree: 2.3.1 - fast-glob: 3.3.2 - magic-string: 0.30.9 - postcss: 8.4.38 - dev: true - /@unocss/preset-attributify@0.59.2: - resolution: {integrity: sha512-iQsKoQAaEwosqe9199rhlZqUeRZ3A39QKqLNxLRf+zkiIQaL0yHlsTYVg9VjbiEb8A1JDi7nHDgZNRBJRyb3nQ==} - dependencies: - '@unocss/core': 0.59.2 - dev: true + '@unocss/preset-attributify@66.0.0': + resolution: {integrity: sha512-eYsOgmcDoiIgGAepIwRX+DKGYxc/wm0r4JnDuZdz29AB+A6oY/FGHS1BVt4rq9ny4B5PofP4p6Rty+vwD9rigw==} - /@unocss/preset-icons@0.59.2: - resolution: {integrity: sha512-Qg/zXqzlt0qLdC7DmDVilX0gdgiM1IPqy+fZ8sAfWy3CtAfMIg4rSHn3qELZdExGvp0WfnkLC+q0t7AwyVyQPw==} - dependencies: - '@iconify/utils': 2.1.22 - '@unocss/core': 0.59.2 - ofetch: 1.3.4 - transitivePeerDependencies: - - supports-color - dev: true + '@unocss/preset-icons@66.0.0': + resolution: {integrity: sha512-6ObwTvEGuPBbKWRoMMiDioHtwwQTFI5oojFLJ32Y8tW6TdXvBLkO88d7qpgQxEjgVt4nJrqF1WEfR4niRgBm0Q==} - /@unocss/preset-mini@0.59.2: - resolution: {integrity: sha512-OFFPNyuuQcPJU4lIE1nQXnmH6uOuinA0+bCAjyB6/1Bj7LCLJGPqdviud/to6cLT90PUsKTIG2TTEQisO3CWAQ==} - dependencies: - '@unocss/core': 0.59.2 - '@unocss/extractor-arbitrary-variants': 0.59.2 - '@unocss/rule-utils': 0.59.2 - dev: true + '@unocss/preset-mini@66.0.0': + resolution: {integrity: sha512-d62eACnuKtR0dwCFOQXgvw5VLh5YSyK56xCzpHkh0j0GstgfDLfKTys0T/XVAAvdSvAy/8A8vhSNJ4PlIc9V2A==} - /@unocss/preset-tagify@0.59.2: - resolution: {integrity: sha512-/dhu5G3P0084wn+gxqaLpChv8EyXh9q070uYUxdzNjmZgZ0JDZaeSrcfiyzLJO5RoYCyJNAsp32mBK+//N3XPg==} - dependencies: - '@unocss/core': 0.59.2 - dev: true + '@unocss/preset-tagify@66.0.0': + resolution: {integrity: sha512-GGYGyWxaevh0jN0NoATVO1Qe7DFXM3ykLxchlXmG6/zy963pZxItg/njrKnxE9la4seCdxpFH7wQBa68imwwdA==} - /@unocss/preset-typography@0.59.2: - resolution: {integrity: sha512-02NSGlEhxSDYl58ZiorP4EUiFI5z+j9ez5XjF+FKrZwK2J/L3/DRXcW00n9ERhtc44H6RP2Laj3X7sH8ggJ37A==} - dependencies: - '@unocss/core': 0.59.2 - '@unocss/preset-mini': 0.59.2 - dev: true + '@unocss/preset-typography@66.0.0': + resolution: {integrity: sha512-apjckP5nPU5mtaHTCzz5u/dK9KJWwJ2kOFCVk0+a/KhUWmnqnzmjRYZlEuWxxr5QxTdCW+9cIoRDSA0lYZS5tg==} - /@unocss/preset-uno@0.59.2: - resolution: {integrity: sha512-+decQShFqTz00w6rpNRQZEZm8PV1MHHs0thUNaooBUF+pISNhJlXJisE2rz4V7KVCCMgZZTRtyPZxmblGVXbJg==} - dependencies: - '@unocss/core': 0.59.2 - '@unocss/preset-mini': 0.59.2 - '@unocss/preset-wind': 0.59.2 - '@unocss/rule-utils': 0.59.2 - dev: true + '@unocss/preset-uno@66.0.0': + resolution: {integrity: sha512-qgoZ/hzTI32bQvcyjcwvv1X/dbPlmQNehzgjUaL7QFT0q0/CN/SRpysfzoQ8DLl2se9T+YCOS9POx3KrpIiYSQ==} - /@unocss/preset-web-fonts@0.59.2: - resolution: {integrity: sha512-F7NTjDnmmWlu/NlFjtFR92PnONGax1geXFQFb/dh7QlEBZiVe/qzHRtKLtsYaOGSPr5CSamo0LORx4wug7gjIA==} - dependencies: - '@unocss/core': 0.59.2 - ofetch: 1.3.4 - dev: true + '@unocss/preset-web-fonts@66.0.0': + resolution: {integrity: sha512-9MzfDc6AJILN4Kq7Z91FfFbizBOYgw3lJd2UwqIs3PDYWG5iH5Zv5zhx6jelZVqEW5uWcIARYEEg2m4stZO1ZA==} - /@unocss/preset-wind@0.59.2: - resolution: {integrity: sha512-LbdsxU8M90guqV4e7K1weDp3wWcSwzcSmxkogSI/R818SJgnocv4eNzeIR5/mbZu8y8ENtEiE8rEYL1jA6L2GQ==} - dependencies: - '@unocss/core': 0.59.2 - '@unocss/preset-mini': 0.59.2 - '@unocss/rule-utils': 0.59.2 - dev: true + '@unocss/preset-wind3@66.0.0': + resolution: {integrity: sha512-WAGRmpi1sb2skvYn9DBQUvhfqrJ+VmQmn5ZGsT2ewvsk7HFCvVLAMzZeKrrTQepeNBRhg6HzFDDi8yg6yB5c9g==} - /@unocss/reset@0.59.2: - resolution: {integrity: sha512-xEo2ogs42FlNUca3BiPesGg9/FevJ6cmkxnzzbwlqIEeZjiCH6o+nGdNNUbi6p+gto2P9v4L8ZOeMFYQCwpFzg==} - dev: true + '@unocss/preset-wind@66.0.0': + resolution: {integrity: sha512-FtvGpHnGC7FiyKJavPnn5y9lsaoWRhXlujCqlT5Bw63kKhMNr0ogKySBpenUhJOhWhVM0OQXn2nZ3GZRxW2qpw==} - /@unocss/rule-utils@0.59.2: - resolution: {integrity: sha512-2F1Q1pCfeG65GxPEhGQDZXXoZk38fX4o5LOYf35XkknhjQmkaeK76szVYXLDoyK30n9EiwXqoc0MdKrGjeCMUA==} + '@unocss/reset@66.0.0': + resolution: {integrity: sha512-YLFz/5yT7mFJC8JSmIUA5+bS3CBCJbtztOw+8rWzjQr/BEVSGuihWUUpI2Df6VVxXIXxKanZR6mIl59yvf+GEA==} + + '@unocss/rule-utils@66.0.0': + resolution: {integrity: sha512-UJ51YHbwxYTGyj35ugsPlOT4gaa7tCbXdywZ3m5Nn0JgywwIqGmBFyiN9ZjHBHfJuDxmmPd6lxojoBscih/WMQ==} engines: {node: '>=14'} - dependencies: - '@unocss/core': 0.59.2 - magic-string: 0.30.9 - dev: true - /@unocss/scope@0.59.2: - resolution: {integrity: sha512-V6ZS+QonrmqRfZ1/oYmEusASBjbbO+eeL+Fau3bh8IZyPq2HkngJvLNwcyQUPk3/pH18anuzBktSYP0BD2GsKA==} - dev: true + '@unocss/transformer-attributify-jsx@66.0.0': + resolution: {integrity: sha512-jS7szFXXC6RjTv9wo0NACskf618w981bkbyQ5izRO7Ha47sNpHhHDpaltnG7SR9qV4cCtGalOw4onVMHsRKwRg==} - /@unocss/transformer-attributify-jsx-babel@0.59.2: - resolution: {integrity: sha512-tFFncKR9WkGs8asi00lboVbQ/GjHWrE3YBY1GCrSZpeW+XOpGkkEEo03ncVW2c2s0ie4Zl5T7UWcRzFY8gyITQ==} - dependencies: - '@babel/core': 7.24.4 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.4) - '@babel/preset-typescript': 7.24.1(@babel/core@7.24.4) - '@unocss/core': 0.59.2 - transitivePeerDependencies: - - supports-color - dev: true + '@unocss/transformer-compile-class@66.0.0': + resolution: {integrity: sha512-ytUIE0nAcHRMACuTXkHp8auZ483DXrOZw99jk3FJ+aFjpD/pVSFmX14AWJ7bqPFObxb4SLFs6KhQma30ESC22A==} - /@unocss/transformer-attributify-jsx@0.59.2: - resolution: {integrity: sha512-mqcA02tkgeEdMH99K3YJFwHhyT/qvM/0+amfZ3nYlNAiiyCumdb980fSdUvx/cTyXmnocD6tG+UPnx2kD3zdQg==} - dependencies: - '@unocss/core': 0.59.2 - dev: true + '@unocss/transformer-directives@66.0.0': + resolution: {integrity: sha512-utcg7m2Foi7uHrU5WHadNuJ0a3qWG8tZNkQMi+m0DQpX6KWfuDtDn0zDZ1X+z5lmiB3WGSJERRrsvZbj1q50Mw==} - /@unocss/transformer-compile-class@0.59.2: - resolution: {integrity: sha512-yXKoAJU0QcRx3c2XAalHgcVculIPDRCanBm5A3XZPp35eKhcni3VedzUQY6RYFfoETOgQ5x0SV73Ttbj/zvZBQ==} - dependencies: - '@unocss/core': 0.59.2 - dev: true + '@unocss/transformer-variant-group@66.0.0': + resolution: {integrity: sha512-1BLjNWtAnR1JAcQGw0TS+nGrVoB9aznzvVZRoTx23dtRr3btvgKPHb8LrD48eD/p8Dtw9j3WfuxMDKXKegKDLg==} - /@unocss/transformer-directives@0.59.2: - resolution: {integrity: sha512-FiLcBtwUIUNFpE2SxeUeslJGShHimOJyk30+m2BP+Af7QsxcamWb8/w7YKRMz5MAmE6ZnzAzx/ZAdrK540ho0A==} - dependencies: - '@unocss/core': 0.59.2 - '@unocss/rule-utils': 0.59.2 - css-tree: 2.3.1 - dev: true - - /@unocss/transformer-variant-group@0.59.2: - resolution: {integrity: sha512-nlEI5ts2YVKvL0dFaIozFIefPUTDZhYCNS6Oie5DPVXDTVufkh9OinLiCo/2ggytkY/VZL00wJm6Iknrp7HL7Q==} - dependencies: - '@unocss/core': 0.59.2 - dev: true - - /@unocss/vite@0.59.2(rollup@2.79.1)(vite@5.2.8): - resolution: {integrity: sha512-cCATFcyoHKr/5c/ccnwhtYoUA42v+SXp2xmpR4hgE0U4WFgGqIYOx5pzWap73DbywQJuU0hklq7lgvO9b+L/sQ==} + '@unocss/vite@66.0.0': + resolution: {integrity: sha512-IVcPX8xL+2edyXKt4tp9yu5A6gcbPVCsspfcL0XgziCr01kS+4qSoZ90F3IUs3hXc/AyO5eCpRtGFMPLpOjXQg==} peerDependencies: - vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 - dependencies: - '@ampproject/remapping': 2.3.0 - '@rollup/pluginutils': 5.1.0(rollup@2.79.1) - '@unocss/config': 0.59.2 - '@unocss/core': 0.59.2 - '@unocss/inspector': 0.59.2 - '@unocss/scope': 0.59.2 - '@unocss/transformer-directives': 0.59.2 - chokidar: 3.6.0 - fast-glob: 3.3.2 - magic-string: 0.30.9 - vite: 5.2.8(@types/node@20.12.7) - transitivePeerDependencies: - - rollup - dev: true + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 - /@vite-pwa/vitepress@0.4.0(vite-plugin-pwa@0.19.8): - resolution: {integrity: sha512-MrsSCK5EBCzQAQgq5/3XHaFIjkypda58Wzy6PkDwZoRHnWexik0C2GUxMOe+RA+qdpGxB0mEkhqajeOmuYMvhw==} + '@vite-pwa/vitepress@1.0.0': + resolution: {integrity: sha512-i5RFah4urA6tZycYlGyBslVx8cVzbZBcARJLDg5rWMfAkRmyLtpRU6usGfVOwyN9kjJ2Bkm+gBHXF1hhr7HptQ==} peerDependencies: - '@vite-pwa/assets-generator': ^0.2.4 - vite-plugin-pwa: '>=0.19.0 <1' + '@vite-pwa/assets-generator': ^1.0.0 + vite-plugin-pwa: ^1.0.0 peerDependenciesMeta: '@vite-pwa/assets-generator': optional: true - dependencies: - vite-plugin-pwa: 0.19.8(vite@5.2.8)(workbox-build@7.0.0)(workbox-window@7.0.0) - dev: true - /@vitejs/plugin-vue@5.0.4(vite@5.2.8)(vue@3.4.21): - resolution: {integrity: sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==} + '@vitejs/plugin-vue@5.2.1': + resolution: {integrity: sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: - vite: ^5.0.0 + vite: ^5.0.0 || ^6.0.0 vue: ^3.2.25 - dependencies: - vite: 5.2.8(@types/node@20.12.7) - vue: 3.4.21(typescript@5.4.5) - dev: true - /@vitest/coverage-v8@1.5.0(vitest@1.5.0): - resolution: {integrity: sha512-1igVwlcqw1QUMdfcMlzzY4coikSIBN944pkueGi0pawrX5I5Z+9hxdTR+w3Sg6Q3eZhvdMAs8ZaF9JuTG1uYOQ==} + '@vitest/coverage-v8@3.0.6': + resolution: {integrity: sha512-JRTlR8Bw+4BcmVTICa7tJsxqphAktakiLsAmibVLAWbu1lauFddY/tXeM6sAyl1cgkPuXtpnUgaCPhTdz1Qapg==} peerDependencies: - vitest: 1.5.0 - dependencies: - '@ampproject/remapping': 2.3.0 - '@bcoe/v8-coverage': 0.2.3 - debug: 4.3.4(supports-color@8.1.1) - istanbul-lib-coverage: 3.2.2 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 5.0.4 - istanbul-reports: 3.1.7 - magic-string: 0.30.9 - magicast: 0.3.4 - picocolors: 1.0.0 - std-env: 3.7.0 - strip-literal: 2.1.0 - test-exclude: 6.0.0 - vitest: 1.5.0(@types/node@20.12.7)(@vitest/ui@1.5.0)(jsdom@24.0.0) - transitivePeerDependencies: - - supports-color - dev: true + '@vitest/browser': 3.0.6 + vitest: 3.0.6 + peerDependenciesMeta: + '@vitest/browser': + optional: true - /@vitest/expect@1.5.0: - resolution: {integrity: sha512-0pzuCI6KYi2SIC3LQezmxujU9RK/vwC1U9R0rLuGlNGcOuDWxqWKu6nUdFsX9tH1WU0SXtAxToOsEjeUn1s3hA==} - dependencies: - '@vitest/spy': 1.5.0 - '@vitest/utils': 1.5.0 - chai: 4.4.1 - dev: true + '@vitest/expect@3.0.6': + resolution: {integrity: sha512-zBduHf/ja7/QRX4HdP1DSq5XrPgdN+jzLOwaTq/0qZjYfgETNFCKf9nOAp2j3hmom3oTbczuUzrzg9Hafh7hNg==} - /@vitest/runner@1.5.0: - resolution: {integrity: sha512-7HWwdxXP5yDoe7DTpbif9l6ZmDwCzcSIK38kTSIt6CFEpMjX4EpCgT6wUmS0xTXqMI6E/ONmfgRKmaujpabjZQ==} - dependencies: - '@vitest/utils': 1.5.0 - p-limit: 5.0.0 - pathe: 1.1.2 - dev: true - - /@vitest/snapshot@1.5.0: - resolution: {integrity: sha512-qpv3fSEuNrhAO3FpH6YYRdaECnnRjg9VxbhdtPwPRnzSfHVXnNzzrpX4cJxqiwgRMo7uRMWDFBlsBq4Cr+rO3A==} - dependencies: - magic-string: 0.30.9 - pathe: 1.1.2 - pretty-format: 29.7.0 - dev: true - - /@vitest/spy@1.5.0: - resolution: {integrity: sha512-vu6vi6ew5N5MMHJjD5PoakMRKYdmIrNJmyfkhRpQt5d9Ewhw9nZ5Aqynbi3N61bvk9UvZ5UysMT6ayIrZ8GA9w==} - dependencies: - tinyspy: 2.2.1 - dev: true - - /@vitest/ui@1.5.0(vitest@1.5.0): - resolution: {integrity: sha512-ETcToK2TzICf/Oartvt19IH7yR4oCs8GrQk5hRhZ5oZFaSdDHTh6o3EdzyxOaY24NZ20cXYYNGjj1se/5vHfFg==} + '@vitest/mocker@3.0.6': + resolution: {integrity: sha512-KPztr4/tn7qDGZfqlSPQoF2VgJcKxnDNhmfR3VgZ6Fy1bO8T9Fc1stUiTXtqz0yG24VpD00pZP5f8EOFknjNuQ==} peerDependencies: - vitest: 1.5.0 - dependencies: - '@vitest/utils': 1.5.0 - fast-glob: 3.3.2 - fflate: 0.8.2 - flatted: 3.3.1 - pathe: 1.1.2 - picocolors: 1.0.0 - sirv: 2.0.4 - vitest: 1.5.0(@types/node@20.12.7)(@vitest/ui@1.5.0)(jsdom@24.0.0) - dev: true + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true - /@vitest/utils@1.5.0: - resolution: {integrity: sha512-BDU0GNL8MWkRkSRdNFvCUCAVOeHaUlVJ9Tx0TYBZyXaaOTmGtUFObzchCivIBrIwKzvZA7A9sCejVhXM2aY98A==} - dependencies: - diff-sequences: 29.6.3 - estree-walker: 3.0.3 - loupe: 2.3.7 - pretty-format: 29.7.0 - dev: true + '@vitest/pretty-format@3.0.6': + resolution: {integrity: sha512-Zyctv3dbNL+67qtHfRnUE/k8qxduOamRfAL1BurEIQSyOEFffoMvx2pnDSSbKAAVxY0Ej2J/GH2dQKI0W2JyVg==} - /@vue/compat@3.4.21(vue@3.4.21): - resolution: {integrity: sha512-hKM6C5tTqduZcNOwp4oBa6qplAQ0NsMvGtLCTKmkhjVqrFzUfS9CyLN6ktzEfPwbgeC/wYYd7PtH+H8jNGvTjQ==} + '@vitest/runner@3.0.6': + resolution: {integrity: sha512-JopP4m/jGoaG1+CBqubV/5VMbi7L+NQCJTu1J1Pf6YaUbk7bZtaq5CX7p+8sY64Sjn1UQ1XJparHfcvTTdu9cA==} + + '@vitest/snapshot@3.0.6': + resolution: {integrity: sha512-qKSmxNQwT60kNwwJHMVwavvZsMGXWmngD023OHSgn873pV0lylK7dwBTfYP7e4URy5NiBCHHiQGA9DHkYkqRqg==} + + '@vitest/spy@3.0.6': + resolution: {integrity: sha512-HfOGx/bXtjy24fDlTOpgiAEJbRfFxoX3zIGagCqACkFKKZ/TTOE6gYMKXlqecvxEndKFuNHcHqP081ggZ2yM0Q==} + + '@vitest/ui@3.0.6': + resolution: {integrity: sha512-N4M2IUG2Q5LCeX4OWs48pQF4P3qsFejmDTc6QWGRFTLPrEe5EvM5HN0WSUnGAmuzQpSWv7ItfSsIJIWaEM2wpQ==} peerDependencies: - vue: 3.4.21 - dependencies: - '@babel/parser': 7.24.4 - estree-walker: 2.0.2 - source-map-js: 1.2.0 - vue: 3.4.21(typescript@5.4.5) - dev: false + vitest: 3.0.6 - /@vue/compiler-core@3.4.21: - resolution: {integrity: sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==} - dependencies: - '@babel/parser': 7.24.0 - '@vue/shared': 3.4.21 - entities: 4.5.0 - estree-walker: 2.0.2 - source-map-js: 1.2.0 + '@vitest/utils@3.0.6': + resolution: {integrity: sha512-18ktZpf4GQFTbf9jK543uspU03Q2qya7ZGya5yiZ0Gx0nnnalBvd5ZBislbl2EhLjM8A8rt4OilqKG7QwcGkvQ==} - /@vue/compiler-dom@3.4.21: - resolution: {integrity: sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==} - dependencies: - '@vue/compiler-core': 3.4.21 - '@vue/shared': 3.4.21 - - /@vue/compiler-sfc@3.4.21: - resolution: {integrity: sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==} - dependencies: - '@babel/parser': 7.24.1 - '@vue/compiler-core': 3.4.21 - '@vue/compiler-dom': 3.4.21 - '@vue/compiler-ssr': 3.4.21 - '@vue/shared': 3.4.21 - estree-walker: 2.0.2 - magic-string: 0.30.8 - postcss: 8.4.38 - source-map-js: 1.2.0 - - /@vue/compiler-ssr@3.4.21: - resolution: {integrity: sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==} - dependencies: - '@vue/compiler-dom': 3.4.21 - '@vue/shared': 3.4.21 - - /@vue/devtools-api@6.6.1: - resolution: {integrity: sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==} - dev: false - - /@vue/devtools-api@7.0.27(vue@3.4.21): - resolution: {integrity: sha512-BFCFCusSDcw2UcOFD/QeK7OxD1x2C/m+uAN30Q7jLKECSW53hmz0urzJmX834GuWDZX/hIxkyUKnLLfEIP1c/w==} - dependencies: - '@vue/devtools-kit': 7.0.27(vue@3.4.21) - transitivePeerDependencies: - - vue - dev: true - - /@vue/devtools-kit@7.0.27(vue@3.4.21): - resolution: {integrity: sha512-/A5xM38pPCFX5Yhl/lRFAzjyK6VNsH670nww2WbjFKWqlu3I+lMxWKzQkCW6A1V8bduITgl2kHORfg2gTw6QaA==} + '@vue/compat@3.5.13': + resolution: {integrity: sha512-Q3xRdTPN4l+kddxU98REyUBgvc0meAo9CefCWE2lW8Fg3dyPn3vSCce52b338ihrJAx1RQQhO5wMWhJ/PAKUpA==} peerDependencies: - vue: ^3.0.0 - dependencies: - '@vue/devtools-shared': 7.0.27 - hookable: 5.5.3 - mitt: 3.0.1 - perfect-debounce: 1.0.0 - speakingurl: 14.0.1 - vue: 3.4.21(typescript@5.4.5) - dev: true + vue: 3.5.13 - /@vue/devtools-shared@7.0.27: - resolution: {integrity: sha512-4VxtmZ6yjhiSloqZZq2UYU0TBGxOJ8GxWvp5OlAH70zYqi0FIAyWGPkOhvfoZ7DKQyv2UU0mmKzFHjsEkelGyQ==} - dependencies: - rfdc: 1.3.1 - dev: true + '@vue/compiler-core@3.5.13': + resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} - /@vue/reactivity@3.4.21: - resolution: {integrity: sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==} - dependencies: - '@vue/shared': 3.4.21 + '@vue/compiler-dom@3.5.13': + resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} - /@vue/runtime-core@3.4.21: - resolution: {integrity: sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==} - dependencies: - '@vue/reactivity': 3.4.21 - '@vue/shared': 3.4.21 + '@vue/compiler-sfc@3.5.13': + resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==} - /@vue/runtime-dom@3.4.21: - resolution: {integrity: sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==} - dependencies: - '@vue/runtime-core': 3.4.21 - '@vue/shared': 3.4.21 - csstype: 3.1.3 + '@vue/compiler-ssr@3.5.13': + resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==} - /@vue/server-renderer@3.4.21(vue@3.4.21): - resolution: {integrity: sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==} + '@vue/devtools-api@6.6.4': + resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} + + '@vue/devtools-api@7.7.2': + resolution: {integrity: sha512-1syn558KhyN+chO5SjlZIwJ8bV/bQ1nOVTG66t2RbG66ZGekyiYNmRO7X9BJCXQqPsFHlnksqvPhce2qpzxFnA==} + + '@vue/devtools-kit@7.7.2': + resolution: {integrity: sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ==} + + '@vue/devtools-shared@7.7.2': + resolution: {integrity: sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA==} + + '@vue/reactivity@3.5.13': + resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==} + + '@vue/runtime-core@3.5.13': + resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==} + + '@vue/runtime-dom@3.5.13': + resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==} + + '@vue/server-renderer@3.5.13': + resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==} peerDependencies: - vue: 3.4.21 - dependencies: - '@vue/compiler-ssr': 3.4.21 - '@vue/shared': 3.4.21 - vue: 3.4.21(typescript@5.4.5) + vue: 3.5.13 - /@vue/shared@3.4.21: - resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==} + '@vue/shared@3.5.13': + resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} - /@vueuse/core@10.9.0(vue@3.4.21): - resolution: {integrity: sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==} - dependencies: - '@types/web-bluetooth': 0.0.20 - '@vueuse/metadata': 10.9.0 - '@vueuse/shared': 10.9.0(vue@3.4.21) - vue-demi: 0.14.7(vue@3.4.21) - transitivePeerDependencies: - - '@vue/composition-api' - - vue + '@vueuse/core@12.7.0': + resolution: {integrity: sha512-jtK5B7YjZXmkGNHjviyGO4s3ZtEhbzSgrbX+s5o+Lr8i2nYqNyHuPVOeTdM1/hZ5Tkxg/KktAuAVDDiHMraMVA==} - /@vueuse/integrations@10.9.0(focus-trap@7.5.4)(vue@3.4.21): - resolution: {integrity: sha512-acK+A01AYdWSvL4BZmCoJAcyHJ6EqhmkQEXbQLwev1MY7NBnS+hcEMx/BzVoR9zKI+UqEPMD9u6PsyAuiTRT4Q==} + '@vueuse/core@13.1.0': + resolution: {integrity: sha512-PAauvdRXZvTWXtGLg8cPUFjiZEddTqmogdwYpnn60t08AA5a8Q4hZokBnpTOnVNqySlFlTcRYIC8OqreV4hv3Q==} peerDependencies: - async-validator: '*' - axios: '*' - change-case: '*' - drauu: '*' - focus-trap: '*' - fuse.js: '*' - idb-keyval: '*' - jwt-decode: '*' - nprogress: '*' - qrcode: '*' - sortablejs: '*' - universal-cookie: '*' + vue: ^3.5.0 + + '@vueuse/integrations@12.7.0': + resolution: {integrity: sha512-IEq7K4bCl7mn3uKJaWtNXnd1CAPaHLUMuyj5K1/k/pVcItt0VONZW8xiGxdIovJcQjkzOHjImhX5t6gija+0/g==} + peerDependencies: + async-validator: ^4 + axios: ^1 + change-case: ^5 + drauu: ^0.4 + focus-trap: ^7 + fuse.js: ^7 + idb-keyval: ^6 + jwt-decode: ^4 + nprogress: ^0.2 + qrcode: ^1.5 + sortablejs: ^1 + universal-cookie: ^7 peerDependenciesMeta: async-validator: optional: true @@ -5361,57 +3571,34 @@ packages: optional: true universal-cookie: optional: true - dependencies: - '@vueuse/core': 10.9.0(vue@3.4.21) - '@vueuse/shared': 10.9.0(vue@3.4.21) - focus-trap: 7.5.4 - vue-demi: 0.14.7(vue@3.4.21) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: true - /@vueuse/metadata@10.9.0: - resolution: {integrity: sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==} + '@vueuse/metadata@12.7.0': + resolution: {integrity: sha512-4VvTH9mrjXqFN5LYa5YfqHVRI6j7R00Vy4995Rw7PQxyCL3z0Lli86iN4UemWqixxEvYfRjG+hF9wL8oLOn+3g==} - /@vueuse/shared@10.9.0(vue@3.4.21): - resolution: {integrity: sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==} - dependencies: - vue-demi: 0.14.7(vue@3.4.21) - transitivePeerDependencies: - - '@vue/composition-api' - - vue + '@vueuse/metadata@13.1.0': + resolution: {integrity: sha512-+TDd7/a78jale5YbHX9KHW3cEDav1lz1JptwDvep2zSG8XjCsVE+9mHIzjTOaPbHUAk5XiE4jXLz51/tS+aKQw==} - /@wdio/config@7.31.1(typescript@5.4.5): + '@vueuse/shared@12.7.0': + resolution: {integrity: sha512-coLlUw2HHKsm7rPN6WqHJQr18WymN4wkA/3ThFaJ4v4gWGWAQQGK+MJxLuJTBs4mojQiazlVWAKNJNpUWGRkNw==} + + '@vueuse/shared@13.1.0': + resolution: {integrity: sha512-IVS/qRRjhPTZ6C2/AM3jieqXACGwFZwWTdw5sNTSKk2m/ZpkuuN+ri+WCVUP8TqaKwJYt/KuMwmXspMAw8E6ew==} + peerDependencies: + vue: ^3.5.0 + + '@wdio/config@7.31.1': resolution: {integrity: sha512-WAfswbCatwiaDVqy6kfF/5T8/WS/US/SRhBGUFrfBuGMIe+RRoHgy7jURFWSvUIE7CNHj8yvs46fLUcxhXjzcQ==} engines: {node: '>=12.0.0'} - dependencies: - '@types/glob': 8.1.0 - '@wdio/logger': 7.26.0 - '@wdio/types': 7.30.2(typescript@5.4.5) - '@wdio/utils': 7.30.2(typescript@5.4.5) - deepmerge: 4.3.1 - glob: 8.1.0 - transitivePeerDependencies: - - typescript - dev: true - /@wdio/logger@7.26.0: + '@wdio/logger@7.26.0': resolution: {integrity: sha512-kQj9s5JudAG9qB+zAAcYGPHVfATl2oqKgqj47yjehOQ1zzG33xmtL1ArFbQKWhDG32y1A8sN6b0pIqBEIwgg8Q==} engines: {node: '>=12.0.0'} - dependencies: - chalk: 4.1.2 - loglevel: 1.9.1 - loglevel-plugin-prefix: 0.8.4 - strip-ansi: 6.0.1 - dev: true - /@wdio/protocols@7.27.0: + '@wdio/protocols@7.27.0': resolution: {integrity: sha512-hT/U22R5i3HhwPjkaKAG0yd59eaOaZB0eibRj2+esCImkb5Y6rg8FirrlYRxIGFVBl0+xZV0jKHzR5+o097nvg==} engines: {node: '>=12.0.0'} - dev: true - /@wdio/types@7.30.2(typescript@5.4.5): + '@wdio/types@7.30.2': resolution: {integrity: sha512-uZ8o7FX8RyBsaXiOWa59UKTCHTtADNvOArYTcHNEIzt+rh4JdB/uwqfc8y4TCNA2kYm7PWaQpUFwpStLeg0H1Q==} engines: {node: '>=12.0.0'} peerDependencies: @@ -5419,149 +3606,68 @@ packages: peerDependenciesMeta: typescript: optional: true - dependencies: - '@types/node': 18.19.31 - got: 11.8.6 - typescript: 5.4.5 - dev: true - /@wdio/utils@7.30.2(typescript@5.4.5): + '@wdio/utils@7.30.2': resolution: {integrity: sha512-np7I+smszFUennbQKdzbMN/zUL3s3EZq9pCCUcTRjjs9TE4tnn0wfmGdoz2o7REYu6kn9NfFFJyVIM2VtBbKEA==} engines: {node: '>=12.0.0'} - dependencies: - '@wdio/logger': 7.26.0 - '@wdio/types': 7.30.2(typescript@5.4.5) - p-iteration: 1.1.8 - transitivePeerDependencies: - - typescript - dev: true - /@webassemblyjs/ast@1.12.1: + '@webassemblyjs/ast@1.12.1': resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} - dependencies: - '@webassemblyjs/helper-numbers': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - dev: true - /@webassemblyjs/floating-point-hex-parser@1.11.6: + '@webassemblyjs/floating-point-hex-parser@1.11.6': resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} - dev: true - /@webassemblyjs/helper-api-error@1.11.6: + '@webassemblyjs/helper-api-error@1.11.6': resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} - dev: true - /@webassemblyjs/helper-buffer@1.12.1: + '@webassemblyjs/helper-buffer@1.12.1': resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==} - dev: true - /@webassemblyjs/helper-numbers@1.11.6: + '@webassemblyjs/helper-numbers@1.11.6': resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} - dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.11.6 - '@webassemblyjs/helper-api-error': 1.11.6 - '@xtuc/long': 4.2.2 - dev: true - /@webassemblyjs/helper-wasm-bytecode@1.11.6: + '@webassemblyjs/helper-wasm-bytecode@1.11.6': resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} - dev: true - /@webassemblyjs/helper-wasm-section@1.12.1: + '@webassemblyjs/helper-wasm-section@1.12.1': resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/wasm-gen': 1.12.1 - dev: true - /@webassemblyjs/ieee754@1.11.6: + '@webassemblyjs/ieee754@1.11.6': resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} - dependencies: - '@xtuc/ieee754': 1.2.0 - dev: true - /@webassemblyjs/leb128@1.11.6: + '@webassemblyjs/leb128@1.11.6': resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} - dependencies: - '@xtuc/long': 4.2.2 - dev: true - /@webassemblyjs/utf8@1.11.6: + '@webassemblyjs/utf8@1.11.6': resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} - dev: true - /@webassemblyjs/wasm-edit@1.12.1: + '@webassemblyjs/wasm-edit@1.12.1': resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/helper-wasm-section': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-opt': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - '@webassemblyjs/wast-printer': 1.12.1 - dev: true - /@webassemblyjs/wasm-gen@1.12.1: + '@webassemblyjs/wasm-gen@1.12.1': resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 - dev: true - /@webassemblyjs/wasm-opt@1.12.1: + '@webassemblyjs/wasm-opt@1.12.1': resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - dev: true - /@webassemblyjs/wasm-parser@1.12.1: + '@webassemblyjs/wasm-parser@1.12.1': resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-api-error': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 - dev: true - /@webassemblyjs/wast-printer@1.12.1: + '@webassemblyjs/wast-printer@1.12.1': resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@xtuc/long': 4.2.2 - dev: true - /@webpack-cli/configtest@1.2.0(webpack-cli@4.10.0)(webpack@5.91.0): + '@webpack-cli/configtest@1.2.0': resolution: {integrity: sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==} peerDependencies: webpack: 4.x.x || 5.x.x webpack-cli: 4.x.x - dependencies: - webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@4.10.0) - webpack-cli: 4.10.0(webpack-dev-server@4.15.2)(webpack@5.91.0) - dev: true - /@webpack-cli/info@1.5.0(webpack-cli@4.10.0): + '@webpack-cli/info@1.5.0': resolution: {integrity: sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==} peerDependencies: webpack-cli: 4.x.x - dependencies: - envinfo: 7.10.0 - webpack-cli: 4.10.0(webpack-dev-server@4.15.2)(webpack@5.91.0) - dev: true - /@webpack-cli/serve@1.7.0(webpack-cli@4.10.0)(webpack-dev-server@4.15.2): + '@webpack-cli/serve@1.7.0': resolution: {integrity: sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==} peerDependencies: webpack-cli: 4.x.x @@ -5569,2085 +3675,1220 @@ packages: peerDependenciesMeta: webpack-dev-server: optional: true - dependencies: - webpack-cli: 4.10.0(webpack-dev-server@4.15.2)(webpack@5.91.0) - webpack-dev-server: 4.15.2(webpack-cli@4.10.0)(webpack@5.91.0) - dev: true - /@xmldom/xmldom@0.8.10: + '@xmldom/xmldom@0.8.10': resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} engines: {node: '>=10.0.0'} - dev: true - /@xtuc/ieee754@1.2.0: + '@xtuc/ieee754@1.2.0': resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} - dev: true - /@xtuc/long@4.2.2: + '@xtuc/long@4.2.2': resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - dev: true - /@zenuml/core@3.21.2(typescript@5.4.5): - resolution: {integrity: sha512-e63W3sb+cSafRaN+g2l2sYMdFMxDC0bRMqo+spRW48LoK0/7MQsSf6f9xEtSly/iTaXUGedw1TpvktzAxeKFjA==} + '@zenuml/core@3.27.12': + resolution: {integrity: sha512-cNIQM6CCcsz4VqgHySIxjIlqjRnVO7d3HfBQtBkw8woBrvssHfU6FxSg23RVUsb8j98TdruPgEgLbpFbKCGlHA==} engines: {node: '>=12.0.0'} - dependencies: - '@headlessui-float/vue': 0.11.4(vue@3.4.21) - '@headlessui/tailwindcss': 0.2.0(tailwindcss@3.4.3) - '@headlessui/vue': 1.7.19(vue@3.4.21) - '@types/assert': 1.5.10 - '@types/ramda': 0.28.25 - '@vue/compat': 3.4.21(vue@3.4.21) - antlr4: 4.11.0 - color-string: 1.9.1 - dom-to-image-more: 2.16.0 - file-saver: 2.0.5 - highlight.js: 10.7.3 - html-to-image: 1.11.11 - lodash: 4.17.21 - marked: 4.3.0 - pino: 8.20.0 - postcss: 8.4.38 - ramda: 0.28.0 - tailwindcss: 3.4.3 - vue: 3.4.21(typescript@5.4.5) - vuex: 4.1.0(vue@3.4.21) - transitivePeerDependencies: - - '@vue/composition-api' - - ts-node - - typescript - dev: false - /JSONSelect@0.4.0: + JSONSelect@0.4.0: resolution: {integrity: sha512-VRLR3Su35MH+XV2lrvh9O7qWoug/TUyj9tLDjn9rtpUCNnILLrHjgd/tB0KrhugCxUpj3UqoLqfYb3fLJdIQQQ==} engines: {node: '>=0.4.7'} - dev: true - /JSV@4.0.2: + JSV@4.0.2: resolution: {integrity: sha512-ZJ6wx9xaKJ3yFUhq5/sk82PJMuUyLk277I8mQeyDgCTjGdjWJIvPfaU5LIXaMuaN2UO1X3kZH4+lgphublZUHw==} - dev: true - /abort-controller@3.0.0: + abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} - dependencies: - event-target-shim: 5.0.1 - /abstract-logging@2.0.1: + abstract-logging@2.0.1: resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} - dev: true - /accepts@1.3.8: + accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - dev: true - /acorn-import-assertions@1.9.0(acorn@8.11.3): - resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + + acorn-import-attributes@1.9.5: + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} peerDependencies: acorn: ^8 - dependencies: - acorn: 8.11.3 - dev: true - /acorn-jsx@5.3.2(acorn@8.11.3): + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.11.3 - dev: true - /acorn-walk@8.3.2: - resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} engines: {node: '>=0.4.0'} - dev: true - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} engines: {node: '>=0.4.0'} hasBin: true - dev: true - /agent-base@6.0.2: + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} - dependencies: - debug: 4.3.4(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - dev: true - /agent-base@7.1.0: - resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} + agent-base@7.1.1: + resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} engines: {node: '>= 14'} - dependencies: - debug: 4.3.4(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - dev: true - /aggregate-error@3.1.0: + agent-base@7.1.3: + resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} + engines: {node: '>= 14'} + + aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - dev: true - /aggregate-error@4.0.1: + aggregate-error@4.0.1: resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==} engines: {node: '>=12'} - dependencies: - clean-stack: 4.2.0 - indent-string: 5.0.0 - dev: true - /ajv-formats@2.1.1(ajv@8.12.0): + ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: ajv: ^8.0.0 peerDependenciesMeta: ajv: optional: true - dependencies: - ajv: 8.12.0 - dev: true - /ajv-keywords@3.5.2(ajv@6.12.6): + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-keywords@3.5.2: resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} peerDependencies: ajv: ^6.9.1 - dependencies: - ajv: 6.12.6 - dev: true - /ajv-keywords@5.1.0(ajv@8.12.0): + ajv-keywords@5.1.0: resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} peerDependencies: ajv: ^8.8.2 - dependencies: - ajv: 8.12.0 - fast-deep-equal: 3.1.3 - dev: true - /ajv@6.12.6: + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - /ajv@8.12.0: + ajv@8.12.0: resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: true - /algoliasearch@4.23.3: - resolution: {integrity: sha512-Le/3YgNvjW9zxIQMRhUHuhiUjAlKY/zsdZpfq4dlLqg6mEm0nL6yk+7f2hDOtLpxsgE4jSzDmvHL7nXdBp5feg==} - dependencies: - '@algolia/cache-browser-local-storage': 4.23.3 - '@algolia/cache-common': 4.23.3 - '@algolia/cache-in-memory': 4.23.3 - '@algolia/client-account': 4.23.3 - '@algolia/client-analytics': 4.23.3 - '@algolia/client-common': 4.23.3 - '@algolia/client-personalization': 4.23.3 - '@algolia/client-search': 4.23.3 - '@algolia/logger-common': 4.23.3 - '@algolia/logger-console': 4.23.3 - '@algolia/recommend': 4.23.3 - '@algolia/requester-browser-xhr': 4.23.3 - '@algolia/requester-common': 4.23.3 - '@algolia/requester-node-http': 4.23.3 - '@algolia/transporter': 4.23.3 - dev: true + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - /amdefine@1.0.1: + algoliasearch@5.20.3: + resolution: {integrity: sha512-iNC6BGvipaalFfDfDnXUje8GUlW5asj0cTMsZJwO/0rhsyLx1L7GZFAY8wW+eQ6AM4Yge2p5GSE5hrBlfSD90Q==} + engines: {node: '>= 14.0.0'} + + amdefine@1.0.1: resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} engines: {node: '>=0.4.2'} - requiresBuild: true - dev: true - optional: true - /ansi-align@3.0.1: + ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} - dependencies: - string-width: 4.2.3 - dev: true - /ansi-colors@4.1.3: + ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} - dev: true - /ansi-escapes@4.3.2: + ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - dev: true - /ansi-escapes@6.2.1: - resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==} - engines: {node: '>=14.16'} - dev: true + ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} - /ansi-html-community@0.0.8: + ansi-html-community@0.0.8: resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} engines: {'0': node >= 0.8.0} hasBin: true - dev: true - /ansi-regex@2.1.1: + ansi-regex@2.1.1: resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} engines: {node: '>=0.10.0'} - dev: true - /ansi-regex@5.0.1: + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} engines: {node: '>=12'} - /ansi-sequence-parser@1.1.1: - resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==} - dev: true - - /ansi-styles@2.2.1: + ansi-styles@2.2.1: resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} engines: {node: '>=0.10.0'} - dev: true - /ansi-styles@3.2.1: + ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - /ansi-styles@4.3.0: + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - /ansi-styles@5.2.0: + ansi-styles@5.2.0: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} - dev: true - /ansi-styles@6.2.1: + ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - /antlr4@4.11.0: + antlr4@4.11.0: resolution: {integrity: sha512-GUGlpE2JUjAN+G8G5vY+nOoeyNhHsXoIJwP1XF1oRw89vifA1K46T6SEkwLwr7drihN7I/lf0DIjKc4OZvBX8w==} engines: {node: '>=14'} - dev: false - /any-promise@1.3.0: + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - /anymatch@3.1.3: + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - /app-path@3.3.0: + app-module-path@2.2.0: + resolution: {integrity: sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ==} + + app-path@3.3.0: resolution: {integrity: sha512-EAgEXkdcxH1cgEePOSsmUtw9ItPl0KTxnh/pj9ZbhvbKbij9x0oX6PWpGnorDr0DS5AosLgoa5n3T/hZmKQpYA==} engines: {node: '>=8'} - dependencies: - execa: 1.0.0 - dev: true - /appdata-path@1.0.0: + appdata-path@1.0.0: resolution: {integrity: sha512-ZbH3ezXfnT/YE3NdqduIt4lBV+H0ybvA2Qx3K76gIjQvh8gROpDFdDLpx6B1QJtW7zxisCbpTlCLhKqoR8cDBw==} - dev: true - /append-transform@2.0.0: + append-transform@2.0.0: resolution: {integrity: sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==} engines: {node: '>=8'} - dependencies: - default-require-extensions: 3.0.1 - dev: true - /arch@2.2.0: + arch@2.2.0: resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} - dev: true - /archy@1.0.0: + archy@1.0.0: resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} - dev: true - /are-docs-informative@0.0.2: + are-docs-informative@0.0.2: resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} engines: {node: '>=14'} - dev: true - /arg@5.0.2: + arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - /argparse@1.0.10: + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - dependencies: - sprintf-js: 1.0.3 - dev: true - /argparse@2.0.1: + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - /array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - is-array-buffer: 3.0.4 - dev: true - /array-flatten@1.1.1: + array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - dev: true - /array-flatten@2.1.2: - resolution: {integrity: sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==} - dev: true - - /array-timsort@1.0.3: + array-timsort@1.0.3: resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} - dev: true - /array-union@2.1.0: + array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - dev: true - /arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - is-array-buffer: 3.0.4 - is-shared-array-buffer: 1.0.3 - dev: true - /arrify@3.0.0: + arrify@3.0.0: resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==} engines: {node: '>=12'} - dev: true - /asn1@0.2.6: + asn1@0.2.6: resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} - dependencies: - safer-buffer: 2.1.2 - dev: true - /assert-plus@1.0.0: + assert-plus@1.0.0: resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} engines: {node: '>=0.8'} - dev: true - /assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - dev: true + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} - /astral-regex@2.0.0: + ast-module-types@6.0.0: + resolution: {integrity: sha512-LFRg7178Fw5R4FAEwZxVqiRI8IxSM+Ay2UBrHoCerXNme+kMMMfz7T3xDGV/c2fer87hcrtgJGsnSOfUrPK6ng==} + engines: {node: '>=18'} + + astral-regex@2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} - dev: true - /async@3.2.5: - resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} - dev: true + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} - /asynckit@0.4.0: + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true - /at-least-node@1.0.0: + at-least-node@1.0.0: resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} engines: {node: '>= 4.0.0'} - dev: true - /atomic-sleep@1.0.0: + atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} - /available-typed-arrays@1.0.7: + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - dependencies: - possible-typed-array-names: 1.0.0 - dev: true - /avvio@7.2.5: - resolution: {integrity: sha512-AOhBxyLVdpOad3TujtC9kL/9r3HnTkxwQ5ggOsYrvvZP1cCFvzHWJd5XxZDFuTn+IN8vkKSG5SEJrd27vCSbeA==} - dependencies: - archy: 1.0.0 - debug: 4.3.4(supports-color@8.1.1) - fastq: 1.17.1 - queue-microtask: 1.2.3 - transitivePeerDependencies: - - supports-color - dev: true + avvio@8.4.0: + resolution: {integrity: sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA==} - /aws-sign2@0.7.0: + aws-sign2@0.7.0: resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} - dev: true - /aws4@1.12.0: - resolution: {integrity: sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==} - dev: true + aws4@1.13.2: + resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} - /axios@1.6.7(debug@4.3.4): - resolution: {integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==} - dependencies: - follow-redirects: 1.15.5(debug@4.3.4) - form-data: 4.0.0 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - dev: true + axios@1.7.9: + resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==} - /babel-jest@29.7.0(@babel/core@7.24.4): + axios@1.8.4: + resolution: {integrity: sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==} + + babel-jest@29.7.0: resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: '@babel/core': ^7.8.0 - dependencies: - '@babel/core': 7.24.4 - '@jest/transform': 29.7.0 - '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.24.4) - chalk: 4.1.2 - graceful-fs: 4.2.11 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true - /babel-loader@9.1.3(@babel/core@7.24.4)(webpack@5.91.0): - resolution: {integrity: sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==} + babel-loader@9.2.1: + resolution: {integrity: sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==} engines: {node: '>= 14.15.0'} peerDependencies: '@babel/core': ^7.12.0 webpack: '>=5' - dependencies: - '@babel/core': 7.24.4 - find-cache-dir: 4.0.0 - schema-utils: 4.2.0 - webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@4.10.0) - dev: true - /babel-plugin-istanbul@6.1.1: + babel-plugin-istanbul@6.1.1: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} engines: {node: '>=8'} - dependencies: - '@babel/helper-plugin-utils': 7.24.0 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - dev: true - /babel-plugin-jest-hoist@29.6.3: + babel-plugin-jest-hoist@29.6.3: resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.0 - '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.5 - dev: true - /babel-plugin-polyfill-corejs2@0.4.10(@babel/core@7.24.4): - resolution: {integrity: sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==} + babel-plugin-polyfill-corejs2@0.4.12: + resolution: {integrity: sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/compat-data': 7.24.4 - '@babel/core': 7.24.4 - '@babel/helper-define-polyfill-provider': 0.6.1(@babel/core@7.24.4) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - /babel-plugin-polyfill-corejs3@0.10.4(@babel/core@7.24.4): - resolution: {integrity: sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==} + babel-plugin-polyfill-corejs3@0.11.1: + resolution: {integrity: sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-define-polyfill-provider': 0.6.1(@babel/core@7.24.4) - core-js-compat: 3.36.1 - transitivePeerDependencies: - - supports-color - dev: true - /babel-plugin-polyfill-regenerator@0.6.1(@babel/core@7.24.4): - resolution: {integrity: sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==} + babel-plugin-polyfill-regenerator@0.6.3: + resolution: {integrity: sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/helper-define-polyfill-provider': 0.6.1(@babel/core@7.24.4) - transitivePeerDependencies: - - supports-color - dev: true - /babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.4): - resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} + babel-preset-current-node-syntax@1.1.0: + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} peerDependencies: '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.4) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.4) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.4) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.4) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.4) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.4) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.4) - dev: true - /babel-preset-jest@29.6.3(@babel/core@7.24.4): + babel-preset-jest@29.6.3: resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.4 - babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.4) - dev: true - /bail@2.0.2: + bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - dev: true - /balanced-match@1.0.2: + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - /base64-js@1.5.1: + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - /batch@0.6.1: + batch@0.6.1: resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} - dev: true - /bcrypt-pbkdf@1.0.2: + bcrypt-pbkdf@1.0.2: resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} - dependencies: - tweetnacl: 0.14.5 - dev: true - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - /binary-searching@2.0.5: + binary-searching@2.0.5: resolution: {integrity: sha512-v4N2l3RxL+m4zDxyxz3Ne2aTmiPn8ZUpKFpdPtO+ItW1NcTCXA7JeHG5GMBSvoKSkQZ9ycS+EouDVxYB9ufKWA==} - dev: true - /binary@0.3.0: + binary@0.3.0: resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==} - dependencies: - buffers: 0.1.1 - chainsaw: 0.1.0 - dev: true - /blob-util@2.0.2: + birpc@0.2.19: + resolution: {integrity: sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==} + + blob-util@2.0.2: resolution: {integrity: sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==} - dev: true - /bluebird@3.7.1: + bluebird@3.7.1: resolution: {integrity: sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==} - dev: true - /bluebird@3.7.2: + bluebird@3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} - dev: true - /bmpimagejs@1.0.4: + bmpimagejs@1.0.4: resolution: {integrity: sha512-21oKU7kbRt2OgOOj7rdiNr/yznDNUQ585plxR00rsmECcZr+6O1oCwB8OIoSHk/bDhbG8mFXIdeQuCPHgZ6QBw==} - dev: true - /body-parser@1.20.1: - resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.1 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - /body-parser@1.20.2: - resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.2 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true + body-parser@2.2.0: + resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} + engines: {node: '>=18'} - /bonjour-service@1.1.1: - resolution: {integrity: sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==} - dependencies: - array-flatten: 2.1.2 - dns-equal: 1.0.0 - fast-deep-equal: 3.1.3 - multicast-dns: 7.2.5 - dev: true + bonjour-service@1.2.1: + resolution: {integrity: sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==} - /boxen@5.1.2: + boxen@5.1.2: resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} engines: {node: '>=10'} - dependencies: - ansi-align: 3.0.1 - camelcase: 6.3.0 - chalk: 4.1.2 - cli-boxes: 2.2.1 - string-width: 4.2.3 - type-fest: 0.20.2 - widest-line: 3.1.0 - wrap-ansi: 7.0.0 - dev: true - /brace-expansion@1.1.11: + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - /brace-expansion@2.0.1: + brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - /browserslist@4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + browserslist@4.24.0: + resolution: {integrity: sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - dependencies: - caniuse-lite: 1.0.30001594 - electron-to-chromium: 1.4.692 - node-releases: 2.0.14 - update-browserslist-db: 1.0.13(browserslist@4.23.0) - dev: true - /bser@2.1.1: + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - dependencies: - node-int64: 0.4.0 - dev: true - /buffer-crc32@0.2.13: + buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - dev: true - /buffer-from@1.1.2: + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true - /buffer@5.7.1: + buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: true - /buffer@6.0.3: + buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: false - /buffers@0.1.1: + buffers@0.1.1: resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==} engines: {node: '>=0.2.0'} - dev: true - /builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - dev: true + builtin-modules@5.0.0: + resolution: {integrity: sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==} + engines: {node: '>=18.20'} - /bytes@3.0.0: + bytes@3.0.0: resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} engines: {node: '>= 0.8'} - dev: true - /bytes@3.1.2: + bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} - dev: true - /cac@6.7.14: + cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - dev: true - /cacheable-lookup@5.0.4: + cacheable-lookup@5.0.4: resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} engines: {node: '>=10.6.0'} - dev: true - /cacheable-request@7.0.4: + cacheable-request@7.0.4: resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} engines: {node: '>=8'} - dependencies: - clone-response: 1.0.3 - get-stream: 5.2.0 - http-cache-semantics: 4.1.1 - keyv: 4.5.4 - lowercase-keys: 2.0.0 - normalize-url: 6.1.0 - responselike: 2.0.1 - dev: true - /cachedir@2.4.0: + cachedir@2.4.0: resolution: {integrity: sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==} engines: {node: '>=6'} - dev: true - /caching-transform@4.0.0: + caching-transform@4.0.0: resolution: {integrity: sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==} engines: {node: '>=8'} - dependencies: - hasha: 5.2.2 - make-dir: 3.1.0 - package-hash: 4.0.0 - write-file-atomic: 3.0.3 - dev: true - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 - dev: true - /call-me-maybe@1.0.2: - resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} - dev: true + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} - /callsites@3.1.0: + call-bound@1.0.3: + resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - dev: true - /camelcase-css@2.0.1: + camelcase-css@2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} - dev: false - /camelcase@5.3.1: + camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} - dev: true - /camelcase@6.3.0: + camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - dev: true - /caniuse-lite@1.0.30001594: - resolution: {integrity: sha512-VblSX6nYqyJVs8DKFMldE2IVCJjZ225LW00ydtUWwh5hk9IfkTOffO6r8gJNsH0qqqeAF8KrbMYA2VEwTlGW5g==} - dev: true + caniuse-lite@1.0.30001700: + resolution: {integrity: sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==} - /caseless@0.12.0: + caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - dev: true - /ccount@2.0.1: + ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - dev: true - /chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} - engines: {node: '>=4'} - dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.3 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.0.8 - dev: true + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} + engines: {node: '>=12'} - /chainsaw@0.1.0: + chainsaw@0.1.0: resolution: {integrity: sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==} - dependencies: - traverse: 0.3.9 - dev: true - /chalk-template@1.1.0: + chalk-template@1.1.0: resolution: {integrity: sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==} engines: {node: '>=14.16'} - dependencies: - chalk: 5.3.0 - dev: true - /chalk@1.1.3: + chalk@1.1.3: resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} engines: {node: '>=0.10.0'} - dependencies: - ansi-styles: 2.2.1 - escape-string-regexp: 1.0.5 - has-ansi: 2.0.0 - strip-ansi: 3.0.1 - supports-color: 2.0.0 - dev: true - /chalk@2.4.2: + chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - /chalk@3.0.0: + chalk@3.0.0: resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - /chalk@4.1.2: + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - /chalk@5.3.0: + chalk@5.3.0: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: true - /char-regex@1.0.2: + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + char-regex@1.0.2: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} - dev: true - /character-entities-legacy@1.1.4: + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@1.1.4: resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} - dev: true - /character-entities@1.2.4: + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@1.2.4: resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} - dev: true - /character-entities@2.0.2: + character-entities@2.0.2: resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - /character-reference-invalid@1.1.4: + character-reference-invalid@1.1.4: resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} - dev: true - /check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - dependencies: - get-func-name: 2.0.2 - dev: true + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - /check-more-types@2.24.0: + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + + check-more-types@2.24.0: resolution: {integrity: sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==} engines: {node: '>= 0.8.0'} - dev: true - /chevrotain-allstar@0.3.1(chevrotain@11.0.3): + chevrotain-allstar@0.3.1: resolution: {integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==} peerDependencies: chevrotain: ^11.0.0 - dependencies: - chevrotain: 11.0.3 - lodash-es: 4.17.21 - /chevrotain@11.0.3: + chevrotain@11.0.3: resolution: {integrity: sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==} - dependencies: - '@chevrotain/cst-dts-gen': 11.0.3 - '@chevrotain/gast': 11.0.3 - '@chevrotain/regexp-to-ast': 11.0.3 - '@chevrotain/types': 11.0.3 - '@chevrotain/utils': 11.0.3 - lodash-es: 4.17.21 - /chokidar@3.6.0: + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - /chrome-trace-event@1.0.3: - resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} - dev: true - /ci-info@3.9.0: + ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} - dev: true - /ci-info@4.0.0: - resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} + ci-info@4.1.0: + resolution: {integrity: sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==} engines: {node: '>=8'} - dev: true - /cjs-module-lexer@1.2.3: - resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} - dev: true + ci-info@4.2.0: + resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} + engines: {node: '>=8'} - /cjson@0.3.0: + cjs-module-lexer@1.4.1: + resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} + + cjson@0.3.0: resolution: {integrity: sha512-bBRQcCIHzI1IVH59fR0bwGrFmi3Btb/JNwM/n401i1DnYgWndpsUBiQRAddLflkZage20A2d25OAWZZk0vBRlA==} engines: {node: '>= 0.3.0'} - dependencies: - jsonlint: 1.6.0 - dev: true - /clap@3.1.1: + clap@3.1.1: resolution: {integrity: sha512-vp42956Ax06WwaaheYEqEOgXZ3VKJxgccZ0gJL0HpyiupkIS9RVJFo5eDU1BPeQAOqz+cclndZg4DCqG1sJReQ==} engines: {node: ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - dependencies: - ansi-colors: 4.1.3 - dev: true - /clean-regexp@1.0.0: + clean-regexp@1.0.0: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - /clean-stack@2.2.0: + clean-stack@2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} - dev: true - /clean-stack@4.2.0: + clean-stack@4.2.0: resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==} engines: {node: '>=12'} - dependencies: - escape-string-regexp: 5.0.0 - dev: true - /clear-module@4.1.2: + clear-module@4.1.2: resolution: {integrity: sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==} engines: {node: '>=8'} - dependencies: - parent-module: 2.0.0 - resolve-from: 5.0.0 - dev: true - /cli-boxes@2.2.1: + cli-boxes@2.2.1: resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} engines: {node: '>=6'} - dev: true - /cli-color@2.0.4: - resolution: {integrity: sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==} - engines: {node: '>=0.10'} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - es6-iterator: 2.0.3 - memoizee: 0.4.15 - timers-ext: 0.1.7 - dev: true - - /cli-cursor@3.1.0: + cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} - dependencies: - restore-cursor: 3.1.0 - dev: true - /cli-cursor@4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - restore-cursor: 4.0.0 - dev: true + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} - /cli-table3@0.6.4: - resolution: {integrity: sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==} + cli-table3@0.6.5: + resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} engines: {node: 10.* || >= 12.*} - dependencies: - string-width: 4.2.3 - optionalDependencies: - '@colors/colors': 1.5.0 - dev: true - /cli-truncate@2.1.0: + cli-truncate@2.1.0: resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} engines: {node: '>=8'} - dependencies: - slice-ansi: 3.0.0 - string-width: 4.2.3 - dev: true - /cli-truncate@4.0.0: + cli-truncate@4.0.0: resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} engines: {node: '>=18'} - dependencies: - slice-ansi: 5.0.0 - string-width: 7.1.0 - dev: true - /cliui@6.0.0: + cliui@6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - dev: true - /cliui@8.0.1: + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - /clone-deep@4.0.1: + clone-deep@4.0.1: resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} engines: {node: '>=6'} - dependencies: - is-plain-object: 2.0.4 - kind-of: 6.0.3 - shallow-clone: 3.0.1 - dev: true - /clone-response@1.0.3: + clone-response@1.0.3: resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} - dependencies: - mimic-response: 1.0.1 - dev: true - /co@4.6.0: + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + co@4.6.0: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - dev: true - /collect-v8-coverage@1.0.2: + collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} - dev: true - /color-convert@1.9.3: + color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - /color-convert@2.0.1: + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - /color-name@1.1.3: + color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - /color-name@1.1.4: + color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - /color-string@1.9.1: + color-string@1.9.1: resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - dependencies: - color-name: 1.1.4 - simple-swizzle: 0.2.2 - dev: false - /colorette@2.0.20: + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + + colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - dev: true - /colors@0.5.1: + colors@0.5.1: resolution: {integrity: sha512-XjsuUwpDeY98+yz959OlUK6m7mLBM+1MEG5oaenfuQnNnrQk1WvtcvFgN3FNDP3f2NmZ211t0mNEfSEN1h0eIg==} engines: {node: '>=0.1.90'} - dev: true - /combined-stream@1.0.8: + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - dev: true - /commander@11.0.0: + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@11.0.0: resolution: {integrity: sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==} engines: {node: '>=16'} - dev: true - /commander@11.1.0: - resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} - engines: {node: '>=16'} - dev: true - - /commander@12.0.0: - resolution: {integrity: sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} - dev: true - /commander@2.20.3: + commander@13.1.0: + resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} + engines: {node: '>=18'} + + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - dev: true - /commander@4.1.1: + commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} - dev: false - /commander@5.1.0: - resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} - engines: {node: '>= 6'} - dev: true - - /commander@6.2.1: + commander@6.2.1: resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} engines: {node: '>= 6'} - dev: true - /commander@7.2.0: + commander@7.2.0: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} - /commander@8.3.0: + commander@8.3.0: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} - dev: false - /comment-json@4.2.3: - resolution: {integrity: sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==} + comment-json@4.2.5: + resolution: {integrity: sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==} engines: {node: '>= 6'} - dependencies: - array-timsort: 1.0.3 - core-util-is: 1.0.3 - esprima: 4.0.1 - has-own-prop: 2.0.0 - repeat-string: 1.6.1 - dev: true - /comment-parser@1.4.1: + comment-parser@1.4.1: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} - dev: true - /common-path-prefix@3.0.0: + common-path-prefix@3.0.0: resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} - dev: true - /common-tags@1.8.2: + common-tags@1.8.2: resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} engines: {node: '>=4.0.0'} - dev: true - /commondir@1.0.1: + commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - dev: true - /compressible@2.0.18: + compressible@2.0.18: resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: true - /compression@1.7.4: + compression@1.7.4: resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} engines: {node: '>= 0.8.0'} - dependencies: - accepts: 1.3.8 - bytes: 3.0.0 - compressible: 2.0.18 - debug: 2.6.9 - on-headers: 1.0.2 - safe-buffer: 5.1.2 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: true - /concat-map@0.0.1: + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - /concurrently@8.2.2: - resolution: {integrity: sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==} - engines: {node: ^14.13.0 || >=16.0.0} + concurrently@9.1.2: + resolution: {integrity: sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==} + engines: {node: '>=18'} hasBin: true - dependencies: - chalk: 4.1.2 - date-fns: 2.30.0 - lodash: 4.17.21 - rxjs: 7.8.1 - shell-quote: 1.8.1 - spawn-command: 0.0.2 - supports-color: 8.1.1 - tree-kill: 1.2.2 - yargs: 17.7.2 - dev: true - /configstore@6.0.0: - resolution: {integrity: sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==} - engines: {node: '>=12'} - dependencies: - dot-prop: 6.0.1 - graceful-fs: 4.2.11 - unique-string: 3.0.0 - write-file-atomic: 3.0.3 - xdg-basedir: 5.1.0 - dev: true + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} - /connect-history-api-fallback@2.0.0: + connect-history-api-fallback@2.0.0: resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} engines: {node: '>=0.8'} - dev: true - /consola@3.2.3: - resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} + consola@3.4.0: + resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==} engines: {node: ^14.18.0 || >=16.10.0} - dev: true - /content-disposition@0.5.4: + console.table@0.10.0: + resolution: {integrity: sha512-dPyZofqggxuvSf7WXvNjuRfnsOk1YazkVP8FdxH4tcH2c37wc79/Yl6Bhr7Lsu00KMgy2ql/qCMuNu8xctZM8g==} + engines: {node: '> 0.10'} + + content-disposition@0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.2.1 - dev: true - /content-type@1.0.5: + content-disposition@1.0.0: + resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} - dev: true - /convert-source-map@1.9.0: + convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - dev: true - /convert-source-map@2.0.0: + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - /cookie-signature@1.0.6: + convict@6.2.4: + resolution: {integrity: sha512-qN60BAwdMVdofckX7AlohVJ2x9UvjTNoKVXCL2LxFk1l7757EJqf1nySdMkPQer0bt8kQ5lQiyZ9/2NvrFBuwQ==} + engines: {node: '>=6'} + + cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - dev: true - /cookie@0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} - engines: {node: '>= 0.6'} - dev: true + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} - /cookie@0.6.0: + cookie@0.6.0: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} - dev: true - /core-js-compat@3.36.0: - resolution: {integrity: sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==} - dependencies: - browserslist: 4.23.0 - dev: true + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} - /core-js-compat@3.36.1: - resolution: {integrity: sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==} - dependencies: - browserslist: 4.23.0 - dev: true + copy-anything@3.0.5: + resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} + engines: {node: '>=12.13'} - /core-util-is@1.0.2: + core-js-compat@3.41.0: + resolution: {integrity: sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==} + + core-util-is@1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} - dev: true - /core-util-is@1.0.3: + core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true - /cors@2.8.5: + cors@2.8.5: resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} engines: {node: '>= 0.10'} - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - dev: true - /cose-base@1.0.3: + cose-base@1.0.3: resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} - dependencies: - layout-base: 1.0.2 - dev: false - /cp-file@10.0.0: + cose-base@2.2.0: + resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} + + cp-file@10.0.0: resolution: {integrity: sha512-vy2Vi1r2epK5WqxOLnskeKeZkdZvTKfFZQCplE3XWsP+SUJyd5XAUFC9lFgTjjXJF2GMne/UML14iEmkAaDfFg==} engines: {node: '>=14.16'} - dependencies: - graceful-fs: 4.2.11 - nested-error-stacks: 2.1.1 - p-event: 5.0.1 - dev: true - /cpy-cli@5.0.0: + cpy-cli@5.0.0: resolution: {integrity: sha512-fb+DZYbL9KHc0BC4NYqGRrDIJZPXUmjjtqdw4XRRg8iV8dIfghUX/WiL+q4/B/KFTy3sK6jsbUhBaz0/Hxg7IQ==} engines: {node: '>=16'} hasBin: true - dependencies: - cpy: 10.1.0 - meow: 12.1.1 - dev: true - /cpy@10.1.0: + cpy@10.1.0: resolution: {integrity: sha512-VC2Gs20JcTyeQob6UViBLnyP0bYHkBh6EiKzot9vi2DmeGlFT9Wd7VG3NBrkNx/jYvFBeyDOMMHdHQhbtKLgHQ==} engines: {node: '>=16'} - dependencies: - arrify: 3.0.0 - cp-file: 10.0.0 - globby: 13.2.2 - junk: 4.0.1 - micromatch: 4.0.5 - nested-error-stacks: 2.1.1 - p-filter: 3.0.0 - p-map: 6.0.0 - dev: true - /create-jest@29.7.0(@types/node@20.12.7): + create-jest@29.7.0: resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.12.7) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - dev: true - /cross-env@7.0.3: + cross-env@7.0.3: resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} hasBin: true - dependencies: - cross-spawn: 7.0.3 - dev: true - /cross-spawn@6.0.5: - resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} + cross-spawn@6.0.6: + resolution: {integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==} engines: {node: '>=4.8'} - dependencies: - nice-try: 1.0.5 - path-key: 2.0.1 - semver: 5.7.2 - shebang-command: 1.2.0 - which: 1.3.1 - dev: true - /cross-spawn@7.0.3: + cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - /crypto-random-string@2.0.0: + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crypto-random-string@2.0.0: resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} engines: {node: '>=8'} - dev: true - /crypto-random-string@4.0.0: - resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} - engines: {node: '>=12'} - dependencies: - type-fest: 1.4.0 - dev: true - - /cspell-config-lib@8.7.0: - resolution: {integrity: sha512-depsd01GbLBo71/tfRrL5iECWQLS4CjCxA9C01dVkFAJqVB0s+K9KLKjTlq5aHOhcvo9Z3dHV+bGQCf5/Q7bfw==} + cspell-config-lib@8.17.4: + resolution: {integrity: sha512-vOi3B5gnngGeI1HMVDosHTBCRROx7XQXpD6rcKFxxehrs3hw1/EGGEKPKWX5R1UKhOiUNVmvicpqTXU+4/tbZA==} engines: {node: '>=18'} - dependencies: - '@cspell/cspell-types': 8.7.0 - comment-json: 4.2.3 - yaml: 2.4.1 - dev: true - /cspell-dictionary@8.7.0: - resolution: {integrity: sha512-S6IpZSzIMxlOO/33NgCOuP0TPH2mZbw8d5CP44z5jajflloq8l74MeJLkeDzYfCRcm0Rtk0A5drBeMg+Ai34OA==} + cspell-config-lib@8.18.1: + resolution: {integrity: sha512-zdJ0uhLROSUrHoibysPw+AkxKPUmiG95hDtiL7s8smewkuaS1hpjqwsDBx981nHYs3xW3qDUfVATrAkSzb0VMw==} engines: {node: '>=18'} - dependencies: - '@cspell/cspell-pipe': 8.7.0 - '@cspell/cspell-types': 8.7.0 - cspell-trie-lib: 8.7.0 - fast-equals: 5.0.1 - gensequence: 7.0.0 - dev: true - /cspell-gitignore@8.7.0: - resolution: {integrity: sha512-yvUZ86qyopUpDgn+YXP1qTpUe/lp65ZFvpMtw21lWHTFlg1OWKntr349EQU/5ben/K6koxk1FiElCBV7Lr4uFg==} + cspell-dictionary@8.17.4: + resolution: {integrity: sha512-nzFc/+r6Q0wP5KpvKnjtnI+C2HMaLfrzMaY4VtoCzyqEF8inYQz430e6sSReBDzjshoU9YUxhShXl18aA3eAqA==} + engines: {node: '>=18'} + + cspell-dictionary@8.18.1: + resolution: {integrity: sha512-vKHEPSfkMKMR4S4tk6K2vHC+f3kdJK8Kdh/C0jDh6RRDjDsyAPxshtbremxOgAX6X8GaRUCROoMZ7FhB92+Y9w==} + engines: {node: '>=18'} + + cspell-gitignore@8.17.4: + resolution: {integrity: sha512-9KwnXwNwE1eXYRyqHAMFPowJd3yFh2pQnnrfdQRvdculqFY39G4g/d4OQV9W/iMpcednL9K01IhxuUvbF7ZrIA==} engines: {node: '>=18'} hasBin: true - dependencies: - cspell-glob: 8.7.0 - find-up-simple: 1.0.0 - dev: true - /cspell-glob@8.7.0: - resolution: {integrity: sha512-AMdfx0gvROA/aIL8t8b5Y5NtMgscGZELFj6WhCSZiQSuWRxXUKiLGGLUFjx2y0hgXN9LUYOo6aBjvhnxI/v71g==} + cspell-glob@8.17.4: + resolution: {integrity: sha512-HbAyg/t6l2Um0kgeTZeTEyXgVkIQX/ir2uLW/W3T9foOkSZ016Os6GRYDRJX7ebfREk8cCZ0uFtOi1Yn56INEQ==} engines: {node: '>=18'} - dependencies: - micromatch: 4.0.5 - dev: true - /cspell-grammar@8.7.0: - resolution: {integrity: sha512-SGcXc7322wU2WNRi7vtpToWDXTqZHhxqvR+aIXHT2kkxlMSWp3Rvfpshd0ckgY54nZtgw7R/JtKND2jeACRpwQ==} + cspell-glob@8.18.1: + resolution: {integrity: sha512-tlZXvzsN7dByHo69dz/HbJuQDUtrfhdioZ/LHaW7W9diG9NpaghgEfyX4fmsIXjU/2f66LDpYVY6osjtlOgyrg==} + engines: {node: '>=18'} + + cspell-grammar@8.17.4: + resolution: {integrity: sha512-RgnpQPVSOdWxq7fLHUkjGJCkMNay4p2cZXRYwhTBJf2kWNsDC39tjRhugFweyxxZPamEbLERgkCaFzE54enuMw==} engines: {node: '>=18'} hasBin: true - dependencies: - '@cspell/cspell-pipe': 8.7.0 - '@cspell/cspell-types': 8.7.0 - dev: true - /cspell-io@8.7.0: - resolution: {integrity: sha512-o7OltyyvVkRG1gQrIqGpN5pUkHNnv6rvihb7Qu6cJ8jITinLGuWJuEQpgt0eF5yIr624jDbFwSzAxsFox8riQg==} - engines: {node: '>=18'} - dependencies: - '@cspell/cspell-service-bus': 8.7.0 - dev: true - - /cspell-lib@8.7.0: - resolution: {integrity: sha512-qDSHZGekwiDmouYRECTQokE+hgAuPqREm+Hb+G3DoIo3ZK5H47TtEUo8fNCw22XsKefcF8X28LiyoZwiYHVpSg==} - engines: {node: '>=18'} - dependencies: - '@cspell/cspell-bundled-dicts': 8.7.0 - '@cspell/cspell-pipe': 8.7.0 - '@cspell/cspell-resolver': 8.7.0 - '@cspell/cspell-types': 8.7.0 - '@cspell/dynamic-import': 8.7.0 - '@cspell/strong-weak-map': 8.7.0 - clear-module: 4.1.2 - comment-json: 4.2.3 - configstore: 6.0.0 - cspell-config-lib: 8.7.0 - cspell-dictionary: 8.7.0 - cspell-glob: 8.7.0 - cspell-grammar: 8.7.0 - cspell-io: 8.7.0 - cspell-trie-lib: 8.7.0 - fast-equals: 5.0.1 - gensequence: 7.0.0 - import-fresh: 3.3.0 - resolve-from: 5.0.0 - vscode-languageserver-textdocument: 1.0.11 - vscode-uri: 3.0.8 - dev: true - - /cspell-trie-lib@8.7.0: - resolution: {integrity: sha512-W3Nh2cO7gMV91r+hLqyTMgKlvRl4W5diKs5YiyOxjZumRkMBy42IzcNYtgIIacOxghklv96F5Bd1Vx/zY6ylGA==} - engines: {node: '>=18'} - dependencies: - '@cspell/cspell-pipe': 8.7.0 - '@cspell/cspell-types': 8.7.0 - gensequence: 7.0.0 - dev: true - - /cspell@8.7.0: - resolution: {integrity: sha512-77nRPgLl240C6FK8RKVKo34lP15Lzp/6bk+SKYJFwUKKXlcgWXDis+Lw4JolA741/JgHtuxmhW1C8P7dCKjJ3w==} + cspell-grammar@8.18.1: + resolution: {integrity: sha512-V6XTN1B++7EzJA0H4g4XbNJtqm6Y3/iXdLeZ6sMRDaNFKXXwTbWRtn8gukDQIytyw09AnCUKeqGSzCVqw26Omg==} engines: {node: '>=18'} hasBin: true - dependencies: - '@cspell/cspell-json-reporter': 8.7.0 - '@cspell/cspell-pipe': 8.7.0 - '@cspell/cspell-types': 8.7.0 - '@cspell/dynamic-import': 8.7.0 - chalk: 5.3.0 - chalk-template: 1.1.0 - commander: 12.0.0 - cspell-gitignore: 8.7.0 - cspell-glob: 8.7.0 - cspell-io: 8.7.0 - cspell-lib: 8.7.0 - fast-glob: 3.3.2 - fast-json-stable-stringify: 2.1.0 - file-entry-cache: 8.0.0 - get-stdin: 9.0.0 - semver: 7.6.0 - strip-ansi: 7.1.0 - vscode-uri: 3.0.8 - dev: true - /css-tree@2.3.1: - resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + cspell-io@8.17.4: + resolution: {integrity: sha512-lHvkxquov5XfIXSenzXrWcOWPiW79+uySoExb20UXHvPSMz0Bk7ZIqDf6lMwTquXbM4BvGGsKQbQE/D4SLD9jw==} + engines: {node: '>=18'} + + cspell-io@8.18.1: + resolution: {integrity: sha512-mm9SUEF2yShuTXDSjCbsAqYTEb6jrtgcCnlqIzpsZOJOOe+zj/VyzTy2NJvOrdvR59dikdaqB75VGBMfHi804g==} + engines: {node: '>=18'} + + cspell-lib@8.17.4: + resolution: {integrity: sha512-BxQy4MDFSjMQ74SYptWJOLLPsNC8XDtKyey0IfMQaqeFmuxrz727GWcONQ2KROrPPs9dnmccDs6Kn8Tx7Wug4A==} + engines: {node: '>=18'} + + cspell-lib@8.18.1: + resolution: {integrity: sha512-t1j+XB7515yHmrczK6I1N6j0a72vmL/6OxsMJnCucHC6DO0WkOqmHulNRH7LpFacnns0dx15lmrAqPg7gQFcIg==} + engines: {node: '>=18'} + + cspell-trie-lib@8.17.4: + resolution: {integrity: sha512-Ou2MGBnZyC+Hti57m4T4D/Tq1P3G570rFPkxgi32f325xsLz1AVEvqrM5oVHDilFH2guUYFaelmL0UcGeP3L6w==} + engines: {node: '>=18'} + + cspell-trie-lib@8.18.1: + resolution: {integrity: sha512-UaB36wsyp2eWeMtrbS6Q2t2WFvpedmGXJ879yHn9qKD7ViyUpI4cAbh6v7gWMUu+gjqCulXtke64k1ddmBihPQ==} + engines: {node: '>=18'} + + cspell@8.17.4: + resolution: {integrity: sha512-cQ6KyYB7itXxc+roxvozIKksbOyBO1NY5Dt5RWHl1Uh4OO++RJAKxmVWrY0g1ubBxKWGXk8TvuunK1+L/jvjIQ==} + engines: {node: '>=18'} + hasBin: true + + css-tree@3.1.0: + resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - dependencies: - mdn-data: 2.0.30 - source-map-js: 1.0.2 - dev: true - /cssesc@3.0.0: + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true - dev: false - /cssstyle@4.0.1: - resolution: {integrity: sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==} + cssstyle@4.2.1: + resolution: {integrity: sha512-9+vem03dMXG7gDmZ62uqmRiMRNtinIZ9ZyuF6BdxzfOD+FdN5hretzynkn0ReS2DO2GSw76RWHs0UmJPI2zUjw==} engines: {node: '>=18'} - dependencies: - rrweb-cssom: 0.6.0 - dev: true - /csstree-validator@3.0.0: - resolution: {integrity: sha512-Y5OSq3wI0Xz6L7DCgJQtQ97U+v99SkX9r663VjpvUMJPhEr0A149OxiAGqcnokB5bt81irgnMudspBzujzqn0w==} + csstree-validator@4.0.1: + resolution: {integrity: sha512-ywwDonvo6BuhXkrNSCAW4JLxsNd8HzpOtVVv22W5BNtZNeviZORSOLb7CLskeaKnL9jjvi24kL7UNh5m52ygpw==} engines: {node: ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} hasBin: true - dependencies: - clap: 3.1.1 - css-tree: 2.3.1 - resolve: 1.22.4 - dev: true - /csstype@3.1.3: + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - /cuint@0.2.2: + cuint@0.2.2: resolution: {integrity: sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==} - dev: true - /cypress-image-snapshot@4.0.1(cypress@13.7.3)(jest@29.7.0): + cypress-image-snapshot@4.0.1: resolution: {integrity: sha512-PBpnhX/XItlx3/DAk5ozsXQHUi72exybBNH5Mpqj1DVmjq+S5Jd9WE5CRa4q5q0zuMZb2V2VpXHth6MjFpgj9Q==} engines: {node: '>=8'} peerDependencies: cypress: ^4.5.0 - dependencies: - chalk: 2.4.2 - cypress: 13.7.3 - fs-extra: 7.0.1 - glob: 7.2.3 - jest-image-snapshot: 4.2.0(jest@29.7.0) - pkg-dir: 3.0.0 - term-img: 4.1.0 - transitivePeerDependencies: - - jest - dev: true - /cypress@13.7.3: - resolution: {integrity: sha512-uoecY6FTCAuIEqLUYkTrxamDBjMHTYak/1O7jtgwboHiTnS1NaMOoR08KcTrbRZFCBvYOiS4tEkQRmsV+xcrag==} - engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0} + cypress-split@1.24.14: + resolution: {integrity: sha512-lc5KuntDKK/n8/XxDh97OeKLWZP6bLbKTiIdoxtsgg2FEXta4hM7mg0xeLPB0IfBRQWKp5g6uyEM1vHAl36f0w==} hasBin: true - requiresBuild: true - dependencies: - '@cypress/request': 3.0.1 - '@cypress/xvfb': 1.2.4(supports-color@8.1.1) - '@types/sinonjs__fake-timers': 8.1.1 - '@types/sizzle': 2.3.8 - arch: 2.2.0 - blob-util: 2.0.2 - bluebird: 3.7.2 - buffer: 5.7.1 - cachedir: 2.4.0 - chalk: 4.1.2 - check-more-types: 2.24.0 - cli-cursor: 3.1.0 - cli-table3: 0.6.4 - commander: 6.2.1 - common-tags: 1.8.2 - dayjs: 1.11.10 - debug: 4.3.4(supports-color@8.1.1) - enquirer: 2.4.1 - eventemitter2: 6.4.7 - execa: 4.1.0 - executable: 4.1.1 - extract-zip: 2.0.1(supports-color@8.1.1) - figures: 3.2.0 - fs-extra: 9.1.0 - getos: 3.2.1 - is-ci: 3.0.1 - is-installed-globally: 0.4.0 - lazy-ass: 1.6.0 - listr2: 3.14.0(enquirer@2.4.1) - lodash: 4.17.21 - log-symbols: 4.1.0 - minimist: 1.2.8 - ospath: 1.2.2 - pretty-bytes: 5.6.0 - process: 0.11.10 - proxy-from-env: 1.0.0 - request-progress: 3.0.0 - semver: 7.6.0 - supports-color: 8.1.1 - tmp: 0.2.3 - untildify: 4.0.0 - yauzl: 2.10.0 - dev: true - /cytoscape-cose-bilkent@4.1.0(cytoscape@3.28.1): + cypress-wait-until@3.0.2: + resolution: {integrity: sha512-iemies796dD5CgjG5kV0MnpEmKSH+s7O83ZoJLVzuVbZmm4lheMsZqAVT73hlMx4QlkwhxbyUzhOBUOZwoOe0w==} + + cypress@14.0.3: + resolution: {integrity: sha512-yIdvobANw3kS+KF/t5vwjjPNufBA8ux7iQHaWxPTkUw2yCKI72m9mKM24eOwE84Wk4ALPsSvEcGbDrwgmhr4RA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + cytoscape-cose-bilkent@4.1.0: resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} peerDependencies: cytoscape: ^3.2.0 - dependencies: - cose-base: 1.0.3 - cytoscape: 3.28.1(patch_hash=claipxynndhyqyu2csninuoh5e) - dev: false - /cytoscape@3.28.1(patch_hash=claipxynndhyqyu2csninuoh5e): - resolution: {integrity: sha512-xyItz4O/4zp9/239wCcH8ZcFuuZooEeF8KHRmzjDfGdXsj3OG9MFSMA0pJE0uX3uCN/ygof6hHf4L7lst+JaDg==} + cytoscape-fcose@2.2.0: + resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==} + peerDependencies: + cytoscape: ^3.2.0 + + cytoscape@3.31.0: + resolution: {integrity: sha512-zDGn1K/tfZwEnoGOcHc0H4XazqAAXAuDpcYw9mUnUjATjqljyCNGJv8uEvbvxGaGHaVshxMecyl6oc6uKzRfbw==} engines: {node: '>=0.10'} - dependencies: - heap: 0.2.7 - lodash: 4.17.21 - dev: false - patched: true - /d3-array@2.12.1: + d3-array@2.12.1: resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} - dependencies: - internmap: 1.0.1 - dev: false - /d3-array@3.2.4: + d3-array@3.2.4: resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} engines: {node: '>=12'} - dependencies: - internmap: 2.0.3 - dev: false - /d3-axis@3.0.0: + d3-axis@3.0.0: resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} engines: {node: '>=12'} - dev: false - /d3-brush@3.0.0: + d3-brush@3.0.0: resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} engines: {node: '>=12'} - dependencies: - d3-dispatch: 3.0.1 - d3-drag: 3.0.0 - d3-interpolate: 3.0.1 - d3-selection: 3.0.0 - d3-transition: 3.0.1(d3-selection@3.0.0) - dev: false - /d3-chord@3.0.1: + d3-chord@3.0.1: resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} engines: {node: '>=12'} - dependencies: - d3-path: 3.1.0 - dev: false - /d3-color@3.1.0: + d3-color@3.1.0: resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} engines: {node: '>=12'} - dev: false - /d3-contour@4.0.2: + d3-contour@4.0.2: resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} engines: {node: '>=12'} - dependencies: - d3-array: 3.2.4 - dev: false - /d3-delaunay@6.0.4: + d3-delaunay@6.0.4: resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} engines: {node: '>=12'} - dependencies: - delaunator: 5.0.1 - dev: false - /d3-dispatch@3.0.1: + d3-dispatch@3.0.1: resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} engines: {node: '>=12'} - dev: false - /d3-drag@3.0.0: + d3-drag@3.0.0: resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} engines: {node: '>=12'} - dependencies: - d3-dispatch: 3.0.1 - d3-selection: 3.0.0 - dev: false - /d3-dsv@3.0.1: + d3-dsv@3.0.1: resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} engines: {node: '>=12'} hasBin: true - dependencies: - commander: 7.2.0 - iconv-lite: 0.6.3 - rw: 1.3.3 - dev: false - /d3-ease@3.0.1: + d3-ease@3.0.1: resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} engines: {node: '>=12'} - dev: false - /d3-fetch@3.0.1: + d3-fetch@3.0.1: resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} engines: {node: '>=12'} - dependencies: - d3-dsv: 3.0.1 - dev: false - /d3-force@3.0.0: + d3-force@3.0.0: resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} engines: {node: '>=12'} - dependencies: - d3-dispatch: 3.0.1 - d3-quadtree: 3.0.1 - d3-timer: 3.0.1 - dev: false - /d3-format@3.1.0: + d3-format@3.1.0: resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} engines: {node: '>=12'} - dev: false - /d3-geo@3.1.0: - resolution: {integrity: sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==} + d3-geo@3.1.1: + resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} engines: {node: '>=12'} - dependencies: - d3-array: 3.2.4 - dev: false - /d3-hierarchy@3.1.2: + d3-hierarchy@3.1.2: resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} engines: {node: '>=12'} - dev: false - /d3-interpolate@3.0.1: + d3-interpolate@3.0.1: resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} engines: {node: '>=12'} - dependencies: - d3-color: 3.1.0 - dev: false - /d3-path@1.0.9: + d3-path@1.0.9: resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==} - dev: false - /d3-path@3.1.0: + d3-path@3.1.0: resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} engines: {node: '>=12'} - dev: false - /d3-polygon@3.0.1: + d3-polygon@3.0.1: resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} engines: {node: '>=12'} - dev: false - /d3-quadtree@3.0.1: + d3-quadtree@3.0.1: resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} engines: {node: '>=12'} - dev: false - /d3-random@3.0.1: + d3-random@3.0.1: resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} engines: {node: '>=12'} - dev: false - /d3-sankey@0.12.3: + d3-sankey@0.12.3: resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==} - dependencies: - d3-array: 2.12.1 - d3-shape: 1.3.7 - dev: false - /d3-scale-chromatic@3.0.0: - resolution: {integrity: sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==} + d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} engines: {node: '>=12'} - dependencies: - d3-color: 3.1.0 - d3-interpolate: 3.0.1 - dev: false - /d3-scale@4.0.2: + d3-scale@4.0.2: resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} engines: {node: '>=12'} - dependencies: - d3-array: 3.2.4 - d3-format: 3.1.0 - d3-interpolate: 3.0.1 - d3-time: 3.1.0 - d3-time-format: 4.1.0 - dev: false - /d3-selection@3.0.0: + d3-selection@3.0.0: resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} engines: {node: '>=12'} - dev: false - /d3-shape@1.3.7: + d3-shape@1.3.7: resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} - dependencies: - d3-path: 1.0.9 - dev: false - /d3-shape@3.2.0: + d3-shape@3.2.0: resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} engines: {node: '>=12'} - dependencies: - d3-path: 3.1.0 - dev: false - /d3-time-format@4.1.0: + d3-time-format@4.1.0: resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} engines: {node: '>=12'} - dependencies: - d3-time: 3.1.0 - dev: false - /d3-time@3.1.0: + d3-time@3.1.0: resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} engines: {node: '>=12'} - dependencies: - d3-array: 3.2.4 - dev: false - /d3-timer@3.0.1: + d3-timer@3.0.1: resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} engines: {node: '>=12'} - dev: false - /d3-transition@3.0.1(d3-selection@3.0.0): + d3-transition@3.0.1: resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} engines: {node: '>=12'} peerDependencies: d3-selection: 2 - 3 - dependencies: - d3-color: 3.1.0 - d3-dispatch: 3.0.1 - d3-ease: 3.0.1 - d3-interpolate: 3.0.1 - d3-selection: 3.0.0 - d3-timer: 3.0.1 - dev: false - /d3-zoom@3.0.0: + d3-zoom@3.0.0: resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} engines: {node: '>=12'} - dependencies: - d3-dispatch: 3.0.1 - d3-drag: 3.0.0 - d3-interpolate: 3.0.1 - d3-selection: 3.0.0 - d3-transition: 3.0.1(d3-selection@3.0.0) - dev: false - /d3@7.9.0: + d3@7.9.0: resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} engines: {node: '>=12'} - dependencies: - d3-array: 3.2.4 - d3-axis: 3.0.0 - d3-brush: 3.0.0 - d3-chord: 3.0.1 - d3-color: 3.1.0 - d3-contour: 4.0.2 - d3-delaunay: 6.0.4 - d3-dispatch: 3.0.1 - d3-drag: 3.0.0 - d3-dsv: 3.0.1 - d3-ease: 3.0.1 - d3-fetch: 3.0.1 - d3-force: 3.0.0 - d3-format: 3.1.0 - d3-geo: 3.1.0 - d3-hierarchy: 3.1.2 - d3-interpolate: 3.0.1 - d3-path: 3.1.0 - d3-polygon: 3.0.1 - d3-quadtree: 3.0.1 - d3-random: 3.0.1 - d3-scale: 4.0.2 - d3-scale-chromatic: 3.0.0 - d3-selection: 3.0.0 - d3-shape: 3.2.0 - d3-time: 3.1.0 - d3-time-format: 4.1.0 - d3-timer: 3.0.1 - d3-transition: 3.0.1(d3-selection@3.0.0) - d3-zoom: 3.0.0 - dev: false - /d@1.0.2: - resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} - engines: {node: '>=0.12'} - dependencies: - es5-ext: 0.10.64 - type: 2.7.2 - dev: true + dagre-d3-es@7.0.11: + resolution: {integrity: sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw==} - /dagre-d3-es@7.0.10: - resolution: {integrity: sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==} - dependencies: - d3: 7.9.0 - lodash-es: 4.17.21 - dev: false - - /dashdash@1.14.1: + dashdash@1.14.1: resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} engines: {node: '>=0.10'} - dependencies: - assert-plus: 1.0.0 - dev: true - /data-uri-to-buffer@4.0.1: + data-uri-to-buffer@4.0.1: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} - dev: true - /data-urls@5.0.0: + data-urls@5.0.0: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} - dependencies: - whatwg-mimetype: 4.0.0 - whatwg-url: 14.0.0 - dev: true - /data-view-buffer@1.0.1: - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - /data-view-byte-length@1.0.1: - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - /data-view-byte-offset@1.0.0: - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - /date-fns@2.30.0: - resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} - engines: {node: '>=0.11'} - dependencies: - '@babel/runtime': 7.24.0 - dev: true + dataloader@1.4.0: + resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} - /dayjs@1.11.10: - resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} - /debug@2.6.9: + debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: supports-color: '*' peerDependenciesMeta: supports-color: optional: true - dependencies: - ms: 2.0.0 - dev: true - /debug@3.2.7(supports-color@8.1.1): + debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: supports-color: '*' peerDependenciesMeta: supports-color: optional: true - dependencies: - ms: 2.1.3 - supports-color: 8.1.1 - dev: true - /debug@4.3.3: + debug@4.3.3: resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} engines: {node: '>=6.0'} peerDependencies: @@ -7655,11 +4896,8 @@ packages: peerDependenciesMeta: supports-color: optional: true - dependencies: - ms: 2.1.2 - dev: true - /debug@4.3.4(supports-color@8.1.1): + debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: @@ -7667,2825 +4905,1673 @@ packages: peerDependenciesMeta: supports-color: optional: true - dependencies: - ms: 2.1.2 - supports-color: 8.1.1 - /decamelize@1.2.0: + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize@1.2.0: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} - dev: true - /decimal.js@10.4.3: + decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} - dev: true - /decode-named-character-reference@1.0.2: + decode-named-character-reference@1.0.2: resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} - dependencies: - character-entities: 2.0.2 - /decompress-response@6.0.0: + decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} - dependencies: - mimic-response: 3.1.0 - dev: true - /dedent@1.5.1: - resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==} + dedent@1.5.3: + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: babel-plugin-macros: optional: true - dev: true - /deep-eql@4.1.3: - resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} - dependencies: - type-detect: 4.0.8 - dev: true - /deep-is@0.1.4: + deep-equal@2.2.3: + resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} + engines: {node: '>= 0.4'} + + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - /deepmerge@4.3.1: + deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - dev: true - /default-gateway@6.0.3: + default-gateway@6.0.3: resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} engines: {node: '>= 10'} - dependencies: - execa: 5.1.1 - dev: true - /default-require-extensions@3.0.1: + default-require-extensions@3.0.1: resolution: {integrity: sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==} engines: {node: '>=8'} - dependencies: - strip-bom: 4.0.0 - dev: true - /defer-to-connect@2.0.1: + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + defer-to-connect@2.0.1: resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} engines: {node: '>=10'} - dev: true - /define-data-property@1.1.4: + define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.0.1 - dev: true - /define-lazy-prop@2.0.0: + define-lazy-prop@2.0.0: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} engines: {node: '>=8'} - dev: true - /define-properties@1.2.1: + define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - dev: true - /defu@6.1.4: + defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} - dev: true - /delaunator@5.0.1: + delaunator@5.0.1: resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} - dependencies: - robust-predicates: 3.0.2 - dev: false - /delayed-stream@1.0.0: + delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - dev: true - /depd@1.1.2: + depd@1.1.2: resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} engines: {node: '>= 0.6'} - dev: true - /depd@2.0.0: + depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} - dev: true - /dequal@2.0.3: + dependency-tree@11.0.1: + resolution: {integrity: sha512-eCt7HSKIC9NxgIykG2DRq3Aewn9UhVS14MB3rEn6l/AsEI1FBg6ZGSlCU0SZ6Tjm2kkhj6/8c2pViinuyKELhg==} + engines: {node: '>=18'} + hasBin: true + + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} - /destr@2.0.3: + destr@2.0.3: resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} - dev: true - /destroy@1.2.0: + destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: true - /detect-newline@3.1.0: + detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} - dev: true - /detect-node@2.1.0: + detect-node@2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} - dev: true - /devlop@1.1.0: + detective-amd@6.0.0: + resolution: {integrity: sha512-NTqfYfwNsW7AQltKSEaWR66hGkTeD52Kz3eRQ+nfkA9ZFZt3iifRCWh+yZ/m6t3H42JFwVFTrml/D64R2PAIOA==} + engines: {node: '>=18'} + hasBin: true + + detective-cjs@6.0.0: + resolution: {integrity: sha512-R55jTS6Kkmy6ukdrbzY4x+I7KkXiuDPpFzUViFV/tm2PBGtTCjkh9ZmTuJc1SaziMHJOe636dtiZLEuzBL9drg==} + engines: {node: '>=18'} + + detective-es6@5.0.0: + resolution: {integrity: sha512-NGTnzjvgeMW1khUSEXCzPDoraLenWbUjCFjwxReH+Ir+P6LGjYtaBbAvITWn2H0VSC+eM7/9LFOTAkrta6hNYg==} + engines: {node: '>=18'} + + detective-postcss@7.0.0: + resolution: {integrity: sha512-pSXA6dyqmBPBuERpoOKKTUUjQCZwZPLRbd1VdsTbt6W+m/+6ROl4BbE87yQBUtLoK7yX8pvXHdKyM/xNIW9F7A==} + engines: {node: ^14.0.0 || >=16.0.0} + peerDependencies: + postcss: ^8.4.38 + + detective-sass@6.0.0: + resolution: {integrity: sha512-h5GCfFMkPm4ZUUfGHVPKNHKT8jV7cSmgK+s4dgQH4/dIUNh9/huR1fjEQrblOQNDalSU7k7g+tiW9LJ+nVEUhg==} + engines: {node: '>=18'} + + detective-scss@5.0.0: + resolution: {integrity: sha512-Y64HyMqntdsCh1qAH7ci95dk0nnpA29g319w/5d/oYcHolcGUVJbIhOirOFjfN1KnMAXAFm5FIkZ4l2EKFGgxg==} + engines: {node: '>=18'} + + detective-stylus@5.0.0: + resolution: {integrity: sha512-KMHOsPY6aq3196WteVhkY5FF+6Nnc/r7q741E+Gq+Ax9mhE2iwj8Hlw8pl+749hPDRDBHZ2WlgOjP+twIG61vQ==} + engines: {node: '>=18'} + + detective-typescript@13.0.0: + resolution: {integrity: sha512-tcMYfiFWoUejSbvSblw90NDt76/4mNftYCX0SMnVRYzSXv8Fvo06hi4JOPdNvVNxRtCAKg3MJ3cBJh+ygEMH+A==} + engines: {node: ^14.14.0 || >=16.0.0} + peerDependencies: + typescript: ^5.4.4 + + detective-vue2@2.0.3: + resolution: {integrity: sha512-AgWdSfVnft8uPGnUkdvE1EDadEENDCzoSRMt2xZfpxsjqVO617zGWXbB8TGIxHaqHz/nHa6lOSgAB8/dt0yEug==} + engines: {node: '>=18'} + peerDependencies: + typescript: ^5.4.4 + + devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} - dependencies: - dequal: 2.0.3 - /didyoumean@1.2.2: + didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - dev: false - /diff-sequences@29.6.3: + diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - /dir-glob@3.0.1: + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - /dlv@1.1.3: + dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} - dev: false - /dns-equal@1.0.0: - resolution: {integrity: sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==} - dev: true - - /dns-packet@5.6.0: - resolution: {integrity: sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==} + dns-packet@5.6.1: + resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} engines: {node: '>=6'} - dependencies: - '@leichtgewicht/ip-codec': 2.0.4 - dev: true - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /dom-serializer@2.0.0: + dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - dev: true - /dom-to-image-more@2.16.0: + dom-to-image-more@2.16.0: resolution: {integrity: sha512-RyjtkaM/zVy90uJ20lT+/G7MwBZx6l/ePliq5CQOeAnPeew7aUGS6IqRWBkHpstU+POmhaKA8A9H9qf476gisQ==} - dev: false - /domelementtype@2.3.0: + domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - dev: true - /domhandler@5.0.3: + domhandler@5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} - dependencies: - domelementtype: 2.3.0 - dev: true - /dompurify@3.1.0: - resolution: {integrity: sha512-yoU4rhgPKCo+p5UrWWWNKiIq+ToGqmVVhk0PmMYBK4kRsR3/qhemNFL8f6CFmBd4gMwm3F4T7HBoydP5uY07fA==} - dev: false + dompurify@3.2.5: + resolution: {integrity: sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ==} - /domutils@3.1.0: + domutils@3.1.0: resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - dev: true - /dot-prop@6.0.1: - resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} - engines: {node: '>=10'} - dependencies: - is-obj: 2.0.0 - dev: true - - /dotenv@16.4.5: - resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} engines: {node: '>=12'} - dev: true - /duplexer@0.1.2: + dotenv@8.6.0: + resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} + engines: {node: '>=10'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} - dev: true - /eastasianwidth@0.2.0: + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - /ebnf-parser@0.1.10: + easy-table@1.1.0: + resolution: {integrity: sha512-oq33hWOSSnl2Hoh00tZWaIPi1ievrD9aFG82/IgjlycAnW9hHx5PkJiXpxPsgEE+H7BsbVQXFVFST8TEXS6/pA==} + + ebnf-parser@0.1.10: resolution: {integrity: sha512-urvSxVQ6XJcoTpc+/x2pWhhuOX4aljCNQpwzw+ifZvV1andZkAmiJc3Rq1oGEAQmcjiLceyMXOy1l8ms8qs2fQ==} - dev: true - /ecc-jsbn@0.1.2: + ecc-jsbn@0.1.2: resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} - dependencies: - jsbn: 0.1.1 - safer-buffer: 2.1.2 - dev: true - /ee-first@1.1.1: + ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: true - /ejs@3.1.10: + ejs@3.1.10: resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} engines: {node: '>=0.10.0'} hasBin: true - dependencies: - jake: 10.8.7 - dev: true - /electron-to-chromium@1.4.692: - resolution: {integrity: sha512-d5rZRka9n2Y3MkWRN74IoAsxR0HK3yaAt7T50e3iT9VZmCCQDT3geXUO5ZRMhDToa1pkCeQXuNo+0g+NfDOVPA==} - dev: true + electron-to-chromium@1.5.101: + resolution: {integrity: sha512-L0ISiQrP/56Acgu4/i/kfPwWSgrzYZUnQrC0+QPFuhqlLP1Ir7qzPPDVS9BcKIyWTRU8+o6CC8dKw38tSWhYIA==} - /elkjs@0.9.2: - resolution: {integrity: sha512-2Y/RaA1pdgSHpY0YG4TYuYCD2wh97CRvu22eLG3Kz0pgQ/6KbIFTxsTnDc4MH/6hFlg2L/9qXrDMG0nMjP63iw==} - dev: false + elkjs@0.9.3: + resolution: {integrity: sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==} - /emittery@0.13.1: + emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} engines: {node: '>=12'} - dev: true - /emoji-regex@10.3.0: - resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} - dev: true + emoji-regex-xs@1.0.0: + resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} - /emoji-regex@8.0.0: + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - /emoji-regex@9.2.2: + emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - /encodeurl@1.0.2: + encodeurl@1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} - dev: true - /encoding@0.1.13: + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + encoding@0.1.13: resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} - dependencies: - iconv-lite: 0.6.3 - dev: true - /end-of-stream@1.4.4: + end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - dependencies: - once: 1.4.0 - dev: true - /enhanced-resolve@5.16.0: - resolution: {integrity: sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==} + enhanced-resolve@5.17.1: + resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} engines: {node: '>=10.13.0'} - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - dev: true - /enquirer@2.4.1: + enquirer@2.4.1: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} - dependencies: - ansi-colors: 4.1.3 - strip-ansi: 6.0.1 - dev: true - /entities@3.0.1: + entities@3.0.1: resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==} engines: {node: '>=0.12'} - dev: true - /entities@4.5.0: + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - /envinfo@7.10.0: - resolution: {integrity: sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==} + env-paths@3.0.0: + resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + envinfo@7.14.0: + resolution: {integrity: sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==} engines: {node: '>=4'} hasBin: true - dev: true - /error-ex@1.3.2: + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - /es-abstract@1.23.3: - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + es-abstract@1.23.9: + resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - arraybuffer.prototype.slice: 1.0.3 - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - data-view-buffer: 1.0.1 - data-view-byte-length: 1.0.1 - data-view-byte-offset: 1.0.0 - es-define-property: 1.0.0 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-set-tostringtag: 2.0.3 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.6 - get-intrinsic: 1.2.4 - get-symbol-description: 1.0.2 - globalthis: 1.0.3 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - internal-slot: 1.0.7 - is-array-buffer: 3.0.4 - is-callable: 1.2.7 - is-data-view: 1.0.1 - is-negative-zero: 2.0.3 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.3 - is-string: 1.0.7 - is-typed-array: 1.1.13 - is-weakref: 1.0.2 - object-inspect: 1.13.1 - object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.5.2 - safe-array-concat: 1.1.2 - safe-regex-test: 1.0.3 - string.prototype.trim: 1.2.9 - string.prototype.trimend: 1.0.8 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.2 - typed-array-byte-length: 1.0.1 - typed-array-byte-offset: 1.0.2 - typed-array-length: 1.0.6 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.15 - dev: true - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - dev: true - /es-errors@1.3.0: + es-errors@1.3.0: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - dev: true - /es-module-lexer@1.4.1: - resolution: {integrity: sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==} - dev: true + es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} - /es-object-atoms@1.0.0: - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + + es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - dev: true - /es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - dev: true - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: true - /es2015-i18n-tag@1.6.1: + es2015-i18n-tag@1.6.1: resolution: {integrity: sha512-MYoh9p+JTkgnzBh0MEBON6xUyzdmwT6wzsmmFJvZujGSXiI2kM+3XvFl6+AcIO2eeL6VWgtX9szSiDTMwDxyYA==} engines: {node: '>= 4.0.0'} - dev: true - /es5-ext@0.10.64: - resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} - engines: {node: '>=0.10'} - requiresBuild: true - dependencies: - es6-iterator: 2.0.3 - es6-symbol: 3.1.4 - esniff: 2.0.1 - next-tick: 1.1.0 - dev: true - - /es6-error@4.1.1: + es6-error@4.1.1: resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} - dev: true - /es6-iterator@2.0.3: - resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - es6-symbol: 3.1.4 - dev: true - - /es6-symbol@3.1.4: - resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} - engines: {node: '>=0.12'} - dependencies: - d: 1.0.2 - ext: 1.7.0 - dev: true - - /es6-weak-map@2.0.3: - resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - es6-iterator: 2.0.3 - es6-symbol: 3.1.4 - dev: true - - /esbuild@0.19.12: - resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.19.12 - '@esbuild/android-arm': 0.19.12 - '@esbuild/android-arm64': 0.19.12 - '@esbuild/android-x64': 0.19.12 - '@esbuild/darwin-arm64': 0.19.12 - '@esbuild/darwin-x64': 0.19.12 - '@esbuild/freebsd-arm64': 0.19.12 - '@esbuild/freebsd-x64': 0.19.12 - '@esbuild/linux-arm': 0.19.12 - '@esbuild/linux-arm64': 0.19.12 - '@esbuild/linux-ia32': 0.19.12 - '@esbuild/linux-loong64': 0.19.12 - '@esbuild/linux-mips64el': 0.19.12 - '@esbuild/linux-ppc64': 0.19.12 - '@esbuild/linux-riscv64': 0.19.12 - '@esbuild/linux-s390x': 0.19.12 - '@esbuild/linux-x64': 0.19.12 - '@esbuild/netbsd-x64': 0.19.12 - '@esbuild/openbsd-x64': 0.19.12 - '@esbuild/sunos-x64': 0.19.12 - '@esbuild/win32-arm64': 0.19.12 - '@esbuild/win32-ia32': 0.19.12 - '@esbuild/win32-x64': 0.19.12 - dev: true - /esbuild@0.20.2: - resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} - engines: {node: '>=12'} + esbuild@0.24.2: + resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} + engines: {node: '>=18'} hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.20.2 - '@esbuild/android-arm': 0.20.2 - '@esbuild/android-arm64': 0.20.2 - '@esbuild/android-x64': 0.20.2 - '@esbuild/darwin-arm64': 0.20.2 - '@esbuild/darwin-x64': 0.20.2 - '@esbuild/freebsd-arm64': 0.20.2 - '@esbuild/freebsd-x64': 0.20.2 - '@esbuild/linux-arm': 0.20.2 - '@esbuild/linux-arm64': 0.20.2 - '@esbuild/linux-ia32': 0.20.2 - '@esbuild/linux-loong64': 0.20.2 - '@esbuild/linux-mips64el': 0.20.2 - '@esbuild/linux-ppc64': 0.20.2 - '@esbuild/linux-riscv64': 0.20.2 - '@esbuild/linux-s390x': 0.20.2 - '@esbuild/linux-x64': 0.20.2 - '@esbuild/netbsd-x64': 0.20.2 - '@esbuild/openbsd-x64': 0.20.2 - '@esbuild/sunos-x64': 0.20.2 - '@esbuild/win32-arm64': 0.20.2 - '@esbuild/win32-ia32': 0.20.2 - '@esbuild/win32-x64': 0.20.2 - dev: true - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + esbuild@0.25.0: + resolution: {integrity: sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} - dev: true - /escape-html@1.0.3: + escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: true - /escape-string-regexp@1.0.5: + escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} - dev: true - /escape-string-regexp@2.0.0: + escape-string-regexp@2.0.0: resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} engines: {node: '>=8'} - dev: true - /escape-string-regexp@4.0.0: + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - dev: true - /escape-string-regexp@5.0.0: + escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} - dev: true - /escodegen@1.3.3: + escodegen@1.3.3: resolution: {integrity: sha512-z9FWgKc48wjMlpzF5ymKS1AF8OIgnKLp9VyN7KbdtyrP/9lndwUFqCtMm+TAJmJf7KJFFYc4cFJfVTTGkKEwsA==} engines: {node: '>=0.10.0'} hasBin: true - dependencies: - esprima: 1.1.1 - estraverse: 1.5.1 - esutils: 1.0.0 - optionalDependencies: - source-map: 0.1.43 - dev: true - /eslint-config-prettier@9.1.0(eslint@8.57.0): - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + eslint-config-prettier@10.1.1: + resolution: {integrity: sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==} hasBin: true peerDependencies: eslint: '>=7.0.0' - dependencies: - eslint: 8.57.0 - dev: true - /eslint-plugin-cypress@2.15.1(eslint@8.57.0): - resolution: {integrity: sha512-eLHLWP5Q+I4j2AWepYq0PgFEei9/s5LvjuSqWrxurkg1YZ8ltxdvMNmdSf0drnsNo57CTgYY/NIHHLRSWejR7w==} + eslint-plugin-cypress@4.2.1: + resolution: {integrity: sha512-WNhKkQPqXcbDL7pxGnNYBVLlAIOk6eHdFGQFRELsba871guZZe8zZe50GAjBXSZKcvUWbzCUopM+8ArlngdyGQ==} peerDependencies: - eslint: '>= 3.2.1' - dependencies: - eslint: 8.57.0 - globals: 13.24.0 - dev: true + eslint: '>=9' - /eslint-plugin-html@8.1.0: - resolution: {integrity: sha512-5bRZQwxZew2Yo9Fa8diz2C9RmzIw9Gs4yzmmjUcpuzhdLW8aVcDtYzEHhNNdt01Z0m4AzSJNuY63RXvzStvDgA==} + eslint-plugin-html@8.1.2: + resolution: {integrity: sha512-pbRchDV2SmqbCi/Ev/q3aAikzG9BcFe0IjjqjtMn8eTLq71ZUggyJB6CDmuwGAXmYZHrXI12XTfCqvgcnPRqGw==} engines: {node: '>=16.0.0'} - dependencies: - htmlparser2: 9.1.0 - dev: true - /eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@7.6.0)(eslint@8.57.0)(jest@29.7.0)(typescript@5.4.5): - resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + eslint-plugin-jest@28.11.0: + resolution: {integrity: sha512-QAfipLcNCWLVocVbZW8GimKn5p5iiMcgGbRzz8z/P5q7xw+cNEpYqyzFMtIF/ZgF2HLOyy+dYBut+DoYolvqig==} + engines: {node: ^16.10.0 || ^18.12.0 || >=20.0.0} peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 || ^6.0.0 || ^7.0.0 - eslint: ^7.0.0 || ^8.0.0 + '@typescript-eslint/eslint-plugin': ^6.0.0 || ^7.0.0 || ^8.0.0 + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 jest: '*' peerDependenciesMeta: '@typescript-eslint/eslint-plugin': optional: true jest: optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 7.6.0(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5) - eslint: 8.57.0 - jest: 29.7.0(@types/node@20.12.7) - transitivePeerDependencies: - - supports-color - - typescript - dev: true - /eslint-plugin-jsdoc@48.2.3(eslint@8.57.0): - resolution: {integrity: sha512-r9DMAmFs66VNvNqRLLjHejdnJtILrt3xGi+Qx0op0oRfFGVpOR1Hb3BC++MacseHx93d8SKYPhyrC9BS7Os2QA==} + eslint-plugin-jsdoc@50.6.9: + resolution: {integrity: sha512-7/nHu3FWD4QRG8tCVqcv+BfFtctUtEDWc29oeDXB4bwmDM2/r1ndl14AG/2DUntdqH7qmpvdemJKwb3R97/QEw==} engines: {node: '>=18'} peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - dependencies: - '@es-joy/jsdoccomment': 0.42.0 - are-docs-informative: 0.0.2 - comment-parser: 1.4.1 - debug: 4.3.4(supports-color@8.1.1) - escape-string-regexp: 4.0.0 - eslint: 8.57.0 - esquery: 1.5.0 - is-builtin-module: 3.2.1 - semver: 7.6.0 - spdx-expression-parse: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: true - /eslint-plugin-json@3.1.0: - resolution: {integrity: sha512-MrlG2ynFEHe7wDGwbUuFPsaT2b1uhuEFhJ+W1f1u+1C2EkXmTYJp4B1aAdQQ8M+CC3t//N/oRKiIVw14L2HR1g==} - engines: {node: '>=12.0'} - dependencies: - lodash: 4.17.21 - vscode-json-languageservice: 4.2.1 - dev: true + eslint-plugin-json@4.0.1: + resolution: {integrity: sha512-3An5ISV5dq/kHfXdNyY5TUe2ONC3yXFSkLX2gu+W8xAhKhfvrRvkSAeKXCxZqZ0KJLX15ojBuLPyj+UikQMkOA==} + engines: {node: '>=18.0'} - /eslint-plugin-lodash@7.4.0(eslint@8.57.0): - resolution: {integrity: sha512-Tl83UwVXqe1OVeBRKUeWcfg6/pCW1GTRObbdnbEJgYwjxp5Q92MEWQaH9+dmzbRt6kvYU1Mp893E79nJiCSM8A==} + eslint-plugin-lodash@8.0.0: + resolution: {integrity: sha512-7DA8485FolmWRzh+8t4S8Pzin2TTuWfb0ZW3j/2fYElgk82ZanFz8vDcvc4BBPceYdX1p/za+tkbO68maDBGGw==} engines: {node: '>=10'} peerDependencies: - eslint: '>=2' - dependencies: - eslint: 8.57.0 - lodash: 4.17.21 - dev: true + eslint: '>=9.0.0' - /eslint-plugin-markdown@4.0.1(eslint@8.57.0): - resolution: {integrity: sha512-5/MnGvYU0i8MbHH5cg8S+Vl3DL+bqRNYshk1xUO86DilNBaxtTkhH+5FD0/yO03AmlI6+lfNFdk2yOw72EPzpA==} + eslint-plugin-markdown@5.1.0: + resolution: {integrity: sha512-SJeyKko1K6GwI0AN6xeCDToXDkfKZfXcexA6B+O2Wr2btUS9GrC+YgwSyVli5DJnctUHjFXcQ2cqTaAmVoLi2A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=8' - dependencies: - eslint: 8.57.0 - mdast-util-from-markdown: 0.8.5 - transitivePeerDependencies: - - supports-color - dev: true - /eslint-plugin-no-only-tests@3.1.0: - resolution: {integrity: sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==} + eslint-plugin-no-only-tests@3.3.0: + resolution: {integrity: sha512-brcKcxGnISN2CcVhXJ/kEQlNa0MEfGRtwKtWA16SkqXHKitaKIMrfemJKLKX1YqDU5C/5JY3PvZXd5jEW04e0Q==} engines: {node: '>=5.0.0'} - dev: true - /eslint-plugin-tsdoc@0.2.17: - resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==} - dependencies: - '@microsoft/tsdoc': 0.14.2 - '@microsoft/tsdoc-config': 0.16.2 - dev: true + eslint-plugin-tsdoc@0.4.0: + resolution: {integrity: sha512-MT/8b4aKLdDClnS8mP3R/JNjg29i0Oyqd/0ym6NnQf+gfKbJJ4ZcSh2Bs1H0YiUMTBwww5JwXGTWot/RwyJ7aQ==} - /eslint-plugin-unicorn@51.0.1(eslint@8.57.0): - resolution: {integrity: sha512-MuR/+9VuB0fydoI0nIn2RDA5WISRn4AsJyNSaNKLVwie9/ONvQhxOBbkfSICBPnzKrB77Fh6CZZXjgTt/4Latw==} - engines: {node: '>=16'} + eslint-plugin-unicorn@58.0.0: + resolution: {integrity: sha512-fc3iaxCm9chBWOHPVjn+Czb/wHS0D2Mko7wkOdobqo9R2bbFObc4LyZaLTNy0mhZOP84nKkLhTUQxlLOZ7EjKw==} + engines: {node: ^18.20.0 || ^20.10.0 || >=21.0.0} peerDependencies: - eslint: '>=8.56.0' - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint/eslintrc': 2.1.4 - ci-info: 4.0.0 - clean-regexp: 1.0.0 - core-js-compat: 3.36.0 - eslint: 8.57.0 - esquery: 1.5.0 - indent-string: 4.0.0 - is-builtin-module: 3.2.1 - jsesc: 3.0.2 - pluralize: 8.0.0 - read-pkg-up: 7.0.1 - regexp-tree: 0.1.27 - regjsparser: 0.10.0 - semver: 7.6.0 - strip-indent: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true + eslint: '>=9.22.0' - /eslint-scope@5.1.1: + eslint-scope@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: 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} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true + eslint-scope@8.3.0: + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - /eslint-visitor-keys@3.4.3: + 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} - dev: true - /eslint-visitor-keys@4.0.0: - resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint@9.24.0: + resolution: {integrity: sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@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(supports-color@8.1.1) - 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 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - 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 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true - /esniff@2.0.1: - resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} - engines: {node: '>=0.10'} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - event-emitter: 0.3.5 - type: 2.7.2 - dev: true - - /espree@10.0.1: - resolution: {integrity: sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==} + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 4.0.0 - dev: true - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 - dev: true - - /esprima@1.1.1: + esprima@1.1.1: resolution: {integrity: sha512-qxxB994/7NtERxgXdFgLHIs9M6bhLXc6qtUmWZ3L8+gTQ9qaoyki2887P2IqAYsoENyr8SUbTutStDniOHSDHg==} engines: {node: '>=0.4.0'} hasBin: true - dev: true - /esprima@4.0.1: + esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} hasBin: true - dev: true - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - /esrecurse@4.3.0: + esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - /estraverse@1.5.1: + estraverse@1.5.1: resolution: {integrity: sha512-FpCjJDfmo3vsc/1zKSeqR5k42tcIhxFIlvq+h9j0fO2q/h2uLKyweq7rYJ+0CoVvrGQOxIS5wyBrW/+vF58BUQ==} engines: {node: '>=0.4.0'} - dev: true - /estraverse@4.3.0: + estraverse@4.3.0: resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} engines: {node: '>=4.0'} - dev: true - /estraverse@5.3.0: + estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - dev: true - /estree-walker@1.0.1: + estree-walker@1.0.1: resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} - dev: true - /estree-walker@2.0.2: + estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - /estree-walker@3.0.3: + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - dependencies: - '@types/estree': 1.0.5 - dev: true - /esutils@1.0.0: + esutils@1.0.0: resolution: {integrity: sha512-x/iYH53X3quDwfHRz4y8rn4XcEwwCJeWsul9pF1zldMbGtgOtMNBEOuYWwB1EQlK2LRa1fev3YAgym/RElp5Cg==} engines: {node: '>=0.10.0'} - dev: true - /esutils@2.0.3: + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - dev: true - /etag@1.8.1: + etag@1.8.1: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} - dev: true - /event-emitter@0.3.5: - resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - dev: true - - /event-stream@3.3.4: + event-stream@3.3.4: resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} - dependencies: - duplexer: 0.1.2 - from: 0.1.7 - map-stream: 0.1.0 - pause-stream: 0.0.11 - split: 0.3.3 - stream-combiner: 0.0.4 - through: 2.3.8 - dev: true - /event-target-shim@5.0.1: + event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} - /eventemitter2@6.4.7: + eventemitter2@6.4.7: resolution: {integrity: sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==} - dev: true - /eventemitter3@4.0.7: + eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - dev: true - /eventemitter3@5.0.1: + eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - dev: true - /events@3.3.0: + events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - /execa@1.0.0: + execa@1.0.0: resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} engines: {node: '>=6'} - dependencies: - cross-spawn: 6.0.5 - get-stream: 4.1.0 - is-stream: 1.1.0 - npm-run-path: 2.0.2 - p-finally: 1.0.0 - signal-exit: 3.0.7 - strip-eof: 1.0.0 - dev: true - /execa@4.1.0: + execa@4.1.0: resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 5.2.0 - human-signals: 1.1.1 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - /execa@5.1.1: + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - /execa@8.0.1: + execa@8.0.1: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - dev: true - /executable@4.1.1: + executable@4.1.1: resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==} engines: {node: '>=4'} - dependencies: - pify: 2.3.0 - dev: true - /exit@0.1.2: + exit@0.1.2: resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} engines: {node: '>= 0.8.0'} - dev: true - /expect@29.7.0: + expect-type@1.1.0: + resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==} + engines: {node: '>=12.0.0'} + + expect@29.7.0: resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/expect-utils': 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - dev: true - /express@4.18.2: - resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} + express@4.21.0: + resolution: {integrity: sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==} engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.1 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.5.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: true - /express@4.19.1: - resolution: {integrity: sha512-K4w1/Bp7y8iSiVObmCrtq8Cs79XjJc/RU2YYkZQ7wpUu5ZyZ7MtPHkqoMz4pf+mgXfNvo2qft8D9OnrH2ABk9w==} - engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.2 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.6.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: true + express@5.1.0: + resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} + engines: {node: '>= 18'} - /express@4.19.2: - resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} - engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.2 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.6.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /ext@1.7.0: - resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} - dependencies: - type: 2.7.2 - dev: true - - /extend@3.0.2: + extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: true - /extract-zip@2.0.1(supports-color@8.1.1): + extendable-error@0.1.7: + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} + + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + + extract-zip@2.0.1: resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} engines: {node: '>= 10.17.0'} hasBin: true - dependencies: - debug: 4.3.4(supports-color@8.1.1) - get-stream: 5.2.0 - yauzl: 2.10.0 - optionalDependencies: - '@types/yauzl': 2.10.3 - transitivePeerDependencies: - - supports-color - dev: true - /extsprintf@1.3.0: + extsprintf@1.3.0: resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} engines: {'0': node >=0.6.0} - dev: true - /fast-content-type-parse@1.1.0: + fast-content-type-parse@1.1.0: resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==} - dev: true - /fast-decode-uri-component@1.0.1: + fast-decode-uri-component@1.0.1: resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} - dev: true - /fast-deep-equal@3.1.3: + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - /fast-equals@5.0.1: - resolution: {integrity: sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==} + fast-equals@5.2.2: + resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==} engines: {node: '>=6.0.0'} - dev: true - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - /fast-json-stable-stringify@2.1.0: + fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - /fast-json-stringify@2.7.13: - resolution: {integrity: sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA==} - engines: {node: '>= 10.0.0'} - dependencies: - ajv: 6.12.6 - deepmerge: 4.3.1 - rfdc: 1.3.1 - string-similarity: 4.0.4 - dev: true + fast-json-stringify@5.16.1: + resolution: {integrity: sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==} - /fast-levenshtein@2.0.6: + fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - /fast-redact@3.5.0: + fast-querystring@1.1.2: + resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} + + fast-redact@3.5.0: resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} engines: {node: '>=6'} - /fast-safe-stringify@2.1.1: - resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - dev: true + fast-shuffle@6.1.0: + resolution: {integrity: sha512-3aj8oO6bvZFKYDGvXNmmEuxyOjre8trCpIbtFSM/DSKd+o3iSbQQPb5BZQeJ7SPYVivn9EeW3gKh0QdnD027MQ==} - /fastest-levenshtein@1.0.16: + fast-uri@2.4.0: + resolution: {integrity: sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==} + + fast-uri@3.0.2: + resolution: {integrity: sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==} + + fastest-levenshtein@1.0.16: resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} engines: {node: '>= 4.9.1'} - dev: true - /fastestsmallesttextencoderdecoder@1.0.22: + fastestsmallesttextencoderdecoder@1.0.22: resolution: {integrity: sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==} - dev: true - /fastify-plugin@3.0.1: + fastify-plugin@3.0.1: resolution: {integrity: sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA==} - dev: true - /fastify@3.29.5: - resolution: {integrity: sha512-FBDgb1gkenZxxh4sTD6AdI6mFnZnsgckpjIXzIvfLSYCa4isfQeD8QWGPib63dxq6btnY0l1j8I0xYhMvUb+sw==} - dependencies: - '@fastify/ajv-compiler': 1.1.0 - '@fastify/error': 2.0.0 - abstract-logging: 2.0.1 - avvio: 7.2.5 - fast-content-type-parse: 1.1.0 - fast-json-stringify: 2.7.13 - find-my-way: 4.5.1 - flatstr: 1.0.12 - light-my-request: 4.12.0 - pino: 6.14.0 - process-warning: 1.0.0 - proxy-addr: 2.0.7 - rfdc: 1.3.1 - secure-json-parse: 2.7.0 - semver: 7.5.4 - tiny-lru: 8.0.2 - transitivePeerDependencies: - - supports-color - dev: true + fastify@4.29.0: + resolution: {integrity: sha512-MaaUHUGcCgC8fXQDsDtioaCcag1fmPJ9j64vAKunqZF4aSub040ZGi/ag8NGE2714yREPOKZuHCfpPzuUD3UQQ==} - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - dependencies: - reusify: 1.0.4 + fastq@1.19.0: + resolution: {integrity: sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==} - /fault@2.0.1: + fault@2.0.1: resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} - dependencies: - format: 0.2.2 - dev: true - /faye-websocket@0.11.4: + faye-websocket@0.11.4: resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} engines: {node: '>=0.8.0'} - dependencies: - websocket-driver: 0.7.4 - dev: true - /fb-watchman@2.0.2: + fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} - dependencies: - bser: 2.1.1 - dev: true - /fd-slicer@1.1.0: + fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} - dependencies: - pend: 1.2.0 - dev: true - /ferrum@1.9.4: + fdir@6.4.3: + resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + ferrum@1.9.4: resolution: {integrity: sha512-ooNerLoIht/dK4CQJux93z/hnt9JysrXniJCI3r6YRgmHeXC57EJ8XaTCT1Gm8LfhIAeWxyJA0O7d/W3pqDYRg==} - dependencies: - fastestsmallesttextencoderdecoder: 1.0.22 - lodash.isplainobject: 4.0.6 - xxhashjs: 0.2.2 - dev: true - /fetch-blob@3.2.0: + fetch-blob@3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 3.3.3 - dev: true - /fflate@0.8.2: + fflate@0.8.2: resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} - dev: true - /figures@3.2.0: + figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.2.0 - dev: true - - /file-entry-cache@8.0.0: + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} - dependencies: - flat-cache: 4.0.1 - dev: true - /file-saver@2.0.5: + file-entry-cache@9.1.0: + resolution: {integrity: sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==} + engines: {node: '>=18'} + + file-saver@2.0.5: resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==} - dev: false - /filelist@1.0.4: + filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - dependencies: - minimatch: 5.1.6 - dev: true - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + filing-cabinet@5.0.2: + resolution: {integrity: sha512-RZlFj8lzyu6jqtFBeXNqUjjNG6xm+gwXue3T70pRxw1W40kJwlgq0PSWAmh0nAnn5DHuBIecLXk9+1VKS9ICXA==} + engines: {node: '>=18'} + hasBin: true + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - /finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - /find-cache-dir@3.3.2: + finalhandler@2.1.0: + resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} + engines: {node: '>= 0.8'} + + find-cache-dir@3.3.2: resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} engines: {node: '>=8'} - dependencies: - commondir: 1.0.1 - make-dir: 3.1.0 - pkg-dir: 4.2.0 - dev: true - /find-cache-dir@4.0.0: + find-cache-dir@4.0.0: resolution: {integrity: sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==} engines: {node: '>=14.16'} - dependencies: - common-path-prefix: 3.0.0 - pkg-dir: 7.0.0 - dev: true - /find-my-way@4.5.1: - resolution: {integrity: sha512-kE0u7sGoUFbMXcOG/xpkmz4sRLCklERnBcg7Ftuu1iAxsfEt2S46RLJ3Sq7vshsEy2wJT2hZxE58XZK27qa8kg==} - engines: {node: '>=10'} - dependencies: - fast-decode-uri-component: 1.0.1 - fast-deep-equal: 3.1.3 - safe-regex2: 2.0.0 - semver-store: 0.3.0 - dev: true - - /find-process@1.4.7: - resolution: {integrity: sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==} + find-cypress-specs@1.47.9: + resolution: {integrity: sha512-sB1q4aDq9eqaeCqWdr4wHUk6gpXNfa2HoZDsZxT+MZcC4nTw6kU+t9KpFIHudSRGXsQF/3xpdTGWKmgAgaDtyA==} + engines: {node: '>=18'} hasBin: true - dependencies: - chalk: 4.1.2 - commander: 5.1.0 - debug: 4.3.4(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - dev: true - /find-up-simple@1.0.0: + find-my-way@8.2.2: + resolution: {integrity: sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA==} + engines: {node: '>=14'} + + find-process@1.4.10: + resolution: {integrity: sha512-ncYFnWEIwL7PzmrK1yZtaccN8GhethD37RzBHG6iOZoFYB4vSmLLXfeWJjeN5nMvCJMjOtBvBBF8OgxEcikiZg==} + hasBin: true + + find-test-names@1.29.5: + resolution: {integrity: sha512-PsD3qx5miZKhT/766UGAgmApU8NwGAqUKPwIRVOuYgjKHOvWzL5OYbHJIhKC0nVvhVedIOvH1SwJG/Df8EN/8w==} + hasBin: true + + find-up-simple@1.0.0: resolution: {integrity: sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==} engines: {node: '>=18'} - dev: true - /find-up@3.0.0: + find-up@3.0.0: resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} engines: {node: '>=6'} - dependencies: - locate-path: 3.0.0 - dev: true - /find-up@4.1.0: + find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - /find-up@5.0.0: + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - /find-up@6.3.0: + find-up@6.3.0: resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - locate-path: 7.2.0 - path-exists: 5.0.0 - dev: true - /flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - dev: true - - /flat-cache@4.0.1: + flat-cache@4.0.1: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - dev: true - /flatstr@1.0.12: - resolution: {integrity: sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==} - dev: true + flat-cache@5.0.0: + resolution: {integrity: sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==} + engines: {node: '>=18'} - /flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - dev: true + flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true - /flexsearch@0.7.43: + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + flexsearch@0.7.43: resolution: {integrity: sha512-c5o/+Um8aqCSOXGcZoqZOm+NqtVwNsvVpWv6lfmSclU954O3wvQKxxK8zj74fPaSJbXpSLTs4PRhh+wnoCXnKg==} - dev: true - /focus-trap@7.5.4: - resolution: {integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==} - dependencies: - tabbable: 6.2.0 - dev: true + focus-trap@7.6.4: + resolution: {integrity: sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw==} - /follow-redirects@1.15.5(debug@4.3.4): - resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} peerDependencies: debug: '*' peerDependenciesMeta: debug: optional: true - dependencies: - debug: 4.3.4(supports-color@8.1.1) - dev: true - /font-awesome@4.7.0: + font-awesome@4.7.0: resolution: {integrity: sha512-U6kGnykA/6bFmg1M/oT9EkFeIYv7JlX3bozwQJWiiLz6L0w3F5vBVPxHlwyX/vtNq1ckcpRKOB9f2Qal/VtFpg==} engines: {node: '>=0.10.3'} - dev: false - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.7 - dev: true + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} - /foreground-child@2.0.0: + foreground-child@2.0.0: resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} engines: {node: '>=8.0.0'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 3.0.7 - dev: true - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - /forever-agent@0.6.1: + forever-agent@0.6.1: resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} - dev: true - /form-data@2.3.3: - resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} - engines: {node: '>= 0.12'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: true - - /form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: true - /format@0.2.2: + format@0.2.2: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} - dev: true - /formdata-polyfill@4.0.10: + formdata-polyfill@4.0.10: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} engines: {node: '>=12.20.0'} - dependencies: - fetch-blob: 3.2.0 - dev: true - /forwarded@0.2.0: + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} - dev: true - /fresh@0.5.2: + fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} - dev: true - /from@0.1.7: + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + + from@0.1.7: resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} - dev: true - /fromentries@1.3.2: + fromentries@1.3.2: resolution: {integrity: sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==} - dev: true - /fs-extra@11.1.1: + fs-extra@11.1.1: resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} engines: {node: '>=14.14'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - dev: true - /fs-extra@11.2.0: + fs-extra@11.2.0: resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} engines: {node: '>=14.14'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - dev: true - /fs-extra@7.0.1: + fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - dev: true - /fs-extra@9.1.0: + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@9.1.0: resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} engines: {node: '>=10'} - dependencies: - at-least-node: 1.0.0 - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - dev: true - /fs-monkey@1.0.4: - resolution: {integrity: sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==} - dev: true + fs-monkey@1.0.6: + resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==} - /fs.realpath@1.0.0: + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - /fsevents@2.3.3: + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - requiresBuild: true - optional: true - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true - - /function-bind@1.1.2: + function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - /function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - functions-have-names: 1.2.3 - dev: true - /functions-have-names@1.2.3: + functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true - /gensequence@7.0.0: + gensequence@7.0.0: resolution: {integrity: sha512-47Frx13aZh01afHJTB3zTtKIlFI6vWY+MYCN9Qpew6i52rfKjnhCF/l1YlC8UmEMvvntZZ6z4PiCcmyuedR2aQ==} engines: {node: '>=18'} - dev: true - /gensync@1.0.0-beta.2: + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - dev: true - /get-caller-file@2.0.5: + get-amd-module-type@6.0.0: + resolution: {integrity: sha512-hFM7oivtlgJ3d6XWD6G47l8Wyh/C6vFw5G24Kk1Tbq85yh5gcM8Fne5/lFhiuxB+RT6+SI7I1ThB9lG4FBh3jw==} + engines: {node: '>=18'} + + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - dev: true - /get-east-asian-width@1.2.0: - resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} engines: {node: '>=18'} - dev: true - /get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - dev: true - - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + get-intrinsic@1.2.7: + resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==} engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - dev: true - /get-own-enumerable-property-symbols@3.0.2: + get-own-enumerable-property-symbols@3.0.2: resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} - dev: true - /get-package-type@0.1.0: + get-package-type@0.1.0: resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} engines: {node: '>=8.0.0'} - dev: true - /get-stdin@5.0.1: + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stdin@5.0.1: resolution: {integrity: sha512-jZV7n6jGE3Gt7fgSTJoz91Ak5MuTLwMwkoYdjxuJ/AmjIsE1UC03y/IWkZCQGEvVNS9qoRNwy5BCqxImv0FVeA==} engines: {node: '>=0.12.0'} - dev: true - /get-stdin@8.0.0: - resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==} - engines: {node: '>=10'} - dev: true - - /get-stdin@9.0.0: + get-stdin@9.0.0: resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} engines: {node: '>=12'} - dev: true - /get-stream@4.1.0: + get-stream@4.1.0: resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} engines: {node: '>=6'} - dependencies: - pump: 3.0.0 - dev: true - /get-stream@5.2.0: + get-stream@5.2.0: resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} engines: {node: '>=8'} - dependencies: - pump: 3.0.0 - dev: true - /get-stream@6.0.1: + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - dev: true - /get-stream@8.0.1: + get-stream@8.0.1: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} - dev: true - /get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - dev: true - /get-tsconfig@4.7.3: - resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==} - dependencies: - resolve-pkg-maps: 1.0.0 - dev: true + get-tsconfig@4.8.1: + resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==} - /getos@3.2.1: + getos@3.2.1: resolution: {integrity: sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==} - dependencies: - async: 3.2.5 - dev: true - /getpass@0.1.7: + getpass@0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} - dependencies: - assert-plus: 1.0.0 - dev: true - /github-slugger@2.0.0: + github-slugger@2.0.0: resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} - dev: true - /glob-parent@5.1.2: + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - /glob-parent@6.0.2: + glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - /glob-promise@4.2.2(glob@7.2.3): - resolution: {integrity: sha512-xcUzJ8NWN5bktoTIX7eOclO1Npxd/dyVqUJxlLIDasT4C7KZyqlPIwkdJ0Ypiy3p2ZKahTjK4M9uC3sNSfNMzw==} - engines: {node: '>=12'} - peerDependencies: - glob: ^7.1.6 - dependencies: - '@types/glob': 7.2.0 - glob: 7.2.3 - dev: true - - /glob-to-regexp@0.4.1: + glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - dev: true - /glob@10.3.10: - resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} - engines: {node: '>=16 || 14 >=14.17'} + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.3 - minipass: 7.0.4 - path-scurry: 1.10.1 - dev: true - /glob@10.3.12: - resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} - engines: {node: '>=16 || 14 >=14.17'} + glob@11.0.1: + resolution: {integrity: sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==} + engines: {node: 20 || >=22} hasBin: true - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.4 - minipass: 7.0.4 - path-scurry: 1.10.2 - dev: false - /glob@7.2.3: + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true + deprecated: Glob versions prior to v9 are no longer supported - /glob@8.1.0: + glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - dev: true + deprecated: Glob versions prior to v9 are no longer supported - /global-directory@4.0.1: + global-directory@4.0.1: resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} engines: {node: '>=18'} - dependencies: - ini: 4.1.1 - dev: true - /global-dirs@3.0.1: + global-dirs@3.0.1: resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} engines: {node: '>=10'} - dependencies: - ini: 2.0.0 - dev: true - /globals@11.12.0: + globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - dev: true - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + globals@15.15.0: + resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} + engines: {node: '>=18'} + + globals@16.0.0: + resolution: {integrity: sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - dev: true - /globby@11.1.0: + globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - /globby@13.2.2: + globby@13.2.2: resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 4.0.0 - dev: true - /globby@14.0.1: - resolution: {integrity: sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==} + globby@14.1.0: + resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==} engines: {node: '>=18'} - dependencies: - '@sindresorhus/merge-streams': 2.3.0 - fast-glob: 3.3.2 - ignore: 5.3.1 - path-type: 5.0.0 - slash: 5.1.0 - unicorn-magic: 0.1.0 - dev: true - /glur@1.1.2: + glur@1.1.2: resolution: {integrity: sha512-l+8esYHTKOx2G/Aao4lEQ0bnHWg4fWtJbVoZZT9Knxi01pB8C80BR85nONLFwkkQoFRCmXY+BUcGZN3yZ2QsRA==} - dev: true - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.4 - dev: true + gonzales-pe@4.3.0: + resolution: {integrity: sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==} + engines: {node: '>=0.6.0'} + hasBin: true - /got@11.8.6: + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + got@11.8.6: resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} engines: {node: '>=10.19.0'} - dependencies: - '@sindresorhus/is': 4.6.0 - '@szmarczak/http-timer': 4.0.6 - '@types/cacheable-request': 6.0.3 - '@types/responselike': 1.0.3 - cacheable-lookup: 5.0.4 - cacheable-request: 7.0.4 - decompress-response: 6.0.0 - http2-wrapper: 1.0.3 - lowercase-keys: 2.0.0 - p-cancelable: 2.1.1 - responselike: 2.0.1 - dev: true - /graceful-fs@4.2.11: + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: true - /graphemer@1.4.0: + graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true - /gzip-size@6.0.0: + gzip-size@6.0.0: resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} engines: {node: '>=10'} - dependencies: - duplexer: 0.1.2 - dev: true - /handle-thing@2.0.1: + hachure-fill@0.5.2: + resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} + + handle-thing@2.0.1: resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} - dev: true - /handlebars@4.7.8: - resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} - engines: {node: '>=0.4.7'} - hasBin: true - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.17.4 - dev: true - - /has-ansi@2.0.0: + has-ansi@2.0.0: resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} engines: {node: '>=0.10.0'} - dependencies: - ansi-regex: 2.1.1 - dev: true - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} - /has-flag@3.0.0: + has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} - dev: true - /has-flag@4.0.0: + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - /has-own-prop@2.0.0: + has-own-prop@2.0.0: resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==} engines: {node: '>=8'} - dev: true - /has-property-descriptors@1.0.2: + has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - dependencies: - es-define-property: 1.0.0 - dev: true - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} engines: {node: '>= 0.4'} - dev: true - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} - dev: true - /has-tostringtag@1.0.2: + has-tostringtag@1.0.2: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - dependencies: - function-bind: 1.1.1 - dev: true - - /hasha@5.2.2: + hasha@5.2.2: resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} engines: {node: '>=8'} - dependencies: - is-stream: 2.0.1 - type-fest: 0.8.1 - dev: true - /hasown@2.0.2: + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - /heap@0.2.7: - resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} - dev: false + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} - /highlight.js@10.7.3: + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + highlight.js@10.7.3: resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} - dev: false - /hookable@5.5.3: + hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} - dev: true - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true + hosted-git-info@7.0.2: + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} + engines: {node: ^16.14.0 || >=18.0.0} - /hpack.js@2.1.6: + hpack.js@2.1.6: resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} - dependencies: - inherits: 2.0.4 - obuf: 1.1.2 - readable-stream: 2.3.8 - wbuf: 1.7.3 - dev: true - /html-encoding-sniffer@4.0.0: + html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} - dependencies: - whatwg-encoding: 3.1.1 - dev: true - /html-entities@2.4.0: - resolution: {integrity: sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==} - dev: true + html-entities@2.5.2: + resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} - /html-escaper@2.0.2: + html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - dev: true - /html-to-image@1.11.11: - resolution: {integrity: sha512-9gux8QhvjRO/erSnDPv28noDZcPZmYE7e1vFsBLKLlRlKDSqNJYebj6Qz1TGd5lsRV+X+xYyjCKjuZdABinWjA==} - dev: false + html-to-image@1.11.13: + resolution: {integrity: sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==} - /htmlparser2@9.1.0: + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + htmlparser2@9.1.0: resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.1.0 - entities: 4.5.0 - dev: true - /http-cache-semantics@4.1.1: + http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - dev: true - /http-deceiver@1.2.7: + http-deceiver@1.2.7: resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} - dev: true - /http-errors@1.6.3: + http-errors@1.6.3: resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==} engines: {node: '>= 0.6'} - dependencies: - depd: 1.1.2 - inherits: 2.0.3 - setprototypeof: 1.1.0 - statuses: 1.5.0 - dev: true - /http-errors@2.0.0: + http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: true - /http-parser-js@0.5.8: + http-parser-js@0.5.8: resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} - dev: true - /http-proxy-agent@5.0.0: + http-proxy-agent@5.0.0: resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} engines: {node: '>= 6'} - dependencies: - '@tootallnate/once': 2.0.0 - agent-base: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - dev: true - /http-proxy-agent@7.0.2: + http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.0 - debug: 4.3.4(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - dev: true - /http-proxy-middleware@2.0.6(@types/express@4.17.21): - resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} + http-proxy-middleware@2.0.7: + resolution: {integrity: sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==} engines: {node: '>=12.0.0'} peerDependencies: '@types/express': ^4.17.13 peerDependenciesMeta: '@types/express': optional: true - dependencies: - '@types/express': 4.17.21 - '@types/http-proxy': 1.17.11 - http-proxy: 1.18.1 - is-glob: 4.0.3 - is-plain-obj: 3.0.0 - micromatch: 4.0.5 - transitivePeerDependencies: - - debug - dev: true - /http-proxy@1.18.1: + http-proxy@1.18.1: resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} engines: {node: '>=8.0.0'} - dependencies: - eventemitter3: 4.0.7 - follow-redirects: 1.15.5(debug@4.3.4) - requires-port: 1.0.0 - transitivePeerDependencies: - - debug - dev: true - /http-signature@1.3.6: - resolution: {integrity: sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==} + http-signature@1.4.0: + resolution: {integrity: sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==} engines: {node: '>=0.10'} - dependencies: - assert-plus: 1.0.0 - jsprim: 2.0.2 - sshpk: 1.18.0 - dev: true - /http2-wrapper@1.0.3: + http2-wrapper@1.0.3: resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} engines: {node: '>=10.19.0'} - dependencies: - quick-lru: 5.1.1 - resolve-alpn: 1.2.1 - dev: true - /https-localhost@4.7.1: + https-localhost@4.7.1: resolution: {integrity: sha512-rl+NFV0l67/0W7fZwk4LB5gS6HdhtSFLpCpf1N+KD5WQAXtPXX1QE8H0cP8VNJii18rtpTkE9eAHdUfJ0goAnQ==} hasBin: true - dependencies: - appdata-path: 1.0.0 - compression: 1.7.4 - cors: 2.8.5 - express: 4.18.2 - spdy: 4.0.2 - uglify-js: 3.17.4 - transitivePeerDependencies: - - supports-color - dev: true - /https-proxy-agent@5.0.1: + https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - dev: true - /https-proxy-agent@7.0.4: - resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} - dependencies: - agent-base: 7.1.0 - debug: 4.3.4(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - dev: true - /human-signals@1.1.1: + human-id@4.1.1: + resolution: {integrity: sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg==} + hasBin: true + + human-signals@1.1.1: resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} engines: {node: '>=8.12.0'} - dev: true - /human-signals@2.1.0: + human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} - dev: true - /human-signals@5.0.0: + human-signals@5.0.0: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - dev: true - /husky@9.0.11: - resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} + humanize-duration@3.32.1: + resolution: {integrity: sha512-inh5wue5XdfObhu/IGEMiA1nUXigSGcaKNemcbLRKa7jXYGDZXr3LoT9pTIzq2hPEbld7w/qv9h+ikWGz8fL1g==} + + husky@9.1.7: + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} engines: {node: '>=18'} hasBin: true - dev: true - /iconv-lite@0.4.24: + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - /iconv-lite@0.6.3: + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - /idb@7.1.1: + idb@7.1.1: resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} - dev: true - /ieee754@1.2.1: + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - dev: true - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + ignore@7.0.3: + resolution: {integrity: sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - /import-local@3.1.0: - resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} engines: {node: '>=8'} hasBin: true - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - dev: true - /import-meta-resolve@4.0.0: - resolution: {integrity: sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==} - dev: true + import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} - /imurmurhash@0.1.4: + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - dev: true - /indent-string@4.0.0: + indent-string@4.0.0: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} - dev: true - /indent-string@5.0.0: + indent-string@5.0.0: resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} engines: {node: '>=12'} - dev: true - /inflight@1.0.6: + index-to-position@0.1.2: + resolution: {integrity: sha512-MWDKS3AS1bGCHLBA2VLImJz42f7bJh8wQsTGCzI3j519/CASStoDONUBVz2I/VID0MpiX3SGSnbOD2xUalbE5g==} + engines: {node: '>=18'} + + inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - /inherits@2.0.3: + inherits@2.0.3: resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} - dev: true - /inherits@2.0.4: + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - /ini@2.0.0: + ini@2.0.0: resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} engines: {node: '>=10'} - dev: true - /ini@3.0.1: + ini@3.0.1: resolution: {integrity: sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dev: true - /ini@4.1.1: + ini@4.1.1: resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true - /internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.0.6 - dev: true - /internmap@1.0.1: + internmap@1.0.1: resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} - dev: false - /internmap@2.0.3: + internmap@2.0.3: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} - dev: false - /interpret@2.2.0: + interpret@1.4.0: + resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} + engines: {node: '>= 0.10'} + + interpret@2.2.0: resolution: {integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==} engines: {node: '>= 0.10'} - dev: true - /ipaddr.js@1.9.1: + ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - dev: true - /ipaddr.js@2.1.0: - resolution: {integrity: sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==} + ipaddr.js@2.2.0: + resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} engines: {node: '>= 10'} - dev: true - /is-alphabetical@1.0.4: + is-alphabetical@1.0.4: resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} - dev: true - /is-alphanumerical@1.0.4: + is-alphanumerical@1.0.4: resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==} - dependencies: - is-alphabetical: 1.0.4 - is-decimal: 1.0.4 - dev: true - /is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - dev: true - /is-arrayish@0.2.1: + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - /is-arrayish@0.3.2: + is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - dev: false - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - dev: true + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} - /is-binary-path@2.1.0: + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} - dependencies: - binary-extensions: 2.2.0 - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - dev: true - /is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - dependencies: - builtin-modules: 3.3.0 - dev: true + is-builtin-module@5.0.0: + resolution: {integrity: sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==} + engines: {node: '>=18.20'} - /is-callable@1.2.7: + is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - dev: true - /is-ci@3.0.1: - resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} - hasBin: true - dependencies: - ci-info: 3.9.0 - dev: true - - /is-core-module@2.13.0: - resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} - dependencies: - has: 1.0.3 - dev: true - - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - dependencies: - hasown: 2.0.2 - - /is-data-view@1.0.1: - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} - dependencies: - is-typed-array: 1.1.13 - dev: true - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - /is-decimal@1.0.4: + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-decimal@1.0.4: resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} - dev: true - /is-docker@2.2.1: + is-docker@2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} hasBin: true - dev: true - /is-extglob@2.1.1: + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - /is-fullwidth-code-point@3.0.0: + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - /is-fullwidth-code-point@4.0.0: + is-fullwidth-code-point@4.0.0: resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} engines: {node: '>=12'} - dev: true - /is-fullwidth-code-point@5.0.0: + is-fullwidth-code-point@5.0.0: resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} engines: {node: '>=18'} - dependencies: - get-east-asian-width: 1.2.0 - dev: true - /is-generator-fn@2.1.0: + is-generator-fn@2.1.0: resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} engines: {node: '>=6'} - dev: true - /is-glob@4.0.3: + is-generator-function@1.1.0: + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - /is-hexadecimal@1.0.4: + is-hexadecimal@1.0.4: resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} - dev: true - /is-installed-globally@0.4.0: + is-installed-globally@0.4.0: resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} engines: {node: '>=10'} - dependencies: - global-dirs: 3.0.1 - is-path-inside: 3.0.3 - dev: true - /is-localhost-ip@2.0.0: + is-localhost-ip@2.0.0: resolution: {integrity: sha512-vlgs2cSgMOfnKU8c1ewgKPyum9rVrjjLLW2HBdL5i0iAJjOs8NY55ZBd/hqUTaYR0EO9CKZd3hVSC2HlIbygTQ==} engines: {node: '>=12'} - dev: true - /is-module@1.0.0: + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - dev: true - /is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} - dev: true - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-number@7.0.0: + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - /is-obj@1.0.1: + is-obj@1.0.1: resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==} engines: {node: '>=0.10.0'} - dev: true - /is-obj@2.0.0: - resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} - engines: {node: '>=8'} - dev: true - - /is-path-inside@3.0.3: + is-path-inside@3.0.3: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} - dev: true - /is-plain-obj@3.0.0: + is-plain-obj@3.0.0: resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} engines: {node: '>=10'} - dev: true - /is-plain-obj@4.1.0: + is-plain-obj@4.1.0: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} - dev: true - /is-plain-object@2.0.4: + is-plain-object@2.0.4: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - dev: true - /is-potential-custom-element-name@1.0.1: + is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - dev: true - /is-promise@2.2.2: - resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} - dev: true + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - dev: true - /is-regexp@1.0.0: + is-regexp@1.0.0: resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==} engines: {node: '>=0.10.0'} - dev: true - /is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - dev: true - /is-stream@1.1.0: + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-stream@1.1.0: resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} engines: {node: '>=0.10.0'} - dev: true - /is-stream@2.0.1: + is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - dev: true - /is-stream@3.0.0: + is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - /is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} - dependencies: - which-typed-array: 1.1.15 - dev: true - /is-typedarray@1.0.0: + is-typedarray@1.0.0: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - dev: true - /is-unicode-supported@0.1.0: + is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} - dev: true - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.7 - dev: true + is-url-superb@4.0.0: + resolution: {integrity: sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA==} + engines: {node: '>=10'} - /is-windows@1.0.2: + is-url@1.2.4: + resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.3: + resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} + engines: {node: '>= 0.4'} + + is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + + is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} - dev: true - /is-wsl@2.2.0: + is-wsl@2.2.0: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - dev: true - /isarray@1.0.0: + isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true - /isarray@2.0.5: + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true - /isexe@2.0.0: + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - /isobject@3.0.1: + isobject@3.0.1: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} - dev: true - /isstream@0.1.2: + isstream@0.1.2: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} - dev: true - /istanbul-lib-coverage@3.2.0: - resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} - engines: {node: '>=8'} - dev: true - - /istanbul-lib-coverage@3.2.2: + istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} - dev: true - /istanbul-lib-hook@3.0.0: + istanbul-lib-hook@3.0.0: resolution: {integrity: sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==} engines: {node: '>=8'} - dependencies: - append-transform: 2.0.0 - dev: true - /istanbul-lib-instrument@4.0.3: + istanbul-lib-instrument@4.0.3: resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==} engines: {node: '>=8'} - dependencies: - '@babel/core': 7.24.4 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.0 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - /istanbul-lib-instrument@5.2.1: + istanbul-lib-instrument@5.2.1: resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} engines: {node: '>=8'} - dependencies: - '@babel/core': 7.24.4 - '@babel/parser': 7.24.4 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - /istanbul-lib-instrument@6.0.2: - resolution: {integrity: sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==} + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} engines: {node: '>=10'} - dependencies: - '@babel/core': 7.24.4 - '@babel/parser': 7.24.4 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - dev: true - /istanbul-lib-processinfo@2.0.3: + istanbul-lib-processinfo@2.0.3: resolution: {integrity: sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==} engines: {node: '>=8'} - dependencies: - archy: 1.0.0 - cross-spawn: 7.0.3 - istanbul-lib-coverage: 3.2.0 - p-map: 3.0.0 - rimraf: 3.0.2 - uuid: 8.3.2 - dev: true - /istanbul-lib-report@3.0.1: + istanbul-lib-report@3.0.1: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} - dependencies: - istanbul-lib-coverage: 3.2.2 - make-dir: 4.0.0 - supports-color: 7.2.0 - dev: true - /istanbul-lib-source-maps@4.0.1: + istanbul-lib-source-maps@4.0.1: resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} engines: {node: '>=10'} - dependencies: - debug: 4.3.4(supports-color@8.1.1) - istanbul-lib-coverage: 3.2.0 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - dev: true - /istanbul-lib-source-maps@5.0.4: - resolution: {integrity: sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==} + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} engines: {node: '>=10'} - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - debug: 4.3.4(supports-color@8.1.1) - istanbul-lib-coverage: 3.2.2 - transitivePeerDependencies: - - supports-color - dev: true - /istanbul-reports@3.1.6: - resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} - engines: {node: '>=8'} - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.1 - dev: true - - /istanbul-reports@3.1.7: + istanbul-reports@3.1.7: resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} engines: {node: '>=8'} - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.1 - dev: true - /iterm2-version@4.2.0: + iterm2-version@4.2.0: resolution: {integrity: sha512-IoiNVk4SMPu6uTcK+1nA5QaHNok2BMDLjSl5UomrOixe5g4GkylhPwuiGdw00ysSCrXAKNMfFTu+u/Lk5f6OLQ==} engines: {node: '>=8'} - dependencies: - app-path: 3.3.0 - plist: 3.1.0 - dev: true - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - /jake@10.8.7: - resolution: {integrity: sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==} + jackspeak@4.0.3: + resolution: {integrity: sha512-oSwM7q8PTHQWuZAlp995iPpPJ4Vkl7qT0ZRD+9duL9j2oBy6KcTfyxc8mEuHJYC+z/kbps80aJLkaNzTOrf/kw==} + engines: {node: 20 || >=22} + + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} engines: {node: '>=10'} hasBin: true - dependencies: - async: 3.2.5 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - dev: true - /jest-changed-files@29.7.0: + jest-changed-files@29.7.0: resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - execa: 5.1.1 - jest-util: 29.7.0 - p-limit: 3.1.0 - dev: true - /jest-circus@29.7.0: + jest-circus@29.7.0: resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.12.7 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.5.1 - is-generator-fn: 2.1.0 - jest-each: 29.7.0 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - p-limit: 3.1.0 - pretty-format: 29.7.0 - pure-rand: 6.0.4 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - dev: true - /jest-cli@29.7.0(@types/node@20.12.7): + jest-cli@29.7.0: resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -10494,26 +6580,8 @@ packages: peerDependenciesMeta: node-notifier: optional: true - dependencies: - '@jest/core': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.12.7) - exit: 0.1.2 - import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.12.7) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - dev: true - /jest-config@29.7.0(@types/node@20.12.7): + jest-config@29.7.0: resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -10524,160 +6592,54 @@ packages: optional: true ts-node: optional: true - dependencies: - '@babel/core': 7.24.4 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.12.7 - babel-jest: 29.7.0(@babel/core@7.24.4) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.5 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - dev: true - /jest-diff@29.7.0: + jest-diff@29.7.0: resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - diff-sequences: 29.6.3 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - dev: true - /jest-docblock@29.7.0: + jest-docblock@29.7.0: resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - detect-newline: 3.1.0 - dev: true - /jest-each@29.7.0: + jest-each@29.7.0: resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - jest-get-type: 29.6.3 - jest-util: 29.7.0 - pretty-format: 29.7.0 - dev: true - /jest-environment-node@29.7.0: + jest-environment-node@29.7.0: resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.12.7 - jest-mock: 29.7.0 - jest-util: 29.7.0 - dev: true - /jest-get-type@29.6.3: + jest-get-type@29.6.3: resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - /jest-haste-map@29.7.0: + jest-haste-map@29.7.0: resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.9 - '@types/node': 20.12.7 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.11 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - jest-worker: 29.7.0 - micromatch: 4.0.5 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.3 - dev: true - /jest-image-snapshot@4.2.0(jest@29.7.0): + jest-image-snapshot@4.2.0: resolution: {integrity: sha512-6aAqv2wtfOgxiJeBayBCqHo1zX+A12SUNNzo7rIxiXh6W6xYVu8QyHWkada8HeRi+QUTHddp0O0Xa6kmQr+xbQ==} engines: {node: '>= 10.14.2'} peerDependencies: jest: '>=20 <=26' - dependencies: - chalk: 1.1.3 - get-stdin: 5.0.1 - glur: 1.1.2 - jest: 29.7.0(@types/node@20.12.7) - lodash: 4.17.21 - mkdirp: 0.5.6 - pixelmatch: 5.3.0 - pngjs: 3.4.0 - rimraf: 2.7.1 - ssim.js: 3.5.0 - dev: true - /jest-leak-detector@29.7.0: + jest-leak-detector@29.7.0: resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - dev: true - /jest-matcher-utils@29.7.0: + jest-matcher-utils@29.7.0: resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - dev: true - /jest-message-util@29.7.0: + jest-message-util@29.7.0: resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/code-frame': 7.24.2 - '@jest/types': 29.6.3 - '@types/stack-utils': 2.0.3 - chalk: 4.1.2 - graceful-fs: 4.2.11 - micromatch: 4.0.5 - pretty-format: 29.7.0 - slash: 3.0.0 - stack-utils: 2.0.6 - dev: true - /jest-mock@29.7.0: + jest-mock@29.7.0: resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 20.12.7 - jest-util: 29.7.0 - dev: true - /jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + jest-pnp-resolver@1.2.3: resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} engines: {node: '>=6'} peerDependencies: @@ -10685,194 +6647,52 @@ packages: peerDependenciesMeta: jest-resolve: optional: true - dependencies: - jest-resolve: 29.7.0 - dev: true - /jest-regex-util@29.6.3: + jest-regex-util@29.6.3: resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - /jest-resolve-dependencies@29.7.0: + jest-resolve-dependencies@29.7.0: resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-regex-util: 29.6.3 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - dev: true - /jest-resolve@29.7.0: + jest-resolve@29.7.0: resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - resolve: 1.22.8 - resolve.exports: 2.0.2 - slash: 3.0.0 - dev: true - /jest-runner@29.7.0: + jest-runner@29.7.0: resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.7.0 - '@jest/environment': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.12.7 - chalk: 4.1.2 - emittery: 0.13.1 - graceful-fs: 4.2.11 - jest-docblock: 29.7.0 - jest-environment-node: 29.7.0 - jest-haste-map: 29.7.0 - jest-leak-detector: 29.7.0 - jest-message-util: 29.7.0 - jest-resolve: 29.7.0 - jest-runtime: 29.7.0 - jest-util: 29.7.0 - jest-watcher: 29.7.0 - jest-worker: 29.7.0 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color - dev: true - /jest-runtime@29.7.0: + jest-runtime@29.7.0: resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/globals': 29.7.0 - '@jest/source-map': 29.6.3 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.12.7 - chalk: 4.1.2 - cjs-module-lexer: 1.2.3 - collect-v8-coverage: 1.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: true - /jest-snapshot@29.7.0: + jest-snapshot@29.7.0: resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.24.4 - '@babel/generator': 7.24.4 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.4) - '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.4) - '@babel/types': 7.24.0 - '@jest/expect-utils': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.4) - chalk: 4.1.2 - expect: 29.7.0 - graceful-fs: 4.2.11 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - natural-compare: 1.4.0 - pretty-format: 29.7.0 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - dev: true - /jest-util@29.7.0: + jest-util@29.7.0: resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 20.12.7 - chalk: 4.1.2 - ci-info: 3.9.0 - graceful-fs: 4.2.11 - picomatch: 2.3.1 - dev: true - /jest-validate@29.7.0: + jest-validate@29.7.0: resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 29.6.3 - leven: 3.1.0 - pretty-format: 29.7.0 - dev: true - /jest-watcher@29.7.0: + jest-watcher@29.7.0: resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.12.7 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 29.7.0 - string-length: 4.0.2 - dev: true - /jest-worker@26.6.2: - resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} - engines: {node: '>= 10.13.0'} - dependencies: - '@types/node': 20.12.7 - merge-stream: 2.0.0 - supports-color: 7.2.0 - dev: true - - /jest-worker@27.5.1: + jest-worker@27.5.1: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} - dependencies: - '@types/node': 20.12.7 - merge-stream: 2.0.0 - supports-color: 8.1.1 - dev: true - /jest-worker@29.7.0: + jest-worker@29.7.0: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@types/node': 20.12.7 - jest-util: 29.7.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - dev: true - /jest@29.7.0(@types/node@20.12.7): + jest@29.7.0: resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -10881,412 +6701,224 @@ packages: peerDependenciesMeta: node-notifier: optional: true - dependencies: - '@jest/core': 29.7.0 - '@jest/types': 29.6.3 - import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.12.7) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - dev: true - /jison-lex@0.3.4: + jison-lex@0.3.4: resolution: {integrity: sha512-EBh5wrXhls1cUwROd5DcDHR1sG7CdsCFSqY1027+YA1RGxz+BX2TDLAhdsQf40YEtFDGoiO0Qm8PpnBl2EzDJw==} engines: {node: '>=0.4'} hasBin: true - dependencies: - lex-parser: 0.1.4 - nomnom: 1.5.2 - dev: true - /jison@0.4.18: + jison@0.4.18: resolution: {integrity: sha512-FKkCiJvozgC7VTHhMJ00a0/IApSxhlGsFIshLW6trWJ8ONX2TQJBBz6DlcO1Gffy4w9LT+uL+PA+CVnUSJMF7w==} engines: {node: '>=0.4'} hasBin: true - dependencies: - JSONSelect: 0.4.0 - cjson: 0.3.0 - ebnf-parser: 0.1.10 - escodegen: 1.3.3 - esprima: 1.1.1 - jison-lex: 0.3.4 - lex-parser: 0.1.4 - nomnom: 1.5.2 - dev: true - /jiti@1.21.0: - resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + jiti@1.21.7: + resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} hasBin: true - /jju@1.4.0: + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + + jju@1.4.0: resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} - dev: true - /joi@17.12.2: - resolution: {integrity: sha512-RonXAIzCiHLc8ss3Ibuz45u28GOsWE1UpfDXLbN/9NKbL4tCJf8TWYVKsoYuuh+sAUt7fsSNpA+r2+TBA6Wjmw==} - dependencies: - '@hapi/hoek': 9.3.0 - '@hapi/topo': 5.1.0 - '@sideway/address': 4.1.5 - '@sideway/formula': 3.0.1 - '@sideway/pinpoint': 2.0.0 - dev: true + joi@17.13.3: + resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} - /jpeg-js@0.4.4: + jpeg-js@0.4.4: resolution: {integrity: sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==} - dev: true - /js-base64@3.7.7: + js-base64@3.7.7: resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} - dev: true - /js-tokens@4.0.0: + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true - /js-tokens@9.0.0: - resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} - dev: true - - /js-yaml@3.14.1: + js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - dev: true - /js-yaml@4.1.0: + js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - /jsbn@0.1.1: + jsbn@0.1.1: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} - dev: true - /jsdoc-type-pratt-parser@4.0.0: - resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} + jsdoc-type-pratt-parser@4.1.0: + resolution: {integrity: sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==} engines: {node: '>=12.0.0'} - dev: true - /jsdom@24.0.0: - resolution: {integrity: sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==} + jsdom@26.0.0: + resolution: {integrity: sha512-BZYDGVAIriBWTpIxYzrXjv3E/4u8+/pSG5bQdIYCbNCGOvsPkDQfTVLAIXAf9ETdCpduCVTkDe2NNZ8NIwUVzw==} engines: {node: '>=18'} peerDependencies: - canvas: ^2.11.2 + canvas: ^3.0.0 peerDependenciesMeta: canvas: optional: true - dependencies: - cssstyle: 4.0.1 - data-urls: 5.0.0 - decimal.js: 10.4.3 - form-data: 4.0.0 - html-encoding-sniffer: 4.0.0 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.4 - is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.7 - parse5: 7.1.2 - rrweb-cssom: 0.6.0 - saxes: 6.0.0 - symbol-tree: 3.2.4 - tough-cookie: 4.1.3 - w3c-xmlserializer: 5.0.0 - webidl-conversions: 7.0.0 - whatwg-encoding: 3.1.1 - whatwg-mimetype: 4.0.0 - whatwg-url: 14.0.0 - ws: 8.16.0 - xml-name-validator: 5.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - /jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /jsesc@3.0.2: + jsesc@3.0.2: resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} engines: {node: '>=6'} hasBin: true - dev: true - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json-schema-to-typescript@13.1.2: - resolution: {integrity: sha512-17G+mjx4nunvOpkPvcz7fdwUwYCEwyH8vR3Ym3rFiQ8uzAL3go+c1306Kk7iGRk8HuXBXqy+JJJmpYl0cvOllw==} - engines: {node: '>=12.0.0'} + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} hasBin: true - dependencies: - '@bcherny/json-schema-ref-parser': 10.0.5-fork - '@types/json-schema': 7.0.15 - '@types/lodash': 4.17.0 - '@types/prettier': 2.7.3 - cli-color: 2.0.4 - get-stdin: 8.0.0 - glob: 7.2.3 - glob-promise: 4.2.2(glob@7.2.3) - is-glob: 4.0.3 - lodash: 4.17.21 - minimist: 1.2.8 - mkdirp: 1.0.4 - mz: 2.7.0 - prettier: 2.8.8 - dev: true - /json-schema-traverse@0.4.1: + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-ref-resolver@1.0.1: + resolution: {integrity: sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==} + + json-schema-to-typescript@15.0.4: + resolution: {integrity: sha512-Su9oK8DR4xCmDsLlyvadkXzX6+GGXJpbhwoLtOGArAG61dvbW4YQmSEno2y66ahpIdmLMg6YUf/QHLgiwvkrHQ==} + engines: {node: '>=16.0.0'} + hasBin: true + + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - /json-schema-traverse@1.0.0: + json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true - /json-schema@0.4.0: + json-schema@0.4.0: resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} - dev: true - /json-stable-stringify-without-jsonify@1.0.1: + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - /json-stringify-safe@5.0.1: + json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - dev: true - /json5@2.2.3: + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true - dev: true - /jsonc-parser@3.2.1: - resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} - dev: true + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} - /jsonfile@4.0.0: + jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - /jsonfile@6.1.0: + jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - /jsonlint@1.6.0: + jsonlint@1.6.0: resolution: {integrity: sha512-x6YLBe6NjdpmIeiklwQOxsZuYj/SOWkT33GlTpaG1UdFGjdWjPcxJ1CWZAX3wA7tarz8E2YHF6KiW5HTapPlXw==} engines: {node: '>= 0.6'} hasBin: true - dependencies: - JSV: 4.0.2 - nomnom: 1.5.2 - dev: true - /jsonpointer@5.0.1: + jsonpointer@5.0.1: resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} engines: {node: '>=0.10.0'} - dev: true - /jsonschema@1.4.1: + jsonschema@1.4.1: resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==} - dev: true - /jsprim@2.0.2: + jsprim@2.0.2: resolution: {integrity: sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==} engines: {'0': node >=0.6.0} - dependencies: - assert-plus: 1.0.0 - extsprintf: 1.3.0 - json-schema: 0.4.0 - verror: 1.10.0 - dev: true - /junk@4.0.1: + junk@4.0.1: resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==} engines: {node: '>=12.20'} - dev: true - /katex@0.16.10: - resolution: {integrity: sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==} + katex@0.16.11: + resolution: {integrity: sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==} hasBin: true - dependencies: - commander: 8.3.0 - dev: false - /keyv@4.5.4: + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - dev: true - /khroma@2.1.0: + khroma@2.1.0: resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} - dev: false - /kind-of@6.0.3: + kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - dev: true - /kleur@3.0.3: + kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} - dev: true - /kolorist@1.8.0: + kolorist@1.8.0: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} - dev: true - /ky@0.30.0: + ky@0.30.0: resolution: {integrity: sha512-X/u76z4JtDVq10u1JA5UQfatPxgPaVDMYTrgHyiTpGN2z4TMEJkIHsoSBBSg9SWZEIXTKsi9kHgiQ9o3Y/4yog==} engines: {node: '>=12'} - dev: true - /langium-cli@3.0.1: - resolution: {integrity: sha512-s1R/4GKkWItfu2o05DxqP71ID5MiGqb1BfXyPeFvIO3+aRSCj6fCj9EXtasvf18lSTUe27H37aO66TNU9VRr+Q==} + langium-cli@3.3.0: + resolution: {integrity: sha512-QWvlOYdLbso8/lv6Ma+SBtvMN9k70JrplLx6VSIcV7gJNDTXeS+tjwC/f6T0aco1fg8uLL8GiAcaMovd1FnneA==} engines: {node: '>=16.0.0'} hasBin: true - dependencies: - chalk: 5.3.0 - commander: 11.0.0 - fs-extra: 11.1.1 - jsonschema: 1.4.1 - langium: 3.0.0 - langium-railroad: 3.0.0 - lodash: 4.17.21 - dev: true - /langium-railroad@3.0.0: - resolution: {integrity: sha512-GQOnQBGl5gJqzgK/4bKvJO5QhJGNnprpYH6Fghbl4FviVLHwP6yzyqiouDelLSoCadChCr2JqKaBp5HXv7CgWw==} - dependencies: - langium: 3.0.0 - railroad-diagrams: 1.0.0 - dev: true + langium-railroad@3.3.0: + resolution: {integrity: sha512-x56CU0KnLoqYLkHEPDJjFoekFoCVbbZbmHduldiXjKD8owt6t5aqgWfg31OeMeR+7XgONZTtmsO76yl6GvEkzQ==} - /langium@3.0.0: - resolution: {integrity: sha512-+Ez9EoiByeoTu/2BXmEaZ06iPNXM6thWJp02KfBO/raSMyCJ4jw7AkWWa+zBCTm0+Tw1Fj9FOxdqSskyN5nAwg==} + langium@3.3.1: + resolution: {integrity: sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==} engines: {node: '>=16.0.0'} - dependencies: - chevrotain: 11.0.3 - chevrotain-allstar: 0.3.1(chevrotain@11.0.3) - vscode-languageserver: 9.0.1 - vscode-languageserver-textdocument: 1.0.11 - vscode-uri: 3.0.8 - /launch-editor@2.6.1: - resolution: {integrity: sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==} - dependencies: - picocolors: 1.0.0 - shell-quote: 1.8.1 - dev: true + launch-editor@2.9.1: + resolution: {integrity: sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==} - /layout-base@1.0.2: + layout-base@1.0.2: resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} - dev: false - /lazy-ass@1.6.0: + layout-base@2.0.1: + resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} + + lazy-ass@1.6.0: resolution: {integrity: sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==} engines: {node: '> 0.8'} - dev: true - /leven@3.1.0: + lazy-ass@2.0.3: + resolution: {integrity: sha512-/O3/DoQmI1XAhklDvF1dAjFf/epE8u3lzOZegQfLZ8G7Ud5bTRSZiFOpukHCu6jODrCA4gtIdwUCC7htxcDACA==} + engines: {node: '> 0.8'} + + leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} - dev: true - /levn@0.4.1: + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - /lex-parser@0.1.4: + lex-parser@0.1.4: resolution: {integrity: sha512-DuAEISsr1H4LOpmFLkyMc8YStiRWZCO8hMsoXAXSbgyfvs2WQhSt0+/FBv3ZU/JBFZMGcE+FWzEBSzwUU7U27w==} - dev: true - /light-my-request@4.12.0: - resolution: {integrity: sha512-0y+9VIfJEsPVzK5ArSIJ8Dkxp8QMP7/aCuxCUtG/tr9a2NoOf/snATE/OUc05XUplJCEnRh6gTkH7xh9POt1DQ==} - dependencies: - ajv: 8.12.0 - cookie: 0.5.0 - process-warning: 1.0.0 - set-cookie-parser: 2.6.0 - dev: true + light-my-request@5.14.0: + resolution: {integrity: sha512-aORPWntbpH5esaYpGOOmri0OHDOe3wC5M2MQxZ9dvMLZm6DnaAn0kJlcbU9hwsQgLzmZyReKwFwwPkR+nHu5kA==} - /lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} - dev: false - - /lilconfig@3.0.0: - resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} - dev: true - /lilconfig@3.1.1: - resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==} - engines: {node: '>=14'} - dev: false - - /lines-and-columns@1.2.4: + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - /linkify-it@4.0.1: + linkify-it@4.0.1: resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==} - dependencies: - uc.micro: 1.0.6 - dev: true - /lint-staged@15.2.2: - resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==} + linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + + lint-staged@15.4.3: + resolution: {integrity: sha512-FoH1vOeouNh1pw+90S+cnuoFwRfUD9ijY2GKy5h7HS3OR7JVir2N2xrsa0+Twc1B7cW72L+88geG5cW4wIhn7g==} engines: {node: '>=18.12.0'} hasBin: true - dependencies: - chalk: 5.3.0 - commander: 11.1.0 - debug: 4.3.4(supports-color@8.1.1) - execa: 8.0.1 - lilconfig: 3.0.0 - listr2: 8.0.1 - micromatch: 4.0.5 - pidtree: 0.6.0 - string-argv: 0.3.2 - yaml: 2.3.4 - transitivePeerDependencies: - - supports-color - dev: true - /listr2@3.14.0(enquirer@2.4.1): + listr2@3.14.0: resolution: {integrity: sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==} engines: {node: '>=10.0.0'} peerDependencies: @@ -11294,921 +6926,515 @@ packages: peerDependenciesMeta: enquirer: optional: true - dependencies: - cli-truncate: 2.1.0 - colorette: 2.0.20 - enquirer: 2.4.1 - log-update: 4.0.0 - p-map: 4.0.0 - rfdc: 1.3.1 - rxjs: 7.8.1 - through: 2.3.8 - wrap-ansi: 7.0.0 - dev: true - /listr2@8.0.1: - resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==} + listr2@8.2.5: + resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} engines: {node: '>=18.0.0'} - dependencies: - cli-truncate: 4.0.0 - colorette: 2.0.20 - eventemitter3: 5.0.1 - log-update: 6.0.0 - rfdc: 1.3.1 - wrap-ansi: 9.0.0 - dev: true - /loader-runner@4.3.0: + loader-runner@4.3.0: resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} engines: {node: '>=6.11.5'} - dev: true - /local-pkg@0.4.3: - resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} + local-pkg@1.0.0: + resolution: {integrity: sha512-bbgPw/wmroJsil/GgL4qjDzs5YLTBMQ99weRsok1XCDccQeehbHA/I1oRvk2NPtr7KGZgT/Y5tPRnAtMqeG2Kg==} engines: {node: '>=14'} - dev: true - /local-pkg@0.5.0: - resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} - engines: {node: '>=14'} - dependencies: - mlly: 1.6.1 - pkg-types: 1.0.3 - dev: true - - /locate-path@3.0.0: + locate-path@3.0.0: resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} engines: {node: '>=6'} - dependencies: - p-locate: 3.0.0 - path-exists: 3.0.0 - dev: true - /locate-path@5.0.0: + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - /locate-path@6.0.0: + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: true - /locate-path@7.2.0: + locate-path@7.2.0: resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - p-locate: 6.0.0 - dev: true - /lodash-es@4.17.21: + lodash-es@4.17.21: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} - /lodash.debounce@4.0.8: + lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + + lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - dev: true - /lodash.flattendeep@4.4.0: + lodash.flattendeep@4.4.0: resolution: {integrity: sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==} - dev: true - /lodash.isplainobject@4.0.6: + lodash.isplainobject@4.0.6: resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} - dev: true - /lodash.merge@4.6.2: + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - /lodash.once@4.1.1: + lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} - dev: true - /lodash.sortby@4.7.0: + lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} - dev: true - /lodash@4.17.21: + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - /log-symbols@4.1.0: + log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - dev: true - /log-update@4.0.0: + log-update@4.0.0: resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} engines: {node: '>=10'} - dependencies: - ansi-escapes: 4.3.2 - cli-cursor: 3.1.0 - slice-ansi: 4.0.0 - wrap-ansi: 6.2.0 - dev: true - /log-update@6.0.0: - resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} - dependencies: - ansi-escapes: 6.2.1 - cli-cursor: 4.0.0 - slice-ansi: 7.1.0 - strip-ansi: 7.1.0 - wrap-ansi: 9.0.0 - dev: true - /loglevel-plugin-prefix@0.8.4: + loglevel-plugin-prefix@0.8.4: resolution: {integrity: sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==} - dev: true - /loglevel@1.9.1: - resolution: {integrity: sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==} + loglevel@1.9.2: + resolution: {integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==} engines: {node: '>= 0.6.0'} - dev: true - /longest-streak@3.1.0: + long@5.2.3: + resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + + longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - dev: true - /loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - dependencies: - get-func-name: 2.0.2 - dev: true + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} - /lowercase-keys@2.0.0: + lowercase-keys@2.0.0: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} engines: {node: '>=8'} - dev: true - /lru-cache@10.2.0: - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} - engines: {node: 14 || >=16.14} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - /lru-cache@5.1.1: + lru-cache@11.0.2: + resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: true - - /lru-queue@0.1.0: - resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} - dependencies: - es5-ext: 0.10.64 - dev: true - - /lunr@2.3.9: + lunr@2.3.9: resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} - dev: true - /magic-string@0.25.9: + magic-string@0.25.9: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} - dependencies: - sourcemap-codec: 1.4.8 - dev: true - /magic-string@0.30.5: - resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} - /magic-string@0.30.8: - resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} - /magic-string@0.30.9: - resolution: {integrity: sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /magicast@0.3.4: - resolution: {integrity: sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==} - dependencies: - '@babel/parser': 7.24.4 - '@babel/types': 7.24.0 - source-map-js: 1.2.0 - dev: true - - /make-dir@3.1.0: + make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} - dependencies: - semver: 6.3.1 - dev: true - /make-dir@4.0.0: + make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} - dependencies: - semver: 7.6.0 - dev: true - /makeerror@1.0.12: + makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - dependencies: - tmpl: 1.0.5 - dev: true - /map-stream@0.1.0: + map-stream@0.1.0: resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} - dev: true - /mark.js@8.11.1: + mark.js@8.11.1: resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} - dev: true - /markdown-it@13.0.1: - resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==} + markdown-it@13.0.2: + resolution: {integrity: sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==} hasBin: true - dependencies: - argparse: 2.0.1 - entities: 3.0.1 - linkify-it: 4.0.1 - mdurl: 1.0.1 - uc.micro: 1.0.6 - dev: true - /markdown-table@3.0.3: - resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} - dev: true + markdown-it@14.1.0: + resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} + hasBin: true - /marked@4.3.0: + markdown-table@3.0.4: + resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + + marked@15.0.7: + resolution: {integrity: sha512-dgLIeKGLx5FwziAnsk4ONoGwHwGPJzselimvlVskE9XLN4Orv9u2VA3GWw/lYUqjfA0rUT/6fqKwfZJapP9BEg==} + engines: {node: '>= 18'} + hasBin: true + + marked@4.3.0: resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} engines: {node: '>= 12'} hasBin: true - /mdast-builder@1.1.1: + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdast-builder@1.1.1: resolution: {integrity: sha512-a3KBk/LmYD6wKsWi8WJrGU/rXR4yuF4Men0JO0z6dSZCm5FrXXWTRDjqK0vGSqa+1M6p9edeuypZAZAzSehTUw==} - dependencies: - '@types/unist': 2.0.10 - dev: true - /mdast-util-find-and-replace@3.0.1: + mdast-util-find-and-replace@3.0.1: resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} - dependencies: - '@types/mdast': 4.0.3 - escape-string-regexp: 5.0.0 - unist-util-is: 6.0.0 - unist-util-visit-parents: 6.0.1 - dev: true - /mdast-util-from-markdown@0.8.5: + mdast-util-from-markdown@0.8.5: resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==} - dependencies: - '@types/mdast': 3.0.15 - mdast-util-to-string: 2.0.0 - micromark: 2.11.4 - parse-entities: 2.0.0 - unist-util-stringify-position: 2.0.3 - transitivePeerDependencies: - - supports-color - dev: true - /mdast-util-from-markdown@2.0.0: - resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} - dependencies: - '@types/mdast': 4.0.3 - '@types/unist': 3.0.2 - decode-named-character-reference: 1.0.2 - devlop: 1.1.0 - mdast-util-to-string: 4.0.0 - micromark: 4.0.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-decode-string: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - unist-util-stringify-position: 4.0.0 - transitivePeerDependencies: - - supports-color + mdast-util-from-markdown@2.0.1: + resolution: {integrity: sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==} - /mdast-util-frontmatter@2.0.1: + mdast-util-frontmatter@2.0.1: resolution: {integrity: sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==} - dependencies: - '@types/mdast': 4.0.3 - devlop: 1.1.0 - escape-string-regexp: 5.0.0 - mdast-util-from-markdown: 2.0.0 - mdast-util-to-markdown: 2.1.0 - micromark-extension-frontmatter: 2.0.0 - transitivePeerDependencies: - - supports-color - dev: true - /mdast-util-gfm-autolink-literal@2.0.0: - resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==} - dependencies: - '@types/mdast': 4.0.3 - ccount: 2.0.1 - devlop: 1.1.0 - mdast-util-find-and-replace: 3.0.1 - micromark-util-character: 2.1.0 - dev: true + mdast-util-gfm-autolink-literal@2.0.1: + resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} - /mdast-util-gfm-footnote@2.0.0: + mdast-util-gfm-footnote@2.0.0: resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} - dependencies: - '@types/mdast': 4.0.3 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.0 - mdast-util-to-markdown: 2.1.0 - micromark-util-normalize-identifier: 2.0.0 - transitivePeerDependencies: - - supports-color - dev: true - /mdast-util-gfm-strikethrough@2.0.0: + mdast-util-gfm-strikethrough@2.0.0: resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} - dependencies: - '@types/mdast': 4.0.3 - mdast-util-from-markdown: 2.0.0 - mdast-util-to-markdown: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: true - /mdast-util-gfm-table@2.0.0: + mdast-util-gfm-table@2.0.0: resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} - dependencies: - '@types/mdast': 4.0.3 - devlop: 1.1.0 - markdown-table: 3.0.3 - mdast-util-from-markdown: 2.0.0 - mdast-util-to-markdown: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: true - /mdast-util-gfm-task-list-item@2.0.0: + mdast-util-gfm-task-list-item@2.0.0: resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} - dependencies: - '@types/mdast': 4.0.3 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.0 - mdast-util-to-markdown: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: true - /mdast-util-gfm@3.0.0: + mdast-util-gfm@3.0.0: resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} - dependencies: - mdast-util-from-markdown: 2.0.0 - mdast-util-gfm-autolink-literal: 2.0.0 - mdast-util-gfm-footnote: 2.0.0 - mdast-util-gfm-strikethrough: 2.0.0 - mdast-util-gfm-table: 2.0.0 - mdast-util-gfm-task-list-item: 2.0.0 - mdast-util-to-markdown: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: true - /mdast-util-phrasing@4.1.0: + mdast-util-phrasing@4.1.0: resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} - dependencies: - '@types/mdast': 4.0.3 - unist-util-is: 6.0.0 - dev: true - /mdast-util-to-markdown@2.1.0: + mdast-util-to-hast@13.2.0: + resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} + + mdast-util-to-markdown@2.1.0: resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} - dependencies: - '@types/mdast': 4.0.3 - '@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 - dev: true - /mdast-util-to-string@2.0.0: + mdast-util-to-string@2.0.0: resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} - dev: true - /mdast-util-to-string@4.0.0: + mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} - dependencies: - '@types/mdast': 4.0.3 - /mdn-data@2.0.30: - resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} - dev: true - - /mdn-data@2.1.0: + mdn-data@2.1.0: resolution: {integrity: sha512-dbAWH6A+2NGuVJlQFrTKHJc07Vqn5frnhyTOGz+7BsK7V2hHdoBcwoiyV3QVhLHYpM/zqe2OSUn5ZWbVXLBB8A==} - dev: true - /mdurl@1.0.1: + mdn-data@2.12.2: + resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + + mdurl@1.0.1: resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} - dev: true - /media-typer@0.3.0: + mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + + media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - dev: true - /memfs@3.5.3: + media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + + memfs@3.5.3: resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} engines: {node: '>= 4.0.0'} - dependencies: - fs-monkey: 1.0.4 - dev: true - /memoizee@0.4.15: - resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - es6-weak-map: 2.0.3 - event-emitter: 0.3.5 - is-promise: 2.2.2 - lru-queue: 0.1.0 - next-tick: 1.1.0 - timers-ext: 0.1.7 - dev: true - - /meow@12.1.1: + meow@12.1.1: resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} engines: {node: '>=16.10'} - dev: true - /merge-descriptors@1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - dev: true + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} - /merge-stream@2.0.0: + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - /merge2@1.4.1: + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - /methods@1.1.2: + methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} - dev: true - /micromark-core-commonmark@2.0.0: - resolution: {integrity: sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==} - dependencies: - decode-named-character-reference: 1.0.2 - devlop: 1.1.0 - micromark-factory-destination: 2.0.0 - micromark-factory-label: 2.0.0 - micromark-factory-space: 2.0.0 - micromark-factory-title: 2.0.0 - micromark-factory-whitespace: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-classify-character: 2.0.0 - micromark-util-html-tag-name: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-resolve-all: 2.0.0 - micromark-util-subtokenize: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-core-commonmark@2.0.1: + resolution: {integrity: sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==} - /micromark-extension-frontmatter@2.0.0: + micromark-extension-frontmatter@2.0.0: resolution: {integrity: sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==} - dependencies: - fault: 2.0.1 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true - /micromark-extension-gfm-autolink-literal@2.0.0: - resolution: {integrity: sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-sanitize-uri: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true + micromark-extension-gfm-autolink-literal@2.1.0: + resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} - /micromark-extension-gfm-footnote@2.0.0: - resolution: {integrity: sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==} - dependencies: - devlop: 1.1.0 - micromark-core-commonmark: 2.0.0 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-sanitize-uri: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true + micromark-extension-gfm-footnote@2.1.0: + resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} - /micromark-extension-gfm-strikethrough@2.0.0: - resolution: {integrity: sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==} - dependencies: - devlop: 1.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-classify-character: 2.0.0 - micromark-util-resolve-all: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true + micromark-extension-gfm-strikethrough@2.1.0: + resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} - /micromark-extension-gfm-table@2.0.0: - resolution: {integrity: sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==} - dependencies: - devlop: 1.1.0 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true + micromark-extension-gfm-table@2.1.0: + resolution: {integrity: sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==} - /micromark-extension-gfm-tagfilter@2.0.0: + micromark-extension-gfm-tagfilter@2.0.0: resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} - dependencies: - micromark-util-types: 2.0.0 - dev: true - /micromark-extension-gfm-task-list-item@2.0.1: - resolution: {integrity: sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==} - dependencies: - devlop: 1.1.0 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - dev: true + micromark-extension-gfm-task-list-item@2.1.0: + resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} - /micromark-extension-gfm@3.0.0: + micromark-extension-gfm@3.0.0: resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} - dependencies: - micromark-extension-gfm-autolink-literal: 2.0.0 - micromark-extension-gfm-footnote: 2.0.0 - micromark-extension-gfm-strikethrough: 2.0.0 - micromark-extension-gfm-table: 2.0.0 - micromark-extension-gfm-tagfilter: 2.0.0 - micromark-extension-gfm-task-list-item: 2.0.1 - micromark-util-combine-extensions: 2.0.0 - micromark-util-types: 2.0.0 - dev: true - /micromark-factory-destination@2.0.0: + micromark-factory-destination@2.0.0: resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - /micromark-factory-label@2.0.0: + micromark-factory-label@2.0.0: resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} - dependencies: - devlop: 1.1.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - /micromark-factory-space@2.0.0: + micromark-factory-space@2.0.0: resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-types: 2.0.0 - /micromark-factory-title@2.0.0: + micromark-factory-title@2.0.0: resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==} - dependencies: - 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-factory-whitespace@2.0.0: + micromark-factory-whitespace@2.0.0: resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} - dependencies: - 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-util-character@2.1.0: + micromark-util-character@2.1.0: resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} - dependencies: - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - /micromark-util-chunked@2.0.0: + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-chunked@2.0.0: resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} - dependencies: - micromark-util-symbol: 2.0.0 - /micromark-util-classify-character@2.0.0: + micromark-util-classify-character@2.0.0: resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - /micromark-util-combine-extensions@2.0.0: + micromark-util-combine-extensions@2.0.0: resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==} - dependencies: - micromark-util-chunked: 2.0.0 - micromark-util-types: 2.0.0 - /micromark-util-decode-numeric-character-reference@2.0.1: + micromark-util-decode-numeric-character-reference@2.0.1: resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==} - dependencies: - micromark-util-symbol: 2.0.0 - /micromark-util-decode-string@2.0.0: + micromark-util-decode-string@2.0.0: resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==} - dependencies: - decode-named-character-reference: 1.0.2 - micromark-util-character: 2.1.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-symbol: 2.0.0 - /micromark-util-encode@2.0.0: - resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} - /micromark-util-html-tag-name@2.0.0: + micromark-util-html-tag-name@2.0.0: resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} - /micromark-util-normalize-identifier@2.0.0: + micromark-util-normalize-identifier@2.0.0: resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==} - dependencies: - micromark-util-symbol: 2.0.0 - /micromark-util-resolve-all@2.0.0: + micromark-util-resolve-all@2.0.0: resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==} - dependencies: - micromark-util-types: 2.0.0 - /micromark-util-sanitize-uri@2.0.0: - resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} - dependencies: - micromark-util-character: 2.1.0 - micromark-util-encode: 2.0.0 - micromark-util-symbol: 2.0.0 + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} - /micromark-util-subtokenize@2.0.0: - resolution: {integrity: sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==} - dependencies: - devlop: 1.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-subtokenize@2.0.1: + resolution: {integrity: sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==} - /micromark-util-symbol@2.0.0: + micromark-util-symbol@2.0.0: resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} - /micromark-util-types@2.0.0: + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.0: resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} - /micromark@2.11.4: + micromark-util-types@2.0.1: + resolution: {integrity: sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ==} + + micromark@2.11.4: resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} - dependencies: - debug: 4.3.4(supports-color@8.1.1) - parse-entities: 2.0.0 - transitivePeerDependencies: - - supports-color - dev: true - /micromark@4.0.0: + micromark@4.0.0: resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} - dependencies: - '@types/debug': 4.1.12 - debug: 4.3.4(supports-color@8.1.1) - decode-named-character-reference: 1.0.2 - devlop: 1.1.0 - micromark-core-commonmark: 2.0.0 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-combine-extensions: 2.0.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-encode: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-resolve-all: 2.0.0 - micromark-util-sanitize-uri: 2.0.0 - micromark-util-subtokenize: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - transitivePeerDependencies: - - supports-color - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - /mime-db@1.52.0: + mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - dev: true - /mime-types@2.1.35: + mime-db@1.53.0: + resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: true - /mime@1.6.0: + mime-types@3.0.1: + resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} + engines: {node: '>= 0.6'} + + mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} hasBin: true - dev: true - /mimic-fn@2.1.0: + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} - dev: true - /mimic-fn@4.0.0: + mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - dev: true - /mimic-response@1.0.1: + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + mimic-response@1.0.1: resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} engines: {node: '>=4'} - dev: true - /mimic-response@3.1.0: + mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} - dev: true - /min-indent@1.0.1: + min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} - dev: true - /minimalistic-assert@1.0.1: + minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: true - /minimatch@3.1.2: + minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} + + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - /minimatch@5.1.6: + minimatch@5.1.6: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: true - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - /minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - - /minimist@1.2.8: + minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: true - /minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} - /minisearch@6.3.0: - resolution: {integrity: sha512-ihFnidEeU8iXzcVHy74dhkxh/dn8Dc08ERl0xwoMMGqp4+LvRSCgicb+zGqWthVokQKvCSxITlh3P08OzdTYCQ==} - dev: true + minisearch@7.1.2: + resolution: {integrity: sha512-R1Pd9eF+MD5JYDDSPAp/q1ougKglm14uEkPMvQ/05RGmx6G9wvmLTrTI/Q5iPNJLYqNdsDQ7qTGIcNWR+FrHmA==} - /mitt@3.0.1: + mitt@3.0.1: resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} - dev: true - /mkdirp@0.5.6: + mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true - dependencies: - minimist: 1.2.8 - dev: true - /mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} + mlly@1.7.4: + resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} + + module-definition@6.0.0: + resolution: {integrity: sha512-sEGP5nKEXU7fGSZUML/coJbrO+yQtxcppDAYWRE9ovWsTbFoUHB2qDUx564WUzDaBHXsD46JBbIK5WVTwCyu3w==} + engines: {node: '>=18'} hasBin: true - dev: true - /mlly@1.6.1: - resolution: {integrity: sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==} - dependencies: - acorn: 8.11.3 - pathe: 1.1.2 - pkg-types: 1.0.3 - ufo: 1.5.3 - dev: true + module-lookup-amd@9.0.2: + resolution: {integrity: sha512-p7PzSVEWiW9fHRX9oM+V4aV5B2nCVddVNv4DZ/JB6t9GsXY4E+ZVhPpnwUX7bbJyGeeVZqhS8q/JZ/H77IqPFA==} + engines: {node: '>=18'} + hasBin: true - /mrmime@2.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'} - dev: true - /ms@2.0.0: + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: true - /ms@2.1.2: + ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - /ms@2.1.3: + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true - /multicast-dns@7.2.5: + multicast-dns@7.2.5: resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} hasBin: true - dependencies: - dns-packet: 5.6.0 - thunky: 1.1.0 - dev: true - /mz@2.7.0: + mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - /natural-compare@1.4.0: + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - /negotiator@0.6.3: + negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} - dev: true - /neo-async@2.6.2: + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + + neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true - /nested-error-stacks@2.1.1: + nested-error-stacks@2.1.1: resolution: {integrity: sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==} - dev: true - /next-tick@1.1.0: - resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} - dev: true - - /nice-try@1.0.5: + nice-try@1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} - dev: true - /node-cleanup@2.1.2: + node-cleanup@2.1.2: resolution: {integrity: sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==} - dev: true - /node-domexception@1.0.0: + node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} - dev: true - /node-fetch-native@1.6.4: + node-fetch-native@1.6.4: resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} - dev: true - /node-fetch@2.6.7(encoding@0.1.13): + node-fetch@2.6.7: resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} engines: {node: 4.x || >=6.0.0} peerDependencies: @@ -12216,683 +7442,488 @@ packages: peerDependenciesMeta: encoding: optional: true - dependencies: - encoding: 0.1.13 - whatwg-url: 5.0.0 - dev: true - /node-fetch@3.3.1: + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-fetch@3.3.1: resolution: {integrity: sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - data-uri-to-buffer: 4.0.1 - fetch-blob: 3.2.0 - formdata-polyfill: 4.0.10 - dev: true - /node-forge@1.3.1: + node-forge@1.3.1: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} - dev: true - /node-int64@0.4.0: + node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - dev: true - /node-preload@0.2.1: + node-preload@0.2.1: resolution: {integrity: sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==} engines: {node: '>=8'} - dependencies: - process-on-spawn: 1.0.0 - dev: true - /node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - dev: true + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - /nomnom@1.5.2: + node-source-walk@7.0.0: + resolution: {integrity: sha512-1uiY543L+N7Og4yswvlm5NCKgPKDEXd9AUR9Jh3gen6oOeBsesr6LqhXom1er3eRzSUcVRWXzhv8tSNrIfGHKw==} + engines: {node: '>=18'} + + nomnom@1.5.2: resolution: {integrity: sha512-fiVbT7BqxiQqjlR9U3FDGOSERFCKoXVCdxV2FwZuNN7/cmJ42iQx35nUFOAFDcyvemu9Adp+IlsCGlKQYLmBKw==} deprecated: Package no longer supported. Contact support@npmjs.com for more info. - dependencies: - colors: 0.5.1 - underscore: 1.1.7 - dev: true - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.8 - semver: 5.7.2 - validate-npm-package-license: 3.0.4 - dev: true + normalize-package-data@6.0.2: + resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} + engines: {node: ^16.14.0 || >=18.0.0} - /normalize-path@3.0.0: + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - /normalize-url@6.1.0: + normalize-url@6.1.0: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} - dev: true - /npm-run-path@2.0.2: + npm-run-path@2.0.2: resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} engines: {node: '>=4'} - dependencies: - path-key: 2.0.1 - dev: true - /npm-run-path@4.0.1: + npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - /npm-run-path@5.3.0: + npm-run-path@5.3.0: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - path-key: 4.0.0 - dev: true - /nwsapi@2.2.7: - resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} - dev: true + nwsapi@2.2.16: + resolution: {integrity: sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==} - /nyc@15.1.0: + nyc@15.1.0: resolution: {integrity: sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==} engines: {node: '>=8.9'} hasBin: true - dependencies: - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - caching-transform: 4.0.0 - convert-source-map: 1.9.0 - decamelize: 1.2.0 - find-cache-dir: 3.3.2 - find-up: 4.1.0 - foreground-child: 2.0.0 - get-package-type: 0.1.0 - glob: 7.2.3 - istanbul-lib-coverage: 3.2.0 - istanbul-lib-hook: 3.0.0 - istanbul-lib-instrument: 4.0.3 - istanbul-lib-processinfo: 2.0.3 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.6 - make-dir: 3.1.0 - node-preload: 0.2.1 - p-map: 3.0.0 - process-on-spawn: 1.0.0 - resolve-from: 5.0.0 - rimraf: 3.0.2 - signal-exit: 3.0.7 - spawn-wrap: 2.0.0 - test-exclude: 6.0.0 - yargs: 15.4.1 - transitivePeerDependencies: - - supports-color - dev: true - /object-assign@4.1.1: + nyc@17.1.0: + resolution: {integrity: sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ==} + engines: {node: '>=18'} + hasBin: true + + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - /object-hash@3.0.0: + object-hash@3.0.0: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} - dev: false - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - dev: true + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} - /object-keys@1.1.1: + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - dev: true - /object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: true - /obuf@1.1.2: + obuf@1.1.2: resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} - dev: true - /ofetch@1.3.4: - resolution: {integrity: sha512-KLIET85ik3vhEfS+3fDlc/BAZiAp+43QEC/yCo5zkNoY2YaKvNkOaFr/6wCFgFH1kuYQM5pMNi0Tg8koiIemtw==} - dependencies: - destr: 2.0.3 - node-fetch-native: 1.6.4 - ufo: 1.5.3 - dev: true + ofetch@1.4.1: + resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==} - /omggif@1.0.10: + omggif@1.0.10: resolution: {integrity: sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==} - dev: true - /on-exit-leak-free@2.1.2: + on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} - dev: false - /on-finished@2.4.1: + on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: true - /on-headers@1.0.2: + on-headers@1.0.2: resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} engines: {node: '>= 0.8'} - dev: true - /once@1.4.0: + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: true - /onetime@5.1.2: + onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - /onetime@6.0.0: + onetime@6.0.0: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} - dependencies: - mimic-fn: 4.0.0 - dev: true - /open@8.4.2: + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + oniguruma-to-es@3.1.1: + resolution: {integrity: sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==} + + open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} - dependencies: - define-lazy-prop: 2.0.0 - is-docker: 2.2.1 - is-wsl: 2.2.0 - dev: true - /optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + openapi-fetch@0.13.5: + resolution: {integrity: sha512-AQK8T9GSKFREFlN1DBXTYsLjs7YV2tZcJ7zUWxbjMoQmj8dDSFRrzhLCbHPZWA1TMV3vACqfCxLEZcwf2wxV6Q==} + + openapi-typescript-helpers@0.0.15: + resolution: {integrity: sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} - dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - /ospath@1.2.2: + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + ospath@1.2.2: resolution: {integrity: sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==} - dev: true - /p-cancelable@2.1.1: + outdent@0.5.0: + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + p-cancelable@2.1.1: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} engines: {node: '>=8'} - dev: true - /p-event@5.0.1: + p-event@5.0.1: resolution: {integrity: sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - p-timeout: 5.1.0 - dev: true - /p-filter@3.0.0: + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-filter@3.0.0: resolution: {integrity: sha512-QtoWLjXAW++uTX67HZQz1dbTpqBfiidsB6VtQUC9iR85S120+s0T5sO6s+B5MLzFcZkrEd/DGMmCjR+f2Qpxwg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - p-map: 5.5.0 - dev: true - /p-finally@1.0.0: + p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} - dev: true - /p-iteration@1.1.8: + p-iteration@1.1.8: resolution: {integrity: sha512-IMFBSDIYcPNnW7uWYGrBqmvTiq7W0uB0fJn6shQZs7dlF3OvrHOre+JT9ikSZ7gZS3vWqclVgoQSvToJrns7uQ==} engines: {node: '>=8.0.0'} - dev: true - /p-limit@2.3.0: + p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - /p-limit@3.1.0: + p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - /p-limit@4.0.0: + p-limit@4.0.0: resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - yocto-queue: 1.0.0 - dev: true - /p-limit@5.0.0: - resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} - engines: {node: '>=18'} - dependencies: - yocto-queue: 1.0.0 - dev: true - - /p-locate@3.0.0: + p-locate@3.0.0: resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} engines: {node: '>=6'} - dependencies: - p-limit: 2.3.0 - dev: true - /p-locate@4.1.0: + p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - /p-locate@5.0.0: + p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: true - /p-locate@6.0.0: + p-locate@6.0.0: resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - p-limit: 4.0.0 - dev: true - /p-map@3.0.0: + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-map@3.0.0: resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} engines: {node: '>=8'} - dependencies: - aggregate-error: 3.1.0 - dev: true - /p-map@4.0.0: + p-map@4.0.0: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} engines: {node: '>=10'} - dependencies: - aggregate-error: 3.1.0 - dev: true - /p-map@5.5.0: + p-map@5.5.0: resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==} engines: {node: '>=12'} - dependencies: - aggregate-error: 4.0.1 - dev: true - /p-map@6.0.0: + p-map@6.0.0: resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==} engines: {node: '>=16'} - dev: true - /p-retry@4.6.2: + p-retry@4.6.2: resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} engines: {node: '>=8'} - dependencies: - '@types/retry': 0.12.0 - retry: 0.13.1 - dev: true - /p-timeout@5.1.0: + p-timeout@5.1.0: resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==} engines: {node: '>=12'} - dev: true - /p-try@2.2.0: + p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} - dev: true - /package-hash@4.0.0: + package-hash@4.0.0: resolution: {integrity: sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==} engines: {node: '>=8'} - dependencies: - graceful-fs: 4.2.11 - hasha: 5.2.2 - lodash.flattendeep: 4.4.0 - release-zalgo: 1.0.0 - dev: true - /pako@1.0.11: + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + package-manager-detector@0.2.9: + resolution: {integrity: sha512-+vYvA/Y31l8Zk8dwxHhL3JfTuHPm6tlxM2A3GeQyl7ovYnSp1+mzAxClxaOr0qO1TtPxbQxetI7v5XqKLJZk7Q==} + + pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} - dev: true - /parent-module@1.0.1: + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - /parent-module@2.0.0: + parent-module@2.0.0: resolution: {integrity: sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==} engines: {node: '>=8'} - dependencies: - callsites: 3.1.0 - dev: true - /parse-entities@2.0.0: + parse-entities@2.0.0: resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==} - dependencies: - character-entities: 1.2.4 - character-entities-legacy: 1.1.4 - character-reference-invalid: 1.1.4 - is-alphanumerical: 1.0.4 - is-decimal: 1.0.4 - is-hexadecimal: 1.0.4 - dev: true - /parse-json@5.2.0: + parse-imports@2.2.1: + resolution: {integrity: sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==} + engines: {node: '>= 18'} + + parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.23.5 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - /parse5@7.1.2: - resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} - dependencies: - entities: 4.5.0 - dev: true + parse-json@8.1.0: + resolution: {integrity: sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==} + engines: {node: '>=18'} - /parseurl@1.3.3: + parse5@7.2.1: + resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} + + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} - dev: true - /path-browserify@1.0.1: + path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - dev: true - /path-exists@3.0.0: + path-data-parser@0.1.0: + resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==} + + path-exists@3.0.0: resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} engines: {node: '>=4'} - dev: true - /path-exists@4.0.0: + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - dev: true - /path-exists@5.0.0: + path-exists@5.0.0: resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - /path-is-absolute@1.0.1: + path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} - dev: true - /path-key@2.0.1: + path-key@2.0.1: resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} engines: {node: '>=4'} - dev: true - /path-key@3.1.1: + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - /path-key@4.0.0: + path-key@4.0.0: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} - dev: true - /path-parse@1.0.7: + path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - /path-scurry@1.10.1: - resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - lru-cache: 10.2.0 - minipass: 7.0.4 - dev: true + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} - /path-scurry@1.10.2: - resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - lru-cache: 10.2.0 - minipass: 7.0.4 - dev: false + path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} - /path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - dev: true + path-to-regexp@0.1.10: + resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==} - /path-type@4.0.0: + path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} + engines: {node: '>=16'} + + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - dev: true - /path-type@5.0.0: - resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} - engines: {node: '>=12'} - dev: true + path-type@6.0.0: + resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==} + engines: {node: '>=18'} - /pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - dev: true + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - /pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - dev: true + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} - /pause-stream@0.0.11: + pause-stream@0.0.11: resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} - dependencies: - through: 2.3.8 - dev: true - /pend@1.2.0: + pcg@1.0.0: + resolution: {integrity: sha512-6wjoSJZ4TEJhI0rLDOKd5mOu6TwS4svn9oBaRsD1PCrhlDNLWAaTimWJgBABmIGJxzkI+RbaHJYRLGVf9QFE5Q==} + + pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - dev: true - /perfect-debounce@1.0.0: + perfect-debounce@1.0.0: resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} - dev: true - /performance-now@2.1.0: + performance-now@2.1.0: resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} - dev: true - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - /picomatch@2.3.1: + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - /pidtree@0.6.0: + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'} hasBin: true - dev: true - /pify@2.3.0: + pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} - /pino-abstract-transport@1.1.0: - resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==} - dependencies: - readable-stream: 4.5.2 - split2: 4.2.0 - dev: false + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} - /pino-std-serializers@3.2.0: - resolution: {integrity: sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==} - dev: true + pino-abstract-transport@1.2.0: + resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} - /pino-std-serializers@6.2.2: + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-std-serializers@6.2.2: resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} - dev: false - /pino@6.14.0: - resolution: {integrity: sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==} + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + + pino@8.21.0: + resolution: {integrity: sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==} hasBin: true - dependencies: - fast-redact: 3.5.0 - fast-safe-stringify: 2.1.1 - flatstr: 1.0.12 - pino-std-serializers: 3.2.0 - process-warning: 1.0.0 - quick-format-unescaped: 4.0.4 - sonic-boom: 1.4.1 - dev: true - /pino@8.20.0: - resolution: {integrity: sha512-uhIfMj5TVp+WynVASaVEJFTncTUe4dHBq6CWplu/vBgvGHhvBvQfxz+vcOrnnBQdORH3izaGEurLfNlq3YxdFQ==} + pino@9.6.0: + resolution: {integrity: sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==} hasBin: true - dependencies: - atomic-sleep: 1.0.0 - fast-redact: 3.5.0 - on-exit-leak-free: 2.1.2 - pino-abstract-transport: 1.1.0 - pino-std-serializers: 6.2.2 - process-warning: 3.0.0 - quick-format-unescaped: 4.0.4 - real-require: 0.2.0 - safe-stable-stringify: 2.4.3 - sonic-boom: 3.8.1 - thread-stream: 2.4.1 - dev: false - /pirates@4.0.6: + pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} - /pixelmatch@5.3.0: + pixelmatch@5.3.0: resolution: {integrity: sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==} hasBin: true - dependencies: - pngjs: 6.0.0 - dev: true - /pkg-dir@3.0.0: + pkg-dir@3.0.0: resolution: {integrity: sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==} engines: {node: '>=6'} - dependencies: - find-up: 3.0.0 - dev: true - /pkg-dir@4.2.0: + pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - dev: true - /pkg-dir@7.0.0: + pkg-dir@7.0.0: resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} engines: {node: '>=14.16'} - dependencies: - find-up: 6.3.0 - dev: true - /pkg-types@1.0.3: - resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} - dependencies: - jsonc-parser: 3.2.1 - mlly: 1.6.1 - pathe: 1.1.2 - dev: true + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - /plist@3.1.0: + plist@3.1.0: resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==} engines: {node: '>=10.4.0'} - dependencies: - '@xmldom/xmldom': 0.8.10 - base64-js: 1.5.1 - xmlbuilder: 15.1.1 - dev: true - /pluralize@8.0.0: + pluralize@8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} - dev: true - /png-async@0.9.4: + png-async@0.9.4: resolution: {integrity: sha512-B//AXX9TkneKfgtOpT1mdUnnhk2BImGD+a98vImsMU8uo1dBeHyW/kM2erWZ/CsYteTPU/xKG+t6T62heHkC3A==} - dev: true - /pngjs@3.4.0: + pngjs@3.4.0: resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==} engines: {node: '>=4.0.0'} - dev: true - /pngjs@6.0.0: + pngjs@6.0.0: resolution: {integrity: sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==} engines: {node: '>=12.13.0'} - dev: true - /pnpm@8.15.7: - resolution: {integrity: sha512-yFzSG22hAzIVaxyiqnnAph7nrS6wRTuIqymSienoypPmCRIyslwHy/YfbfdxKNnISeXJrG5EhU29IRxJ86Z63A==} - engines: {node: '>=16.14'} - hasBin: true - dev: true + points-on-curve@0.2.0: + resolution: {integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==} - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + points-on-path@0.2.1: + resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} - dev: true - /postcss-import@15.1.0(postcss@8.4.38): + postcss-import@15.1.0: resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} engines: {node: '>=14.0.0'} peerDependencies: postcss: ^8.0.0 - dependencies: - postcss: 8.4.38 - postcss-value-parser: 4.2.0 - read-cache: 1.0.0 - resolve: 1.22.8 - dev: false - /postcss-js@4.0.1(postcss@8.4.38): + postcss-js@4.0.1: resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: postcss: ^8.4.21 - dependencies: - camelcase-css: 2.0.1 - postcss: 8.4.38 - dev: false - /postcss-load-config@4.0.2(postcss@8.4.38): + postcss-load-config@4.0.2: resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} engines: {node: '>= 14'} peerDependencies: @@ -12903,1566 +7934,978 @@ packages: optional: true ts-node: optional: true - dependencies: - lilconfig: 3.1.1 - postcss: 8.4.38 - yaml: 2.4.1 - dev: false - /postcss-nested@6.0.1(postcss@8.4.38): - resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.2.14 - dependencies: - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 - dev: false - /postcss-selector-parser@6.0.16: - resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - dev: false - /postcss-value-parser@4.2.0: + postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: false - /postcss@8.4.38: - resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + postcss-values-parser@6.0.2: + resolution: {integrity: sha512-YLJpK0N1brcNJrs9WatuJFtHaV9q5aAOj+S4DI5S7jgHlRfm0PIbDCAFRYMQD5SHq7Fy6xsDhyutgS0QOAs0qw==} + engines: {node: '>=10'} + peerDependencies: + postcss: ^8.2.9 + + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.2.0 - /preact@10.20.2: - resolution: {integrity: sha512-S1d1ernz3KQ+Y2awUxKakpfOg2CEmJmwOP+6igPx6dgr6pgDvenqYviyokWso2rhHvGtTlWWnJDa7RaPbQerTg==} - dev: true + preact@10.26.2: + resolution: {integrity: sha512-0gNmv4qpS9HaN3+40CLBAnKe0ZfyE4ZWo5xKlC1rVrr0ckkEvJvAQqKaHANdFKsGstoxrY4AItZ7kZSGVoVjgg==} - /prelude-ls@1.2.1: + precinct@12.1.2: + resolution: {integrity: sha512-x2qVN3oSOp3D05ihCd8XdkIPuEQsyte7PSxzLqiRgktu79S5Dr1I75/S+zAup8/0cwjoiJTQztE9h0/sWp9bJQ==} + engines: {node: '>=18'} + hasBin: true + + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - dev: true - /prettier-plugin-jsdoc@1.3.0(prettier@3.2.5): - resolution: {integrity: sha512-cQm8xIa0fN9ieJFMXACQd6JPycl+8ouOijAqUqu44EF/s4fXL3Wi9sKXuEaodsEWgCN42Xby/bNhqgM1iWx4uw==} + prettier-plugin-jsdoc@1.3.2: + resolution: {integrity: sha512-LNi9eq0TjyZn/PUNf/SYQxxUvGg5FLK4alEbi3i/S+2JbMyTu790c/puFueXzx09KP44oWCJ+TaHRyM/a0rKJQ==} engines: {node: '>=14.13.1 || >=16.0.0'} peerDependencies: prettier: ^3.0.0 - dependencies: - binary-searching: 2.0.5 - comment-parser: 1.4.1 - mdast-util-from-markdown: 2.0.0 - prettier: 3.2.5 - transitivePeerDependencies: - - supports-color - dev: true - /prettier@2.8.8: + prettier@2.8.8: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} engines: {node: '>=10.13.0'} hasBin: true - dev: true - /prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + prettier@3.5.2: + resolution: {integrity: sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==} engines: {node: '>=14'} hasBin: true - dev: true - /pretty-bytes@5.6.0: + pretty-bytes@5.6.0: resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} engines: {node: '>=6'} - dev: true - /pretty-bytes@6.1.1: + pretty-bytes@6.1.1: resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} engines: {node: ^14.13.1 || >=16.0.0} - dev: true - /pretty-format@29.7.0: + pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.2.0 - dev: true - /process-nextick-args@2.0.1: + process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true - /process-on-spawn@1.0.0: + process-on-spawn@1.0.0: resolution: {integrity: sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==} engines: {node: '>=8'} - dependencies: - fromentries: 1.3.2 - dev: true - /process-warning@1.0.0: - resolution: {integrity: sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==} - dev: true - - /process-warning@3.0.0: + process-warning@3.0.0: resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} - dev: false - /process@0.11.10: + process-warning@4.0.1: + resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} + + process@0.11.10: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} - /prompts@2.4.2: + prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - dev: true - /proxy-addr@2.0.7: + property-information@7.0.0: + resolution: {integrity: sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg==} + + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - dev: true - /proxy-from-env@1.0.0: + proxy-from-env@1.0.0: resolution: {integrity: sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==} - dev: true - /proxy-from-env@1.1.0: + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: true - /ps-tree@1.2.0: + ps-tree@1.2.0: resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==} engines: {node: '>= 0.10'} hasBin: true - dependencies: - event-stream: 3.3.4 - dev: true - /psl@1.9.0: - resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} - dev: true + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} - /pump@3.0.0: - resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - dev: true + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} - /punycode@2.3.1: + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - dev: true - /pure-rand@6.0.4: - resolution: {integrity: sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==} - dev: true + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - /qs@6.10.4: - resolution: {integrity: sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==} + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.6 - dev: true - /qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + qs@6.13.1: + resolution: {integrity: sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==} engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.6 - dev: true - /querystringify@2.2.0: - resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} - dev: true + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} - /queue-microtask@1.2.3: + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - /quick-format-unescaped@4.0.4: + quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} - /quick-lru@5.1.1: + quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} - dev: true - /railroad-diagrams@1.0.0: + quote-unquote@1.0.0: + resolution: {integrity: sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg==} + + railroad-diagrams@1.0.0: resolution: {integrity: sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==} - dev: true - /ramda@0.28.0: + ramda@0.28.0: resolution: {integrity: sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==} - dev: false - /randombytes@2.1.0: + ramda@0.29.0: + resolution: {integrity: sha512-BBea6L67bYLtdbOqfp8f58fPMqEwx0doL+pAi8TZyp2YWz8R9G8z9x75CZI8W+ftqhFHCpEX2cRnUUXK130iKA==} + + randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - dependencies: - safe-buffer: 5.2.1 - dev: true - /range-parser@1.2.1: + range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} - dev: true - /raw-body@2.5.1: - resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: true - - /raw-body@2.5.2: + raw-body@2.5.2: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: true - /react-is@18.2.0: - resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} - dev: true + raw-body@3.0.0: + resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} + engines: {node: '>= 0.8'} - /read-cache@1.0.0: + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} - dependencies: - pify: 2.3.0 - dev: false - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - dev: true + read-package-up@11.0.0: + resolution: {integrity: sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==} + engines: {node: '>=18'} - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - dependencies: - '@types/normalize-package-data': 2.4.1 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - dev: true + read-pkg@9.0.1: + resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==} + engines: {node: '>=18'} - /readable-stream@2.3.8: + read-yaml-file@1.1.0: + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} + engines: {node: '>=6'} + + readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - dev: true - /readable-stream@3.6.2: + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - /readable-stream@4.5.2: - resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - abort-controller: 3.0.0 - buffer: 6.0.3 - events: 3.3.0 - process: 0.11.10 - string_decoder: 1.3.0 - dev: false - /readdirp@3.6.0: + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - /real-require@0.2.0: + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + real-require@0.2.0: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} - dev: false - /rechoir@0.7.1: + rechoir@0.6.2: + resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} + engines: {node: '>= 0.10'} + + rechoir@0.7.1: resolution: {integrity: sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==} engines: {node: '>= 0.10'} - dependencies: - resolve: 1.22.4 - dev: true - /regenerate-unicode-properties@10.1.1: - resolution: {integrity: sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==} + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + regenerate-unicode-properties@10.2.0: + resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} engines: {node: '>=4'} - dependencies: - regenerate: 1.4.2 - dev: true - /regenerate@1.4.2: + regenerate@1.4.2: resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} - dev: true - /regenerator-runtime@0.14.1: + regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - dev: true - /regenerator-transform@0.15.2: + regenerator-transform@0.15.2: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} - dependencies: - '@babel/runtime': 7.24.4 - dev: true - /regexp-tree@0.1.27: + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@6.0.1: + resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==} + + regexp-tree@0.1.27: resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true - dev: true - /regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-errors: 1.3.0 - set-function-name: 2.0.2 - dev: true - /regexpu-core@5.3.2: - resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} + regexpu-core@6.2.0: + resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} engines: {node: '>=4'} - dependencies: - '@babel/regjsgen': 0.8.0 - regenerate: 1.4.2 - regenerate-unicode-properties: 10.1.1 - regjsparser: 0.9.1 - unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.1.0 - dev: true - /regjsparser@0.10.0: - resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.12.0: + resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} hasBin: true - dependencies: - jsesc: 0.5.0 - dev: true - /regjsparser@0.9.1: - resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} - hasBin: true - dependencies: - jsesc: 0.5.0 - dev: true - - /release-zalgo@1.0.0: + release-zalgo@1.0.0: resolution: {integrity: sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==} engines: {node: '>=4'} - dependencies: - es6-error: 4.1.1 - dev: true - /remark-frontmatter@5.0.0: + remark-frontmatter@5.0.0: resolution: {integrity: sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==} - dependencies: - '@types/mdast': 4.0.3 - mdast-util-frontmatter: 2.0.1 - micromark-extension-frontmatter: 2.0.0 - unified: 11.0.4 - transitivePeerDependencies: - - supports-color - dev: true - /remark-gfm@4.0.0: - resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} - dependencies: - '@types/mdast': 4.0.3 - mdast-util-gfm: 3.0.0 - micromark-extension-gfm: 3.0.0 - remark-parse: 11.0.0 - remark-stringify: 11.0.0 - unified: 11.0.4 - transitivePeerDependencies: - - supports-color - dev: true + remark-gfm@4.0.1: + resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} - /remark-parse@11.0.0: + remark-parse@11.0.0: resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} - dependencies: - '@types/mdast': 4.0.3 - mdast-util-from-markdown: 2.0.0 - micromark-util-types: 2.0.0 - unified: 11.0.4 - transitivePeerDependencies: - - supports-color - dev: true - /remark-stringify@11.0.0: + remark-stringify@11.0.0: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} - dependencies: - '@types/mdast': 4.0.3 - mdast-util-to-markdown: 2.1.0 - unified: 11.0.4 - dev: true - /remark@15.0.1: + remark@15.0.1: resolution: {integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==} - dependencies: - '@types/mdast': 4.0.3 - remark-parse: 11.0.0 - remark-stringify: 11.0.0 - unified: 11.0.4 - transitivePeerDependencies: - - supports-color - dev: true - /repeat-string@1.6.1: + repeat-string@1.6.1: resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} engines: {node: '>=0.10'} - dev: true - /request-progress@3.0.0: + request-progress@3.0.0: resolution: {integrity: sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==} - dependencies: - throttleit: 1.0.1 - dev: true - /require-directory@2.1.1: + require-and-forget@1.0.1: + resolution: {integrity: sha512-Sea861D/seGo3cptxc857a34Df0oEijXit8Q3IDodiwZMzVmyXrRI9EgQQa3hjkhoEjNzCBvv0t/0fMgebmWLg==} + engines: {node: '>=6'} + + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - dev: true - /require-from-string@2.0.2: + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - dev: true - /require-main-filename@2.0.0: + require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - dev: true - /requires-port@1.0.0: + requirejs-config-file@4.0.0: + resolution: {integrity: sha512-jnIre8cbWOyvr8a5F2KuqBnY+SDA4NXr/hzEZJG79Mxm2WiFQz2dzhC8ibtPJS7zkmBEl1mxSwp5HhC1W4qpxw==} + engines: {node: '>=10.13.0'} + + requirejs@2.3.7: + resolution: {integrity: sha512-DouTG8T1WanGok6Qjg2SXuCMzszOo0eHeH9hDZ5Y4x8Je+9JB38HdTLT4/VA8OaUhBa0JPVHJ0pyBkM1z+pDsw==} + engines: {node: '>=0.4.0'} + hasBin: true + + requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - dev: true - /resolve-alpn@1.2.1: + resolve-alpn@1.2.1: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} - dev: true - /resolve-cwd@3.0.0: + resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} engines: {node: '>=8'} - dependencies: - resolve-from: 5.0.0 - dev: true - /resolve-from@4.0.0: + resolve-dependency-path@4.0.0: + resolution: {integrity: sha512-hlY1SybBGm5aYN3PC4rp15MzsJLM1w+MEA/4KU3UBPfz4S0lL3FL6mgv7JgaA8a+ZTeEQAiF1a1BuN2nkqiIlg==} + engines: {node: '>=18'} + + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - dev: true - /resolve-from@5.0.0: + resolve-from@5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} - dev: true - /resolve-pkg-maps@1.0.0: + resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - dev: true - /resolve.exports@2.0.2: + resolve.exports@2.0.2: resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} engines: {node: '>=10'} - dev: true - /resolve@1.19.0: - resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} - dependencies: - is-core-module: 2.13.0 - path-parse: 1.0.7 - dev: true - - /resolve@1.22.4: - resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} hasBin: true - dependencies: - is-core-module: 2.13.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - /responselike@2.0.1: + responselike@2.0.1: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} - dependencies: - lowercase-keys: 2.0.0 - dev: true - /restore-cursor@3.1.0: + restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: true - /restore-cursor@4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: true + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} - /ret@0.2.2: - resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==} - engines: {node: '>=4'} - dev: true + ret@0.4.3: + resolution: {integrity: sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==} + engines: {node: '>=10'} - /retry@0.13.1: + retry@0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} engines: {node: '>= 4'} - dev: true - /reusify@1.0.4: + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - /rfdc@1.3.1: - resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} - dev: true + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - /rimraf@2.7.1: + rimraf@2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - dependencies: - glob: 7.2.3 - dev: true - /rimraf@3.0.2: + rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - dependencies: - glob: 7.2.3 - dev: true - /rimraf@5.0.5: - resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==} - engines: {node: '>=14'} + rimraf@6.0.1: + resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} + engines: {node: 20 || >=22} hasBin: true - dependencies: - glob: 10.3.10 - dev: true - /robust-predicates@3.0.2: + robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} - dev: false - /rollup-plugin-terser@7.0.2(rollup@2.79.1): - resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} - deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser - peerDependencies: - rollup: ^2.0.0 - dependencies: - '@babel/code-frame': 7.24.2 - jest-worker: 26.6.2 - rollup: 2.79.1 - serialize-javascript: 4.0.0 - terser: 5.30.3 - dev: true - - /rollup-plugin-visualizer@5.12.0: - resolution: {integrity: sha512-8/NU9jXcHRs7Nnj07PF2o4gjxmm9lXIrZ8r175bT9dK8qoLlvKTwRMArRCMgpMGlq8CTLugRvEmyMeMXIU2pNQ==} - engines: {node: '>=14'} + rollup-plugin-visualizer@5.14.0: + resolution: {integrity: sha512-VlDXneTDaKsHIw8yzJAFWtrzguoJ/LnQ+lMpoVfYJ3jJF4Ihe5oYLAqLklIK/35lgUY+1yEzCkHyZ1j4A5w5fA==} + engines: {node: '>=18'} hasBin: true peerDependencies: + rolldown: 1.x rollup: 2.x || 3.x || 4.x peerDependenciesMeta: + rolldown: + optional: true rollup: optional: true - dependencies: - open: 8.4.2 - picomatch: 2.3.1 - source-map: 0.7.4 - yargs: 17.7.2 - dev: true - /rollup@2.79.1: - resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} + rollup@2.79.2: + resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} engines: {node: '>=10.0.0'} hasBin: true - optionalDependencies: - fsevents: 2.3.3 - dev: true - /rollup@4.14.2: - resolution: {integrity: sha512-WkeoTWvuBoFjFAhsEOHKRoZ3r9GfTyhh7Vff1zwebEFLEFjT1lG3784xEgKiTa7E+e70vsC81roVL2MP4tgEEQ==} + rollup@4.34.8: + resolution: {integrity: sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - dependencies: - '@types/estree': 1.0.5 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.14.2 - '@rollup/rollup-android-arm64': 4.14.2 - '@rollup/rollup-darwin-arm64': 4.14.2 - '@rollup/rollup-darwin-x64': 4.14.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.14.2 - '@rollup/rollup-linux-arm64-gnu': 4.14.2 - '@rollup/rollup-linux-arm64-musl': 4.14.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.14.2 - '@rollup/rollup-linux-riscv64-gnu': 4.14.2 - '@rollup/rollup-linux-s390x-gnu': 4.14.2 - '@rollup/rollup-linux-x64-gnu': 4.14.2 - '@rollup/rollup-linux-x64-musl': 4.14.2 - '@rollup/rollup-win32-arm64-msvc': 4.14.2 - '@rollup/rollup-win32-ia32-msvc': 4.14.2 - '@rollup/rollup-win32-x64-msvc': 4.14.2 - fsevents: 2.3.3 - dev: true - /rrweb-cssom@0.6.0: - resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} - dev: true + roughjs@4.6.6: + resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} - /run-parallel@1.2.0: + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - /rw@1.3.3: + rw@1.3.3: resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} - dev: false - /rxjs@7.8.1: + rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} - dependencies: - tslib: 2.6.2 - dev: true - /safe-array-concat@1.1.2: - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} engines: {node: '>=0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - isarray: 2.0.5 - dev: true - /safe-buffer@5.1.2: + safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true - /safe-buffer@5.2.1: + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - /safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-regex: 1.1.4 - dev: true - /safe-regex2@2.0.0: - resolution: {integrity: sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==} - dependencies: - ret: 0.2.2 - dev: true + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} - /safe-stable-stringify@2.4.3: - resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} + safe-regex2@3.1.0: + resolution: {integrity: sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug==} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} engines: {node: '>=10'} - dev: false - /safer-buffer@2.1.2: + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - /saxes@6.0.0: + sass-lookup@6.0.1: + resolution: {integrity: sha512-nl9Wxbj9RjEJA5SSV0hSDoU2zYGtE+ANaDS4OFUR7nYrquvBFvPKZZtQHe3lvnxCcylEDV00KUijjdMTUElcVQ==} + engines: {node: '>=18'} + hasBin: true + + saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} - dependencies: - xmlchars: 2.2.0 - dev: true - /schema-utils@3.3.0: + schema-utils@3.3.0: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} - dependencies: - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - ajv-keywords: 3.5.2(ajv@6.12.6) - dev: true - /schema-utils@4.2.0: + schema-utils@4.2.0: resolution: {integrity: sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==} engines: {node: '>= 12.13.0'} - dependencies: - '@types/json-schema': 7.0.15 - ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) - ajv-keywords: 5.1.0(ajv@8.12.0) - dev: true - /search-insights@2.13.0: - resolution: {integrity: sha512-Orrsjf9trHHxFRuo9/rzm0KIWmgzE8RMlZMzuhZOJ01Rnz3D0YBAe+V6473t6/H6c7irs6Lt48brULAiRWb3Vw==} - dev: true + schema-utils@4.3.0: + resolution: {integrity: sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==} + engines: {node: '>= 10.13.0'} - /secure-json-parse@2.7.0: + search-insights@2.17.2: + resolution: {integrity: sha512-zFNpOpUO+tY2D85KrxJ+aqwnIfdEGi06UH2+xEb+Bp9Mwznmauqc9djbnBibJO5mpfUPPa8st6Sx65+vbeO45g==} + + secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - dev: true - /select-hose@2.0.0: + select-hose@2.0.0: resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} - dev: true - /selfsigned@2.1.1: - resolution: {integrity: sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==} + selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} engines: {node: '>=10'} - dependencies: - node-forge: 1.3.1 - dev: true - /semver-store@0.3.0: - resolution: {integrity: sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==} - dev: true - - /semver@5.7.2: + semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true - dev: true - /semver@6.3.1: + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - dev: true - /semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - /semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} engines: {node: '>=10'} hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - /send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - dev: true - /serialize-javascript@4.0.0: - resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} - dependencies: - randombytes: 2.1.0 - dev: true + send@1.2.0: + resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} + engines: {node: '>= 18'} - /serialize-javascript@6.0.2: + serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} - dependencies: - randombytes: 2.1.0 - dev: true - /serve-index@1.9.1: + serve-index@1.9.1: resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} engines: {node: '>= 0.8.0'} - dependencies: - accepts: 1.3.8 - batch: 0.6.1 - debug: 2.6.9 - escape-html: 1.0.3 - http-errors: 1.6.3 - mime-types: 2.1.35 - parseurl: 1.3.3 - transitivePeerDependencies: - - supports-color - dev: true - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 - transitivePeerDependencies: - - supports-color - dev: true - /set-blocking@2.0.0: + serve-static@2.2.0: + resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==} + engines: {node: '>= 18'} + + set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: true - /set-cookie-parser@2.6.0: - resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} - dev: true + set-cookie-parser@2.7.1: + resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} - /set-function-length@1.2.2: + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - dev: true - /set-function-name@2.0.2: + set-function-name@2.0.2: resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - dev: true - /setprototypeof@1.1.0: + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + setprototypeof@1.1.0: resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} - dev: true - /setprototypeof@1.2.0: + setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: true - /shallow-clone@3.0.1: + shallow-clone@3.0.1: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} engines: {node: '>=8'} - dependencies: - kind-of: 6.0.3 - dev: true - /shebang-command@1.2.0: + sharp@0.33.5: + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shebang-command@1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} engines: {node: '>=0.10.0'} - dependencies: - shebang-regex: 1.0.0 - dev: true - /shebang-command@2.0.0: + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - /shebang-regex@1.0.0: + shebang-regex@1.0.0: resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} engines: {node: '>=0.10.0'} - dev: true - /shebang-regex@3.0.0: + shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - /shell-quote@1.8.1: - resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - dev: true - - /shiki@0.14.7: - resolution: {integrity: sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==} - dependencies: - ansi-sequence-parser: 1.1.1 - jsonc-parser: 3.2.1 - vscode-oniguruma: 1.7.0 - vscode-textmate: 8.0.0 - dev: true - - /shiki@1.3.0: - resolution: {integrity: sha512-9aNdQy/etMXctnPzsje1h1XIGm9YfRcSksKOGqZWXA/qP9G18/8fpz5Bjpma8bOgz3tqIpjERAd6/lLjFyzoww==} - dependencies: - '@shikijs/core': 1.3.0 - dev: true - - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + shell-quote@1.8.2: + resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.1 - dev: true - /siginfo@2.0.0: + shelljs@0.8.5: + resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} + engines: {node: '>=4'} + hasBin: true + + shiki@2.5.0: + resolution: {integrity: sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - dev: true - /signal-exit@3.0.7: + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - /signal-exit@4.1.0: + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - /simple-swizzle@0.2.2: + simple-bin-help@1.8.0: + resolution: {integrity: sha512-0LxHn+P1lF5r2WwVB/za3hLRIsYoLaNq1CXqjbrs3ZvLuvlWnRKrUjEWzV7umZL7hpQ7xULiQMV+0iXdRa5iFg==} + engines: {node: '>=14.16'} + + simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - dependencies: - is-arrayish: 0.3.2 - dev: false - /sirv@2.0.4: - resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} - engines: {node: '>= 10'} - dependencies: - '@polka/url': 1.0.0-next.25 - mrmime: 2.0.0 - totalist: 3.0.1 - dev: true + sirv@3.0.1: + resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} + engines: {node: '>=18'} - /sisteransi@1.0.5: + sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - dev: true - /slash@3.0.0: + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - dev: true - /slash@4.0.0: + slash@4.0.0: resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} engines: {node: '>=12'} - dev: true - /slash@5.1.0: + slash@5.1.0: resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} engines: {node: '>=14.16'} - dev: true - /slice-ansi@3.0.0: + slashes@3.0.12: + resolution: {integrity: sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==} + + slice-ansi@3.0.0: resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - dev: true - /slice-ansi@4.0.0: + slice-ansi@4.0.0: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - dev: true - /slice-ansi@5.0.0: + slice-ansi@5.0.0: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - is-fullwidth-code-point: 4.0.0 - dev: true - /slice-ansi@7.1.0: + slice-ansi@7.1.0: resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} engines: {node: '>=18'} - dependencies: - ansi-styles: 6.2.1 - is-fullwidth-code-point: 5.0.0 - dev: true - /sockjs@0.3.24: + smob@1.5.0: + resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} + + sockjs@0.3.24: resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} - dependencies: - faye-websocket: 0.11.4 - uuid: 8.3.2 - websocket-driver: 0.7.4 - dev: true - /sonic-boom@1.4.1: - resolution: {integrity: sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==} - dependencies: - atomic-sleep: 1.0.0 - flatstr: 1.0.12 - dev: true - - /sonic-boom@3.8.1: + sonic-boom@3.8.1: resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==} - dependencies: - atomic-sleep: 1.0.0 - dev: false - /source-map-js@1.0.1: + sonic-boom@4.2.0: + resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} + + source-map-js@1.0.1: resolution: {integrity: sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==} engines: {node: '>=0.10.0'} - dev: true - /source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - /source-map-support@0.5.13: + source-map-support@0.5.13: resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - /source-map-support@0.5.21: + source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - /source-map@0.1.43: + source-map@0.1.43: resolution: {integrity: sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ==} engines: {node: '>=0.8.0'} - requiresBuild: true - dependencies: - amdefine: 1.0.1 - dev: true - optional: true - /source-map@0.6.1: + source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - dev: true - /source-map@0.7.4: + source-map@0.7.4: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} - dev: true - /source-map@0.8.0-beta.0: + source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} - dependencies: - whatwg-url: 7.1.0 - dev: true - /sourcemap-codec@1.4.8: + sourcemap-codec@1.4.8: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} deprecated: Please use @jridgewell/sourcemap-codec instead - dev: true - /spawn-command@0.0.2: - resolution: {integrity: sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==} - dev: true + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - /spawn-wrap@2.0.0: + spawn-wrap@2.0.0: resolution: {integrity: sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==} engines: {node: '>=8'} - dependencies: - foreground-child: 2.0.0 - is-windows: 1.0.2 - make-dir: 3.1.0 - rimraf: 3.0.2 - signal-exit: 3.0.7 - which: 2.0.2 - dev: true - /spdx-correct@3.2.0: + spawndamnit@3.0.1: + resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} + + spdx-correct@3.2.0: resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.17 - dev: true - /spdx-exceptions@2.5.0: + spdx-exceptions@2.5.0: resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - dev: true - /spdx-expression-parse@3.0.1: + spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.17 - dev: true - /spdx-expression-parse@4.0.0: + spdx-expression-parse@4.0.0: resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.17 - dev: true - /spdx-license-ids@3.0.17: - resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} - dev: true + spdx-license-ids@3.0.21: + resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} - /spdy-transport@3.0.0: + spdy-transport@3.0.0: resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} - dependencies: - debug: 4.3.4(supports-color@8.1.1) - detect-node: 2.1.0 - hpack.js: 2.1.6 - obuf: 1.1.2 - readable-stream: 3.6.2 - wbuf: 1.7.3 - transitivePeerDependencies: - - supports-color - dev: true - /spdy@4.0.2: + spdy@4.0.2: resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} engines: {node: '>=6.0.0'} - dependencies: - debug: 4.3.4(supports-color@8.1.1) - handle-thing: 2.0.1 - http-deceiver: 1.2.7 - select-hose: 2.0.0 - spdy-transport: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true - /speakingurl@14.0.1: + speakingurl@14.0.1: resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} engines: {node: '>=0.10.0'} - dev: true - /split2@4.2.0: + spec-change@1.11.11: + resolution: {integrity: sha512-wSxi1XKeNr8JxBlYj13Lw8TTMpojYU2zRlkmyXl0kHp+xGkwYUpXaVXcofiEmEqrq1HoGg7pwKEzvMjYcQubtw==} + hasBin: true + + split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} - dev: false - /split@0.3.3: + split@0.3.3: resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} - dependencies: - through: 2.3.8 - dev: true - /sprintf-js@1.0.3: + sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true - /sshpk@1.18.0: + sshpk@1.18.0: resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} engines: {node: '>=0.10.0'} hasBin: true - 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 - dev: true - /ssim.js@3.5.0: + ssim.js@3.5.0: resolution: {integrity: sha512-Aj6Jl2z6oDmgYFFbQqK7fght19bXdOxY7Tj03nF+03M9gCBAjeIiO8/PlEGMfKDwYpw4q6iBqVq2YuREorGg/g==} - dev: true - /stack-utils@2.0.6: + stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} - dependencies: - escape-string-regexp: 2.0.0 - dev: true - /stackback@0.0.2: + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - dev: true - /start-server-and-test@2.0.3: - resolution: {integrity: sha512-QsVObjfjFZKJE6CS6bSKNwWZCKBG6975/jKRPPGFfFh+yOQglSeGXiNWjzgQNXdphcBI9nXbyso9tPfX4YAUhg==} + start-server-and-test@2.0.10: + resolution: {integrity: sha512-nZphcfcqGqwk74lbZkqSwClkYz+M5ZPGOMgWxNVJrdztPKN96qe6HooRu6L3TpwITn0lKJJdKACqHbJtqythOQ==} engines: {node: '>=16'} hasBin: true - dependencies: - arg: 5.0.2 - bluebird: 3.7.2 - check-more-types: 2.24.0 - debug: 4.3.4(supports-color@8.1.1) - execa: 5.1.1 - lazy-ass: 1.6.0 - ps-tree: 1.2.0 - wait-on: 7.2.0(debug@4.3.4) - transitivePeerDependencies: - - supports-color - dev: true - /statuses@1.5.0: + statuses@1.5.0: resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} engines: {node: '>= 0.6'} - dev: true - /statuses@2.0.1: + statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} - dev: true - /std-env@3.7.0: - resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} - dev: true + std-env@3.8.0: + resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} - /stream-combiner@0.0.4: + stop-iteration-iterator@1.0.0: + resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} + engines: {node: '>= 0.4'} + + stream-combiner@0.0.4: resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} - dependencies: - duplexer: 0.1.2 - dev: true - /string-argv@0.3.2: + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} - dev: true - /string-length@4.0.2: + string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 - dev: true - /string-similarity@4.0.4: - resolution: {integrity: sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==} - deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. - dev: true - - /string-width@4.2.3: + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - /string-width@5.1.2: + string-width@5.1.2: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - /string-width@7.1.0: - resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} - dependencies: - emoji-regex: 10.3.0 - get-east-asian-width: 1.2.0 - strip-ansi: 7.1.0 - dev: true - /string.prototype.matchall@4.0.11: - resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - regexp.prototype.flags: 1.5.2 - set-function-name: 2.0.2 - side-channel: 1.0.6 - dev: true - /string.prototype.trim@1.2.9: - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - dev: true - /string.prototype.trimend@1.0.8: - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} - /string.prototype.trimstart@1.0.8: + string.prototype.trimstart@1.0.8: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - /string_decoder@1.1.1: + string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - dev: true - /string_decoder@1.3.0: + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - /stringify-object@3.3.0: + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + stringify-object@3.3.0: resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==} engines: {node: '>=4'} - dependencies: - get-own-enumerable-property-symbols: 3.0.2 - is-obj: 1.0.1 - is-regexp: 1.0.0 - dev: true - /strip-ansi@3.0.1: + strip-ansi@3.0.1: resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} engines: {node: '>=0.10.0'} - dependencies: - ansi-regex: 2.1.1 - dev: true - /strip-ansi@6.0.1: + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - /strip-ansi@7.1.0: + strip-ansi@7.1.0: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - /strip-bom@4.0.0: + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-bom@4.0.0: resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} engines: {node: '>=8'} - dev: true - /strip-comments@2.0.1: + strip-comments@2.0.1: resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==} engines: {node: '>=10'} - dev: true - /strip-eof@1.0.0: + strip-eof@1.0.0: resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} engines: {node: '>=0.10.0'} - dev: true - /strip-final-newline@2.0.0: + strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} - dev: true - /strip-final-newline@3.0.0: + strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} - dev: true - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - dependencies: - min-indent: 1.0.1 - dev: true + strip-indent@4.0.0: + resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==} + engines: {node: '>=12'} - /strip-json-comments@3.1.1: + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - dev: true - /strip-literal@2.1.0: - resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} - dependencies: - js-tokens: 9.0.0 - dev: true + stylis@4.3.6: + resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} - /stylis@4.3.1: - resolution: {integrity: sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==} - dev: false + stylus-lookup@6.0.0: + resolution: {integrity: sha512-RaWKxAvPnIXrdby+UWCr1WRfa+lrPMSJPySte4Q6a+rWyjeJyFOLJxr5GrAVfcMCsfVlCuzTAJ/ysYT8p8do7Q==} + engines: {node: '>=18'} + hasBin: true - /sucrase@3.35.0: + sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} hasBin: true - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - commander: 4.1.1 - glob: 10.3.12 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.6 - ts-interface-checker: 0.1.13 - dev: false - /supports-color@2.0.0: + superjson@2.2.2: + resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==} + engines: {node: '>=16'} + + supports-color@2.0.0: resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} engines: {node: '>=0.8.0'} - dev: true - /supports-color@5.5.0: + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - /supports-color@7.2.0: + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - /supports-color@8.1.1: + supports-color@8.1.1: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} - dependencies: - has-flag: 4.0.0 - /supports-preserve-symlinks-flag@1.0.0: + supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - /symbol-tree@3.2.4: + symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - dev: true - /synckit@0.9.0: - resolution: {integrity: sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==} + synckit@0.10.3: + resolution: {integrity: sha512-R1urvuyiTaWfeCggqEvpDJwAlDVdsT9NM+IP//Tk2x7qHCkSvBk/fwFgw/TLAHzZlrAnnazMcRw0ZD8HlYFTEQ==} engines: {node: ^14.18.0 || >=16.0.0} - dependencies: - '@pkgr/core': 0.1.1 - tslib: 2.6.2 - dev: true - /tabbable@6.2.0: + synckit@0.9.2: + resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} + engines: {node: ^14.18.0 || >=16.0.0} + + tabbable@6.2.0: resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} - dev: true - /tailwindcss@3.4.3: - resolution: {integrity: sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==} + tailwindcss@3.4.17: + resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} engines: {node: '>=14.0.0'} hasBin: true - dependencies: - '@alloc/quick-lru': 5.2.0 - arg: 5.0.2 - chokidar: 3.6.0 - didyoumean: 1.2.2 - dlv: 1.1.3 - fast-glob: 3.3.2 - glob-parent: 6.0.2 - is-glob: 4.0.3 - jiti: 1.21.0 - lilconfig: 2.1.0 - micromatch: 4.0.5 - normalize-path: 3.0.0 - object-hash: 3.0.0 - picocolors: 1.0.0 - postcss: 8.4.38 - postcss-import: 15.1.0(postcss@8.4.38) - postcss-js: 4.0.1(postcss@8.4.38) - postcss-load-config: 4.0.2(postcss@8.4.38) - postcss-nested: 6.0.1(postcss@8.4.38) - postcss-selector-parser: 6.0.16 - resolve: 1.22.8 - sucrase: 3.35.0 - transitivePeerDependencies: - - ts-node - dev: false - /tapable@2.2.1: + tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} - dev: true - /teen_process@1.16.0: + teen_process@1.16.0: resolution: {integrity: sha512-RnW7HHZD1XuhSTzD3djYOdIl1adE3oNEprE3HOFFxWs5m4FZsqYRhKJ4mDU2udtNGMLUS7jV7l8vVRLWAvmPDw==} engines: {'0': node} - dependencies: - '@babel/runtime': 7.24.4 - bluebird: 3.7.2 - lodash: 4.17.21 - shell-quote: 1.8.1 - source-map-support: 0.5.21 - which: 2.0.2 - dev: true - /temp-dir@2.0.0: + temp-dir@2.0.0: resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} engines: {node: '>=8'} - dev: true - /tempy@0.6.0: + tempy@0.6.0: resolution: {integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==} engines: {node: '>=10'} - dependencies: - is-stream: 2.0.1 - temp-dir: 2.0.0 - type-fest: 0.16.0 - unique-string: 2.0.0 - dev: true - /term-img@4.1.0: + term-img@4.1.0: resolution: {integrity: sha512-DFpBhaF5j+2f7kheKFc1ajsAUUDGOaNPpKPtiIMxlbfud6mvfFZuWGnTRpaujUa5J7yl6cIw/h6nyr4mSsENPg==} engines: {node: '>=8'} - dependencies: - ansi-escapes: 4.3.2 - iterm2-version: 4.2.0 - dev: true - /terser-webpack-plugin@5.3.10(esbuild@0.20.2)(webpack@5.91.0): + term-size@2.2.1: + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} + engines: {node: '>=8'} + + terser-webpack-plugin@5.3.10: resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -14477,574 +8920,379 @@ packages: optional: true uglify-js: optional: true - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - esbuild: 0.20.2 - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.2 - terser: 5.29.2 - webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@4.10.0) - dev: true - /terser@5.29.2: - resolution: {integrity: sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==} + terser@5.34.1: + resolution: {integrity: sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==} engines: {node: '>=10'} hasBin: true - dependencies: - '@jridgewell/source-map': 0.3.6 - acorn: 8.11.3 - commander: 2.20.3 - source-map-support: 0.5.21 - dev: true - /terser@5.30.3: - resolution: {integrity: sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA==} + terser@5.39.0: + resolution: {integrity: sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==} engines: {node: '>=10'} hasBin: true - dependencies: - '@jridgewell/source-map': 0.3.6 - acorn: 8.11.3 - commander: 2.20.3 - source-map-support: 0.5.21 - dev: true - /test-exclude@6.0.0: + test-exclude@6.0.0: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 - dev: true - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true + test-exclude@7.0.1: + resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} + engines: {node: '>=18'} - /thenify-all@1.6.0: + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} - dependencies: - thenify: 3.3.1 - /thenify@3.3.1: + thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - dependencies: - any-promise: 1.3.0 - /thread-stream@2.4.1: - resolution: {integrity: sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==} - dependencies: - real-require: 0.2.0 - dev: false + thread-stream@2.7.0: + resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==} - /throat@6.0.2: + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + + throat@6.0.2: resolution: {integrity: sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==} - dev: true - /throttleit@1.0.1: + throttleit@1.0.1: resolution: {integrity: sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==} - dev: true - /through@2.3.8: + through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: true - /thunky@1.1.0: + thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} - dev: true - /timers-ext@0.1.7: - resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==} - dependencies: - es5-ext: 0.10.64 - next-tick: 1.1.0 - dev: true + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - /tiny-lru@8.0.2: - resolution: {integrity: sha512-ApGvZ6vVvTNdsmt676grvCkUCGwzG9IqXma5Z07xJgiC5L7akUMof5U8G2JTI9Rz/ovtVhJBlY6mNhEvtjzOIg==} - engines: {node: '>=6'} - dev: true + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - /tinybench@2.7.0: - resolution: {integrity: sha512-Qgayeb106x2o4hNzNjsZEfFziw8IbKqtbXBjVh7VIZfBxfD5M4gWtpyx5+YTae2gJ6Y6Dz/KLepiv16RFeQWNA==} - dev: true + tinyglobby@0.2.12: + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + engines: {node: '>=12.0.0'} - /tinypool@0.8.4: - resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} engines: {node: '>=14.0.0'} - dev: true - /tinyspy@2.2.1: - resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} - dev: true - /tmp@0.2.3: + tldts-core@6.1.78: + resolution: {integrity: sha512-jS0svNsB99jR6AJBmfmEWuKIgz91Haya91Z43PATaeHJ24BkMoNRb/jlaD37VYjb0mYf6gRL/HOnvS1zEnYBiw==} + + tldts@6.1.78: + resolution: {integrity: sha512-fSgYrW0ITH0SR/CqKMXIruYIPpNu5aDgUp22UhYoSrnUQwc7SBqifEBFNce7AAcygUPBo6a/gbtcguWdmko4RQ==} + hasBin: true + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + tmp@0.2.3: resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} engines: {node: '>=14.14'} - dev: true - /tmpl@1.0.5: + tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - dev: true - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - - /to-regex-range@5.0.1: + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - /toidentifier@1.0.1: + toad-cache@3.7.0: + resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} + engines: {node: '>=12'} + + toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - dev: true - /totalist@3.0.1: + totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} - dev: true - /tough-cookie@4.1.3: - resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} - engines: {node: '>=6'} - dependencies: - psl: 1.9.0 - punycode: 2.3.1 - universalify: 0.2.0 - url-parse: 1.5.10 - dev: true + tough-cookie@5.1.1: + resolution: {integrity: sha512-Ek7HndSVkp10hmHP9V4qZO1u+pn1RU5sI0Fw+jCU3lyvuMZcgqsNgc6CmJJZyByK4Vm/qotGRJlfgAX8q+4JiA==} + engines: {node: '>=16'} - /tr46@0.0.3: + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true - /tr46@1.0.1: + tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} - dependencies: - punycode: 2.3.1 - dev: true - /tr46@5.0.0: + tr46@5.0.0: resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==} engines: {node: '>=18'} - dependencies: - punycode: 2.3.1 - dev: true - /traverse@0.3.9: + traverse@0.3.9: resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} - dev: true - /tree-kill@1.2.2: + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true - dev: true - /trough@2.2.0: + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} - dev: true - /ts-api-utils@1.3.0(typescript@5.4.5): + ts-api-utils@1.3.0: resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} peerDependencies: typescript: '>=4.2.0' - dependencies: - typescript: 5.4.5 - dev: true - /ts-dedent@2.2.0: + ts-api-utils@2.0.1: + resolution: {integrity: sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + ts-dedent@2.2.0: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} - dev: false - /ts-interface-checker@0.1.13: + ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - dev: false - /ts-toolbelt@6.15.5: + ts-toolbelt@6.15.5: resolution: {integrity: sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==} - dev: false - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true + tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: true + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - /tsutils@3.21.0(typescript@5.4.5): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 5.4.5 - dev: true - - /tsx@4.7.2: - resolution: {integrity: sha512-BCNd4kz6fz12fyrgCTEdZHGJ9fWTGeUzXmQysh0RVocDY3h4frk05ZNCXSy4kIenF7y/QnrdiVpTsyNRn6vlAw==} + tsx@4.19.3: + resolution: {integrity: sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==} engines: {node: '>=18.0.0'} hasBin: true - dependencies: - esbuild: 0.19.12 - get-tsconfig: 4.7.3 - optionalDependencies: - fsevents: 2.3.3 - dev: true - /tunnel-agent@0.6.0: + tunnel-agent@0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} - dependencies: - safe-buffer: 5.2.1 - dev: true - /tweetnacl@0.14.5: + tunnel@0.0.6: + resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} + engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} + + tweetnacl@0.14.5: resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} - dev: true - /type-check@0.4.0: + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - /type-detect@4.0.8: + type-detect@4.0.8: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} - dev: true - /type-fest@0.16.0: + type-fest@0.16.0: resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} engines: {node: '>=10'} - dev: true - /type-fest@0.20.2: + type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} - dev: true - /type-fest@0.21.3: + type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - dev: true - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true - - /type-fest@0.8.1: + type-fest@0.8.1: resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} - dev: true - /type-fest@1.4.0: - resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} - engines: {node: '>=10'} - dev: true - - /type-fest@4.15.0: - resolution: {integrity: sha512-tB9lu0pQpX5KJq54g+oHOLumOx+pMep4RaM6liXh2PKmVRFF+/vAtUP0ZaJ0kOySfVNjF6doBWPHhBhISKdlIA==} + type-fest@4.35.0: + resolution: {integrity: sha512-2/AwEFQDFEy30iOLjrvHDIH7e4HEWH+f1Yl1bI5XMqzuoCUqwYCdxachgsgv0og/JdVZUhbfjcJAoHj5L1753A==} engines: {node: '>=16'} - dev: true - /type-is@1.6.18: + type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - dev: true - /type@2.7.2: - resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} - dev: true + type-is@2.0.1: + resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} + engines: {node: '>= 0.6'} - /typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-typed-array: 1.1.13 - dev: true - /typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - dev: true - /typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - dev: true - /typed-array-length@1.0.6: - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - possible-typed-array-names: 1.0.0 - dev: true - /typedarray-to-buffer@3.1.5: + typedarray-to-buffer@3.1.5: resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} - dependencies: - is-typedarray: 1.0.0 - dev: true - /typedoc-plugin-markdown@3.17.1(typedoc@0.25.13): - resolution: {integrity: sha512-QzdU3fj0Kzw2XSdoL15ExLASt2WPqD7FbLeaqwT70+XjKyTshBnUlQA5nNREO1C2P8Uen0CDjsBLMsCQ+zd0lw==} + typedoc-plugin-markdown@4.4.2: + resolution: {integrity: sha512-kJVkU2Wd+AXQpyL6DlYXXRrfNrHrEIUgiABWH8Z+2Lz5Sq6an4dQ/hfvP75bbokjNDUskOdFlEEm/0fSVyC7eg==} + engines: {node: '>= 18'} peerDependencies: - typedoc: '>=0.24.0' - dependencies: - handlebars: 4.7.8 - typedoc: 0.25.13(typescript@5.4.5) - dev: true + typedoc: 0.27.x - /typedoc@0.25.13(typescript@5.4.5): - resolution: {integrity: sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==} - engines: {node: '>= 16'} + typedoc@0.27.8: + resolution: {integrity: sha512-q0/2TUunNEDmWkn23ULKGXieK8cgGuAmBUXC/HcZ/rgzMI9Yr4Nq3in1K1vT1NZ9zx6M78yTk3kmIPbwJgK5KA==} + engines: {node: '>= 18'} hasBin: true peerDependencies: - typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x - dependencies: - lunr: 2.3.9 - marked: 4.3.0 - minimatch: 9.0.4 - shiki: 0.14.7 - typescript: 5.4.5 - dev: true + typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x - /typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + typescript-eslint@8.29.1: + resolution: {integrity: sha512-f8cDkvndhbQMPcysk6CUSGBWV+g1utqdn71P5YKwMumVMOG/5k7cHq0KyG4O52nB0oKS4aN2Tp5+wB4APJGC+w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + typescript@5.7.3: + resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} engines: {node: '>=14.17'} hasBin: true - /uc.micro@1.0.6: + uc.micro@1.0.6: resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} - dev: true - /ufo@1.5.3: - resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} - dev: true + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} - /uglify-js@3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} engines: {node: '>=0.8.0'} hasBin: true - dev: true - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - dependencies: - call-bind: 1.0.7 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: true + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} - /unconfig@0.3.12: - resolution: {integrity: sha512-oDtfWDC0TMYFuwdt7E7CaqYZGqq1wAiC12PRTFe/93IkgNi+wVlF/LCjcD/bgNkGoopb0RsU363Ge3YXy7NGSw==} - dependencies: - '@antfu/utils': 0.7.7 - defu: 6.1.4 - jiti: 1.21.0 - mlly: 1.6.1 - dev: true + unconfig@7.0.0: + resolution: {integrity: sha512-G5CJSoG6ZTxgzCJblEfgpdRK2tos9+UdD2WtecDUVfImzQ0hFjwpH5RVvGMhP4pRpC9ML7NrC4qBsBl0Ttj35A==} - /underscore@1.1.7: + underscore@1.1.7: resolution: {integrity: sha512-w4QtCHoLBXw1mjofIDoMyexaEdWGMedWNDhlWTtT1V1lCRqi65Pnoygkh6+WRdr+Bm8ldkBNkNeCsXGMlQS9HQ==} - dev: true - /undici-types@5.26.5: + undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true - /unicode-canonical-property-names-ecmascript@2.0.0: - resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + + undici@5.28.4: + resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} + engines: {node: '>=14.0'} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} engines: {node: '>=4'} - dev: true - /unicode-match-property-ecmascript@2.0.0: + unicode-match-property-ecmascript@2.0.0: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} engines: {node: '>=4'} - dependencies: - unicode-canonical-property-names-ecmascript: 2.0.0 - unicode-property-aliases-ecmascript: 2.1.0 - dev: true - /unicode-match-property-value-ecmascript@2.1.0: - resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} + unicode-match-property-value-ecmascript@2.2.0: + resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} engines: {node: '>=4'} - dev: true - /unicode-property-aliases-ecmascript@2.1.0: + unicode-property-aliases-ecmascript@2.1.0: resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} - dev: true - /unicorn-magic@0.1.0: + unicorn-magic@0.1.0: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} engines: {node: '>=18'} - dev: true - /unified@11.0.4: + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + + unified@11.0.4: resolution: {integrity: sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==} - dependencies: - '@types/unist': 3.0.2 - bail: 2.0.2 - devlop: 1.1.0 - extend: 3.0.2 - is-plain-obj: 4.1.0 - trough: 2.2.0 - vfile: 6.0.1 - dev: true - /unique-string@2.0.0: + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unique-string@2.0.0: resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} engines: {node: '>=8'} - dependencies: - crypto-random-string: 2.0.0 - dev: true - /unique-string@3.0.0: - resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} - engines: {node: '>=12'} - dependencies: - crypto-random-string: 4.0.0 - dev: true - - /unist-util-flatmap@1.0.0: + unist-util-flatmap@1.0.0: resolution: {integrity: sha512-IG32jcKJlhARCYT2LsYPJWdoXYkzz3ESAdl1aa2hn9Auh+cgUmU6wgkII4yCc/1GgeWibRdELdCZh/p3QKQ1dQ==} - dev: true - /unist-util-inspect@8.0.0: + unist-util-inspect@8.0.0: resolution: {integrity: sha512-/3Wn/wU6/H6UEo4FoYUeo8KUePN8ERiZpQYFWYoihOsr1DoDuv80PeB0hobVZyYSvALa2e556bG1A1/AbwU4yg==} - dependencies: - '@types/unist': 3.0.2 - dev: true - /unist-util-is@6.0.0: + unist-util-is@6.0.0: resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} - dependencies: - '@types/unist': 3.0.2 - dev: true - /unist-util-stringify-position@2.0.3: + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} - dependencies: - '@types/unist': 2.0.10 - dev: true - /unist-util-stringify-position@4.0.0: + unist-util-stringify-position@4.0.0: resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} - dependencies: - '@types/unist': 3.0.2 - /unist-util-visit-parents@6.0.1: + unist-util-visit-parents@6.0.1: resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} - dependencies: - '@types/unist': 3.0.2 - unist-util-is: 6.0.0 - dev: true - /unist-util-visit@5.0.0: + unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} - dependencies: - '@types/unist': 3.0.2 - unist-util-is: 6.0.0 - unist-util-visit-parents: 6.0.1 - dev: true - /universalify@0.1.2: + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} - dev: true - /universalify@0.2.0: - resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} - engines: {node: '>= 4.0.0'} - dev: true - - /universalify@2.0.1: + universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} - dev: true - /unocss@0.59.2(postcss@8.4.38)(rollup@2.79.1)(vite@5.2.8): - resolution: {integrity: sha512-9puB1L+VxpCAgeidkd67otmA0pbqNPxBPT/8l6gncF0i2RE0WkKITlMflP0PhLNpOdHUfUWb9Cdj1aVnjRnXFA==} + unocss@66.0.0: + resolution: {integrity: sha512-SHstiv1s7zGPSjzOsADzlwRhQM+6817+OqQE3Fv+N/nn2QLNx1bi3WXybFfz5tWkzBtyTZlwdPmeecsIs1yOCA==} engines: {node: '>=14'} peerDependencies: - '@unocss/webpack': 0.59.2 - vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + '@unocss/webpack': 66.0.0 + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 peerDependenciesMeta: '@unocss/webpack': optional: true vite: optional: true - dependencies: - '@unocss/astro': 0.59.2(rollup@2.79.1)(vite@5.2.8) - '@unocss/cli': 0.59.2(rollup@2.79.1) - '@unocss/core': 0.59.2 - '@unocss/extractor-arbitrary-variants': 0.59.2 - '@unocss/postcss': 0.59.2(postcss@8.4.38) - '@unocss/preset-attributify': 0.59.2 - '@unocss/preset-icons': 0.59.2 - '@unocss/preset-mini': 0.59.2 - '@unocss/preset-tagify': 0.59.2 - '@unocss/preset-typography': 0.59.2 - '@unocss/preset-uno': 0.59.2 - '@unocss/preset-web-fonts': 0.59.2 - '@unocss/preset-wind': 0.59.2 - '@unocss/reset': 0.59.2 - '@unocss/transformer-attributify-jsx': 0.59.2 - '@unocss/transformer-attributify-jsx-babel': 0.59.2 - '@unocss/transformer-compile-class': 0.59.2 - '@unocss/transformer-directives': 0.59.2 - '@unocss/transformer-variant-group': 0.59.2 - '@unocss/vite': 0.59.2(rollup@2.79.1)(vite@5.2.8) - vite: 5.2.8(@types/node@20.12.7) - transitivePeerDependencies: - - postcss - - rollup - - supports-color - dev: true - /unpipe@1.0.0: + unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - dev: true - /unplugin-vue-components@0.26.0(rollup@2.79.1)(vue@3.4.21): - resolution: {integrity: sha512-s7IdPDlnOvPamjunVxw8kNgKNK8A5KM1YpK5j/p97jEKTjlPNrA0nZBiSfAKKlK1gWZuyWXlKL5dk3EDw874LQ==} + unplugin-utils@0.2.4: + resolution: {integrity: sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==} + engines: {node: '>=18.12.0'} + + unplugin-vue-components@28.4.0: + resolution: {integrity: sha512-fnamX2RiKM30nPK4tihEas+bHnbLICo6MmOiP4jGg7fAlgNEuaLvN9yx96JwZDOYfLQcrNzikDdPhZ8k6pkhMg==} engines: {node: '>=14'} peerDependencies: '@babel/parser': ^7.15.8 @@ -15055,190 +9303,92 @@ packages: optional: true '@nuxt/kit': optional: true - dependencies: - '@antfu/utils': 0.7.6 - '@rollup/pluginutils': 5.1.0(rollup@2.79.1) - chokidar: 3.6.0 - debug: 4.3.4(supports-color@8.1.1) - fast-glob: 3.3.2 - local-pkg: 0.4.3 - magic-string: 0.30.5 - minimatch: 9.0.3 - resolve: 1.22.4 - unplugin: 1.4.0 - vue: 3.4.21(typescript@5.4.5) - transitivePeerDependencies: - - rollup - - supports-color - dev: true - /unplugin@1.4.0: - resolution: {integrity: sha512-5x4eIEL6WgbzqGtF9UV8VEC/ehKptPXDS6L2b0mv4FRMkJxRtjaJfOWDd6a8+kYbqsjklix7yWP0N3SUepjXcg==} - dependencies: - acorn: 8.11.3 - chokidar: 3.6.0 - webpack-sources: 3.2.3 - webpack-virtual-modules: 0.5.0 - dev: true + unplugin@2.2.0: + resolution: {integrity: sha512-m1ekpSwuOT5hxkJeZGRxO7gXbXT3gF26NjQ7GdVHoLoF8/nopLcd/QfPigpCy7i51oFHiRJg/CyHhj4vs2+KGw==} + engines: {node: '>=18.12.0'} - /untildify@4.0.0: + untildify@4.0.0: resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} engines: {node: '>=8'} - dev: true - /upath@1.2.0: + upath@1.2.0: resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} engines: {node: '>=4'} - dev: true - /update-browserslist-db@1.0.13(browserslist@4.23.0): - resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + update-browserslist-db@1.1.2: + resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.23.0 - escalade: 3.1.2 - picocolors: 1.0.0 - dev: true - /uri-js@4.4.1: + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - dev: true - /url-parse@1.5.10: - resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} - dependencies: - querystringify: 2.2.0 - requires-port: 1.0.0 - dev: true - - /util-deprecate@1.0.2: + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - /utils-merge@1.0.1: + utils-merge@1.0.1: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} - dev: true - /uuid@8.3.2: + uuid@11.1.0: + resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} + hasBin: true + + uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true - dev: true - /uuid@9.0.1: + uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true - dev: false - /v8-to-istanbul@9.2.0: - resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - '@types/istanbul-lib-coverage': 2.0.6 - convert-source-map: 2.0.0 - dev: true - /validate-npm-package-license@3.0.4: + validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - dev: true - /vary@1.1.2: + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - dev: true - /verror@1.10.0: + verror@1.10.0: resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} engines: {'0': node >=0.6.0} - dependencies: - assert-plus: 1.0.0 - core-util-is: 1.0.2 - extsprintf: 1.3.0 - dev: true - /vfile-message@4.0.2: + vfile-message@4.0.2: resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} - dependencies: - '@types/unist': 3.0.2 - unist-util-stringify-position: 4.0.0 - dev: true - /vfile@6.0.1: - resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} - dependencies: - '@types/unist': 3.0.2 - unist-util-stringify-position: 4.0.0 - vfile-message: 4.0.2 - dev: true + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - /vite-node@1.5.0(@types/node@20.12.7): - resolution: {integrity: sha512-tV8h6gMj6vPzVCa7l+VGq9lwoJjW8Y79vst8QZZGiuRAfijU+EEWuc0kFpmndQrWhMMhet1jdSF+40KSZUqIIw==} - engines: {node: ^18.0.0 || >=20.0.0} + vite-node@3.0.6: + resolution: {integrity: sha512-s51RzrTkXKJrhNbUzQRsarjmAae7VmMPAsRT7lppVpIg6mK3zGthP9Hgz0YQQKuNcF+Ii7DfYk3Fxz40jRmePw==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true - dependencies: - cac: 6.7.14 - debug: 4.3.4(supports-color@8.1.1) - pathe: 1.1.2 - picocolors: 1.0.0 - vite: 5.2.8(@types/node@20.12.7) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - /vite-plugin-istanbul@6.0.0(vite@5.2.8): - resolution: {integrity: sha512-Vwh2XdesjcLwaPbHSOiWHh+0s7CNovQTPEjUCTkqmJUe0FN2TKsOp0qpoaklOuwrKlL9elhD5fPFxi5lmG62zA==} + vite-plugin-istanbul@7.0.0: + resolution: {integrity: sha512-UAXSyS0zslaSP1yCdO54YwrTkoY3VxCBH8y8MAy3I+E6uqT07LEsVOFEHueeDJ+vyyeaA9Rkqz/j6LACJTzTKw==} peerDependencies: vite: '>=4 <=6' - dependencies: - '@istanbuljs/load-nyc-config': 1.1.0 - espree: 10.0.1 - istanbul-lib-instrument: 6.0.2 - picocolors: 1.0.0 - source-map: 0.7.4 - test-exclude: 6.0.0 - vite: 5.2.8(@types/node@20.12.7) - transitivePeerDependencies: - - supports-color - dev: true - /vite-plugin-pwa@0.19.8(vite@5.2.8)(workbox-build@7.0.0)(workbox-window@7.0.0): - resolution: {integrity: sha512-e1oK0dfhzhDhY3VBuML6c0h8Xfx6EkOVYqolj7g+u8eRfdauZe5RLteCIA/c5gH0CBQ0CNFAuv/AFTx4Z7IXTw==} + vite-plugin-pwa@1.0.0: + resolution: {integrity: sha512-X77jo0AOd5OcxmWj3WnVti8n7Kw2tBgV1c8MCXFclrSlDV23ePzv2eTDIALXI2Qo6nJ5pZJeZAuX0AawvRfoeA==} engines: {node: '>=16.0.0'} peerDependencies: - '@vite-pwa/assets-generator': ^0.2.4 - vite: ^3.1.0 || ^4.0.0 || ^5.0.0 - workbox-build: ^7.0.0 - workbox-window: ^7.0.0 + '@vite-pwa/assets-generator': ^1.0.0 + vite: ^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 + workbox-build: ^7.3.0 + workbox-window: ^7.3.0 peerDependenciesMeta: '@vite-pwa/assets-generator': optional: true - dependencies: - debug: 4.3.4(supports-color@8.1.1) - fast-glob: 3.3.2 - pretty-bytes: 6.1.1 - vite: 5.2.8(@types/node@20.12.7) - workbox-build: 7.0.0 - workbox-window: 7.0.0 - transitivePeerDependencies: - - supports-color - dev: true - /vite@5.2.8(@types/node@20.12.7): - resolution: {integrity: sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==} + vite@5.4.14: + resolution: {integrity: sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -15246,6 +9396,7 @@ packages: less: '*' lightningcss: ^1.21.0 sass: '*' + sass-embedded: '*' stylus: '*' sugarss: '*' terser: ^5.4.0 @@ -15258,40 +9409,65 @@ packages: optional: true sass: optional: true + sass-embedded: + optional: true stylus: optional: true sugarss: optional: true terser: optional: true - dependencies: - '@types/node': 20.12.7 - esbuild: 0.20.2 - postcss: 8.4.38 - rollup: 4.14.2 - optionalDependencies: - fsevents: 2.3.3 - dev: true - /vitepress-plugin-search@1.0.4-alpha.22(flexsearch@0.7.43)(vitepress@1.1.0)(vue@3.4.21): + vite@6.1.1: + resolution: {integrity: sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitepress-plugin-search@1.0.4-alpha.22: resolution: {integrity: sha512-IAOEJu+kjVY+0pb6/PeRjIbr175HFFbnMdLmLjqcy7VWxkabIRZbLoQL1VUYDZl804o/Or+GaX02gsiMOnVxFA==} engines: {node: ^14.13.1 || ^16.7.0 || >=18} peerDependencies: flexsearch: ^0.7.31 vitepress: ^1.0.0-rc.35 vue: '3' - dependencies: - '@types/flexsearch': 0.7.3 - '@types/markdown-it': 12.2.3 - flexsearch: 0.7.43 - glob-to-regexp: 0.4.1 - markdown-it: 13.0.1 - vitepress: 1.1.0(@algolia/client-search@4.23.3)(@types/node@20.12.7)(postcss@8.4.38)(search-insights@2.13.0)(typescript@5.4.5) - vue: 3.4.21(typescript@5.4.5) - dev: true - /vitepress@1.1.0(@algolia/client-search@4.23.3)(@types/node@20.12.7)(postcss@8.4.38)(search-insights@2.13.0)(typescript@5.4.5): - resolution: {integrity: sha512-G+NS5I2OETxC0SfGAMDO75JWNkrcir0UCptuhQMNoaZhhlqvYtTDQhph4qGc5dtiTtZkcFa/bCcSx+A2gSS3lA==} + vitepress@1.6.3: + resolution: {integrity: sha512-fCkfdOk8yRZT8GD9BFqusW3+GggWYZ/rYncOfmgcDtP3ualNHCAg+Robxp2/6xfH1WwPHtGpPwv7mbA3qomtBw==} hasBin: true peerDependencies: markdown-it-mathjax3: ^4 @@ -15301,65 +9477,24 @@ packages: optional: true postcss: optional: true - dependencies: - '@docsearch/css': 3.6.0 - '@docsearch/js': 3.6.0(@algolia/client-search@4.23.3)(search-insights@2.13.0) - '@shikijs/core': 1.3.0 - '@shikijs/transformers': 1.3.0 - '@types/markdown-it': 13.0.7 - '@vitejs/plugin-vue': 5.0.4(vite@5.2.8)(vue@3.4.21) - '@vue/devtools-api': 7.0.27(vue@3.4.21) - '@vueuse/core': 10.9.0(vue@3.4.21) - '@vueuse/integrations': 10.9.0(focus-trap@7.5.4)(vue@3.4.21) - focus-trap: 7.5.4 - mark.js: 8.11.1 - minisearch: 6.3.0 - postcss: 8.4.38 - shiki: 1.3.0 - vite: 5.2.8(@types/node@20.12.7) - vue: 3.4.21(typescript@5.4.5) - transitivePeerDependencies: - - '@algolia/client-search' - - '@types/node' - - '@types/react' - - '@vue/composition-api' - - async-validator - - axios - - change-case - - drauu - - fuse.js - - idb-keyval - - jwt-decode - - less - - lightningcss - - nprogress - - qrcode - - react - - react-dom - - sass - - search-insights - - sortablejs - - stylus - - sugarss - - terser - - typescript - - universal-cookie - dev: true - /vitest@1.5.0(@types/node@20.12.7)(@vitest/ui@1.5.0)(jsdom@24.0.0): - resolution: {integrity: sha512-d8UKgR0m2kjdxDWX6911uwxout6GHS0XaGH1cksSIVVG8kRlE7G7aBw7myKQCvDI5dT4j7ZMa+l706BIORMDLw==} - engines: {node: ^18.0.0 || >=20.0.0} + vitest@3.0.6: + resolution: {integrity: sha512-/iL1Sc5VeDZKPDe58oGK4HUFLhw6b5XdY1MYawjuSaDA4sEfYlY9HnS6aCEG26fX+MgUi7MwlduTBHHAI/OvMA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 1.5.0 - '@vitest/ui': 1.5.0 + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.0.6 + '@vitest/ui': 3.0.6 happy-dom: '*' jsdom: '*' peerDependenciesMeta: '@edge-runtime/vm': optional: true + '@types/debug': + optional: true '@types/node': optional: true '@vitest/browser': @@ -15370,221 +9505,106 @@ packages: optional: true jsdom: optional: true - dependencies: - '@types/node': 20.12.7 - '@vitest/expect': 1.5.0 - '@vitest/runner': 1.5.0 - '@vitest/snapshot': 1.5.0 - '@vitest/spy': 1.5.0 - '@vitest/ui': 1.5.0(vitest@1.5.0) - '@vitest/utils': 1.5.0 - acorn-walk: 8.3.2 - chai: 4.4.1 - debug: 4.3.4(supports-color@8.1.1) - execa: 8.0.1 - jsdom: 24.0.0 - local-pkg: 0.5.0 - magic-string: 0.30.9 - pathe: 1.1.2 - picocolors: 1.0.0 - std-env: 3.7.0 - strip-literal: 2.1.0 - tinybench: 2.7.0 - tinypool: 0.8.4 - vite: 5.2.8(@types/node@20.12.7) - vite-node: 1.5.0(@types/node@20.12.7) - why-is-node-running: 2.2.2 - transitivePeerDependencies: - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - /vscode-json-languageservice@4.2.1: + vscode-json-languageservice@4.2.1: resolution: {integrity: sha512-xGmv9QIWs2H8obGbWg+sIPI/3/pFgj/5OWBhNzs00BkYQ9UaB2F6JJaGB/2/YOZJ3BvLXQTC4Q7muqU25QgAhA==} - dependencies: - jsonc-parser: 3.2.1 - vscode-languageserver-textdocument: 1.0.11 - vscode-languageserver-types: 3.17.3 - vscode-nls: 5.2.0 - vscode-uri: 3.0.8 - dev: true - /vscode-jsonrpc@8.2.0: + vscode-jsonrpc@8.2.0: resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} engines: {node: '>=14.0.0'} - /vscode-languageserver-protocol@3.17.5: + vscode-languageserver-protocol@3.17.5: resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} - dependencies: - vscode-jsonrpc: 8.2.0 - vscode-languageserver-types: 3.17.5 - /vscode-languageserver-textdocument@1.0.11: - resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==} + vscode-languageserver-textdocument@1.0.12: + resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} - /vscode-languageserver-types@3.17.3: - resolution: {integrity: sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==} - dev: true - - /vscode-languageserver-types@3.17.5: + vscode-languageserver-types@3.17.5: resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} - /vscode-languageserver@9.0.1: + vscode-languageserver@9.0.1: resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} hasBin: true - dependencies: - vscode-languageserver-protocol: 3.17.5 - /vscode-nls@5.2.0: + vscode-nls@5.2.0: resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==} - dev: true - /vscode-oniguruma@1.7.0: - resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} - dev: true - - /vscode-textmate@8.0.0: - resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} - dev: true - - /vscode-uri@3.0.8: + vscode-uri@3.0.8: resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} - /vue-demi@0.13.11(vue@3.4.21): - resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==} + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} engines: {node: '>=12'} hasBin: true - requiresBuild: true peerDependencies: '@vue/composition-api': ^1.0.0-rc.1 vue: ^3.0.0-0 || ^2.6.0 peerDependenciesMeta: '@vue/composition-api': optional: true - dependencies: - vue: 3.4.21(typescript@5.4.5) - dev: false - /vue-demi@0.14.7(vue@3.4.21): - resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true + vue-flow-layout@0.1.1: + resolution: {integrity: sha512-JdgRRUVrN0Y2GosA0M68DEbKlXMqJ7FQgsK8CjQD2vxvNSqAU6PZEpi4cfcTVtfM2GVOMjHo7GKKLbXxOBqDqA==} peerDependencies: - '@vue/composition-api': ^1.0.0-rc.1 - vue: ^3.0.0-0 || ^2.6.0 - peerDependenciesMeta: - '@vue/composition-api': - optional: true - dependencies: - vue: 3.4.21(typescript@5.4.5) + vue: ^3.4.37 - /vue@3.4.21(typescript@5.4.5): - resolution: {integrity: sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==} + vue@3.5.13: + resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true - dependencies: - '@vue/compiler-dom': 3.4.21 - '@vue/compiler-sfc': 3.4.21 - '@vue/runtime-dom': 3.4.21 - '@vue/server-renderer': 3.4.21(vue@3.4.21) - '@vue/shared': 3.4.21 - typescript: 5.4.5 - /vuex@4.1.0(vue@3.4.21): + vuex@4.1.0: resolution: {integrity: sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==} peerDependencies: vue: ^3.2.0 - dependencies: - '@vue/devtools-api': 6.6.1 - vue: 3.4.21(typescript@5.4.5) - dev: false - /w3c-xmlserializer@5.0.0: + w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} - dependencies: - xml-name-validator: 5.0.0 - dev: true - /wait-on@7.2.0(debug@4.3.4): - resolution: {integrity: sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==} + wait-on@8.0.2: + resolution: {integrity: sha512-qHlU6AawrgAIHlueGQHQ+ETcPLAauXbnoTKl3RKq20W0T8x0DKVAo5xWIYjHSyvHxQlcYbFdR0jp4T9bDVITFA==} engines: {node: '>=12.0.0'} hasBin: true - dependencies: - axios: 1.6.7(debug@4.3.4) - joi: 17.12.2 - lodash: 4.17.21 - minimist: 1.2.8 - rxjs: 7.8.1 - transitivePeerDependencies: - - debug - dev: true - /walker@1.0.8: + walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - dependencies: - makeerror: 1.0.12 - dev: true - /watchpack@2.4.1: - resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} + watchpack@2.4.2: + resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} engines: {node: '>=10.13.0'} - dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - dev: true - /wbuf@1.7.3: + wbuf@1.7.3: resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} - dependencies: - minimalistic-assert: 1.0.1 - dev: true - /web-streams-polyfill@3.3.3: + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} - dev: true - /webdriver@7.31.1(typescript@5.4.5): + webdriver@7.31.1: resolution: {integrity: sha512-nCdJLxRnYvOMFqTEX7sqQtF/hV/Jgov0Y6ICeOm1DMTlZSRRDaUsBMlEAPkEwif9uBJYdM0znv8qzfX358AGqQ==} engines: {node: '>=12.0.0'} - dependencies: - '@types/node': 18.19.31 - '@wdio/config': 7.31.1(typescript@5.4.5) - '@wdio/logger': 7.26.0 - '@wdio/protocols': 7.27.0 - '@wdio/types': 7.30.2(typescript@5.4.5) - '@wdio/utils': 7.30.2(typescript@5.4.5) - got: 11.8.6 - ky: 0.30.0 - lodash.merge: 4.6.2 - transitivePeerDependencies: - - typescript - dev: true - /webidl-conversions@3.0.1: + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true - /webidl-conversions@4.0.2: + webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} - dev: true - /webidl-conversions@7.0.0: + webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} - dev: true - /webpack-cli@4.10.0(webpack-dev-server@4.15.2)(webpack@5.91.0): + webpack-cli@4.10.0: resolution: {integrity: sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==} engines: {node: '>=10.13.0'} hasBin: true @@ -15603,38 +9623,14 @@ packages: optional: true webpack-dev-server: optional: true - dependencies: - '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 1.2.0(webpack-cli@4.10.0)(webpack@5.91.0) - '@webpack-cli/info': 1.5.0(webpack-cli@4.10.0) - '@webpack-cli/serve': 1.7.0(webpack-cli@4.10.0)(webpack-dev-server@4.15.2) - colorette: 2.0.20 - commander: 7.2.0 - cross-spawn: 7.0.3 - fastest-levenshtein: 1.0.16 - import-local: 3.1.0 - interpret: 2.2.0 - rechoir: 0.7.1 - webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@4.10.0) - webpack-dev-server: 4.15.2(webpack-cli@4.10.0)(webpack@5.91.0) - webpack-merge: 5.9.0 - dev: true - /webpack-dev-middleware@5.3.4(webpack@5.91.0): + webpack-dev-middleware@5.3.4: resolution: {integrity: sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==} engines: {node: '>= 12.13.0'} peerDependencies: webpack: ^4.0.0 || ^5.0.0 - dependencies: - colorette: 2.0.20 - memfs: 3.5.3 - mime-types: 2.1.35 - range-parser: 1.2.1 - schema-utils: 4.2.0 - webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@4.10.0) - dev: true - /webpack-dev-server@4.15.2(webpack-cli@4.10.0)(webpack@5.91.0): + webpack-dev-server@4.15.2: resolution: {integrity: sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==} engines: {node: '>= 12.13.0'} hasBin: true @@ -15646,65 +9642,20 @@ packages: optional: true webpack-cli: optional: true - dependencies: - '@types/bonjour': 3.5.10 - '@types/connect-history-api-fallback': 1.5.0 - '@types/express': 4.17.21 - '@types/serve-index': 1.9.1 - '@types/serve-static': 1.15.5 - '@types/sockjs': 0.3.33 - '@types/ws': 8.5.5 - ansi-html-community: 0.0.8 - bonjour-service: 1.1.1 - chokidar: 3.6.0 - colorette: 2.0.20 - compression: 1.7.4 - connect-history-api-fallback: 2.0.0 - default-gateway: 6.0.3 - express: 4.19.1 - graceful-fs: 4.2.11 - html-entities: 2.4.0 - http-proxy-middleware: 2.0.6(@types/express@4.17.21) - ipaddr.js: 2.1.0 - launch-editor: 2.6.1 - open: 8.4.2 - p-retry: 4.6.2 - rimraf: 3.0.2 - schema-utils: 4.2.0 - selfsigned: 2.1.1 - serve-index: 1.9.1 - sockjs: 0.3.24 - spdy: 4.0.2 - webpack: 5.91.0(esbuild@0.20.2)(webpack-cli@4.10.0) - webpack-cli: 4.10.0(webpack-dev-server@4.15.2)(webpack@5.91.0) - webpack-dev-middleware: 5.3.4(webpack@5.91.0) - ws: 8.16.0 - transitivePeerDependencies: - - bufferutil - - debug - - supports-color - - utf-8-validate - dev: true - /webpack-merge@5.9.0: - resolution: {integrity: sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==} + webpack-merge@5.10.0: + resolution: {integrity: sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==} engines: {node: '>=10.0.0'} - dependencies: - clone-deep: 4.0.1 - wildcard: 2.0.1 - dev: true - /webpack-sources@3.2.3: + webpack-sources@3.2.3: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} - dev: true - /webpack-virtual-modules@0.5.0: - resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} - dev: true + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} - /webpack@5.91.0(esbuild@0.20.2)(webpack-cli@4.10.0): - resolution: {integrity: sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==} + webpack@5.95.0: + resolution: {integrity: sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -15712,18 +9663,11211 @@ packages: peerDependenciesMeta: webpack-cli: optional: true + + websocket-driver@0.7.4: + resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} + engines: {node: '>=0.8.0'} + + websocket-extensions@0.1.4: + resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} + engines: {node: '>=0.8.0'} + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@14.0.0: + resolution: {integrity: sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==} + engines: {node: '>=18'} + + whatwg-url@14.1.1: + resolution: {integrity: sha512-mDGf9diDad/giZ/Sm9Xi2YcyzaFpbdLpJPr+E9fSkyQ7KpQD4SdFcugkRQYzhmfI4KeV4Qpnn2sKPdo+kmsgRQ==} + engines: {node: '>=18'} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + + which-typed-array@1.1.18: + resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==} + engines: {node: '>= 0.4'} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + widest-line@3.1.0: + resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} + engines: {node: '>=8'} + + wildcard@2.0.1: + resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + workbox-background-sync@7.1.0: + resolution: {integrity: sha512-rMbgrzueVWDFcEq1610YyDW71z0oAXLfdRHRQcKw4SGihkfOK0JUEvqWHFwA6rJ+6TClnMIn7KQI5PNN1XQXwQ==} + + workbox-broadcast-update@7.1.0: + resolution: {integrity: sha512-O36hIfhjej/c5ar95pO67k1GQw0/bw5tKP7CERNgK+JdxBANQhDmIuOXZTNvwb2IHBx9hj2kxvcDyRIh5nzOgQ==} + + workbox-build@7.1.1: + resolution: {integrity: sha512-WdkVdC70VMpf5NBCtNbiwdSZeKVuhTEd5PV3mAwpTQCGAB5XbOny1P9egEgNdetv4srAMmMKjvBk4RD58LpooA==} + engines: {node: '>=16.0.0'} + + workbox-cacheable-response@7.1.0: + resolution: {integrity: sha512-iwsLBll8Hvua3xCuBB9h92+/e0wdsmSVgR2ZlvcfjepZWwhd3osumQB3x9o7flj+FehtWM2VHbZn8UJeBXXo6Q==} + + workbox-core@7.1.0: + resolution: {integrity: sha512-5KB4KOY8rtL31nEF7BfvU7FMzKT4B5TkbYa2tzkS+Peqj0gayMT9SytSFtNzlrvMaWgv6y/yvP9C0IbpFjV30Q==} + + workbox-core@7.3.0: + resolution: {integrity: sha512-Z+mYrErfh4t3zi7NVTvOuACB0A/jA3bgxUN3PwtAVHvfEsZxV9Iju580VEETug3zYJRc0Dmii/aixI/Uxj8fmw==} + + workbox-expiration@7.1.0: + resolution: {integrity: sha512-m5DcMY+A63rJlPTbbBNtpJ20i3enkyOtSgYfv/l8h+D6YbbNiA0zKEkCUaMsdDlxggla1oOfRkyqTvl5Ni5KQQ==} + + workbox-google-analytics@7.1.0: + resolution: {integrity: sha512-FvE53kBQHfVTcZyczeBVRexhh7JTkyQ8HAvbVY6mXd2n2A7Oyz/9fIwnY406ZcDhvE4NFfKGjW56N4gBiqkrew==} + + workbox-navigation-preload@7.1.0: + resolution: {integrity: sha512-4wyAbo0vNI/X0uWNJhCMKxnPanNyhybsReMGN9QUpaePLTiDpKxPqFxl4oUmBNddPwIXug01eTSLVIFXimRG/A==} + + workbox-precaching@7.1.0: + resolution: {integrity: sha512-LyxzQts+UEpgtmfnolo0hHdNjoB7EoRWcF7EDslt+lQGd0lW4iTvvSe3v5JiIckQSB5KTW5xiCqjFviRKPj1zA==} + + workbox-range-requests@7.1.0: + resolution: {integrity: sha512-m7+O4EHolNs5yb/79CrnwPR/g/PRzMFYEdo01LqwixVnc/sbzNSvKz0d04OE3aMRel1CwAAZQheRsqGDwATgPQ==} + + workbox-recipes@7.1.0: + resolution: {integrity: sha512-NRrk4ycFN9BHXJB6WrKiRX3W3w75YNrNrzSX9cEZgFB5ubeGoO8s/SDmOYVrFYp9HMw6sh1Pm3eAY/1gVS8YLg==} + + workbox-routing@7.1.0: + resolution: {integrity: sha512-oOYk+kLriUY2QyHkIilxUlVcFqwduLJB7oRZIENbqPGeBP/3TWHYNNdmGNhz1dvKuw7aqvJ7CQxn27/jprlTdg==} + + workbox-strategies@7.1.0: + resolution: {integrity: sha512-/UracPiGhUNehGjRm/tLUQ+9PtWmCbRufWtV0tNrALuf+HZ4F7cmObSEK+E4/Bx1p8Syx2tM+pkIrvtyetdlew==} + + workbox-streams@7.1.0: + resolution: {integrity: sha512-WyHAVxRXBMfysM8ORwiZnI98wvGWTVAq/lOyBjf00pXFvG0mNaVz4Ji+u+fKa/mf1i2SnTfikoYKto4ihHeS6w==} + + workbox-sw@7.1.0: + resolution: {integrity: sha512-Hml/9+/njUXBglv3dtZ9WBKHI235AQJyLBV1G7EFmh4/mUdSQuXui80RtjDeVRrXnm/6QWgRUEHG3/YBVbxtsA==} + + workbox-window@7.1.0: + resolution: {integrity: sha512-ZHeROyqR+AS5UPzholQRDttLFqGMwP0Np8MKWAdyxsDETxq3qOAyXvqessc3GniohG6e0mAqSQyKOHmT8zPF7g==} + + workbox-window@7.3.0: + resolution: {integrity: sha512-qW8PDy16OV1UBaUNGlTVcepzrlzyzNW/ZJvFQQs2j2TzGsg6IKjcpZC1RSquqQnTOafl5pCj5bGfAHlCjOOjdA==} + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + + write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xdg-basedir@5.1.0: + resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} + engines: {node: '>=12'} + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlbuilder@15.1.1: + resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} + engines: {node: '>=8.0'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + xxhashjs@0.2.2: + resolution: {integrity: sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==} + + y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yaml@2.7.0: + resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yocto-queue@1.1.1: + resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} + engines: {node: '>=12.20'} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@actions/core@1.11.1': dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.5 + '@actions/exec': 1.1.1 + '@actions/http-client': 2.2.3 + + '@actions/exec@1.1.1': + dependencies: + '@actions/io': 1.1.3 + + '@actions/http-client@2.2.3': + dependencies: + tunnel: 0.0.6 + undici: 5.28.4 + + '@actions/io@1.1.3': {} + + '@adobe/jsonschema2md@8.0.2': + dependencies: + '@types/json-schema': 7.0.15 + '@types/mdast': 4.0.4 + es2015-i18n-tag: 1.6.1 + ferrum: 1.9.4 + fs-extra: 11.2.0 + github-slugger: 2.0.0 + js-yaml: 4.1.0 + json-schema: 0.4.0 + mdast-builder: 1.1.1 + mdast-util-to-string: 4.0.0 + readdirp: 3.6.0 + remark-gfm: 4.0.1 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.4 + unist-util-inspect: 8.0.0 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + + '@algolia/autocomplete-core@1.17.7(@algolia/client-search@5.20.3)(algoliasearch@5.20.3)(search-insights@2.17.2)': + dependencies: + '@algolia/autocomplete-plugin-algolia-insights': 1.17.7(@algolia/client-search@5.20.3)(algoliasearch@5.20.3)(search-insights@2.17.2) + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.20.3)(algoliasearch@5.20.3) + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + - search-insights + + '@algolia/autocomplete-plugin-algolia-insights@1.17.7(@algolia/client-search@5.20.3)(algoliasearch@5.20.3)(search-insights@2.17.2)': + dependencies: + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.20.3)(algoliasearch@5.20.3) + search-insights: 2.17.2 + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + + '@algolia/autocomplete-preset-algolia@1.17.7(@algolia/client-search@5.20.3)(algoliasearch@5.20.3)': + dependencies: + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.20.3)(algoliasearch@5.20.3) + '@algolia/client-search': 5.20.3 + algoliasearch: 5.20.3 + + '@algolia/autocomplete-shared@1.17.7(@algolia/client-search@5.20.3)(algoliasearch@5.20.3)': + dependencies: + '@algolia/client-search': 5.20.3 + algoliasearch: 5.20.3 + + '@algolia/client-abtesting@5.20.3': + dependencies: + '@algolia/client-common': 5.20.3 + '@algolia/requester-browser-xhr': 5.20.3 + '@algolia/requester-fetch': 5.20.3 + '@algolia/requester-node-http': 5.20.3 + + '@algolia/client-analytics@5.20.3': + dependencies: + '@algolia/client-common': 5.20.3 + '@algolia/requester-browser-xhr': 5.20.3 + '@algolia/requester-fetch': 5.20.3 + '@algolia/requester-node-http': 5.20.3 + + '@algolia/client-common@5.20.3': {} + + '@algolia/client-insights@5.20.3': + dependencies: + '@algolia/client-common': 5.20.3 + '@algolia/requester-browser-xhr': 5.20.3 + '@algolia/requester-fetch': 5.20.3 + '@algolia/requester-node-http': 5.20.3 + + '@algolia/client-personalization@5.20.3': + dependencies: + '@algolia/client-common': 5.20.3 + '@algolia/requester-browser-xhr': 5.20.3 + '@algolia/requester-fetch': 5.20.3 + '@algolia/requester-node-http': 5.20.3 + + '@algolia/client-query-suggestions@5.20.3': + dependencies: + '@algolia/client-common': 5.20.3 + '@algolia/requester-browser-xhr': 5.20.3 + '@algolia/requester-fetch': 5.20.3 + '@algolia/requester-node-http': 5.20.3 + + '@algolia/client-search@5.20.3': + dependencies: + '@algolia/client-common': 5.20.3 + '@algolia/requester-browser-xhr': 5.20.3 + '@algolia/requester-fetch': 5.20.3 + '@algolia/requester-node-http': 5.20.3 + + '@algolia/ingestion@1.20.3': + dependencies: + '@algolia/client-common': 5.20.3 + '@algolia/requester-browser-xhr': 5.20.3 + '@algolia/requester-fetch': 5.20.3 + '@algolia/requester-node-http': 5.20.3 + + '@algolia/monitoring@1.20.3': + dependencies: + '@algolia/client-common': 5.20.3 + '@algolia/requester-browser-xhr': 5.20.3 + '@algolia/requester-fetch': 5.20.3 + '@algolia/requester-node-http': 5.20.3 + + '@algolia/recommend@5.20.3': + dependencies: + '@algolia/client-common': 5.20.3 + '@algolia/requester-browser-xhr': 5.20.3 + '@algolia/requester-fetch': 5.20.3 + '@algolia/requester-node-http': 5.20.3 + + '@algolia/requester-browser-xhr@5.20.3': + dependencies: + '@algolia/client-common': 5.20.3 + + '@algolia/requester-fetch@5.20.3': + dependencies: + '@algolia/client-common': 5.20.3 + + '@algolia/requester-node-http@5.20.3': + dependencies: + '@algolia/client-common': 5.20.3 + + '@alloc/quick-lru@5.2.0': {} + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@antfu/install-pkg@1.0.0': + dependencies: + package-manager-detector: 0.2.9 + tinyexec: 0.3.2 + + '@antfu/utils@8.1.1': {} + + '@apideck/better-ajv-errors@0.3.6(ajv@8.17.1)': + dependencies: + ajv: 8.17.1 + json-schema: 0.4.0 + jsonpointer: 5.0.1 + leven: 3.1.0 + + '@apidevtools/json-schema-ref-parser@11.9.1': + dependencies: + '@jsdevtools/ono': 7.1.3 + '@types/json-schema': 7.0.15 + js-yaml: 4.1.0 + + '@applitools/core-base@1.22.1': + dependencies: + '@applitools/image': 1.1.16 + '@applitools/logger': 2.1.0 + '@applitools/req': 1.7.7 + '@applitools/utils': 1.7.7 + abort-controller: 3.0.0 + throat: 6.0.2 + transitivePeerDependencies: + - supports-color + + '@applitools/core@4.31.2(encoding@0.1.13)(typescript@5.7.3)': + dependencies: + '@applitools/core-base': 1.22.1 + '@applitools/dom-capture': 11.5.4 + '@applitools/dom-snapshot': 4.11.15 + '@applitools/driver': 1.20.4 + '@applitools/ec-client': 1.10.4(typescript@5.7.3) + '@applitools/logger': 2.1.0 + '@applitools/nml-client': 1.8.24 + '@applitools/req': 1.7.7 + '@applitools/screenshoter': 3.10.5 + '@applitools/snippets': 2.6.4 + '@applitools/socket': 1.2.1 + '@applitools/spec-driver-webdriver': 1.1.25(webdriver@7.31.1(typescript@5.7.3)) + '@applitools/ufg-client': 1.16.4 + '@applitools/utils': 1.7.7 + '@types/ws': 8.5.5 + abort-controller: 3.0.0 + chalk: 4.1.2 + node-fetch: 2.6.7(encoding@0.1.13) + semver: 7.6.2 + webdriver: 7.31.1(typescript@5.7.3) + ws: 8.17.1 + yargs: 17.7.2 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - typescript + - utf-8-validate + + '@applitools/css-tree@1.1.4': + dependencies: + mdn-data: 2.1.0 + source-map-js: 1.0.1 + + '@applitools/dom-capture@11.5.4': + dependencies: + '@applitools/dom-shared': 1.0.16 + '@applitools/functional-commons': 1.6.0 + + '@applitools/dom-shared@1.0.16': {} + + '@applitools/dom-snapshot@4.11.15': + dependencies: + '@applitools/css-tree': 1.1.4 + '@applitools/dom-shared': 1.0.16 + '@applitools/functional-commons': 1.6.0 + pako: 1.0.11 + + '@applitools/driver@1.20.4': + dependencies: + '@applitools/logger': 2.1.0 + '@applitools/snippets': 2.6.4 + '@applitools/utils': 1.7.7 + semver: 7.6.2 + transitivePeerDependencies: + - supports-color + + '@applitools/ec-client@1.10.4(typescript@5.7.3)': + dependencies: + '@applitools/core-base': 1.22.1 + '@applitools/driver': 1.20.4 + '@applitools/logger': 2.1.0 + '@applitools/req': 1.7.7 + '@applitools/socket': 1.2.1 + '@applitools/spec-driver-webdriver': 1.1.25(webdriver@7.31.1(typescript@5.7.3)) + '@applitools/tunnel-client': 1.6.2 + '@applitools/utils': 1.7.7 + abort-controller: 3.0.0 + webdriver: 7.31.1(typescript@5.7.3) + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + - typescript + + '@applitools/eg-frpc@1.0.5': {} + + '@applitools/eg-socks5-proxy-server@0.5.6': + dependencies: + binary: 0.3.0 + is-localhost-ip: 2.0.0 + + '@applitools/execution-grid-tunnel@3.0.8': + dependencies: + '@applitools/eg-frpc': 1.0.5 + '@applitools/eg-socks5-proxy-server': 0.5.6 + '@applitools/logger': 1.1.53 + dotenv: 16.4.7 + encoding: 0.1.13 + fastify: 4.29.0 + fastify-plugin: 3.0.1 + find-process: 1.4.10 + ini: 3.0.1 + node-cleanup: 2.1.2 + node-fetch: 2.7.0(encoding@0.1.13) + p-retry: 4.6.2 + teen_process: 1.16.0 + uuid: 9.0.1 + transitivePeerDependencies: + - supports-color + + '@applitools/eyes-cypress@3.50.2(encoding@0.1.13)(typescript@5.7.3)': + dependencies: + '@applitools/core': 4.31.2(encoding@0.1.13)(typescript@5.7.3) + '@applitools/eyes': 1.32.1(encoding@0.1.13)(typescript@5.7.3) + '@applitools/functional-commons': 1.6.0 + '@applitools/logger': 2.1.0 + '@applitools/utils': 1.7.7 + boxen: 5.1.2 + chalk: 3.0.0 + semver: 7.6.2 + uuid: 8.3.2 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - typescript + - utf-8-validate + + '@applitools/eyes@1.32.1(encoding@0.1.13)(typescript@5.7.3)': + dependencies: + '@applitools/core': 4.31.2(encoding@0.1.13)(typescript@5.7.3) + '@applitools/logger': 2.1.0 + '@applitools/utils': 1.7.7 + chalk: 4.1.2 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - typescript + - utf-8-validate + + '@applitools/functional-commons@1.6.0': {} + + '@applitools/image@1.1.16': + dependencies: + '@applitools/utils': 1.7.7 + bmpimagejs: 1.0.4 + jpeg-js: 0.4.4 + omggif: 1.0.10 + png-async: 0.9.4 + + '@applitools/logger@1.1.53': + dependencies: + '@applitools/utils': 1.3.36 + chalk: 4.1.2 + debug: 4.3.3 + transitivePeerDependencies: + - supports-color + + '@applitools/logger@2.1.0': + dependencies: + '@applitools/utils': 1.7.7 + chalk: 4.1.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + + '@applitools/nml-client@1.8.24': + dependencies: + '@applitools/logger': 2.1.0 + '@applitools/req': 1.7.7 + '@applitools/utils': 1.7.7 + transitivePeerDependencies: + - supports-color + + '@applitools/req@1.7.7': + dependencies: + '@applitools/utils': 1.7.7 + abort-controller: 3.0.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + node-fetch: 3.3.1 + transitivePeerDependencies: + - supports-color + + '@applitools/screenshoter@3.10.5': + dependencies: + '@applitools/image': 1.1.16 + '@applitools/logger': 2.1.0 + '@applitools/snippets': 2.6.4 + '@applitools/utils': 1.7.7 + transitivePeerDependencies: + - supports-color + + '@applitools/snippets@2.6.4': {} + + '@applitools/socket@1.2.1': + dependencies: + '@applitools/logger': 2.1.0 + '@applitools/utils': 1.7.7 + transitivePeerDependencies: + - supports-color + + '@applitools/spec-driver-webdriver@1.1.25(webdriver@7.31.1(typescript@5.7.3))': + dependencies: + '@applitools/driver': 1.20.4 + '@applitools/utils': 1.7.7 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + webdriver: 7.31.1(typescript@5.7.3) + transitivePeerDependencies: + - supports-color + + '@applitools/tunnel-client@1.6.2': + dependencies: + '@applitools/execution-grid-tunnel': 3.0.8 + '@applitools/logger': 2.1.0 + '@applitools/req': 1.7.7 + '@applitools/socket': 1.2.1 + '@applitools/utils': 1.7.7 + abort-controller: 3.0.0 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + + '@applitools/ufg-client@1.16.4': + dependencies: + '@applitools/css-tree': 1.1.4 + '@applitools/image': 1.1.16 + '@applitools/logger': 2.1.0 + '@applitools/req': 1.7.7 + '@applitools/utils': 1.7.7 + '@xmldom/xmldom': 0.8.10 + abort-controller: 3.0.0 + throat: 6.0.2 + transitivePeerDependencies: + - supports-color + + '@applitools/utils@1.3.36': {} + + '@applitools/utils@1.7.7': {} + + '@argos-ci/api-client@0.8.1': + dependencies: + debug: 4.4.0(supports-color@8.1.1) + openapi-fetch: 0.13.5 + transitivePeerDependencies: + - supports-color + + '@argos-ci/browser@4.1.1': {} + + '@argos-ci/core@3.1.1': + dependencies: + '@argos-ci/api-client': 0.8.1 + '@argos-ci/util': 2.3.1 + axios: 1.8.4(debug@4.4.0) + convict: 6.2.4 + debug: 4.4.0(supports-color@8.1.1) + fast-glob: 3.3.3 + sharp: 0.33.5 + tmp: 0.2.3 + transitivePeerDependencies: + - supports-color + + '@argos-ci/cypress@4.0.3(cypress@14.0.3)': + dependencies: + '@argos-ci/browser': 4.1.1 + '@argos-ci/core': 3.1.1 + '@argos-ci/util': 2.3.1 + cypress: 14.0.3 + cypress-wait-until: 3.0.2 + transitivePeerDependencies: + - supports-color + + '@argos-ci/util@2.3.1': {} + + '@asamuzakjp/css-color@2.8.3': + dependencies: + '@csstools/css-calc': 2.1.1(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) + '@csstools/css-color-parser': 3.0.7(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) + '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) + '@csstools/css-tokenizer': 3.0.3 + lru-cache: 10.4.3 + + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.26.8': {} + + '@babel/core@7.26.9': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helpers': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + convert-source-map: 2.0.0 + debug: 4.4.0(supports-color@8.1.1) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.26.9': + dependencies: + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.25.9': + dependencies: + '@babel/types': 7.26.9 + + '@babel/helper-compilation-targets@7.26.5': + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.4 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.26.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.9) + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/traverse': 7.26.9 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.26.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + regexpu-core: 6.2.0 + semver: 6.3.1 + + '@babel/helper-define-polyfill-provider@0.6.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + debug: 4.4.0(supports-color@8.1.1) + lodash.debounce: 4.0.8 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + + '@babel/helper-member-expression-to-functions@7.25.9': + dependencies: + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.25.9': + dependencies: + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.25.9': + dependencies: + '@babel/types': 7.26.9 + + '@babel/helper-plugin-utils@7.25.7': {} + + '@babel/helper-plugin-utils@7.26.5': {} + + '@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-wrap-function': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.26.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': + dependencies: + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.25.9': {} + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/helper-validator-option@7.25.9': {} + + '@babel/helper-wrap-function@7.25.9': + dependencies: + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helpers@7.26.9': + dependencies: + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 + + '@babel/parser@7.26.9': + dependencies: + '@babel/types': 7.26.9 + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-attributes@7.25.7(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-jsx@7.25.7(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-typescript@7.25.7(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-async-generator-functions@7.26.8(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.9) + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-block-scoped-functions@7.26.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-block-scoping@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-static-block@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.9) + '@babel/traverse': 7.26.9 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-computed-properties@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/template': 7.26.9 + + '@babel/plugin-transform-destructuring@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-exponentiation-operator@7.26.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-export-namespace-from@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-for-of@7.26.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-function-name@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-json-strings@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-literals@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-logical-assignment-operators@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-member-expression-literals@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-modules-amd@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-commonjs@7.26.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-systemjs@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-umd@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-named-capturing-groups-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-new-target@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-nullish-coalescing-operator@7.26.6(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-numeric-separator@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.9) + + '@babel/plugin-transform-object-super@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-catch-binding@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-optional-chaining@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-private-property-in-object@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-property-literals@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-regenerator@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + regenerator-transform: 0.15.2 + + '@babel/plugin-transform-regexp-modifiers@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-spread@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-template-literals@7.26.8(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-typeof-symbol@7.26.7(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/preset-env@7.26.9(@babel/core@7.26.9)': + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/core': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.9) + '@babel/plugin-syntax-import-assertions': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.9) + '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-async-generator-functions': 7.26.8(@babel/core@7.26.9) + '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-block-scoped-functions': 7.26.5(@babel/core@7.26.9) + '@babel/plugin-transform-block-scoping': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-class-static-block': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-transform-classes': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-computed-properties': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-destructuring': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-dotall-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-duplicate-keys': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-dynamic-import': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-exponentiation-operator': 7.26.3(@babel/core@7.26.9) + '@babel/plugin-transform-export-namespace-from': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-for-of': 7.26.9(@babel/core@7.26.9) + '@babel/plugin-transform-function-name': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-json-strings': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-literals': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-logical-assignment-operators': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-member-expression-literals': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-modules-amd': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-modules-commonjs': 7.26.3(@babel/core@7.26.9) + '@babel/plugin-transform-modules-systemjs': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-modules-umd': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-new-target': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-nullish-coalescing-operator': 7.26.6(@babel/core@7.26.9) + '@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-object-super': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-optional-catch-binding': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-private-property-in-object': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-property-literals': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-regenerator': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-regexp-modifiers': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-transform-reserved-words': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-shorthand-properties': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-spread': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-sticky-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-template-literals': 7.26.8(@babel/core@7.26.9) + '@babel/plugin-transform-typeof-symbol': 7.26.7(@babel/core@7.26.9) + '@babel/plugin-transform-unicode-escapes': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-unicode-property-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-unicode-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-unicode-sets-regex': 7.25.9(@babel/core@7.26.9) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.9) + babel-plugin-polyfill-corejs2: 0.4.12(@babel/core@7.26.9) + babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.9) + babel-plugin-polyfill-regenerator: 0.6.3(@babel/core@7.26.9) + core-js-compat: 3.41.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/types': 7.26.9 + esutils: 2.0.3 + + '@babel/runtime@7.26.9': + dependencies: + regenerator-runtime: 0.14.1 + + '@babel/template@7.26.9': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + + '@babel/traverse@7.26.9': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 + debug: 4.4.0(supports-color@8.1.1) + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.26.9': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + + '@bcoe/v8-coverage@0.2.3': {} + + '@bcoe/v8-coverage@1.0.2': {} + + '@braintree/sanitize-url@7.1.0': {} + + '@changesets/apply-release-plan@7.0.10': + dependencies: + '@changesets/config': 3.1.1 + '@changesets/get-version-range-type': 0.4.0 + '@changesets/git': 3.0.2 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + detect-indent: 6.1.0 + fs-extra: 7.0.1 + lodash.startcase: 4.4.0 + outdent: 0.5.0 + prettier: 2.8.8 + resolve-from: 5.0.0 + semver: 7.7.1 + + '@changesets/assemble-release-plan@6.0.6': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + semver: 7.7.1 + + '@changesets/changelog-git@0.2.1': + dependencies: + '@changesets/types': 6.1.0 + + '@changesets/changelog-github@0.5.1(encoding@0.1.13)': + dependencies: + '@changesets/get-github-info': 0.6.0(encoding@0.1.13) + '@changesets/types': 6.1.0 + dotenv: 8.6.0 + transitivePeerDependencies: + - encoding + + '@changesets/cli@2.28.1': + dependencies: + '@changesets/apply-release-plan': 7.0.10 + '@changesets/assemble-release-plan': 6.0.6 + '@changesets/changelog-git': 0.2.1 + '@changesets/config': 3.1.1 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/get-release-plan': 4.0.8 + '@changesets/git': 3.0.2 + '@changesets/logger': 0.1.1 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.3 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@changesets/write': 0.4.0 + '@manypkg/get-packages': 1.1.3 + ansi-colors: 4.1.3 + ci-info: 3.9.0 + enquirer: 2.4.1 + external-editor: 3.1.0 + fs-extra: 7.0.1 + mri: 1.2.0 + p-limit: 2.3.0 + package-manager-detector: 0.2.9 + picocolors: 1.1.1 + resolve-from: 5.0.0 + semver: 7.7.1 + spawndamnit: 3.0.1 + term-size: 2.2.1 + + '@changesets/config@3.1.1': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/logger': 0.1.1 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + micromatch: 4.0.8 + + '@changesets/errors@0.2.0': + dependencies: + extendable-error: 0.1.7 + + '@changesets/get-dependents-graph@2.1.3': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + picocolors: 1.1.1 + semver: 7.7.1 + + '@changesets/get-github-info@0.6.0(encoding@0.1.13)': + dependencies: + dataloader: 1.4.0 + node-fetch: 2.7.0(encoding@0.1.13) + transitivePeerDependencies: + - encoding + + '@changesets/get-release-plan@4.0.8': + dependencies: + '@changesets/assemble-release-plan': 6.0.6 + '@changesets/config': 3.1.1 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.3 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/get-version-range-type@0.4.0': {} + + '@changesets/git@3.0.2': + dependencies: + '@changesets/errors': 0.2.0 + '@manypkg/get-packages': 1.1.3 + is-subdir: 1.2.0 + micromatch: 4.0.8 + spawndamnit: 3.0.1 + + '@changesets/logger@0.1.1': + dependencies: + picocolors: 1.1.1 + + '@changesets/parse@0.4.1': + dependencies: + '@changesets/types': 6.1.0 + js-yaml: 3.14.1 + + '@changesets/pre@2.0.2': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + + '@changesets/read@0.6.3': + dependencies: + '@changesets/git': 3.0.2 + '@changesets/logger': 0.1.1 + '@changesets/parse': 0.4.1 + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + p-filter: 2.1.0 + picocolors: 1.1.1 + + '@changesets/should-skip-package@0.1.2': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/types@4.1.0': {} + + '@changesets/types@6.1.0': {} + + '@changesets/write@0.4.0': + dependencies: + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + human-id: 4.1.1 + prettier: 2.8.8 + + '@chevrotain/cst-dts-gen@11.0.3': + dependencies: + '@chevrotain/gast': 11.0.3 + '@chevrotain/types': 11.0.3 + lodash-es: 4.17.21 + + '@chevrotain/gast@11.0.3': + dependencies: + '@chevrotain/types': 11.0.3 + lodash-es: 4.17.21 + + '@chevrotain/regexp-to-ast@11.0.3': {} + + '@chevrotain/types@11.0.3': {} + + '@chevrotain/utils@11.0.3': {} + + '@colors/colors@1.5.0': + optional: true + + '@cspell/cspell-bundled-dicts@8.17.4': + dependencies: + '@cspell/dict-ada': 4.1.0 + '@cspell/dict-al': 1.1.0 + '@cspell/dict-aws': 4.0.9 + '@cspell/dict-bash': 4.2.0 + '@cspell/dict-companies': 3.1.14 + '@cspell/dict-cpp': 6.0.3 + '@cspell/dict-cryptocurrencies': 5.0.4 + '@cspell/dict-csharp': 4.0.6 + '@cspell/dict-css': 4.0.17 + '@cspell/dict-dart': 2.3.0 + '@cspell/dict-data-science': 2.0.7 + '@cspell/dict-django': 4.1.4 + '@cspell/dict-docker': 1.1.12 + '@cspell/dict-dotnet': 5.0.9 + '@cspell/dict-elixir': 4.0.7 + '@cspell/dict-en-common-misspellings': 2.0.9 + '@cspell/dict-en-gb': 1.1.33 + '@cspell/dict-en_us': 4.3.31 + '@cspell/dict-filetypes': 3.0.11 + '@cspell/dict-flutter': 1.1.0 + '@cspell/dict-fonts': 4.0.4 + '@cspell/dict-fsharp': 1.1.0 + '@cspell/dict-fullstack': 3.2.4 + '@cspell/dict-gaming-terms': 1.1.0 + '@cspell/dict-git': 3.0.4 + '@cspell/dict-golang': 6.0.18 + '@cspell/dict-google': 1.0.8 + '@cspell/dict-haskell': 4.0.5 + '@cspell/dict-html': 4.0.11 + '@cspell/dict-html-symbol-entities': 4.0.3 + '@cspell/dict-java': 5.0.11 + '@cspell/dict-julia': 1.1.0 + '@cspell/dict-k8s': 1.0.10 + '@cspell/dict-kotlin': 1.1.0 + '@cspell/dict-latex': 4.0.3 + '@cspell/dict-lorem-ipsum': 4.0.4 + '@cspell/dict-lua': 4.0.7 + '@cspell/dict-makefile': 1.0.4 + '@cspell/dict-markdown': 2.0.9(@cspell/dict-css@4.0.17)(@cspell/dict-html-symbol-entities@4.0.3)(@cspell/dict-html@4.0.11)(@cspell/dict-typescript@3.2.0) + '@cspell/dict-monkeyc': 1.0.10 + '@cspell/dict-node': 5.0.6 + '@cspell/dict-npm': 5.1.26 + '@cspell/dict-php': 4.0.14 + '@cspell/dict-powershell': 5.0.14 + '@cspell/dict-public-licenses': 2.0.13 + '@cspell/dict-python': 4.2.15 + '@cspell/dict-r': 2.1.0 + '@cspell/dict-ruby': 5.0.7 + '@cspell/dict-rust': 4.0.11 + '@cspell/dict-scala': 5.0.7 + '@cspell/dict-shell': 1.1.0 + '@cspell/dict-software-terms': 4.2.5 + '@cspell/dict-sql': 2.2.0 + '@cspell/dict-svelte': 1.0.6 + '@cspell/dict-swift': 2.0.5 + '@cspell/dict-terraform': 1.1.0 + '@cspell/dict-typescript': 3.2.0 + '@cspell/dict-vue': 3.0.4 + + '@cspell/cspell-bundled-dicts@8.18.1': + dependencies: + '@cspell/dict-ada': 4.1.0 + '@cspell/dict-al': 1.1.0 + '@cspell/dict-aws': 4.0.9 + '@cspell/dict-bash': 4.2.0 + '@cspell/dict-companies': 3.1.14 + '@cspell/dict-cpp': 6.0.7 + '@cspell/dict-cryptocurrencies': 5.0.4 + '@cspell/dict-csharp': 4.0.6 + '@cspell/dict-css': 4.0.17 + '@cspell/dict-dart': 2.3.0 + '@cspell/dict-data-science': 2.0.7 + '@cspell/dict-django': 4.1.4 + '@cspell/dict-docker': 1.1.12 + '@cspell/dict-dotnet': 5.0.9 + '@cspell/dict-elixir': 4.0.7 + '@cspell/dict-en-common-misspellings': 2.0.10 + '@cspell/dict-en-gb': 1.1.33 + '@cspell/dict-en_us': 4.4.0 + '@cspell/dict-filetypes': 3.0.11 + '@cspell/dict-flutter': 1.1.0 + '@cspell/dict-fonts': 4.0.4 + '@cspell/dict-fsharp': 1.1.0 + '@cspell/dict-fullstack': 3.2.6 + '@cspell/dict-gaming-terms': 1.1.0 + '@cspell/dict-git': 3.0.4 + '@cspell/dict-golang': 6.0.20 + '@cspell/dict-google': 1.0.8 + '@cspell/dict-haskell': 4.0.5 + '@cspell/dict-html': 4.0.11 + '@cspell/dict-html-symbol-entities': 4.0.3 + '@cspell/dict-java': 5.0.11 + '@cspell/dict-julia': 1.1.0 + '@cspell/dict-k8s': 1.0.10 + '@cspell/dict-kotlin': 1.1.0 + '@cspell/dict-latex': 4.0.3 + '@cspell/dict-lorem-ipsum': 4.0.4 + '@cspell/dict-lua': 4.0.7 + '@cspell/dict-makefile': 1.0.4 + '@cspell/dict-markdown': 2.0.9(@cspell/dict-css@4.0.17)(@cspell/dict-html-symbol-entities@4.0.3)(@cspell/dict-html@4.0.11)(@cspell/dict-typescript@3.2.0) + '@cspell/dict-monkeyc': 1.0.10 + '@cspell/dict-node': 5.0.6 + '@cspell/dict-npm': 5.1.34 + '@cspell/dict-php': 4.0.14 + '@cspell/dict-powershell': 5.0.14 + '@cspell/dict-public-licenses': 2.0.13 + '@cspell/dict-python': 4.2.17 + '@cspell/dict-r': 2.1.0 + '@cspell/dict-ruby': 5.0.8 + '@cspell/dict-rust': 4.0.11 + '@cspell/dict-scala': 5.0.7 + '@cspell/dict-shell': 1.1.0 + '@cspell/dict-software-terms': 5.0.5 + '@cspell/dict-sql': 2.2.0 + '@cspell/dict-svelte': 1.0.6 + '@cspell/dict-swift': 2.0.5 + '@cspell/dict-terraform': 1.1.1 + '@cspell/dict-typescript': 3.2.0 + '@cspell/dict-vue': 3.0.4 + + '@cspell/cspell-json-reporter@8.17.4': + dependencies: + '@cspell/cspell-types': 8.17.4 + + '@cspell/cspell-pipe@8.17.4': {} + + '@cspell/cspell-pipe@8.18.1': {} + + '@cspell/cspell-resolver@8.17.4': + dependencies: + global-directory: 4.0.1 + + '@cspell/cspell-resolver@8.18.1': + dependencies: + global-directory: 4.0.1 + + '@cspell/cspell-service-bus@8.17.4': {} + + '@cspell/cspell-service-bus@8.18.1': {} + + '@cspell/cspell-types@8.17.4': {} + + '@cspell/cspell-types@8.18.1': {} + + '@cspell/dict-ada@4.1.0': {} + + '@cspell/dict-al@1.1.0': {} + + '@cspell/dict-aws@4.0.9': {} + + '@cspell/dict-bash@4.2.0': + dependencies: + '@cspell/dict-shell': 1.1.0 + + '@cspell/dict-companies@3.1.14': {} + + '@cspell/dict-cpp@6.0.3': {} + + '@cspell/dict-cpp@6.0.7': {} + + '@cspell/dict-cryptocurrencies@5.0.4': {} + + '@cspell/dict-csharp@4.0.6': {} + + '@cspell/dict-css@4.0.17': {} + + '@cspell/dict-dart@2.3.0': {} + + '@cspell/dict-data-science@2.0.7': {} + + '@cspell/dict-data-science@2.0.8': {} + + '@cspell/dict-django@4.1.4': {} + + '@cspell/dict-docker@1.1.12': {} + + '@cspell/dict-dotnet@5.0.9': {} + + '@cspell/dict-elixir@4.0.7': {} + + '@cspell/dict-en-common-misspellings@2.0.10': {} + + '@cspell/dict-en-common-misspellings@2.0.9': {} + + '@cspell/dict-en-gb@1.1.33': {} + + '@cspell/dict-en_us@4.3.31': {} + + '@cspell/dict-en_us@4.4.0': {} + + '@cspell/dict-filetypes@3.0.11': {} + + '@cspell/dict-flutter@1.1.0': {} + + '@cspell/dict-fonts@4.0.4': {} + + '@cspell/dict-fsharp@1.1.0': {} + + '@cspell/dict-fullstack@3.2.4': {} + + '@cspell/dict-fullstack@3.2.6': {} + + '@cspell/dict-gaming-terms@1.1.0': {} + + '@cspell/dict-git@3.0.4': {} + + '@cspell/dict-golang@6.0.18': {} + + '@cspell/dict-golang@6.0.20': {} + + '@cspell/dict-google@1.0.8': {} + + '@cspell/dict-haskell@4.0.5': {} + + '@cspell/dict-html-symbol-entities@4.0.3': {} + + '@cspell/dict-html@4.0.11': {} + + '@cspell/dict-java@5.0.11': {} + + '@cspell/dict-julia@1.1.0': {} + + '@cspell/dict-k8s@1.0.10': {} + + '@cspell/dict-kotlin@1.1.0': {} + + '@cspell/dict-latex@4.0.3': {} + + '@cspell/dict-lorem-ipsum@4.0.4': {} + + '@cspell/dict-lua@4.0.7': {} + + '@cspell/dict-makefile@1.0.4': {} + + '@cspell/dict-markdown@2.0.9(@cspell/dict-css@4.0.17)(@cspell/dict-html-symbol-entities@4.0.3)(@cspell/dict-html@4.0.11)(@cspell/dict-typescript@3.2.0)': + dependencies: + '@cspell/dict-css': 4.0.17 + '@cspell/dict-html': 4.0.11 + '@cspell/dict-html-symbol-entities': 4.0.3 + '@cspell/dict-typescript': 3.2.0 + + '@cspell/dict-monkeyc@1.0.10': {} + + '@cspell/dict-node@5.0.6': {} + + '@cspell/dict-npm@5.1.26': {} + + '@cspell/dict-npm@5.1.34': {} + + '@cspell/dict-php@4.0.14': {} + + '@cspell/dict-powershell@5.0.14': {} + + '@cspell/dict-public-licenses@2.0.13': {} + + '@cspell/dict-python@4.2.15': + dependencies: + '@cspell/dict-data-science': 2.0.7 + + '@cspell/dict-python@4.2.17': + dependencies: + '@cspell/dict-data-science': 2.0.8 + + '@cspell/dict-r@2.1.0': {} + + '@cspell/dict-ruby@5.0.7': {} + + '@cspell/dict-ruby@5.0.8': {} + + '@cspell/dict-rust@4.0.11': {} + + '@cspell/dict-scala@5.0.7': {} + + '@cspell/dict-shell@1.1.0': {} + + '@cspell/dict-software-terms@4.2.5': {} + + '@cspell/dict-software-terms@5.0.5': {} + + '@cspell/dict-sql@2.2.0': {} + + '@cspell/dict-svelte@1.0.6': {} + + '@cspell/dict-swift@2.0.5': {} + + '@cspell/dict-terraform@1.1.0': {} + + '@cspell/dict-terraform@1.1.1': {} + + '@cspell/dict-typescript@3.2.0': {} + + '@cspell/dict-vue@3.0.4': {} + + '@cspell/dynamic-import@8.17.4': + dependencies: + '@cspell/url': 8.17.4 + import-meta-resolve: 4.1.0 + + '@cspell/dynamic-import@8.18.1': + dependencies: + '@cspell/url': 8.18.1 + import-meta-resolve: 4.1.0 + + '@cspell/eslint-plugin@8.18.1(eslint@9.24.0(jiti@2.4.2))': + dependencies: + '@cspell/cspell-types': 8.18.1 + '@cspell/url': 8.18.1 + cspell-lib: 8.18.1 + eslint: 9.24.0(jiti@2.4.2) + synckit: 0.10.3 + + '@cspell/filetypes@8.17.4': {} + + '@cspell/filetypes@8.18.1': {} + + '@cspell/strong-weak-map@8.17.4': {} + + '@cspell/strong-weak-map@8.18.1': {} + + '@cspell/url@8.17.4': {} + + '@cspell/url@8.18.1': {} + + '@csstools/color-helpers@5.0.1': {} + + '@csstools/css-calc@2.1.1(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) + '@csstools/css-tokenizer': 3.0.3 + + '@csstools/css-color-parser@3.0.7(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)': + dependencies: + '@csstools/color-helpers': 5.0.1 + '@csstools/css-calc': 2.1.1(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) + '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) + '@csstools/css-tokenizer': 3.0.3 + + '@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3)': + dependencies: + '@csstools/css-tokenizer': 3.0.3 + + '@csstools/css-tokenizer@3.0.3': {} + + '@cypress/code-coverage@3.13.4(@babel/core@7.26.9)(@babel/preset-env@7.26.9(@babel/core@7.26.9))(babel-loader@9.2.1(@babel/core@7.26.9)(webpack@5.95.0(esbuild@0.25.0)))(cypress@14.0.3)(webpack@5.95.0(esbuild@0.25.0))': + dependencies: + '@babel/core': 7.26.9 + '@babel/preset-env': 7.26.9(@babel/core@7.26.9) + '@cypress/webpack-preprocessor': 6.0.2(@babel/core@7.26.9)(@babel/preset-env@7.26.9(@babel/core@7.26.9))(babel-loader@9.2.1(@babel/core@7.26.9)(webpack@5.95.0(esbuild@0.25.0)))(webpack@5.95.0(esbuild@0.25.0)) + babel-loader: 9.2.1(@babel/core@7.26.9)(webpack@5.95.0(esbuild@0.25.0)) + chalk: 4.1.2 + cypress: 14.0.3 + dayjs: 1.11.13 + debug: 4.3.7 + execa: 4.1.0 + globby: 11.1.0 + istanbul-lib-coverage: 3.2.2 + js-yaml: 4.1.0 + nyc: 15.1.0 + webpack: 5.95.0(esbuild@0.25.0) + transitivePeerDependencies: + - supports-color + + '@cypress/request@3.0.7': + dependencies: + aws-sign2: 0.7.0 + aws4: 1.13.2 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 4.0.2 + http-signature: 1.4.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.35 + performance-now: 2.1.0 + qs: 6.13.1 + safe-buffer: 5.2.1 + tough-cookie: 5.1.1 + tunnel-agent: 0.6.0 + uuid: 8.3.2 + + '@cypress/webpack-preprocessor@6.0.2(@babel/core@7.26.9)(@babel/preset-env@7.26.9(@babel/core@7.26.9))(babel-loader@9.2.1(@babel/core@7.26.9)(webpack@5.95.0(esbuild@0.25.0)))(webpack@5.95.0(esbuild@0.25.0))': + dependencies: + '@babel/core': 7.26.9 + '@babel/preset-env': 7.26.9(@babel/core@7.26.9) + babel-loader: 9.2.1(@babel/core@7.26.9)(webpack@5.95.0(esbuild@0.25.0)) + bluebird: 3.7.1 + debug: 4.4.0(supports-color@8.1.1) + lodash: 4.17.21 + webpack: 5.95.0(esbuild@0.25.0) + transitivePeerDependencies: + - supports-color + + '@cypress/xvfb@1.2.4(supports-color@8.1.1)': + dependencies: + debug: 3.2.7(supports-color@8.1.1) + lodash.once: 4.1.1 + transitivePeerDependencies: + - supports-color + + '@dependents/detective-less@5.0.0': + dependencies: + gonzales-pe: 4.3.0 + node-source-walk: 7.0.0 + + '@discoveryjs/json-ext@0.5.7': {} + + '@docsearch/css@3.8.2': {} + + '@docsearch/js@3.8.2(@algolia/client-search@5.20.3)(search-insights@2.17.2)': + dependencies: + '@docsearch/react': 3.8.2(@algolia/client-search@5.20.3)(search-insights@2.17.2) + preact: 10.26.2 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/react' + - react + - react-dom + - search-insights + + '@docsearch/react@3.8.2(@algolia/client-search@5.20.3)(search-insights@2.17.2)': + dependencies: + '@algolia/autocomplete-core': 1.17.7(@algolia/client-search@5.20.3)(algoliasearch@5.20.3)(search-insights@2.17.2) + '@algolia/autocomplete-preset-algolia': 1.17.7(@algolia/client-search@5.20.3)(algoliasearch@5.20.3) + '@docsearch/css': 3.8.2 + algoliasearch: 5.20.3 + optionalDependencies: + search-insights: 2.17.2 + transitivePeerDependencies: + - '@algolia/client-search' + + '@emnapi/runtime@1.3.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@es-joy/jsdoccomment@0.49.0': + dependencies: + comment-parser: 1.4.1 + esquery: 1.6.0 + jsdoc-type-pratt-parser: 4.1.0 + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/aix-ppc64@0.24.2': + optional: true + + '@esbuild/aix-ppc64@0.25.0': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.24.2': + optional: true + + '@esbuild/android-arm64@0.25.0': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-arm@0.24.2': + optional: true + + '@esbuild/android-arm@0.25.0': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/android-x64@0.24.2': + optional: true + + '@esbuild/android-x64@0.25.0': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.24.2': + optional: true + + '@esbuild/darwin-arm64@0.25.0': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.24.2': + optional: true + + '@esbuild/darwin-x64@0.25.0': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.24.2': + optional: true + + '@esbuild/freebsd-arm64@0.25.0': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.24.2': + optional: true + + '@esbuild/freebsd-x64@0.25.0': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.24.2': + optional: true + + '@esbuild/linux-arm64@0.25.0': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-arm@0.24.2': + optional: true + + '@esbuild/linux-arm@0.25.0': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.24.2': + optional: true + + '@esbuild/linux-ia32@0.25.0': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.24.2': + optional: true + + '@esbuild/linux-loong64@0.25.0': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.24.2': + optional: true + + '@esbuild/linux-mips64el@0.25.0': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.24.2': + optional: true + + '@esbuild/linux-ppc64@0.25.0': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.24.2': + optional: true + + '@esbuild/linux-riscv64@0.25.0': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.24.2': + optional: true + + '@esbuild/linux-s390x@0.25.0': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/linux-x64@0.24.2': + optional: true + + '@esbuild/linux-x64@0.25.0': + optional: true + + '@esbuild/netbsd-arm64@0.24.2': + optional: true + + '@esbuild/netbsd-arm64@0.25.0': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.24.2': + optional: true + + '@esbuild/netbsd-x64@0.25.0': + optional: true + + '@esbuild/openbsd-arm64@0.24.2': + optional: true + + '@esbuild/openbsd-arm64@0.25.0': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.24.2': + optional: true + + '@esbuild/openbsd-x64@0.25.0': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.24.2': + optional: true + + '@esbuild/sunos-x64@0.25.0': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.24.2': + optional: true + + '@esbuild/win32-arm64@0.25.0': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.24.2': + optional: true + + '@esbuild/win32-ia32@0.25.0': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@esbuild/win32-x64@0.24.2': + optional: true + + '@esbuild/win32-x64@0.25.0': + optional: true + + '@eslint-community/eslint-utils@4.5.1(eslint@9.24.0(jiti@2.4.2))': + dependencies: + eslint: 9.24.0(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.20.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.0(supports-color@8.1.1) + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.2.1': {} + + '@eslint/core@0.12.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.0(supports-color@8.1.1) + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.24.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.2.7': + dependencies: + '@eslint/core': 0.12.0 + levn: 0.4.1 + + '@fastify/ajv-compiler@3.6.0': + dependencies: + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + fast-uri: 2.4.0 + + '@fastify/busboy@2.1.1': {} + + '@fastify/error@3.4.1': {} + + '@fastify/fast-json-stringify-compiler@4.3.0': + dependencies: + fast-json-stringify: 5.16.1 + + '@fastify/merge-json-schemas@0.1.1': + dependencies: + fast-deep-equal: 3.1.3 + + '@floating-ui/core@1.6.9': + dependencies: + '@floating-ui/utils': 0.2.9 + + '@floating-ui/dom@1.6.13': + dependencies: + '@floating-ui/core': 1.6.9 + '@floating-ui/utils': 0.2.9 + + '@floating-ui/utils@0.2.9': {} + + '@floating-ui/vue@1.1.6(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@floating-ui/dom': 1.6.13 + '@floating-ui/utils': 0.2.9 + vue-demi: 0.14.10(vue@3.5.13(typescript@5.7.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@gerrit0/mini-shiki@1.27.2': + dependencies: + '@shikijs/engine-oniguruma': 1.29.2 + '@shikijs/types': 1.29.2 + '@shikijs/vscode-textmate': 10.0.2 + + '@hapi/hoek@9.3.0': {} + + '@hapi/topo@5.1.0': + dependencies: + '@hapi/hoek': 9.3.0 + + '@headlessui-float/vue@0.14.4(@headlessui/vue@1.7.23(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@floating-ui/core': 1.6.9 + '@floating-ui/dom': 1.6.13 + '@floating-ui/vue': 1.1.6(vue@3.5.13(typescript@5.7.3)) + '@headlessui/vue': 1.7.23(vue@3.5.13(typescript@5.7.3)) + vue: 3.5.13(typescript@5.7.3) + transitivePeerDependencies: + - '@vue/composition-api' + + '@headlessui/tailwindcss@0.2.2(tailwindcss@3.4.17)': + dependencies: + tailwindcss: 3.4.17 + + '@headlessui/vue@1.7.23(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@tanstack/vue-virtual': 3.13.0(vue@3.5.13(typescript@5.7.3)) + vue: 3.5.13(typescript@5.7.3) + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.2': {} + + '@iconify-json/carbon@1.2.1': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify-json/simple-icons@1.2.25': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify/types@2.0.0': {} + + '@iconify/utils@2.3.0': + dependencies: + '@antfu/install-pkg': 1.0.0 + '@antfu/utils': 8.1.1 + '@iconify/types': 2.0.0 + debug: 4.4.0(supports-color@8.1.1) + globals: 15.15.0 + kolorist: 1.8.0 + local-pkg: 1.0.0 + mlly: 1.7.4 + transitivePeerDependencies: + - supports-color + + '@img/sharp-darwin-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.4 + optional: true + + '@img/sharp-darwin-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.0.5': + optional: true + + '@img/sharp-libvips-linux-s390x@1.0.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + optional: true + + '@img/sharp-linux-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.4 + optional: true + + '@img/sharp-linux-arm@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.5 + optional: true + + '@img/sharp-linux-s390x@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.4 + optional: true + + '@img/sharp-linux-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + optional: true + + '@img/sharp-wasm32@0.33.5': + dependencies: + '@emnapi/runtime': 1.3.1 + optional: true + + '@img/sharp-win32-ia32@0.33.5': + optional: true + + '@img/sharp-win32-x64@0.33.5': + optional: true + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/console@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.13.5 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + + '@jest/core@29.7.0': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@22.13.5) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.5 + jest-mock: 29.7.0 + + '@jest/expect-utils@29.7.0': + dependencies: + jest-get-type: 29.6.3 + + '@jest/expect@29.7.0': + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/fake-timers@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 22.13.5 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + '@jest/globals@29.7.0': + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/reporters@29.7.0': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + '@types/node': 22.13.5 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + + '@jest/source-map@29.6.3': + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + callsites: 3.1.0 + graceful-fs: 4.2.11 + + '@jest/test-result@29.7.0': + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + + '@jest/test-sequencer@29.7.0': + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 + + '@jest/transform@29.7.0': + dependencies: + '@babel/core': 7.26.9 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.8 + pirates: 4.0.6 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.13.5 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/source-map@0.3.6': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@jsdevtools/ono@7.1.3': {} + + '@leichtgewicht/ip-codec@2.0.5': {} + + '@manypkg/find-root@1.1.0': + dependencies: + '@babel/runtime': 7.26.9 + '@types/node': 12.20.55 + find-up: 4.1.0 + fs-extra: 8.1.0 + + '@manypkg/get-packages@1.1.3': + dependencies: + '@babel/runtime': 7.26.9 + '@changesets/types': 4.1.0 + '@manypkg/find-root': 1.1.0 + fs-extra: 8.1.0 + globby: 11.1.0 + read-yaml-file: 1.1.0 + + '@mdi/font@7.4.47': {} + + '@microsoft/tsdoc-config@0.17.1': + dependencies: + '@microsoft/tsdoc': 0.15.1 + ajv: 8.12.0 + jju: 1.4.0 + resolve: 1.22.10 + + '@microsoft/tsdoc@0.15.1': {} + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.0 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.1.1': {} + + '@pkgr/core@0.2.1': {} + + '@polka/url@1.0.0-next.28': {} + + '@rollup/plugin-babel@5.3.1(@babel/core@7.26.9)(@types/babel__core@7.20.5)(rollup@2.79.2)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + rollup: 2.79.2 + optionalDependencies: + '@types/babel__core': 7.20.5 + transitivePeerDependencies: + - supports-color + + '@rollup/plugin-node-resolve@15.3.1(rollup@2.79.2)': + dependencies: + '@rollup/pluginutils': 5.1.4(rollup@2.79.2) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.10 + optionalDependencies: + rollup: 2.79.2 + + '@rollup/plugin-replace@2.4.2(rollup@2.79.2)': + dependencies: + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + magic-string: 0.25.9 + rollup: 2.79.2 + + '@rollup/plugin-terser@0.4.4(rollup@2.79.2)': + dependencies: + serialize-javascript: 6.0.2 + smob: 1.5.0 + terser: 5.39.0 + optionalDependencies: + rollup: 2.79.2 + + '@rollup/plugin-typescript@12.1.2(rollup@4.34.8)(tslib@2.8.1)(typescript@5.7.3)': + dependencies: + '@rollup/pluginutils': 5.1.4(rollup@4.34.8) + resolve: 1.22.10 + typescript: 5.7.3 + optionalDependencies: + rollup: 4.34.8 + tslib: 2.8.1 + + '@rollup/pluginutils@3.1.0(rollup@2.79.2)': + dependencies: + '@types/estree': 0.0.39 + estree-walker: 1.0.1 + picomatch: 2.3.1 + rollup: 2.79.2 + + '@rollup/pluginutils@5.1.4(rollup@2.79.2)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 2.79.2 + + '@rollup/pluginutils@5.1.4(rollup@4.34.8)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.34.8 + + '@rollup/rollup-android-arm-eabi@4.34.8': + optional: true + + '@rollup/rollup-android-arm64@4.34.8': + optional: true + + '@rollup/rollup-darwin-arm64@4.34.8': + optional: true + + '@rollup/rollup-darwin-x64@4.34.8': + optional: true + + '@rollup/rollup-freebsd-arm64@4.34.8': + optional: true + + '@rollup/rollup-freebsd-x64@4.34.8': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.34.8': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.34.8': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.34.8': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.34.8': + optional: true + + '@rollup/rollup-linux-x64-musl@4.34.8': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.34.8': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.34.8': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.34.8': + optional: true + + '@shikijs/core@2.5.0': + dependencies: + '@shikijs/engine-javascript': 2.5.0 + '@shikijs/engine-oniguruma': 2.5.0 + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + + '@shikijs/engine-javascript@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 3.1.1 + + '@shikijs/engine-oniguruma@1.29.2': + dependencies: + '@shikijs/types': 1.29.2 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/engine-oniguruma@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/langs@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + + '@shikijs/themes@2.5.0': + dependencies: + '@shikijs/types': 2.5.0 + + '@shikijs/transformers@2.5.0': + dependencies: + '@shikijs/core': 2.5.0 + '@shikijs/types': 2.5.0 + + '@shikijs/types@1.29.2': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + '@shikijs/types@2.5.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + '@shikijs/vscode-textmate@10.0.2': {} + + '@sideway/address@4.1.5': + dependencies: + '@hapi/hoek': 9.3.0 + + '@sideway/formula@3.0.1': {} + + '@sideway/pinpoint@2.0.0': {} + + '@sinclair/typebox@0.27.8': {} + + '@sindresorhus/is@4.6.0': {} + + '@sindresorhus/merge-streams@2.3.0': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@10.3.0': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@surma/rollup-plugin-off-main-thread@2.2.3': + dependencies: + ejs: 3.1.10 + json5: 2.2.3 + magic-string: 0.25.9 + string.prototype.matchall: 4.0.12 + + '@szmarczak/http-timer@4.0.6': + dependencies: + defer-to-connect: 2.0.1 + + '@tanstack/virtual-core@3.13.0': {} + + '@tanstack/vue-virtual@3.13.0(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@tanstack/virtual-core': 3.13.0 + vue: 3.5.13(typescript@5.7.3) + + '@tootallnate/once@2.0.0': {} + + '@types/assert@1.5.11': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 + + '@types/babel__generator@7.6.8': + dependencies: + '@babel/types': 7.26.9 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + + '@types/babel__traverse@7.20.6': + dependencies: + '@babel/types': 7.26.9 + + '@types/body-parser@1.19.5': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 22.13.5 + + '@types/bonjour@3.5.13': + dependencies: + '@types/node': 22.13.5 + + '@types/braces@3.0.4': {} + + '@types/cacheable-request@6.0.3': + dependencies: + '@types/http-cache-semantics': 4.0.4 + '@types/keyv': 3.1.4 + '@types/node': 22.13.5 + '@types/responselike': 1.0.3 + + '@types/connect-history-api-fallback@1.5.4': + dependencies: + '@types/express-serve-static-core': 5.0.0 + '@types/node': 22.13.5 + + '@types/connect@3.4.38': + dependencies: + '@types/node': 22.13.5 + + '@types/cors@2.8.17': + dependencies: + '@types/node': 22.13.5 + + '@types/cytoscape-fcose@2.2.4': + dependencies: + '@types/cytoscape': 3.21.9 + + '@types/cytoscape@3.21.9': {} + + '@types/d3-array@3.2.1': {} + + '@types/d3-axis@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-brush@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-chord@3.0.6': {} + + '@types/d3-color@3.1.3': {} + + '@types/d3-contour@3.0.6': + dependencies: + '@types/d3-array': 3.2.1 + '@types/geojson': 7946.0.14 + + '@types/d3-delaunay@6.0.4': {} + + '@types/d3-dispatch@3.0.6': {} + + '@types/d3-drag@3.0.7': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-dsv@3.0.7': {} + + '@types/d3-ease@3.0.2': {} + + '@types/d3-fetch@3.0.7': + dependencies: + '@types/d3-dsv': 3.0.7 + + '@types/d3-force@3.0.10': {} + + '@types/d3-format@3.0.4': {} + + '@types/d3-geo@3.1.0': + dependencies: + '@types/geojson': 7946.0.14 + + '@types/d3-hierarchy@3.1.7': {} + + '@types/d3-interpolate@3.0.4': + dependencies: + '@types/d3-color': 3.1.3 + + '@types/d3-path@1.0.11': {} + + '@types/d3-path@3.1.0': {} + + '@types/d3-polygon@3.0.2': {} + + '@types/d3-quadtree@3.0.6': {} + + '@types/d3-random@3.0.3': {} + + '@types/d3-sankey@0.12.4': + dependencies: + '@types/d3-shape': 1.3.12 + + '@types/d3-scale-chromatic@3.1.0': {} + + '@types/d3-scale@4.0.9': + dependencies: + '@types/d3-time': 3.0.3 + + '@types/d3-selection@3.0.11': {} + + '@types/d3-shape@1.3.12': + dependencies: + '@types/d3-path': 1.0.11 + + '@types/d3-shape@3.1.7': + dependencies: + '@types/d3-path': 3.1.0 + + '@types/d3-time-format@4.0.3': {} + + '@types/d3-time@3.0.3': {} + + '@types/d3-timer@3.0.2': {} + + '@types/d3-transition@3.0.9': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-zoom@3.0.8': + dependencies: + '@types/d3-interpolate': 3.0.4 + '@types/d3-selection': 3.0.11 + + '@types/d3@7.4.3': + dependencies: + '@types/d3-array': 3.2.1 + '@types/d3-axis': 3.0.6 + '@types/d3-brush': 3.0.6 + '@types/d3-chord': 3.0.6 + '@types/d3-color': 3.1.3 + '@types/d3-contour': 3.0.6 + '@types/d3-delaunay': 6.0.4 + '@types/d3-dispatch': 3.0.6 + '@types/d3-drag': 3.0.7 + '@types/d3-dsv': 3.0.7 + '@types/d3-ease': 3.0.2 + '@types/d3-fetch': 3.0.7 + '@types/d3-force': 3.0.10 + '@types/d3-format': 3.0.4 + '@types/d3-geo': 3.1.0 + '@types/d3-hierarchy': 3.1.7 + '@types/d3-interpolate': 3.0.4 + '@types/d3-path': 3.1.0 + '@types/d3-polygon': 3.0.2 + '@types/d3-quadtree': 3.0.6 + '@types/d3-random': 3.0.3 + '@types/d3-scale': 4.0.9 + '@types/d3-scale-chromatic': 3.1.0 + '@types/d3-selection': 3.0.11 + '@types/d3-shape': 3.1.7 + '@types/d3-time': 3.0.3 + '@types/d3-time-format': 4.0.3 + '@types/d3-timer': 3.0.2 + '@types/d3-transition': 3.0.9 + '@types/d3-zoom': 3.0.8 + + '@types/debug@4.1.12': + dependencies: + '@types/ms': 0.7.34 + + '@types/estree@0.0.39': {} + + '@types/estree@1.0.6': {} + + '@types/express-serve-static-core@4.19.6': + dependencies: + '@types/node': 22.13.5 + '@types/qs': 6.9.16 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + + '@types/express-serve-static-core@5.0.0': + dependencies: + '@types/node': 22.13.5 + '@types/qs': 6.9.16 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + + '@types/express@4.17.21': + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.19.6 + '@types/qs': 6.9.16 + '@types/serve-static': 1.15.7 + + '@types/express@5.0.0': + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 5.0.0 + '@types/qs': 6.9.16 + '@types/serve-static': 1.15.7 + + '@types/flexsearch@0.7.6': {} + + '@types/geojson@7946.0.14': {} + + '@types/glob@8.1.0': + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 22.13.5 + + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 22.13.5 + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/http-cache-semantics@4.0.4': {} + + '@types/http-errors@2.0.4': {} + + '@types/http-proxy@1.17.15': + dependencies: + '@types/node': 22.13.5 + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/js-yaml@4.0.9': {} + + '@types/jsdom@21.1.7': + dependencies: + '@types/node': 22.13.5 + '@types/tough-cookie': 4.0.5 + parse5: 7.2.1 + + '@types/json-schema@7.0.15': {} + + '@types/katex@0.16.7': {} + + '@types/keyv@3.1.4': + dependencies: + '@types/node': 22.13.5 + + '@types/linkify-it@5.0.0': {} + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.10 + + '@types/lodash@4.17.10': {} + + '@types/lodash@4.17.15': {} + + '@types/markdown-it@12.2.3': + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + + '@types/markdown-it@14.1.2': + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + + '@types/mdast@3.0.15': + dependencies: + '@types/unist': 2.0.11 + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/mdurl@2.0.0': {} + + '@types/micromatch@4.0.9': + dependencies: + '@types/braces': 3.0.4 + + '@types/mime@1.3.5': {} + + '@types/minimatch@5.1.2': {} + + '@types/ms@0.7.34': {} + + '@types/node-forge@1.3.11': + dependencies: + '@types/node': 22.13.5 + + '@types/node@12.20.55': {} + + '@types/node@18.19.76': + dependencies: + undici-types: 5.26.5 + + '@types/node@22.13.5': + dependencies: + undici-types: 6.20.0 + + '@types/normalize-package-data@2.4.4': {} + + '@types/qs@6.9.16': {} + + '@types/ramda@0.28.25': + dependencies: + ts-toolbelt: 6.15.5 + + '@types/range-parser@1.2.7': {} + + '@types/resolve@1.20.2': {} + + '@types/responselike@1.0.3': + dependencies: + '@types/node': 22.13.5 + + '@types/retry@0.12.0': {} + + '@types/rollup-plugin-visualizer@5.0.3(rollup@4.34.8)': + dependencies: + rollup-plugin-visualizer: 5.14.0(rollup@4.34.8) + transitivePeerDependencies: + - rolldown + - rollup + + '@types/send@0.17.4': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 22.13.5 + + '@types/serve-index@1.9.4': + dependencies: + '@types/express': 5.0.0 + + '@types/serve-static@1.15.7': + dependencies: + '@types/http-errors': 2.0.4 + '@types/node': 22.13.5 + '@types/send': 0.17.4 + + '@types/sinonjs__fake-timers@8.1.1': {} + + '@types/sizzle@2.3.9': {} + + '@types/sockjs@0.3.36': + dependencies: + '@types/node': 22.13.5 + + '@types/stack-utils@2.0.3': {} + + '@types/stylis@4.2.7': {} + + '@types/tough-cookie@4.0.5': {} + + '@types/trusted-types@2.0.7': {} + + '@types/unist@2.0.11': {} + + '@types/unist@3.0.3': {} + + '@types/uuid@10.0.0': {} + + '@types/web-bluetooth@0.0.20': {} + + '@types/web-bluetooth@0.0.21': {} + + '@types/ws@8.5.12': + dependencies: + '@types/node': 22.13.5 + + '@types/ws@8.5.5': + dependencies: + '@types/node': 22.13.5 + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.33': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 22.13.5 + optional: true + + '@typescript-eslint/eslint-plugin@8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/scope-manager': 8.29.1 + '@typescript-eslint/type-utils': 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.29.1 + eslint: 9.24.0(jiti@2.4.2) + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.29.1 + '@typescript-eslint/types': 8.29.1 + '@typescript-eslint/typescript-estree': 8.29.1(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.29.1 + debug: 4.4.0(supports-color@8.1.1) + eslint: 9.24.0(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.24.1': + dependencies: + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/visitor-keys': 8.24.1 + + '@typescript-eslint/scope-manager@8.29.1': + dependencies: + '@typescript-eslint/types': 8.29.1 + '@typescript-eslint/visitor-keys': 8.29.1 + + '@typescript-eslint/type-utils@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@typescript-eslint/typescript-estree': 8.29.1(typescript@5.7.3) + '@typescript-eslint/utils': 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + debug: 4.4.0(supports-color@8.1.1) + eslint: 9.24.0(jiti@2.4.2) + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@7.18.0': {} + + '@typescript-eslint/types@8.24.1': {} + + '@typescript-eslint/types@8.29.1': {} + + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.7.3)': + dependencies: + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.4.0(supports-color@8.1.1) + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.1 + ts-api-utils: 1.3.0(typescript@5.7.3) + optionalDependencies: + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/typescript-estree@8.24.1(typescript@5.7.3)': + dependencies: + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/visitor-keys': 8.24.1 + debug: 4.4.0(supports-color@8.1.1) + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.1 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/typescript-estree@8.29.1(typescript@5.7.3)': + dependencies: + '@typescript-eslint/types': 8.29.1 + '@typescript-eslint/visitor-keys': 8.29.1 + debug: 4.4.0(supports-color@8.1.1) + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.1 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.24.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/eslint-utils': 4.5.1(eslint@9.24.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.7.3) + eslint: 9.24.0(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/eslint-utils': 4.5.1(eslint@9.24.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.29.1 + '@typescript-eslint/types': 8.29.1 + '@typescript-eslint/typescript-estree': 8.29.1(typescript@5.7.3) + eslint: 9.24.0(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@7.18.0': + dependencies: + '@typescript-eslint/types': 7.18.0 + eslint-visitor-keys: 3.4.3 + + '@typescript-eslint/visitor-keys@8.24.1': + dependencies: + '@typescript-eslint/types': 8.24.1 + eslint-visitor-keys: 4.2.0 + + '@typescript-eslint/visitor-keys@8.29.1': + dependencies: + '@typescript-eslint/types': 8.29.1 + eslint-visitor-keys: 4.2.0 + + '@ungap/structured-clone@1.3.0': {} + + '@unocss/astro@66.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@unocss/core': 66.0.0 + '@unocss/reset': 66.0.0 + '@unocss/vite': 66.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) + optionalDependencies: + vite: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) + transitivePeerDependencies: + - vue + + '@unocss/cli@66.0.0': + dependencies: + '@ampproject/remapping': 2.3.0 + '@unocss/config': 66.0.0 + '@unocss/core': 66.0.0 + '@unocss/preset-uno': 66.0.0 + cac: 6.7.14 + chokidar: 3.6.0 + colorette: 2.0.20 + consola: 3.4.0 + magic-string: 0.30.17 + pathe: 2.0.3 + perfect-debounce: 1.0.0 + tinyglobby: 0.2.12 + unplugin-utils: 0.2.4 + + '@unocss/config@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + unconfig: 7.0.0 + + '@unocss/core@66.0.0': {} + + '@unocss/extractor-arbitrary-variants@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + + '@unocss/inspector@66.0.0(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@unocss/core': 66.0.0 + '@unocss/rule-utils': 66.0.0 + colorette: 2.0.20 + gzip-size: 6.0.0 + sirv: 3.0.1 + vue-flow-layout: 0.1.1(vue@3.5.13(typescript@5.7.3)) + transitivePeerDependencies: + - vue + + '@unocss/postcss@66.0.0(postcss@8.5.3)': + dependencies: + '@unocss/config': 66.0.0 + '@unocss/core': 66.0.0 + '@unocss/rule-utils': 66.0.0 + css-tree: 3.1.0 + postcss: 8.5.3 + tinyglobby: 0.2.12 + + '@unocss/preset-attributify@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + + '@unocss/preset-icons@66.0.0': + dependencies: + '@iconify/utils': 2.3.0 + '@unocss/core': 66.0.0 + ofetch: 1.4.1 + transitivePeerDependencies: + - supports-color + + '@unocss/preset-mini@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + '@unocss/extractor-arbitrary-variants': 66.0.0 + '@unocss/rule-utils': 66.0.0 + + '@unocss/preset-tagify@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + + '@unocss/preset-typography@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + '@unocss/preset-mini': 66.0.0 + '@unocss/rule-utils': 66.0.0 + + '@unocss/preset-uno@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + '@unocss/preset-wind3': 66.0.0 + + '@unocss/preset-web-fonts@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + ofetch: 1.4.1 + + '@unocss/preset-wind3@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + '@unocss/preset-mini': 66.0.0 + '@unocss/rule-utils': 66.0.0 + + '@unocss/preset-wind@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + '@unocss/preset-wind3': 66.0.0 + + '@unocss/reset@66.0.0': {} + + '@unocss/rule-utils@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + magic-string: 0.30.17 + + '@unocss/transformer-attributify-jsx@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + + '@unocss/transformer-compile-class@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + + '@unocss/transformer-directives@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + '@unocss/rule-utils': 66.0.0 + css-tree: 3.1.0 + + '@unocss/transformer-variant-group@66.0.0': + dependencies: + '@unocss/core': 66.0.0 + + '@unocss/vite@66.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@unocss/config': 66.0.0 + '@unocss/core': 66.0.0 + '@unocss/inspector': 66.0.0(vue@3.5.13(typescript@5.7.3)) + chokidar: 3.6.0 + magic-string: 0.30.17 + tinyglobby: 0.2.12 + unplugin-utils: 0.2.4 + vite: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) + transitivePeerDependencies: + - vue + + '@vite-pwa/vitepress@1.0.0(vite-plugin-pwa@1.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0))': + dependencies: + vite-plugin-pwa: 1.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0) + + '@vitejs/plugin-vue@5.2.1(vite@5.4.14(@types/node@22.13.5)(terser@5.39.0))(vue@3.5.13(typescript@5.7.3))': + dependencies: + vite: 5.4.14(@types/node@22.13.5)(terser@5.39.0) + vue: 3.5.13(typescript@5.7.3) + + '@vitejs/plugin-vue@5.2.1(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))': + dependencies: + vite: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) + vue: 3.5.13(typescript@5.7.3) + + '@vitest/coverage-v8@3.0.6(vitest@3.0.6)': + dependencies: + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 1.0.2 + debug: 4.4.0(supports-color@8.1.1) + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.1.7 + magic-string: 0.30.17 + magicast: 0.3.5 + std-env: 3.8.0 + test-exclude: 7.0.1 + tinyrainbow: 2.0.0 + vitest: 3.0.6(@types/debug@4.1.12)(@types/node@22.13.5)(@vitest/ui@3.0.6)(jiti@2.4.2)(jsdom@26.0.0)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) + transitivePeerDependencies: + - supports-color + + '@vitest/expect@3.0.6': + dependencies: + '@vitest/spy': 3.0.6 + '@vitest/utils': 3.0.6 + chai: 5.2.0 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.0.6(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))': + dependencies: + '@vitest/spy': 3.0.6 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) + + '@vitest/pretty-format@3.0.6': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.0.6': + dependencies: + '@vitest/utils': 3.0.6 + pathe: 2.0.3 + + '@vitest/snapshot@3.0.6': + dependencies: + '@vitest/pretty-format': 3.0.6 + magic-string: 0.30.17 + pathe: 2.0.3 + + '@vitest/spy@3.0.6': + dependencies: + tinyspy: 3.0.2 + + '@vitest/ui@3.0.6(vitest@3.0.6)': + dependencies: + '@vitest/utils': 3.0.6 + fflate: 0.8.2 + flatted: 3.3.3 + pathe: 2.0.3 + sirv: 3.0.1 + tinyglobby: 0.2.12 + tinyrainbow: 2.0.0 + vitest: 3.0.6(@types/debug@4.1.12)(@types/node@22.13.5)(@vitest/ui@3.0.6)(jiti@2.4.2)(jsdom@26.0.0)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) + + '@vitest/utils@3.0.6': + dependencies: + '@vitest/pretty-format': 3.0.6 + loupe: 3.1.3 + tinyrainbow: 2.0.0 + + '@vue/compat@3.5.13(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@babel/parser': 7.26.9 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + vue: 3.5.13(typescript@5.7.3) + + '@vue/compiler-core@3.5.13': + dependencies: + '@babel/parser': 7.26.9 + '@vue/shared': 3.5.13 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.13': + dependencies: + '@vue/compiler-core': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/compiler-sfc@3.5.13': + dependencies: + '@babel/parser': 7.26.9 + '@vue/compiler-core': 3.5.13 + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-ssr': 3.5.13 + '@vue/shared': 3.5.13 + estree-walker: 2.0.2 + magic-string: 0.30.17 + postcss: 8.5.3 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.13': + dependencies: + '@vue/compiler-dom': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/devtools-api@6.6.4': {} + + '@vue/devtools-api@7.7.2': + dependencies: + '@vue/devtools-kit': 7.7.2 + + '@vue/devtools-kit@7.7.2': + dependencies: + '@vue/devtools-shared': 7.7.2 + birpc: 0.2.19 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 1.0.0 + speakingurl: 14.0.1 + superjson: 2.2.2 + + '@vue/devtools-shared@7.7.2': + dependencies: + rfdc: 1.4.1 + + '@vue/reactivity@3.5.13': + dependencies: + '@vue/shared': 3.5.13 + + '@vue/runtime-core@3.5.13': + dependencies: + '@vue/reactivity': 3.5.13 + '@vue/shared': 3.5.13 + + '@vue/runtime-dom@3.5.13': + dependencies: + '@vue/reactivity': 3.5.13 + '@vue/runtime-core': 3.5.13 + '@vue/shared': 3.5.13 + csstype: 3.1.3 + + '@vue/server-renderer@3.5.13(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@vue/compiler-ssr': 3.5.13 + '@vue/shared': 3.5.13 + vue: 3.5.13(typescript@5.7.3) + + '@vue/shared@3.5.13': {} + + '@vueuse/core@12.7.0(typescript@5.7.3)': + dependencies: + '@types/web-bluetooth': 0.0.20 + '@vueuse/metadata': 12.7.0 + '@vueuse/shared': 12.7.0(typescript@5.7.3) + vue: 3.5.13(typescript@5.7.3) + transitivePeerDependencies: + - typescript + + '@vueuse/core@13.1.0(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 13.1.0 + '@vueuse/shared': 13.1.0(vue@3.5.13(typescript@5.7.3)) + vue: 3.5.13(typescript@5.7.3) + + '@vueuse/integrations@12.7.0(axios@1.8.4)(focus-trap@7.6.4)(typescript@5.7.3)': + dependencies: + '@vueuse/core': 12.7.0(typescript@5.7.3) + '@vueuse/shared': 12.7.0(typescript@5.7.3) + vue: 3.5.13(typescript@5.7.3) + optionalDependencies: + axios: 1.8.4(debug@4.4.0) + focus-trap: 7.6.4 + transitivePeerDependencies: + - typescript + + '@vueuse/metadata@12.7.0': {} + + '@vueuse/metadata@13.1.0': {} + + '@vueuse/shared@12.7.0(typescript@5.7.3)': + dependencies: + vue: 3.5.13(typescript@5.7.3) + transitivePeerDependencies: + - typescript + + '@vueuse/shared@13.1.0(vue@3.5.13(typescript@5.7.3))': + dependencies: + vue: 3.5.13(typescript@5.7.3) + + '@wdio/config@7.31.1(typescript@5.7.3)': + dependencies: + '@types/glob': 8.1.0 + '@wdio/logger': 7.26.0 + '@wdio/types': 7.30.2(typescript@5.7.3) + '@wdio/utils': 7.30.2(typescript@5.7.3) + deepmerge: 4.3.1 + glob: 8.1.0 + transitivePeerDependencies: + - typescript + + '@wdio/logger@7.26.0': + dependencies: + chalk: 4.1.2 + loglevel: 1.9.2 + loglevel-plugin-prefix: 0.8.4 + strip-ansi: 6.0.1 + + '@wdio/protocols@7.27.0': {} + + '@wdio/types@7.30.2(typescript@5.7.3)': + dependencies: + '@types/node': 18.19.76 + got: 11.8.6 + optionalDependencies: + typescript: 5.7.3 + + '@wdio/utils@7.30.2(typescript@5.7.3)': + dependencies: + '@wdio/logger': 7.26.0 + '@wdio/types': 7.30.2(typescript@5.7.3) + p-iteration: 1.1.8 + transitivePeerDependencies: + - typescript + + '@webassemblyjs/ast@1.12.1': + dependencies: + '@webassemblyjs/helper-numbers': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + + '@webassemblyjs/floating-point-hex-parser@1.11.6': {} + + '@webassemblyjs/helper-api-error@1.11.6': {} + + '@webassemblyjs/helper-buffer@1.12.1': {} + + '@webassemblyjs/helper-numbers@1.11.6': + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@xtuc/long': 4.2.2 + + '@webassemblyjs/helper-wasm-bytecode@1.11.6': {} + + '@webassemblyjs/helper-wasm-section@1.12.1': + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/wasm-gen': 1.12.1 + + '@webassemblyjs/ieee754@1.11.6': + dependencies: + '@xtuc/ieee754': 1.2.0 + + '@webassemblyjs/leb128@1.11.6': + dependencies: + '@xtuc/long': 4.2.2 + + '@webassemblyjs/utf8@1.11.6': {} + + '@webassemblyjs/wasm-edit@1.12.1': + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/helper-wasm-section': 1.12.1 + '@webassemblyjs/wasm-gen': 1.12.1 + '@webassemblyjs/wasm-opt': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + '@webassemblyjs/wast-printer': 1.12.1 + + '@webassemblyjs/wasm-gen@1.12.1': + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + + '@webassemblyjs/wasm-opt@1.12.1': + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/wasm-gen': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + + '@webassemblyjs/wasm-parser@1.12.1': + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-api-error': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + + '@webassemblyjs/wast-printer@1.12.1': + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@xtuc/long': 4.2.2 + + '@webpack-cli/configtest@1.2.0(webpack-cli@4.10.0)(webpack@5.95.0)': + dependencies: + webpack: 5.95.0(esbuild@0.25.0)(webpack-cli@4.10.0) + webpack-cli: 4.10.0(webpack-dev-server@4.15.2)(webpack@5.95.0) + + '@webpack-cli/info@1.5.0(webpack-cli@4.10.0)': + dependencies: + envinfo: 7.14.0 + webpack-cli: 4.10.0(webpack-dev-server@4.15.2)(webpack@5.95.0) + + '@webpack-cli/serve@1.7.0(webpack-cli@4.10.0)(webpack-dev-server@4.15.2)': + dependencies: + webpack-cli: 4.10.0(webpack-dev-server@4.15.2)(webpack@5.95.0) + optionalDependencies: + webpack-dev-server: 4.15.2(webpack-cli@4.10.0)(webpack@5.95.0) + + '@xmldom/xmldom@0.8.10': {} + + '@xtuc/ieee754@1.2.0': {} + + '@xtuc/long@4.2.2': {} + + '@zenuml/core@3.27.12(typescript@5.7.3)': + dependencies: + '@headlessui-float/vue': 0.14.4(@headlessui/vue@1.7.23(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3)) + '@headlessui/tailwindcss': 0.2.2(tailwindcss@3.4.17) + '@headlessui/vue': 1.7.23(vue@3.5.13(typescript@5.7.3)) + '@types/assert': 1.5.11 + '@types/ramda': 0.28.25 + '@vue/compat': 3.5.13(vue@3.5.13(typescript@5.7.3)) + antlr4: 4.11.0 + color-string: 1.9.1 + dom-to-image-more: 2.16.0 + dompurify: 3.2.5 + file-saver: 2.0.5 + highlight.js: 10.7.3 + html-to-image: 1.11.13 + lodash: 4.17.21 + marked: 4.3.0 + pino: 8.21.0 + postcss: 8.5.3 + ramda: 0.28.0 + tailwindcss: 3.4.17 + vue: 3.5.13(typescript@5.7.3) + vuex: 4.1.0(vue@3.5.13(typescript@5.7.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - ts-node + - typescript + + JSONSelect@0.4.0: {} + + JSV@4.0.2: {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + abstract-logging@2.0.1: {} + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + accepts@2.0.0: + dependencies: + mime-types: 3.0.1 + negotiator: 1.0.0 + + acorn-import-attributes@1.9.5(acorn@8.12.1): + dependencies: + acorn: 8.12.1 + + acorn-jsx@5.3.2(acorn@8.14.0): + dependencies: + acorn: 8.14.0 + + acorn-walk@8.3.4: + dependencies: + acorn: 8.14.0 + + acorn@8.12.1: {} + + acorn@8.14.0: {} + + agent-base@6.0.2: + dependencies: + debug: 4.4.0(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + agent-base@7.1.1: + dependencies: + debug: 4.4.0(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + agent-base@7.1.3: {} + + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + + aggregate-error@4.0.1: + dependencies: + clean-stack: 4.2.0 + indent-string: 5.0.0 + + ajv-formats@2.1.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + + ajv-formats@3.0.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + + ajv-keywords@3.5.2(ajv@6.12.6): + dependencies: + ajv: 6.12.6 + + ajv-keywords@5.1.0(ajv@8.17.1): + dependencies: + ajv: 8.17.1 + fast-deep-equal: 3.1.3 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.12.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.2 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + algoliasearch@5.20.3: + dependencies: + '@algolia/client-abtesting': 5.20.3 + '@algolia/client-analytics': 5.20.3 + '@algolia/client-common': 5.20.3 + '@algolia/client-insights': 5.20.3 + '@algolia/client-personalization': 5.20.3 + '@algolia/client-query-suggestions': 5.20.3 + '@algolia/client-search': 5.20.3 + '@algolia/ingestion': 1.20.3 + '@algolia/monitoring': 1.20.3 + '@algolia/recommend': 5.20.3 + '@algolia/requester-browser-xhr': 5.20.3 + '@algolia/requester-fetch': 5.20.3 + '@algolia/requester-node-http': 5.20.3 + + amdefine@1.0.1: + optional: true + + ansi-align@3.0.1: + dependencies: + string-width: 4.2.3 + + ansi-colors@4.1.3: {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-escapes@7.0.0: + dependencies: + environment: 1.1.0 + + ansi-html-community@0.0.8: {} + + ansi-regex@2.1.1: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@2.2.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.1: {} + + antlr4@4.11.0: {} + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + app-module-path@2.2.0: {} + + app-path@3.3.0: + dependencies: + execa: 1.0.0 + + appdata-path@1.0.0: {} + + append-transform@2.0.0: + dependencies: + default-require-extensions: 3.0.1 + + arch@2.2.0: {} + + archy@1.0.0: {} + + are-docs-informative@0.0.2: {} + + arg@5.0.2: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.3 + is-array-buffer: 3.0.5 + + array-flatten@1.1.1: {} + + array-timsort@1.0.3: {} + + array-union@2.1.0: {} + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + is-array-buffer: 3.0.5 + + arrify@3.0.0: {} + + asn1@0.2.6: + dependencies: + safer-buffer: 2.1.2 + + assert-plus@1.0.0: {} + + assertion-error@2.0.1: {} + + ast-module-types@6.0.0: {} + + astral-regex@2.0.0: {} + + async-function@1.0.0: {} + + async@3.2.6: {} + + asynckit@0.4.0: {} + + at-least-node@1.0.0: {} + + atomic-sleep@1.0.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + avvio@8.4.0: + dependencies: + '@fastify/error': 3.4.1 + fastq: 1.19.0 + + aws-sign2@0.7.0: {} + + aws4@1.13.2: {} + + axios@1.7.9(debug@4.4.0): + dependencies: + follow-redirects: 1.15.9(debug@4.4.0) + form-data: 4.0.2 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + axios@1.8.4(debug@4.4.0): + dependencies: + follow-redirects: 1.15.9(debug@4.4.0) + form-data: 4.0.2 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + babel-jest@29.7.0(@babel/core@7.26.9): + dependencies: + '@babel/core': 7.26.9 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.26.9) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-loader@9.2.1(@babel/core@7.26.9)(webpack@5.95.0(esbuild@0.25.0)): + dependencies: + '@babel/core': 7.26.9 + find-cache-dir: 4.0.0 + schema-utils: 4.3.0 + webpack: 5.95.0(esbuild@0.25.0) + + babel-plugin-istanbul@6.1.1: + dependencies: + '@babel/helper-plugin-utils': 7.25.7 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@29.6.3: + dependencies: + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.6 + + babel-plugin-polyfill-corejs2@0.4.12(@babel/core@7.26.9): + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/core': 7.26.9 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.9) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.11.1(@babel/core@7.26.9): + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.9) + core-js-compat: 3.41.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.3(@babel/core@7.26.9): + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.9): + dependencies: + '@babel/core': 7.26.9 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.9) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.9) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.9) + '@babel/plugin-syntax-import-attributes': 7.25.7(@babel/core@7.26.9) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.9) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.9) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.9) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.9) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.9) + + babel-preset-jest@29.6.3(@babel/core@7.26.9): + dependencies: + '@babel/core': 7.26.9 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.9) + + bail@2.0.2: {} + + balanced-match@1.0.2: {} + + base64-js@1.5.1: {} + + batch@0.6.1: {} + + bcrypt-pbkdf@1.0.2: + dependencies: + tweetnacl: 0.14.5 + + better-path-resolve@1.0.0: + dependencies: + is-windows: 1.0.2 + + binary-extensions@2.3.0: {} + + binary-searching@2.0.5: {} + + binary@0.3.0: + dependencies: + buffers: 0.1.1 + chainsaw: 0.1.0 + + birpc@0.2.19: {} + + blob-util@2.0.2: {} + + bluebird@3.7.1: {} + + bluebird@3.7.2: {} + + bmpimagejs@1.0.4: {} + + body-parser@1.20.3: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + body-parser@2.2.0: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 4.4.0(supports-color@8.1.1) + http-errors: 2.0.0 + iconv-lite: 0.6.3 + on-finished: 2.4.1 + qs: 6.14.0 + raw-body: 3.0.0 + type-is: 2.0.1 + transitivePeerDependencies: + - supports-color + + bonjour-service@1.2.1: + dependencies: + fast-deep-equal: 3.1.3 + multicast-dns: 7.2.5 + + boxen@5.1.2: + dependencies: + ansi-align: 3.0.1 + camelcase: 6.3.0 + chalk: 4.1.2 + cli-boxes: 2.2.1 + string-width: 4.2.3 + type-fest: 0.20.2 + widest-line: 3.1.0 + wrap-ansi: 7.0.0 + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.24.0: + dependencies: + caniuse-lite: 1.0.30001700 + electron-to-chromium: 1.5.101 + node-releases: 2.0.19 + update-browserslist-db: 1.1.2(browserslist@4.24.0) + + browserslist@4.24.4: + dependencies: + caniuse-lite: 1.0.30001700 + electron-to-chromium: 1.5.101 + node-releases: 2.0.19 + update-browserslist-db: 1.1.2(browserslist@4.24.4) + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-crc32@0.2.13: {} + + buffer-from@1.1.2: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + buffers@0.1.1: {} + + builtin-modules@5.0.0: {} + + bytes@3.0.0: {} + + bytes@3.1.2: {} + + cac@6.7.14: {} + + cacheable-lookup@5.0.4: {} + + cacheable-request@7.0.4: + dependencies: + clone-response: 1.0.3 + get-stream: 5.2.0 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + lowercase-keys: 2.0.0 + normalize-url: 6.1.0 + responselike: 2.0.1 + + cachedir@2.4.0: {} + + caching-transform@4.0.0: + dependencies: + hasha: 5.2.2 + make-dir: 3.1.0 + package-hash: 4.0.0 + write-file-atomic: 3.0.3 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.2.7 + set-function-length: 1.2.2 + + call-bound@1.0.3: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.2.7 + + callsites@3.1.0: {} + + camelcase-css@2.0.1: {} + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001700: {} + + caseless@0.12.0: {} + + ccount@2.0.1: {} + + chai@5.2.0: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.3 + pathval: 2.0.0 + + chainsaw@0.1.0: + dependencies: + traverse: 0.3.9 + + chalk-template@1.1.0: + dependencies: + chalk: 5.4.1 + + chalk@1.1.3: + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.3.0: {} + + chalk@5.4.1: {} + + char-regex@1.0.2: {} + + character-entities-html4@2.1.0: {} + + character-entities-legacy@1.1.4: {} + + character-entities-legacy@3.0.0: {} + + character-entities@1.2.4: {} + + character-entities@2.0.2: {} + + character-reference-invalid@1.1.4: {} + + chardet@0.7.0: {} + + check-error@2.1.1: {} + + check-more-types@2.24.0: {} + + chevrotain-allstar@0.3.1(chevrotain@11.0.3): + dependencies: + chevrotain: 11.0.3 + lodash-es: 4.17.21 + + chevrotain@11.0.3: + dependencies: + '@chevrotain/cst-dts-gen': 11.0.3 + '@chevrotain/gast': 11.0.3 + '@chevrotain/regexp-to-ast': 11.0.3 + '@chevrotain/types': 11.0.3 + '@chevrotain/utils': 11.0.3 + lodash-es: 4.17.21 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + chrome-trace-event@1.0.4: {} + + ci-info@3.9.0: {} + + ci-info@4.1.0: {} + + ci-info@4.2.0: {} + + cjs-module-lexer@1.4.1: {} + + cjson@0.3.0: + dependencies: + jsonlint: 1.6.0 + + clap@3.1.1: + dependencies: + ansi-colors: 4.1.3 + + clean-regexp@1.0.0: + dependencies: + escape-string-regexp: 1.0.5 + + clean-stack@2.2.0: {} + + clean-stack@4.2.0: + dependencies: + escape-string-regexp: 5.0.0 + + clear-module@4.1.2: + dependencies: + parent-module: 2.0.0 + resolve-from: 5.0.0 + + cli-boxes@2.2.1: {} + + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-table3@0.6.5: + dependencies: + string-width: 4.2.3 + optionalDependencies: + '@colors/colors': 1.5.0 + + cli-truncate@2.1.0: + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + + cliui@6.0.0: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone-deep@4.0.1: + dependencies: + is-plain-object: 2.0.4 + kind-of: 6.0.3 + shallow-clone: 3.0.1 + + clone-response@1.0.3: + dependencies: + mimic-response: 1.0.1 + + clone@1.0.4: + optional: true + + co@4.6.0: {} + + collect-v8-coverage@1.0.2: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + + colorette@2.0.20: {} + + colors@0.5.1: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + comma-separated-tokens@2.0.3: {} + + commander@11.0.0: {} + + commander@12.1.0: {} + + commander@13.1.0: {} + + commander@2.20.3: {} + + commander@4.1.1: {} + + commander@6.2.1: {} + + commander@7.2.0: {} + + commander@8.3.0: {} + + comment-json@4.2.5: + dependencies: + array-timsort: 1.0.3 + core-util-is: 1.0.3 + esprima: 4.0.1 + has-own-prop: 2.0.0 + repeat-string: 1.6.1 + + comment-parser@1.4.1: {} + + common-path-prefix@3.0.0: {} + + common-tags@1.8.2: {} + + commondir@1.0.1: {} + + compressible@2.0.18: + dependencies: + mime-db: 1.53.0 + + compression@1.7.4: + dependencies: + accepts: 1.3.8 + bytes: 3.0.0 + compressible: 2.0.18 + debug: 2.6.9 + on-headers: 1.0.2 + safe-buffer: 5.1.2 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + concat-map@0.0.1: {} + + concurrently@9.1.2: + dependencies: + chalk: 4.1.2 + lodash: 4.17.21 + rxjs: 7.8.1 + shell-quote: 1.8.2 + supports-color: 8.1.1 + tree-kill: 1.2.2 + yargs: 17.7.2 + + confbox@0.1.8: {} + + connect-history-api-fallback@2.0.0: {} + + consola@3.4.0: {} + + console.table@0.10.0: + dependencies: + easy-table: 1.1.0 + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-disposition@1.0.0: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + convert-source-map@1.9.0: {} + + convert-source-map@2.0.0: {} + + convict@6.2.4: + dependencies: + lodash.clonedeep: 4.5.0 + yargs-parser: 20.2.9 + + cookie-signature@1.0.6: {} + + cookie-signature@1.2.2: {} + + cookie@0.6.0: {} + + cookie@0.7.2: {} + + copy-anything@3.0.5: + dependencies: + is-what: 4.1.16 + + core-js-compat@3.41.0: + dependencies: + browserslist: 4.24.4 + + core-util-is@1.0.2: {} + + core-util-is@1.0.3: {} + + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cose-base@1.0.3: + dependencies: + layout-base: 1.0.2 + + cose-base@2.2.0: + dependencies: + layout-base: 2.0.1 + + cp-file@10.0.0: + dependencies: + graceful-fs: 4.2.11 + nested-error-stacks: 2.1.1 + p-event: 5.0.1 + + cpy-cli@5.0.0: + dependencies: + cpy: 10.1.0 + meow: 12.1.1 + + cpy@10.1.0: + dependencies: + arrify: 3.0.0 + cp-file: 10.0.0 + globby: 13.2.2 + junk: 4.0.1 + micromatch: 4.0.8 + nested-error-stacks: 2.1.1 + p-filter: 3.0.0 + p-map: 6.0.0 + + create-jest@29.7.0(@types/node@22.13.5): + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@22.13.5) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + cross-env@7.0.3: + dependencies: + cross-spawn: 7.0.3 + + cross-spawn@6.0.6: + dependencies: + nice-try: 1.0.5 + path-key: 2.0.1 + semver: 5.7.2 + shebang-command: 1.2.0 + which: 1.3.1 + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypto-random-string@2.0.0: {} + + cspell-config-lib@8.17.4: + dependencies: + '@cspell/cspell-types': 8.17.4 + comment-json: 4.2.5 + yaml: 2.7.0 + + cspell-config-lib@8.18.1: + dependencies: + '@cspell/cspell-types': 8.18.1 + comment-json: 4.2.5 + yaml: 2.7.0 + + cspell-dictionary@8.17.4: + dependencies: + '@cspell/cspell-pipe': 8.17.4 + '@cspell/cspell-types': 8.17.4 + cspell-trie-lib: 8.17.4 + fast-equals: 5.2.2 + + cspell-dictionary@8.18.1: + dependencies: + '@cspell/cspell-pipe': 8.18.1 + '@cspell/cspell-types': 8.18.1 + cspell-trie-lib: 8.18.1 + fast-equals: 5.2.2 + + cspell-gitignore@8.17.4: + dependencies: + '@cspell/url': 8.17.4 + cspell-glob: 8.17.4 + cspell-io: 8.17.4 + find-up-simple: 1.0.0 + + cspell-glob@8.17.4: + dependencies: + '@cspell/url': 8.17.4 + micromatch: 4.0.8 + + cspell-glob@8.18.1: + dependencies: + '@cspell/url': 8.18.1 + micromatch: 4.0.8 + + cspell-grammar@8.17.4: + dependencies: + '@cspell/cspell-pipe': 8.17.4 + '@cspell/cspell-types': 8.17.4 + + cspell-grammar@8.18.1: + dependencies: + '@cspell/cspell-pipe': 8.18.1 + '@cspell/cspell-types': 8.18.1 + + cspell-io@8.17.4: + dependencies: + '@cspell/cspell-service-bus': 8.17.4 + '@cspell/url': 8.17.4 + + cspell-io@8.18.1: + dependencies: + '@cspell/cspell-service-bus': 8.18.1 + '@cspell/url': 8.18.1 + + cspell-lib@8.17.4: + dependencies: + '@cspell/cspell-bundled-dicts': 8.17.4 + '@cspell/cspell-pipe': 8.17.4 + '@cspell/cspell-resolver': 8.17.4 + '@cspell/cspell-types': 8.17.4 + '@cspell/dynamic-import': 8.17.4 + '@cspell/filetypes': 8.17.4 + '@cspell/strong-weak-map': 8.17.4 + '@cspell/url': 8.17.4 + clear-module: 4.1.2 + comment-json: 4.2.5 + cspell-config-lib: 8.17.4 + cspell-dictionary: 8.17.4 + cspell-glob: 8.17.4 + cspell-grammar: 8.17.4 + cspell-io: 8.17.4 + cspell-trie-lib: 8.17.4 + env-paths: 3.0.0 + fast-equals: 5.2.2 + gensequence: 7.0.0 + import-fresh: 3.3.1 + resolve-from: 5.0.0 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + xdg-basedir: 5.1.0 + + cspell-lib@8.18.1: + dependencies: + '@cspell/cspell-bundled-dicts': 8.18.1 + '@cspell/cspell-pipe': 8.18.1 + '@cspell/cspell-resolver': 8.18.1 + '@cspell/cspell-types': 8.18.1 + '@cspell/dynamic-import': 8.18.1 + '@cspell/filetypes': 8.18.1 + '@cspell/strong-weak-map': 8.18.1 + '@cspell/url': 8.18.1 + clear-module: 4.1.2 + comment-json: 4.2.5 + cspell-config-lib: 8.18.1 + cspell-dictionary: 8.18.1 + cspell-glob: 8.18.1 + cspell-grammar: 8.18.1 + cspell-io: 8.18.1 + cspell-trie-lib: 8.18.1 + env-paths: 3.0.0 + fast-equals: 5.2.2 + gensequence: 7.0.0 + import-fresh: 3.3.1 + resolve-from: 5.0.0 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + xdg-basedir: 5.1.0 + + cspell-trie-lib@8.17.4: + dependencies: + '@cspell/cspell-pipe': 8.17.4 + '@cspell/cspell-types': 8.17.4 + gensequence: 7.0.0 + + cspell-trie-lib@8.18.1: + dependencies: + '@cspell/cspell-pipe': 8.18.1 + '@cspell/cspell-types': 8.18.1 + gensequence: 7.0.0 + + cspell@8.17.4: + dependencies: + '@cspell/cspell-json-reporter': 8.17.4 + '@cspell/cspell-pipe': 8.17.4 + '@cspell/cspell-types': 8.17.4 + '@cspell/dynamic-import': 8.17.4 + '@cspell/url': 8.17.4 + chalk: 5.4.1 + chalk-template: 1.1.0 + commander: 13.1.0 + cspell-dictionary: 8.17.4 + cspell-gitignore: 8.17.4 + cspell-glob: 8.17.4 + cspell-io: 8.17.4 + cspell-lib: 8.17.4 + fast-json-stable-stringify: 2.1.0 + file-entry-cache: 9.1.0 + get-stdin: 9.0.0 + semver: 7.7.1 + tinyglobby: 0.2.12 + + css-tree@3.1.0: + dependencies: + mdn-data: 2.12.2 + source-map-js: 1.2.1 + + cssesc@3.0.0: {} + + cssstyle@4.2.1: + dependencies: + '@asamuzakjp/css-color': 2.8.3 + rrweb-cssom: 0.8.0 + + csstree-validator@4.0.1: + dependencies: + clap: 3.1.1 + css-tree: 3.1.0 + enhanced-resolve: 5.17.1 + + csstype@3.1.3: {} + + cuint@0.2.2: {} + + cypress-image-snapshot@4.0.1(cypress@14.0.3)(jest@29.7.0(@types/node@22.13.5)): + dependencies: + chalk: 2.4.2 + cypress: 14.0.3 + fs-extra: 7.0.1 + glob: 7.2.3 + jest-image-snapshot: 4.2.0(jest@29.7.0(@types/node@22.13.5)) + pkg-dir: 3.0.0 + term-img: 4.1.0 + transitivePeerDependencies: + - jest + + cypress-split@1.24.14(@babel/core@7.26.9): + dependencies: + '@actions/core': 1.11.1 + arg: 5.0.2 + console.table: 0.10.0 + debug: 4.4.0(supports-color@8.1.1) + fast-shuffle: 6.1.0 + find-cypress-specs: 1.47.9(@babel/core@7.26.9) + globby: 11.1.0 + humanize-duration: 3.32.1 + transitivePeerDependencies: + - '@babel/core' + - supports-color + + cypress-wait-until@3.0.2: {} + + cypress@14.0.3: + dependencies: + '@cypress/request': 3.0.7 + '@cypress/xvfb': 1.2.4(supports-color@8.1.1) + '@types/sinonjs__fake-timers': 8.1.1 + '@types/sizzle': 2.3.9 + arch: 2.2.0 + blob-util: 2.0.2 + bluebird: 3.7.2 + buffer: 5.7.1 + cachedir: 2.4.0 + chalk: 4.1.2 + check-more-types: 2.24.0 + ci-info: 4.1.0 + cli-cursor: 3.1.0 + cli-table3: 0.6.5 + commander: 6.2.1 + common-tags: 1.8.2 + dayjs: 1.11.13 + debug: 4.4.0(supports-color@8.1.1) + enquirer: 2.4.1 + eventemitter2: 6.4.7 + execa: 4.1.0 + executable: 4.1.1 + extract-zip: 2.0.1(supports-color@8.1.1) + figures: 3.2.0 + fs-extra: 9.1.0 + getos: 3.2.1 + is-installed-globally: 0.4.0 + lazy-ass: 1.6.0 + listr2: 3.14.0(enquirer@2.4.1) + lodash: 4.17.21 + log-symbols: 4.1.0 + minimist: 1.2.8 + ospath: 1.2.2 + pretty-bytes: 5.6.0 + process: 0.11.10 + proxy-from-env: 1.0.0 + request-progress: 3.0.0 + semver: 7.7.1 + supports-color: 8.1.1 + tmp: 0.2.3 + tree-kill: 1.2.2 + untildify: 4.0.0 + yauzl: 2.10.0 + + cytoscape-cose-bilkent@4.1.0(cytoscape@3.31.0): + dependencies: + cose-base: 1.0.3 + cytoscape: 3.31.0 + + cytoscape-fcose@2.2.0(cytoscape@3.31.0): + dependencies: + cose-base: 2.2.0 + cytoscape: 3.31.0 + + cytoscape@3.31.0: {} + + d3-array@2.12.1: + dependencies: + internmap: 1.0.1 + + d3-array@3.2.4: + dependencies: + internmap: 2.0.3 + + d3-axis@3.0.0: {} + + d3-brush@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3-chord@3.0.1: + dependencies: + d3-path: 3.1.0 + + d3-color@3.1.0: {} + + d3-contour@4.0.2: + dependencies: + d3-array: 3.2.4 + + d3-delaunay@6.0.4: + dependencies: + delaunator: 5.0.1 + + d3-dispatch@3.0.1: {} + + d3-drag@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + + d3-dsv@3.0.1: + dependencies: + commander: 7.2.0 + iconv-lite: 0.6.3 + rw: 1.3.3 + + d3-ease@3.0.1: {} + + d3-fetch@3.0.1: + dependencies: + d3-dsv: 3.0.1 + + d3-force@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + + d3-format@3.1.0: {} + + d3-geo@3.1.1: + dependencies: + d3-array: 3.2.4 + + d3-hierarchy@3.1.2: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-path@1.0.9: {} + + d3-path@3.1.0: {} + + d3-polygon@3.0.1: {} + + d3-quadtree@3.0.1: {} + + d3-random@3.0.1: {} + + d3-sankey@0.12.3: + dependencies: + d3-array: 2.12.1 + d3-shape: 1.3.7 + + d3-scale-chromatic@3.1.0: + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + + d3-scale@4.0.2: + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.0 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + + d3-selection@3.0.0: {} + + d3-shape@1.3.7: + dependencies: + d3-path: 1.0.9 + + d3-shape@3.2.0: + dependencies: + d3-path: 3.1.0 + + d3-time-format@4.1.0: + dependencies: + d3-time: 3.1.0 + + d3-time@3.1.0: + dependencies: + d3-array: 3.2.4 + + d3-timer@3.0.1: {} + + d3-transition@3.0.1(d3-selection@3.0.0): + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + + d3-zoom@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3@7.9.0: + dependencies: + d3-array: 3.2.4 + d3-axis: 3.0.0 + d3-brush: 3.0.0 + d3-chord: 3.0.1 + d3-color: 3.1.0 + d3-contour: 4.0.2 + d3-delaunay: 6.0.4 + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-dsv: 3.0.1 + d3-ease: 3.0.1 + d3-fetch: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.0 + d3-geo: 3.1.1 + d3-hierarchy: 3.1.2 + d3-interpolate: 3.0.1 + d3-path: 3.1.0 + d3-polygon: 3.0.1 + d3-quadtree: 3.0.1 + d3-random: 3.0.1 + d3-scale: 4.0.2 + d3-scale-chromatic: 3.1.0 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + d3-timer: 3.0.1 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-zoom: 3.0.0 + + dagre-d3-es@7.0.11: + dependencies: + d3: 7.9.0 + lodash-es: 4.17.21 + + dashdash@1.14.1: + dependencies: + assert-plus: 1.0.0 + + data-uri-to-buffer@4.0.1: {} + + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.0.0 + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + dataloader@1.4.0: {} + + dayjs@1.11.13: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@3.2.7(supports-color@8.1.1): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 + + debug@4.3.3: + dependencies: + ms: 2.1.2 + + debug@4.3.4: + dependencies: + ms: 2.1.2 + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + debug@4.4.0(supports-color@8.1.1): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 + + decamelize@1.2.0: {} + + decimal.js@10.4.3: {} + + decode-named-character-reference@1.0.2: + dependencies: + character-entities: 2.0.2 + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + dedent@1.5.3: {} + + deep-eql@5.0.2: {} + + deep-equal@2.2.3: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + es-get-iterator: 1.1.3 + get-intrinsic: 1.2.7 + is-arguments: 1.1.1 + is-array-buffer: 3.0.5 + is-date-object: 1.1.0 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + isarray: 2.0.5 + object-is: 1.1.6 + object-keys: 1.1.1 + object.assign: 4.1.7 + regexp.prototype.flags: 1.5.4 + side-channel: 1.1.0 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.18 + + deep-is@0.1.4: {} + + deepmerge@4.3.1: {} + + default-gateway@6.0.3: + dependencies: + execa: 5.1.1 + + default-require-extensions@3.0.1: + dependencies: + strip-bom: 4.0.0 + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + optional: true + + defer-to-connect@2.0.1: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-lazy-prop@2.0.0: {} + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + defu@6.1.4: {} + + delaunator@5.0.1: + dependencies: + robust-predicates: 3.0.2 + + delayed-stream@1.0.0: {} + + depd@1.1.2: {} + + depd@2.0.0: {} + + dependency-tree@11.0.1: + dependencies: + commander: 12.1.0 + filing-cabinet: 5.0.2 + precinct: 12.1.2 + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + dequal@2.0.3: {} + + destr@2.0.3: {} + + destroy@1.2.0: {} + + detect-indent@6.1.0: {} + + detect-libc@2.0.3: {} + + detect-newline@3.1.0: {} + + detect-node@2.1.0: {} + + detective-amd@6.0.0: + dependencies: + ast-module-types: 6.0.0 + escodegen: 2.1.0 + get-amd-module-type: 6.0.0 + node-source-walk: 7.0.0 + + detective-cjs@6.0.0: + dependencies: + ast-module-types: 6.0.0 + node-source-walk: 7.0.0 + + detective-es6@5.0.0: + dependencies: + node-source-walk: 7.0.0 + + detective-postcss@7.0.0(postcss@8.5.3): + dependencies: + is-url: 1.2.4 + postcss: 8.5.3 + postcss-values-parser: 6.0.2(postcss@8.5.3) + + detective-sass@6.0.0: + dependencies: + gonzales-pe: 4.3.0 + node-source-walk: 7.0.0 + + detective-scss@5.0.0: + dependencies: + gonzales-pe: 4.3.0 + node-source-walk: 7.0.0 + + detective-stylus@5.0.0: {} + + detective-typescript@13.0.0(typescript@5.7.3): + dependencies: + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.7.3) + ast-module-types: 6.0.0 + node-source-walk: 7.0.0 + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + detective-vue2@2.0.3(typescript@5.7.3): + dependencies: + '@vue/compiler-sfc': 3.5.13 + detective-es6: 5.0.0 + detective-sass: 6.0.0 + detective-scss: 5.0.0 + detective-stylus: 5.0.0 + detective-typescript: 13.0.0(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + didyoumean@1.2.2: {} + + diff-sequences@29.6.3: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dlv@1.1.3: {} + + dns-packet@5.6.1: + dependencies: + '@leichtgewicht/ip-codec': 2.0.5 + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + dom-to-image-more@2.16.0: {} + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + dompurify@3.2.5: + optionalDependencies: + '@types/trusted-types': 2.0.7 + + domutils@3.1.0: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dotenv@16.4.7: {} + + dotenv@8.6.0: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + duplexer@0.1.2: {} + + eastasianwidth@0.2.0: {} + + easy-table@1.1.0: + optionalDependencies: + wcwidth: 1.0.1 + + ebnf-parser@0.1.10: {} + + ecc-jsbn@0.1.2: + dependencies: + jsbn: 0.1.1 + safer-buffer: 2.1.2 + + ee-first@1.1.1: {} + + ejs@3.1.10: + dependencies: + jake: 10.9.2 + + electron-to-chromium@1.5.101: {} + + elkjs@0.9.3: {} + + emittery@0.13.1: {} + + emoji-regex-xs@1.0.0: {} + + emoji-regex@10.4.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + encoding@0.1.13: + dependencies: + iconv-lite: 0.6.3 + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + enhanced-resolve@5.17.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + + entities@3.0.1: {} + + entities@4.5.0: {} + + env-paths@3.0.0: {} + + envinfo@7.14.0: {} + + environment@1.1.0: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + es-abstract@1.23.9: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.3 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.2.7 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.18 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-get-iterator@1.1.3: + dependencies: + call-bind: 1.0.8 + get-intrinsic: 1.2.7 + has-symbols: 1.1.0 + is-arguments: 1.1.1 + is-map: 2.0.3 + is-set: 2.0.3 + is-string: 1.1.1 + isarray: 2.0.5 + stop-iteration-iterator: 1.0.0 + + es-module-lexer@1.5.4: {} + + es-module-lexer@1.6.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + es2015-i18n-tag@1.6.1: {} + + es6-error@4.1.1: {} + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + esbuild@0.24.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.2 + '@esbuild/android-arm': 0.24.2 + '@esbuild/android-arm64': 0.24.2 + '@esbuild/android-x64': 0.24.2 + '@esbuild/darwin-arm64': 0.24.2 + '@esbuild/darwin-x64': 0.24.2 + '@esbuild/freebsd-arm64': 0.24.2 + '@esbuild/freebsd-x64': 0.24.2 + '@esbuild/linux-arm': 0.24.2 + '@esbuild/linux-arm64': 0.24.2 + '@esbuild/linux-ia32': 0.24.2 + '@esbuild/linux-loong64': 0.24.2 + '@esbuild/linux-mips64el': 0.24.2 + '@esbuild/linux-ppc64': 0.24.2 + '@esbuild/linux-riscv64': 0.24.2 + '@esbuild/linux-s390x': 0.24.2 + '@esbuild/linux-x64': 0.24.2 + '@esbuild/netbsd-arm64': 0.24.2 + '@esbuild/netbsd-x64': 0.24.2 + '@esbuild/openbsd-arm64': 0.24.2 + '@esbuild/openbsd-x64': 0.24.2 + '@esbuild/sunos-x64': 0.24.2 + '@esbuild/win32-arm64': 0.24.2 + '@esbuild/win32-ia32': 0.24.2 + '@esbuild/win32-x64': 0.24.2 + + esbuild@0.25.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.0 + '@esbuild/android-arm': 0.25.0 + '@esbuild/android-arm64': 0.25.0 + '@esbuild/android-x64': 0.25.0 + '@esbuild/darwin-arm64': 0.25.0 + '@esbuild/darwin-x64': 0.25.0 + '@esbuild/freebsd-arm64': 0.25.0 + '@esbuild/freebsd-x64': 0.25.0 + '@esbuild/linux-arm': 0.25.0 + '@esbuild/linux-arm64': 0.25.0 + '@esbuild/linux-ia32': 0.25.0 + '@esbuild/linux-loong64': 0.25.0 + '@esbuild/linux-mips64el': 0.25.0 + '@esbuild/linux-ppc64': 0.25.0 + '@esbuild/linux-riscv64': 0.25.0 + '@esbuild/linux-s390x': 0.25.0 + '@esbuild/linux-x64': 0.25.0 + '@esbuild/netbsd-arm64': 0.25.0 + '@esbuild/netbsd-x64': 0.25.0 + '@esbuild/openbsd-arm64': 0.25.0 + '@esbuild/openbsd-x64': 0.25.0 + '@esbuild/sunos-x64': 0.25.0 + '@esbuild/win32-arm64': 0.25.0 + '@esbuild/win32-ia32': 0.25.0 + '@esbuild/win32-x64': 0.25.0 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@2.0.0: {} + + escape-string-regexp@4.0.0: {} + + escape-string-regexp@5.0.0: {} + + escodegen@1.3.3: + dependencies: + esprima: 1.1.1 + estraverse: 1.5.1 + esutils: 1.0.0 + optionalDependencies: + source-map: 0.1.43 + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + eslint-config-prettier@10.1.1(eslint@9.24.0(jiti@2.4.2)): + dependencies: + eslint: 9.24.0(jiti@2.4.2) + + eslint-plugin-cypress@4.2.1(eslint@9.24.0(jiti@2.4.2)): + dependencies: + eslint: 9.24.0(jiti@2.4.2) + globals: 15.15.0 + + eslint-plugin-html@8.1.2: + dependencies: + htmlparser2: 9.1.0 + + eslint-plugin-jest@28.11.0(@typescript-eslint/eslint-plugin@8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(jest@29.7.0(@types/node@22.13.5))(typescript@5.7.3): + dependencies: + '@typescript-eslint/utils': 8.24.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + eslint: 9.24.0(jiti@2.4.2) + optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + jest: 29.7.0(@types/node@22.13.5) + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-jsdoc@50.6.9(eslint@9.24.0(jiti@2.4.2)): + dependencies: + '@es-joy/jsdoccomment': 0.49.0 + are-docs-informative: 0.0.2 + comment-parser: 1.4.1 + debug: 4.4.0(supports-color@8.1.1) + escape-string-regexp: 4.0.0 + eslint: 9.24.0(jiti@2.4.2) + espree: 10.3.0 + esquery: 1.6.0 + parse-imports: 2.2.1 + semver: 7.7.1 + spdx-expression-parse: 4.0.0 + synckit: 0.9.2 + transitivePeerDependencies: + - supports-color + + eslint-plugin-json@4.0.1: + dependencies: + lodash: 4.17.21 + vscode-json-languageservice: 4.2.1 + + eslint-plugin-lodash@8.0.0(eslint@9.24.0(jiti@2.4.2)): + dependencies: + eslint: 9.24.0(jiti@2.4.2) + lodash: 4.17.21 + + eslint-plugin-markdown@5.1.0(eslint@9.24.0(jiti@2.4.2)): + dependencies: + eslint: 9.24.0(jiti@2.4.2) + mdast-util-from-markdown: 0.8.5 + transitivePeerDependencies: + - supports-color + + eslint-plugin-no-only-tests@3.3.0: {} + + eslint-plugin-tsdoc@0.4.0: + dependencies: + '@microsoft/tsdoc': 0.15.1 + '@microsoft/tsdoc-config': 0.17.1 + + eslint-plugin-unicorn@58.0.0(eslint@9.24.0(jiti@2.4.2)): + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + '@eslint-community/eslint-utils': 4.5.1(eslint@9.24.0(jiti@2.4.2)) + '@eslint/plugin-kit': 0.2.7 + ci-info: 4.2.0 + clean-regexp: 1.0.0 + core-js-compat: 3.41.0 + eslint: 9.24.0(jiti@2.4.2) + esquery: 1.6.0 + globals: 16.0.0 + indent-string: 5.0.0 + is-builtin-module: 5.0.0 + jsesc: 3.1.0 + pluralize: 8.0.0 + read-package-up: 11.0.0 + regexp-tree: 0.1.27 + regjsparser: 0.12.0 + semver: 7.7.1 + strip-indent: 4.0.0 + + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + + eslint-scope@8.3.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.0: {} + + eslint@9.24.0(jiti@2.4.2): + dependencies: + '@eslint-community/eslint-utils': 4.5.1(eslint@9.24.0(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.20.0 + '@eslint/config-helpers': 0.2.1 + '@eslint/core': 0.12.0 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.24.0 + '@eslint/plugin-kit': 0.2.7 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.2 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.0(supports-color@8.1.1) + escape-string-regexp: 4.0.0 + eslint-scope: 8.3.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.4.2 + transitivePeerDependencies: + - supports-color + + espree@10.3.0: + dependencies: + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 4.2.0 + + esprima@1.1.1: {} + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@1.5.1: {} + + estraverse@4.3.0: {} + + estraverse@5.3.0: {} + + estree-walker@1.0.1: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.6 + + esutils@1.0.0: {} + + esutils@2.0.3: {} + + etag@1.8.1: {} + + event-stream@3.3.4: + dependencies: + duplexer: 0.1.2 + from: 0.1.7 + map-stream: 0.1.0 + pause-stream: 0.0.11 + split: 0.3.3 + stream-combiner: 0.0.4 + through: 2.3.8 + + event-target-shim@5.0.1: {} + + eventemitter2@6.4.7: {} + + eventemitter3@4.0.7: {} + + eventemitter3@5.0.1: {} + + events@3.3.0: {} + + execa@1.0.0: + dependencies: + cross-spawn: 6.0.6 + get-stream: 4.1.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.7 + strip-eof: 1.0.0 + + execa@4.1.0: + dependencies: + cross-spawn: 7.0.6 + get-stream: 5.2.0 + human-signals: 1.1.1 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + executable@4.1.1: + dependencies: + pify: 2.3.0 + + exit@0.1.2: {} + + expect-type@1.1.0: {} + + expect@29.7.0: + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + + express@4.21.0: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.6.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.10 + proxy-addr: 2.0.7 + qs: 6.13.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + express@5.1.0: + dependencies: + accepts: 2.0.0 + body-parser: 2.2.0 + content-disposition: 1.0.0 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.0(supports-color@8.1.1) + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.0 + fresh: 2.0.0 + http-errors: 2.0.0 + merge-descriptors: 2.0.0 + mime-types: 3.0.1 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.14.0 + range-parser: 1.2.1 + router: 2.2.0 + send: 1.2.0 + serve-static: 2.2.0 + statuses: 2.0.1 + type-is: 2.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + extend@3.0.2: {} + + extendable-error@0.1.7: {} + + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + + extract-zip@2.0.1(supports-color@8.1.1): + dependencies: + debug: 4.4.0(supports-color@8.1.1) + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + + extsprintf@1.3.0: {} + + fast-content-type-parse@1.1.0: {} + + fast-decode-uri-component@1.0.1: {} + + fast-deep-equal@3.1.3: {} + + fast-equals@5.2.2: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-json-stringify@5.16.1: + dependencies: + '@fastify/merge-json-schemas': 0.1.1 + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) + fast-deep-equal: 3.1.3 + fast-uri: 2.4.0 + json-schema-ref-resolver: 1.0.1 + rfdc: 1.4.1 + + fast-levenshtein@2.0.6: {} + + fast-querystring@1.1.2: + dependencies: + fast-decode-uri-component: 1.0.1 + + fast-redact@3.5.0: {} + + fast-shuffle@6.1.0: + dependencies: + pcg: 1.0.0 + + fast-uri@2.4.0: {} + + fast-uri@3.0.2: {} + + fastest-levenshtein@1.0.16: {} + + fastestsmallesttextencoderdecoder@1.0.22: {} + + fastify-plugin@3.0.1: {} + + fastify@4.29.0: + dependencies: + '@fastify/ajv-compiler': 3.6.0 + '@fastify/error': 3.4.1 + '@fastify/fast-json-stringify-compiler': 4.3.0 + abstract-logging: 2.0.1 + avvio: 8.4.0 + fast-content-type-parse: 1.1.0 + fast-json-stringify: 5.16.1 + find-my-way: 8.2.2 + light-my-request: 5.14.0 + pino: 9.6.0 + process-warning: 3.0.0 + proxy-addr: 2.0.7 + rfdc: 1.4.1 + secure-json-parse: 2.7.0 + semver: 7.7.1 + toad-cache: 3.7.0 + + fastq@1.19.0: + dependencies: + reusify: 1.0.4 + + fault@2.0.1: + dependencies: + format: 0.2.2 + + faye-websocket@0.11.4: + dependencies: + websocket-driver: 0.7.4 + + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + fdir@6.4.3(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + + ferrum@1.9.4: + dependencies: + fastestsmallesttextencoderdecoder: 1.0.22 + lodash.isplainobject: 4.0.6 + xxhashjs: 0.2.2 + + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + + fflate@0.8.2: {} + + figures@3.2.0: + dependencies: + escape-string-regexp: 1.0.5 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + file-entry-cache@9.1.0: + dependencies: + flat-cache: 5.0.0 + + file-saver@2.0.5: {} + + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + + filing-cabinet@5.0.2: + dependencies: + app-module-path: 2.2.0 + commander: 12.1.0 + enhanced-resolve: 5.17.1 + module-definition: 6.0.0 + module-lookup-amd: 9.0.2 + resolve: 1.22.10 + resolve-dependency-path: 4.0.0 + sass-lookup: 6.0.1 + stylus-lookup: 6.0.0 + tsconfig-paths: 4.2.0 + typescript: 5.7.3 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.3.1: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + finalhandler@2.1.0: + dependencies: + debug: 4.4.0(supports-color@8.1.1) + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + find-cache-dir@3.3.2: + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + + find-cache-dir@4.0.0: + dependencies: + common-path-prefix: 3.0.0 + pkg-dir: 7.0.0 + + find-cypress-specs@1.47.9(@babel/core@7.26.9): + dependencies: + '@actions/core': 1.11.1 + arg: 5.0.2 + console.table: 0.10.0 + debug: 4.4.0(supports-color@8.1.1) + find-test-names: 1.29.5(@babel/core@7.26.9) + globby: 11.1.0 + minimatch: 3.1.2 + pluralize: 8.0.0 + require-and-forget: 1.0.1 + shelljs: 0.8.5 + spec-change: 1.11.11 + tsx: 4.19.3 + transitivePeerDependencies: + - '@babel/core' + - supports-color + + find-my-way@8.2.2: + dependencies: + fast-deep-equal: 3.1.3 + fast-querystring: 1.1.2 + safe-regex2: 3.1.0 + + find-process@1.4.10: + dependencies: + chalk: 4.1.2 + commander: 12.1.0 + loglevel: 1.9.2 + + find-test-names@1.29.5(@babel/core@7.26.9): + dependencies: + '@babel/parser': 7.26.9 + '@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.26.9) + acorn-walk: 8.3.4 + debug: 4.4.0(supports-color@8.1.1) + globby: 11.1.0 + simple-bin-help: 1.8.0 + transitivePeerDependencies: + - '@babel/core' + - supports-color + + find-up-simple@1.0.0: {} + + find-up@3.0.0: + dependencies: + locate-path: 3.0.0 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + find-up@6.3.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flat-cache@5.0.0: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flat@5.0.2: {} + + flatted@3.3.3: {} + + flexsearch@0.7.43: {} + + focus-trap@7.6.4: + dependencies: + tabbable: 6.2.0 + + follow-redirects@1.15.9(debug@4.4.0): + optionalDependencies: + debug: 4.4.0(supports-color@8.1.1) + + font-awesome@4.7.0: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + foreground-child@2.0.0: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 3.0.7 + + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + forever-agent@0.6.1: {} + + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + + format@0.2.2: {} + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + + forwarded@0.2.0: {} + + fresh@0.5.2: {} + + fresh@2.0.0: {} + + from@0.1.7: {} + + fromentries@1.3.2: {} + + fs-extra@11.1.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@11.2.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-monkey@1.0.6: {} + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + gensequence@7.0.0: {} + + gensync@1.0.0-beta.2: {} + + get-amd-module-type@6.0.0: + dependencies: + ast-module-types: 6.0.0 + node-source-walk: 7.0.0 + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.3.0: {} + + get-intrinsic@1.2.7: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-own-enumerable-property-symbols@3.0.2: {} + + get-package-type@0.1.0: {} + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stdin@5.0.1: {} + + get-stdin@9.0.0: {} + + get-stream@4.1.0: + dependencies: + pump: 3.0.2 + + get-stream@5.2.0: + dependencies: + pump: 3.0.2 + + get-stream@6.0.1: {} + + get-stream@8.0.1: {} + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + + get-tsconfig@4.8.1: + dependencies: + resolve-pkg-maps: 1.0.0 + + getos@3.2.1: + dependencies: + async: 3.2.6 + + getpass@0.1.7: + dependencies: + assert-plus: 1.0.0 + + github-slugger@2.0.0: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob-to-regexp@0.4.1: {} + + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@11.0.1: + dependencies: + foreground-child: 3.3.0 + jackspeak: 4.0.3 + minimatch: 10.0.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.0 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + + global-dirs@3.0.1: + dependencies: + ini: 2.0.0 + + globals@11.12.0: {} + + globals@14.0.0: {} + + globals@15.15.0: {} + + globals@16.0.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + globby@13.2.2: + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 4.0.0 + + globby@14.1.0: + dependencies: + '@sindresorhus/merge-streams': 2.3.0 + fast-glob: 3.3.3 + ignore: 7.0.3 + path-type: 6.0.0 + slash: 5.1.0 + unicorn-magic: 0.3.0 + + glur@1.1.2: {} + + gonzales-pe@4.3.0: + dependencies: + minimist: 1.2.8 + + gopd@1.2.0: {} + + got@11.8.6: + dependencies: + '@sindresorhus/is': 4.6.0 + '@szmarczak/http-timer': 4.0.6 + '@types/cacheable-request': 6.0.3 + '@types/responselike': 1.0.3 + cacheable-lookup: 5.0.4 + cacheable-request: 7.0.4 + decompress-response: 6.0.0 + http2-wrapper: 1.0.3 + lowercase-keys: 2.0.0 + p-cancelable: 2.1.1 + responselike: 2.0.1 + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + + hachure-fill@0.5.2: {} + + handle-thing@2.0.1: {} + + has-ansi@2.0.0: + dependencies: + ansi-regex: 2.1.1 + + has-bigints@1.1.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-own-prop@2.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasha@5.2.2: + dependencies: + is-stream: 2.0.1 + type-fest: 0.8.1 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hast-util-to-html@9.0.5: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.0 + property-information: 7.0.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + highlight.js@10.7.3: {} + + hookable@5.5.3: {} + + hosted-git-info@7.0.2: + dependencies: + lru-cache: 10.4.3 + + hpack.js@2.1.6: + dependencies: + inherits: 2.0.4 + obuf: 1.1.2 + readable-stream: 2.3.8 + wbuf: 1.7.3 + + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + + html-entities@2.5.2: {} + + html-escaper@2.0.2: {} + + html-to-image@1.11.13: {} + + html-void-elements@3.0.0: {} + + htmlparser2@9.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + entities: 4.5.0 + + http-cache-semantics@4.1.1: {} + + http-deceiver@1.2.7: {} + + http-errors@1.6.3: + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.0 + statuses: 1.5.0 + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + http-parser-js@0.5.8: {} + + http-proxy-agent@5.0.0: + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.4.0(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.1 + debug: 4.4.0(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + http-proxy-middleware@2.0.7(@types/express@4.17.21): + dependencies: + '@types/http-proxy': 1.17.15 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.8 + optionalDependencies: + '@types/express': 4.17.21 + transitivePeerDependencies: + - debug + + http-proxy@1.18.1: + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.9(debug@4.4.0) + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + + http-signature@1.4.0: + dependencies: + assert-plus: 1.0.0 + jsprim: 2.0.2 + sshpk: 1.18.0 + + http2-wrapper@1.0.3: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + + https-localhost@4.7.1: + dependencies: + appdata-path: 1.0.0 + compression: 1.7.4 + cors: 2.8.5 + express: 4.21.0 + spdy: 4.0.2 + uglify-js: 3.19.3 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.0(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.3 + debug: 4.4.0(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + human-id@4.1.1: {} + + human-signals@1.1.1: {} + + human-signals@2.1.0: {} + + human-signals@5.0.0: {} + + humanize-duration@3.32.1: {} + + husky@9.1.7: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + idb@7.1.1: {} + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + ignore@7.0.3: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-local@3.2.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + import-meta-resolve@4.1.0: {} + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + indent-string@5.0.0: {} + + index-to-position@0.1.2: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.3: {} + + inherits@2.0.4: {} + + ini@2.0.0: {} + + ini@3.0.1: {} + + ini@4.1.1: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + internmap@1.0.1: {} + + internmap@2.0.3: {} + + interpret@1.4.0: {} + + interpret@2.2.0: {} + + ipaddr.js@1.9.1: {} + + ipaddr.js@2.2.0: {} + + is-alphabetical@1.0.4: {} + + is-alphanumerical@1.0.4: + dependencies: + is-alphabetical: 1.0.4 + is-decimal: 1.0.4 + + is-arguments@1.1.1: + dependencies: + call-bind: 1.0.8 + has-tostringtag: 1.0.2 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + get-intrinsic: 1.2.7 + + is-arrayish@0.2.1: {} + + is-arrayish@0.3.2: {} + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.3 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + + is-builtin-module@5.0.0: + dependencies: + builtin-modules: 5.0.0 + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.3 + get-intrinsic: 1.2.7 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + + is-decimal@1.0.4: {} + + is-docker@2.2.1: {} + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.3 + + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.3.0 + + is-generator-fn@2.1.0: {} + + is-generator-function@1.1.0: + dependencies: + call-bound: 1.0.3 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-hexadecimal@1.0.4: {} + + is-installed-globally@0.4.0: + dependencies: + global-dirs: 3.0.1 + is-path-inside: 3.0.3 + + is-localhost-ip@2.0.0: {} + + is-map@2.0.3: {} + + is-module@1.0.0: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-obj@1.0.1: {} + + is-path-inside@3.0.3: {} + + is-plain-obj@3.0.0: {} + + is-plain-obj@4.1.0: {} + + is-plain-object@2.0.4: + dependencies: + isobject: 3.0.1 + + is-potential-custom-element-name@1.0.1: {} + + is-promise@4.0.0: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.3 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-regexp@1.0.0: {} + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.3 + + is-stream@1.1.0: {} + + is-stream@2.0.1: {} + + is-stream@3.0.0: {} + + is-string@1.1.1: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + + is-subdir@1.2.0: + dependencies: + better-path-resolve: 1.0.0 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.3 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.18 + + is-typedarray@1.0.0: {} + + is-unicode-supported@0.1.0: {} + + is-url-superb@4.0.0: {} + + is-url@1.2.4: {} + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.3 + + is-weakset@2.0.3: + dependencies: + call-bind: 1.0.8 + get-intrinsic: 1.2.7 + + is-what@4.1.16: {} + + is-windows@1.0.2: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + isobject@3.0.1: {} + + isstream@0.1.2: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-hook@3.0.0: + dependencies: + append-transform: 2.0.0 + + istanbul-lib-instrument@4.0.3: + dependencies: + '@babel/core': 7.26.9 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-instrument@5.2.1: + dependencies: + '@babel/core': 7.26.9 + '@babel/parser': 7.26.9 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-instrument@6.0.3: + dependencies: + '@babel/core': 7.26.9 + '@babel/parser': 7.26.9 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-processinfo@2.0.3: + dependencies: + archy: 1.0.0 + cross-spawn: 7.0.6 + istanbul-lib-coverage: 3.2.2 + p-map: 3.0.0 + rimraf: 3.0.2 + uuid: 8.3.2 + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@4.0.1: + dependencies: + debug: 4.4.0(supports-color@8.1.1) + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + debug: 4.4.0(supports-color@8.1.1) + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + iterm2-version@4.2.0: + dependencies: + app-path: 3.3.0 + plist: 3.1.0 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jackspeak@4.0.3: + dependencies: + '@isaacs/cliui': 8.0.2 + + jake@10.9.2: + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + + jest-changed-files@29.7.0: + dependencies: + execa: 5.1.1 + jest-util: 29.7.0 + p-limit: 3.1.0 + + jest-circus@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.5 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.5.3 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.1.0 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-cli@29.7.0(@types/node@22.13.5): + dependencies: + '@jest/core': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@22.13.5) + exit: 0.1.2 + import-local: 3.2.0 + jest-config: 29.7.0(@types/node@22.13.5) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jest-config@29.7.0(@types/node@22.13.5): + dependencies: + '@babel/core': 7.26.9 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.26.9) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 22.13.5 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-diff@29.7.0: + dependencies: + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-docblock@29.7.0: + dependencies: + detect-newline: 3.1.0 + + jest-each@29.7.0: + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 + + jest-environment-node@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.5 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + jest-get-type@29.6.3: {} + + jest-haste-map@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 22.13.5 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-image-snapshot@4.2.0(jest@29.7.0(@types/node@22.13.5)): + dependencies: + chalk: 1.1.3 + get-stdin: 5.0.1 + glur: 1.1.2 + jest: 29.7.0(@types/node@22.13.5) + lodash: 4.17.21 + mkdirp: 0.5.6 + pixelmatch: 5.3.0 + pngjs: 3.4.0 + rimraf: 2.7.1 + ssim.js: 3.5.0 + + jest-leak-detector@29.7.0: + dependencies: + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-matcher-utils@29.7.0: + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-message-util@29.7.0: + dependencies: + '@babel/code-frame': 7.26.2 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.13.5 + jest-util: 29.7.0 + + jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + optionalDependencies: + jest-resolve: 29.7.0 + + jest-regex-util@29.6.3: {} + + jest-resolve-dependencies@29.7.0: + dependencies: + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + jest-resolve@29.7.0: + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.10 + resolve.exports: 2.0.2 + slash: 3.0.0 + + jest-runner@29.7.0: + dependencies: + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.5 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0 + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + + jest-runtime@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0 + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.5 + chalk: 4.1.2 + cjs-module-lexer: 1.4.1 + collect-v8-coverage: 1.0.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + + jest-snapshot@29.7.0: + dependencies: + '@babel/core': 7.26.9 + '@babel/generator': 7.26.9 + '@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.26.9) + '@babel/plugin-syntax-typescript': 7.25.7(@babel/core@7.26.9) + '@babel/types': 7.26.9 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.9) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + + jest-util@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.13.5 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + jest-validate@29.7.0: + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + + jest-watcher@29.7.0: + dependencies: + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 + + jest-worker@27.5.1: + dependencies: + '@types/node': 22.13.5 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest-worker@29.7.0: + dependencies: + '@types/node': 22.13.5 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest@29.7.0(@types/node@22.13.5): + dependencies: + '@jest/core': 29.7.0 + '@jest/types': 29.6.3 + import-local: 3.2.0 + jest-cli: 29.7.0(@types/node@22.13.5) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jison-lex@0.3.4: + dependencies: + lex-parser: 0.1.4 + nomnom: 1.5.2 + + jison@0.4.18: + dependencies: + JSONSelect: 0.4.0 + cjson: 0.3.0 + ebnf-parser: 0.1.10 + escodegen: 1.3.3 + esprima: 1.1.1 + jison-lex: 0.3.4 + lex-parser: 0.1.4 + nomnom: 1.5.2 + + jiti@1.21.7: {} + + jiti@2.4.2: {} + + jju@1.4.0: {} + + joi@17.13.3: + dependencies: + '@hapi/hoek': 9.3.0 + '@hapi/topo': 5.1.0 + '@sideway/address': 4.1.5 + '@sideway/formula': 3.0.1 + '@sideway/pinpoint': 2.0.0 + + jpeg-js@0.4.4: {} + + js-base64@3.7.7: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsbn@0.1.1: {} + + jsdoc-type-pratt-parser@4.1.0: {} + + jsdom@26.0.0: + dependencies: + cssstyle: 4.2.1 + data-urls: 5.0.0 + decimal.js: 10.4.3 + form-data: 4.0.2 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.16 + parse5: 7.2.1 + rrweb-cssom: 0.8.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 5.1.1 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.1.1 + ws: 8.18.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsesc@3.0.2: {} + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-ref-resolver@1.0.1: + dependencies: + fast-deep-equal: 3.1.3 + + json-schema-to-typescript@15.0.4: + dependencies: + '@apidevtools/json-schema-ref-parser': 11.9.1 + '@types/json-schema': 7.0.15 + '@types/lodash': 4.17.10 + is-glob: 4.0.3 + js-yaml: 4.1.0 + lodash: 4.17.21 + minimist: 1.2.8 + prettier: 3.5.2 + tinyglobby: 0.2.12 + + json-schema-traverse@0.4.1: {} + + 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: {} + + json5@2.2.3: {} + + jsonc-parser@3.3.1: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonlint@1.6.0: + dependencies: + JSV: 4.0.2 + nomnom: 1.5.2 + + jsonpointer@5.0.1: {} + + jsonschema@1.4.1: {} + + jsprim@2.0.2: + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + + junk@4.0.1: {} + + katex@0.16.11: + dependencies: + commander: 8.3.0 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + khroma@2.1.0: {} + + kind-of@6.0.3: {} + + kleur@3.0.3: {} + + kolorist@1.8.0: {} + + ky@0.30.0: {} + + langium-cli@3.3.0: + dependencies: + chalk: 5.3.0 + commander: 11.0.0 + fs-extra: 11.1.1 + jsonschema: 1.4.1 + langium: 3.3.1 + langium-railroad: 3.3.0 + lodash: 4.17.21 + + langium-railroad@3.3.0: + dependencies: + langium: 3.3.1 + railroad-diagrams: 1.0.0 + + langium@3.3.1: + dependencies: + chevrotain: 11.0.3 + chevrotain-allstar: 0.3.1(chevrotain@11.0.3) + vscode-languageserver: 9.0.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 + + launch-editor@2.9.1: + dependencies: + picocolors: 1.1.1 + shell-quote: 1.8.2 + + layout-base@1.0.2: {} + + layout-base@2.0.1: {} + + lazy-ass@1.6.0: {} + + lazy-ass@2.0.3: {} + + leven@3.1.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lex-parser@0.1.4: {} + + light-my-request@5.14.0: + dependencies: + cookie: 0.7.2 + process-warning: 3.0.0 + set-cookie-parser: 2.7.1 + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + linkify-it@4.0.1: + dependencies: + uc.micro: 1.0.6 + + linkify-it@5.0.0: + dependencies: + uc.micro: 2.1.0 + + lint-staged@15.4.3: + dependencies: + chalk: 5.4.1 + commander: 13.1.0 + debug: 4.4.0(supports-color@8.1.1) + execa: 8.0.1 + lilconfig: 3.1.3 + listr2: 8.2.5 + micromatch: 4.0.8 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.7.0 + transitivePeerDependencies: + - supports-color + + listr2@3.14.0(enquirer@2.4.1): + dependencies: + cli-truncate: 2.1.0 + colorette: 2.0.20 + log-update: 4.0.0 + p-map: 4.0.0 + rfdc: 1.4.1 + rxjs: 7.8.1 + through: 2.3.8 + wrap-ansi: 7.0.0 + optionalDependencies: + enquirer: 2.4.1 + + listr2@8.2.5: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.0 + + loader-runner@4.3.0: {} + + local-pkg@1.0.0: + dependencies: + mlly: 1.7.4 + pkg-types: 1.3.1 + + locate-path@3.0.0: + dependencies: + p-locate: 3.0.0 + path-exists: 3.0.0 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + locate-path@7.2.0: + dependencies: + p-locate: 6.0.0 + + lodash-es@4.17.21: {} + + lodash.clonedeep@4.5.0: {} + + lodash.debounce@4.0.8: {} + + lodash.flattendeep@4.4.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.merge@4.6.2: {} + + lodash.once@4.1.1: {} + + lodash.sortby@4.7.0: {} + + lodash.startcase@4.4.0: {} + + lodash@4.17.21: {} + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + log-update@4.0.0: + dependencies: + ansi-escapes: 4.3.2 + cli-cursor: 3.1.0 + slice-ansi: 4.0.0 + wrap-ansi: 6.2.0 + + log-update@6.1.0: + dependencies: + ansi-escapes: 7.0.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + + loglevel-plugin-prefix@0.8.4: {} + + loglevel@1.9.2: {} + + long@5.2.3: {} + + longest-streak@3.1.0: {} + + loupe@3.1.3: {} + + lowercase-keys@2.0.0: {} + + lru-cache@10.4.3: {} + + lru-cache@11.0.2: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lunr@2.3.9: {} + + magic-string@0.25.9: + dependencies: + sourcemap-codec: 1.4.8 + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + magicast@0.3.5: + dependencies: + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + source-map-js: 1.2.1 + + make-dir@3.1.0: + dependencies: + semver: 6.3.1 + + make-dir@4.0.0: + dependencies: + semver: 7.7.1 + + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + + map-stream@0.1.0: {} + + mark.js@8.11.1: {} + + markdown-it@13.0.2: + dependencies: + argparse: 2.0.1 + entities: 3.0.1 + linkify-it: 4.0.1 + mdurl: 1.0.1 + uc.micro: 1.0.6 + + markdown-it@14.1.0: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + + markdown-table@3.0.4: {} + + marked@15.0.7: {} + + marked@4.3.0: {} + + math-intrinsics@1.1.0: {} + + mdast-builder@1.1.1: + dependencies: + '@types/unist': 2.0.11 + + mdast-util-find-and-replace@3.0.1: + dependencies: + '@types/mdast': 4.0.4 + escape-string-regexp: 5.0.0 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + + mdast-util-from-markdown@0.8.5: + dependencies: + '@types/mdast': 3.0.15 + mdast-util-to-string: 2.0.0 + micromark: 2.11.4 + parse-entities: 2.0.0 + unist-util-stringify-position: 2.0.3 + transitivePeerDependencies: + - supports-color + + mdast-util-from-markdown@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-decode-string: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-frontmatter@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + escape-string-regexp: 5.0.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + micromark-extension-frontmatter: 2.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-autolink-literal@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.1 + micromark-util-character: 2.1.1 + + mdast-util-gfm-footnote@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + micromark-util-normalize-identifier: 2.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-strikethrough@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-table@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + markdown-table: 3.0.4 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-task-list-item@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm@3.0.0: + dependencies: + mdast-util-from-markdown: 2.0.1 + mdast-util-gfm-autolink-literal: 2.0.1 + mdast-util-gfm-footnote: 2.0.0 + mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 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.2.0: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + + mdast-util-to-markdown@2.1.0: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + 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@2.0.0: {} + + mdast-util-to-string@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + + mdn-data@2.1.0: {} + + mdn-data@2.12.2: {} + + mdurl@1.0.1: {} + + mdurl@2.0.0: {} + + media-typer@0.3.0: {} + + media-typer@1.1.0: {} + + memfs@3.5.3: + dependencies: + fs-monkey: 1.0.6 + + meow@12.1.1: {} + + merge-descriptors@1.0.3: {} + + merge-descriptors@2.0.0: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + methods@1.1.2: {} + + micromark-core-commonmark@2.0.1: + dependencies: + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-factory-destination: 2.0.0 + micromark-factory-label: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-factory-title: 2.0.0 + micromark-factory-whitespace: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.0 + micromark-util-classify-character: 2.0.0 + micromark-util-html-tag-name: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-subtokenize: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-extension-frontmatter@2.0.0: + dependencies: + fault: 2.0.1 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-extension-gfm-autolink-literal@2.1.0: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-extension-gfm-footnote@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-core-commonmark: 2.0.1 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-extension-gfm-strikethrough@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-classify-character: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-extension-gfm-table@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-extension-gfm-tagfilter@2.0.0: + dependencies: + micromark-util-types: 2.0.1 + + micromark-extension-gfm-task-list-item@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-extension-gfm@3.0.0: + dependencies: + micromark-extension-gfm-autolink-literal: 2.1.0 + micromark-extension-gfm-footnote: 2.1.0 + micromark-extension-gfm-strikethrough: 2.1.0 + micromark-extension-gfm-table: 2.1.0 + micromark-extension-gfm-tagfilter: 2.0.0 + micromark-extension-gfm-task-list-item: 2.1.0 + micromark-util-combine-extensions: 2.0.0 + micromark-util-types: 2.0.1 + + micromark-factory-destination@2.0.0: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-factory-label@2.0.0: + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-factory-space@2.0.0: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.1 + + micromark-factory-title@2.0.0: + dependencies: + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-factory-whitespace@2.0.0: + dependencies: + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-character@2.1.0: + dependencies: + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.1 + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-chunked@2.0.0: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-classify-character@2.0.0: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-combine-extensions@2.0.0: + dependencies: + micromark-util-chunked: 2.0.0 + micromark-util-types: 2.0.1 + + micromark-util-decode-numeric-character-reference@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-decode-string@2.0.0: + dependencies: + decode-named-character-reference: 1.0.2 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-encode@2.0.1: {} + + micromark-util-html-tag-name@2.0.0: {} + + micromark-util-normalize-identifier@2.0.0: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-resolve-all@2.0.0: + dependencies: + micromark-util-types: 2.0.1 + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-subtokenize@2.0.1: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-symbol@2.0.0: {} + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.0: {} + + micromark-util-types@2.0.1: {} + + micromark@2.11.4: + dependencies: + debug: 4.4.0(supports-color@8.1.1) + parse-entities: 2.0.0 + transitivePeerDependencies: + - supports-color + + micromark@4.0.0: + dependencies: + '@types/debug': 4.1.12 + debug: 4.4.0(supports-color@8.1.1) + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.1 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.0 + micromark-util-combine-extensions: 2.0.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + transitivePeerDependencies: + - supports-color + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-db@1.53.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime-types@3.0.1: + dependencies: + mime-db: 1.54.0 + + mime@1.6.0: {} + + mimic-fn@2.1.0: {} + + mimic-fn@4.0.0: {} + + mimic-function@5.0.1: {} + + mimic-response@1.0.1: {} + + mimic-response@3.1.0: {} + + min-indent@1.0.1: {} + + minimalistic-assert@1.0.1: {} + + minimatch@10.0.1: + dependencies: + brace-expansion: 2.0.1 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minimist@1.2.8: {} + + minipass@7.1.2: {} + + minisearch@7.1.2: {} + + mitt@3.0.1: {} + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + mlly@1.7.4: + dependencies: + acorn: 8.14.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.5.4 + + module-definition@6.0.0: + dependencies: + ast-module-types: 6.0.0 + node-source-walk: 7.0.0 + + module-lookup-amd@9.0.2: + dependencies: + commander: 12.1.0 + glob: 7.2.3 + requirejs: 2.3.7 + requirejs-config-file: 4.0.0 + + mri@1.2.0: {} + + mrmime@2.0.0: {} + + ms@2.0.0: {} + + ms@2.1.2: {} + + ms@2.1.3: {} + + multicast-dns@7.2.5: + dependencies: + dns-packet: 5.6.1 + thunky: 1.1.0 + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nanoid@3.3.8: {} + + natural-compare@1.4.0: {} + + negotiator@0.6.3: {} + + negotiator@1.0.0: {} + + neo-async@2.6.2: {} + + nested-error-stacks@2.1.1: {} + + nice-try@1.0.5: {} + + node-cleanup@2.1.2: {} + + node-domexception@1.0.0: {} + + node-fetch-native@1.6.4: {} + + node-fetch@2.6.7(encoding@0.1.13): + dependencies: + whatwg-url: 5.0.0 + optionalDependencies: + encoding: 0.1.13 + + node-fetch@2.7.0(encoding@0.1.13): + dependencies: + whatwg-url: 5.0.0 + optionalDependencies: + encoding: 0.1.13 + + node-fetch@3.3.1: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + + node-forge@1.3.1: {} + + node-int64@0.4.0: {} + + node-preload@0.2.1: + dependencies: + process-on-spawn: 1.0.0 + + node-releases@2.0.19: {} + + node-source-walk@7.0.0: + dependencies: + '@babel/parser': 7.26.9 + + nomnom@1.5.2: + dependencies: + colors: 0.5.1 + underscore: 1.1.7 + + normalize-package-data@6.0.2: + dependencies: + hosted-git-info: 7.0.2 + semver: 7.7.1 + validate-npm-package-license: 3.0.4 + + normalize-path@3.0.0: {} + + normalize-url@6.1.0: {} + + npm-run-path@2.0.2: + dependencies: + path-key: 2.0.1 + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + nwsapi@2.2.16: {} + + nyc@15.1.0: + dependencies: + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + caching-transform: 4.0.0 + convert-source-map: 1.9.0 + decamelize: 1.2.0 + find-cache-dir: 3.3.2 + find-up: 4.1.0 + foreground-child: 2.0.0 + get-package-type: 0.1.0 + glob: 7.2.3 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-hook: 3.0.0 + istanbul-lib-instrument: 4.0.3 + istanbul-lib-processinfo: 2.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + make-dir: 3.1.0 + node-preload: 0.2.1 + p-map: 3.0.0 + process-on-spawn: 1.0.0 + resolve-from: 5.0.0 + rimraf: 3.0.2 + signal-exit: 3.0.7 + spawn-wrap: 2.0.0 + test-exclude: 6.0.0 + yargs: 15.4.1 + transitivePeerDependencies: + - supports-color + + nyc@17.1.0: + dependencies: + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + caching-transform: 4.0.0 + convert-source-map: 1.9.0 + decamelize: 1.2.0 + find-cache-dir: 3.3.2 + find-up: 4.1.0 + foreground-child: 3.3.0 + get-package-type: 0.1.0 + glob: 7.2.3 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-hook: 3.0.0 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-processinfo: 2.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + make-dir: 3.1.0 + node-preload: 0.2.1 + p-map: 3.0.0 + process-on-spawn: 1.0.0 + resolve-from: 5.0.0 + rimraf: 3.0.2 + signal-exit: 3.0.7 + spawn-wrap: 2.0.0 + test-exclude: 6.0.0 + yargs: 15.4.1 + transitivePeerDependencies: + - supports-color + + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + + object-inspect@1.13.4: {} + + object-is@1.1.6: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + obuf@1.1.2: {} + + ofetch@1.4.1: + dependencies: + destr: 2.0.3 + node-fetch-native: 1.6.4 + ufo: 1.5.4 + + omggif@1.0.10: {} + + on-exit-leak-free@2.1.2: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + on-headers@1.0.2: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + oniguruma-to-es@3.1.1: + dependencies: + emoji-regex-xs: 1.0.0 + regex: 6.0.1 + regex-recursion: 6.0.2 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + openapi-fetch@0.13.5: + dependencies: + openapi-typescript-helpers: 0.0.15 + + openapi-typescript-helpers@0.0.15: {} + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + os-tmpdir@1.0.2: {} + + ospath@1.2.2: {} + + outdent@0.5.0: {} + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.2.7 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-cancelable@2.1.1: {} + + p-event@5.0.1: + dependencies: + p-timeout: 5.1.0 + + p-filter@2.1.0: + dependencies: + p-map: 2.1.0 + + p-filter@3.0.0: + dependencies: + p-map: 5.5.0 + + p-finally@1.0.0: {} + + p-iteration@1.1.8: {} + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-limit@4.0.0: + dependencies: + yocto-queue: 1.1.1 + + p-locate@3.0.0: + dependencies: + p-limit: 2.3.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-locate@6.0.0: + dependencies: + p-limit: 4.0.0 + + p-map@2.1.0: {} + + p-map@3.0.0: + dependencies: + aggregate-error: 3.1.0 + + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + + p-map@5.5.0: + dependencies: + aggregate-error: 4.0.1 + + p-map@6.0.0: {} + + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + + p-timeout@5.1.0: {} + + p-try@2.2.0: {} + + package-hash@4.0.0: + dependencies: + graceful-fs: 4.2.11 + hasha: 5.2.2 + lodash.flattendeep: 4.4.0 + release-zalgo: 1.0.0 + + package-json-from-dist@1.0.1: {} + + package-manager-detector@0.2.9: {} + + pako@1.0.11: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parent-module@2.0.0: + dependencies: + callsites: 3.1.0 + + parse-entities@2.0.0: + dependencies: + character-entities: 1.2.4 + character-entities-legacy: 1.1.4 + character-reference-invalid: 1.1.4 + is-alphanumerical: 1.0.4 + is-decimal: 1.0.4 + is-hexadecimal: 1.0.4 + + parse-imports@2.2.1: + dependencies: + es-module-lexer: 1.6.0 + slashes: 3.0.12 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.26.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-json@8.1.0: + dependencies: + '@babel/code-frame': 7.26.2 + index-to-position: 0.1.2 + type-fest: 4.35.0 + + parse5@7.2.1: + dependencies: + entities: 4.5.0 + + parseurl@1.3.3: {} + + path-browserify@1.0.1: {} + + path-data-parser@0.1.0: {} + + path-exists@3.0.0: {} + + path-exists@4.0.0: {} + + path-exists@5.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@2.0.1: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-scurry@2.0.0: + dependencies: + lru-cache: 11.0.2 + minipass: 7.1.2 + + path-to-regexp@0.1.10: {} + + path-to-regexp@8.2.0: {} + + path-type@4.0.0: {} + + path-type@6.0.0: {} + + pathe@2.0.3: {} + + pathval@2.0.0: {} + + pause-stream@0.0.11: + dependencies: + through: 2.3.8 + + pcg@1.0.0: + dependencies: + long: 5.2.3 + ramda: 0.29.0 + + pend@1.2.0: {} + + perfect-debounce@1.0.0: {} + + performance-now@2.1.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.2: {} + + pidtree@0.6.0: {} + + pify@2.3.0: {} + + pify@4.0.1: {} + + pino-abstract-transport@1.2.0: + dependencies: + readable-stream: 4.7.0 + split2: 4.2.0 + + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-std-serializers@6.2.2: {} + + pino-std-serializers@7.0.0: {} + + pino@8.21.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 1.2.0 + pino-std-serializers: 6.2.2 + process-warning: 3.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 3.8.1 + thread-stream: 2.7.0 + + pino@9.6.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 4.0.1 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + + pirates@4.0.6: {} + + pixelmatch@5.3.0: + dependencies: + pngjs: 6.0.0 + + pkg-dir@3.0.0: + dependencies: + find-up: 3.0.0 + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + pkg-dir@7.0.0: + dependencies: + find-up: 6.3.0 + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.7.4 + pathe: 2.0.3 + + plist@3.1.0: + dependencies: + '@xmldom/xmldom': 0.8.10 + base64-js: 1.5.1 + xmlbuilder: 15.1.1 + + pluralize@8.0.0: {} + + png-async@0.9.4: {} + + pngjs@3.4.0: {} + + pngjs@6.0.0: {} + + points-on-curve@0.2.0: {} + + points-on-path@0.2.1: + dependencies: + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + + possible-typed-array-names@1.1.0: {} + + postcss-import@15.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.10 + + postcss-js@4.0.1(postcss@8.5.3): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.5.3 + + postcss-load-config@4.0.2(postcss@8.5.3): + dependencies: + lilconfig: 3.1.3 + yaml: 2.7.0 + optionalDependencies: + postcss: 8.5.3 + + postcss-nested@6.2.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss-values-parser@6.0.2(postcss@8.5.3): + dependencies: + color-name: 1.1.4 + is-url-superb: 4.0.0 + postcss: 8.5.3 + quote-unquote: 1.0.0 + + postcss@8.5.3: + dependencies: + nanoid: 3.3.8 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + preact@10.26.2: {} + + precinct@12.1.2: + dependencies: + '@dependents/detective-less': 5.0.0 + commander: 12.1.0 + detective-amd: 6.0.0 + detective-cjs: 6.0.0 + detective-es6: 5.0.0 + detective-postcss: 7.0.0(postcss@8.5.3) + detective-sass: 6.0.0 + detective-scss: 5.0.0 + detective-stylus: 5.0.0 + detective-typescript: 13.0.0(typescript@5.7.3) + detective-vue2: 2.0.3(typescript@5.7.3) + module-definition: 6.0.0 + node-source-walk: 7.0.0 + postcss: 8.5.3 + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + prelude-ls@1.2.1: {} + + prettier-plugin-jsdoc@1.3.2(prettier@3.5.2): + dependencies: + binary-searching: 2.0.5 + comment-parser: 1.4.1 + mdast-util-from-markdown: 2.0.1 + prettier: 3.5.2 + transitivePeerDependencies: + - supports-color + + prettier@2.8.8: {} + + prettier@3.5.2: {} + + pretty-bytes@5.6.0: {} + + pretty-bytes@6.1.1: {} + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + process-nextick-args@2.0.1: {} + + process-on-spawn@1.0.0: + dependencies: + fromentries: 1.3.2 + + process-warning@3.0.0: {} + + process-warning@4.0.1: {} + + process@0.11.10: {} + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + property-information@7.0.0: {} + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + proxy-from-env@1.0.0: {} + + proxy-from-env@1.1.0: {} + + ps-tree@1.2.0: + dependencies: + event-stream: 3.3.4 + + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + punycode.js@2.3.1: {} + + punycode@2.3.1: {} + + pure-rand@6.1.0: {} + + qs@6.13.0: + dependencies: + side-channel: 1.1.0 + + qs@6.13.1: + dependencies: + side-channel: 1.1.0 + + qs@6.14.0: + dependencies: + side-channel: 1.1.0 + + queue-microtask@1.2.3: {} + + quick-format-unescaped@4.0.4: {} + + quick-lru@5.1.1: {} + + quote-unquote@1.0.0: {} + + railroad-diagrams@1.0.0: {} + + ramda@0.28.0: {} + + ramda@0.29.0: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + range-parser@1.2.1: {} + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + raw-body@3.0.0: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.6.3 + unpipe: 1.0.0 + + react-is@18.3.1: {} + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + read-package-up@11.0.0: + dependencies: + find-up-simple: 1.0.0 + read-pkg: 9.0.1 + type-fest: 4.35.0 + + read-pkg@9.0.1: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 6.0.2 + parse-json: 8.1.0 + type-fest: 4.35.0 + unicorn-magic: 0.1.0 + + read-yaml-file@1.1.0: + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.1 + pify: 4.0.1 + strip-bom: 3.0.0 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readable-stream@4.7.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + readdirp@4.1.2: {} + + real-require@0.2.0: {} + + rechoir@0.6.2: + dependencies: + resolve: 1.22.10 + + rechoir@0.7.1: + dependencies: + resolve: 1.22.10 + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.2.7 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regenerate-unicode-properties@10.2.0: + dependencies: + regenerate: 1.4.2 + + regenerate@1.4.2: {} + + regenerator-runtime@0.14.1: {} + + regenerator-transform@0.15.2: + dependencies: + '@babel/runtime': 7.26.9 + + regex-recursion@6.0.2: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@6.0.1: + dependencies: + regex-utilities: 2.3.0 + + regexp-tree@0.1.27: {} + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + regexpu-core@6.2.0: + dependencies: + regenerate: 1.4.2 + regenerate-unicode-properties: 10.2.0 + regjsgen: 0.8.0 + regjsparser: 0.12.0 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.0 + + regjsgen@0.8.0: {} + + regjsparser@0.12.0: + dependencies: + jsesc: 3.0.2 + + release-zalgo@1.0.0: + dependencies: + es6-error: 4.1.1 + + remark-frontmatter@5.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-frontmatter: 2.0.1 + micromark-extension-frontmatter: 2.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-gfm@4.0.1: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-gfm: 3.0.0 + micromark-extension-gfm: 3.0.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-parse@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.1 + micromark-util-types: 2.0.1 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-stringify@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-to-markdown: 2.1.0 + unified: 11.0.5 + + remark@15.0.1: + dependencies: + '@types/mdast': 4.0.4 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + repeat-string@1.6.1: {} + + request-progress@3.0.0: + dependencies: + throttleit: 1.0.1 + + require-and-forget@1.0.1: + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + require-main-filename@2.0.0: {} + + requirejs-config-file@4.0.0: + dependencies: + esprima: 4.0.1 + stringify-object: 3.3.0 + + requirejs@2.3.7: {} + + requires-port@1.0.0: {} + + resolve-alpn@1.2.1: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + + resolve-dependency-path@4.0.0: {} + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve.exports@2.0.2: {} + + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + responselike@2.0.1: + dependencies: + lowercase-keys: 2.0.0 + + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + ret@0.4.3: {} + + retry@0.13.1: {} + + reusify@1.0.4: {} + + rfdc@1.4.1: {} + + rimraf@2.7.1: + dependencies: + glob: 7.2.3 + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + rimraf@6.0.1: + dependencies: + glob: 11.0.1 + package-json-from-dist: 1.0.1 + + robust-predicates@3.0.2: {} + + rollup-plugin-visualizer@5.14.0(rollup@4.34.8): + dependencies: + open: 8.4.2 + picomatch: 4.0.2 + source-map: 0.7.4 + yargs: 17.7.2 + optionalDependencies: + rollup: 4.34.8 + + rollup@2.79.2: + optionalDependencies: + fsevents: 2.3.3 + + rollup@4.34.8: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.34.8 + '@rollup/rollup-android-arm64': 4.34.8 + '@rollup/rollup-darwin-arm64': 4.34.8 + '@rollup/rollup-darwin-x64': 4.34.8 + '@rollup/rollup-freebsd-arm64': 4.34.8 + '@rollup/rollup-freebsd-x64': 4.34.8 + '@rollup/rollup-linux-arm-gnueabihf': 4.34.8 + '@rollup/rollup-linux-arm-musleabihf': 4.34.8 + '@rollup/rollup-linux-arm64-gnu': 4.34.8 + '@rollup/rollup-linux-arm64-musl': 4.34.8 + '@rollup/rollup-linux-loongarch64-gnu': 4.34.8 + '@rollup/rollup-linux-powerpc64le-gnu': 4.34.8 + '@rollup/rollup-linux-riscv64-gnu': 4.34.8 + '@rollup/rollup-linux-s390x-gnu': 4.34.8 + '@rollup/rollup-linux-x64-gnu': 4.34.8 + '@rollup/rollup-linux-x64-musl': 4.34.8 + '@rollup/rollup-win32-arm64-msvc': 4.34.8 + '@rollup/rollup-win32-ia32-msvc': 4.34.8 + '@rollup/rollup-win32-x64-msvc': 4.34.8 + fsevents: 2.3.3 + + roughjs@4.6.6(patch_hash=3543d47108cb41b68ec6a671c0e1f9d0cfe2ce524fea5b0992511ae84c3c6b64): + dependencies: + hachure-fill: 0.5.2 + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + points-on-path: 0.2.1 + + router@2.2.0: + dependencies: + debug: 4.4.0(supports-color@8.1.1) + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.2.0 + transitivePeerDependencies: + - supports-color + + rrweb-cssom@0.8.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + rw@1.3.3: {} + + rxjs@7.8.1: + dependencies: + tslib: 2.8.1 + + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + get-intrinsic: 1.2.7 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safe-regex2@3.1.0: + dependencies: + ret: 0.4.3 + + safe-stable-stringify@2.5.0: {} + + safer-buffer@2.1.2: {} + + sass-lookup@6.0.1: + dependencies: + commander: 12.1.0 + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + schema-utils@3.3.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + + schema-utils@4.2.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.17.1) + + schema-utils@4.3.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.17.1) + + search-insights@2.17.2: {} + + secure-json-parse@2.7.0: {} + + select-hose@2.0.0: {} + + selfsigned@2.4.1: + dependencies: + '@types/node-forge': 1.3.11 + node-forge: 1.3.1 + + semver@5.7.2: {} + + semver@6.3.1: {} + + semver@7.6.2: {} + + semver@7.7.1: {} + + send@0.19.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + send@1.2.0: + dependencies: + debug: 4.4.0(supports-color@8.1.1) + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.0 + mime-types: 3.0.1 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + + serve-index@1.9.1: + dependencies: + accepts: 1.3.8 + batch: 0.6.1 + debug: 2.6.9 + escape-html: 1.0.3 + http-errors: 1.6.3 + mime-types: 2.1.35 + parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color + + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color + + serve-static@2.2.0: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.0 + transitivePeerDependencies: + - supports-color + + set-blocking@2.0.0: {} + + set-cookie-parser@2.7.1: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.7 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + + setprototypeof@1.1.0: {} + + setprototypeof@1.2.0: {} + + shallow-clone@3.0.1: + dependencies: + kind-of: 6.0.3 + + sharp@0.33.5: + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + semver: 7.7.1 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-libvips-darwin-arm64': 1.0.4 + '@img/sharp-libvips-darwin-x64': 1.0.4 + '@img/sharp-libvips-linux-arm': 1.0.5 + '@img/sharp-libvips-linux-arm64': 1.0.4 + '@img/sharp-libvips-linux-s390x': 1.0.4 + '@img/sharp-libvips-linux-x64': 1.0.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-s390x': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-linuxmusl-arm64': 0.33.5 + '@img/sharp-linuxmusl-x64': 0.33.5 + '@img/sharp-wasm32': 0.33.5 + '@img/sharp-win32-ia32': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + + shebang-command@1.2.0: + dependencies: + shebang-regex: 1.0.0 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@1.0.0: {} + + shebang-regex@3.0.0: {} + + shell-quote@1.8.2: {} + + shelljs@0.8.5: + dependencies: + glob: 7.2.3 + interpret: 1.4.0 + rechoir: 0.6.2 + + shiki@2.5.0: + dependencies: + '@shikijs/core': 2.5.0 + '@shikijs/engine-javascript': 2.5.0 + '@shikijs/engine-oniguruma': 2.5.0 + '@shikijs/langs': 2.5.0 + '@shikijs/themes': 2.5.0 + '@shikijs/types': 2.5.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.7 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + siginfo@2.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + simple-bin-help@1.8.0: {} + + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + + sirv@3.0.1: + dependencies: + '@polka/url': 1.0.0-next.28 + mrmime: 2.0.0 + totalist: 3.0.1 + + sisteransi@1.0.5: {} + + slash@3.0.0: {} + + slash@4.0.0: {} + + slash@5.1.0: {} + + slashes@3.0.12: {} + + slice-ansi@3.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + + smob@1.5.0: {} + + sockjs@0.3.24: + dependencies: + faye-websocket: 0.11.4 + uuid: 8.3.2 + websocket-driver: 0.7.4 + + sonic-boom@3.8.1: + dependencies: + atomic-sleep: 1.0.0 + + sonic-boom@4.2.0: + dependencies: + atomic-sleep: 1.0.0 + + source-map-js@1.0.1: {} + + source-map-js@1.2.1: {} + + source-map-support@0.5.13: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.1.43: + dependencies: + amdefine: 1.0.1 + optional: true + + source-map@0.6.1: {} + + source-map@0.7.4: {} + + source-map@0.8.0-beta.0: + dependencies: + whatwg-url: 7.1.0 + + sourcemap-codec@1.4.8: {} + + space-separated-tokens@2.0.2: {} + + spawn-wrap@2.0.0: + dependencies: + foreground-child: 2.0.0 + is-windows: 1.0.2 + make-dir: 3.1.0 + rimraf: 3.0.2 + signal-exit: 3.0.7 + which: 2.0.2 + + spawndamnit@3.0.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.21 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.21 + + spdx-expression-parse@4.0.0: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.21 + + spdx-license-ids@3.0.21: {} + + spdy-transport@3.0.0: + dependencies: + debug: 4.4.0(supports-color@8.1.1) + detect-node: 2.1.0 + hpack.js: 2.1.6 + obuf: 1.1.2 + readable-stream: 3.6.2 + wbuf: 1.7.3 + transitivePeerDependencies: + - supports-color + + spdy@4.0.2: + dependencies: + debug: 4.4.0(supports-color@8.1.1) + handle-thing: 2.0.1 + http-deceiver: 1.2.7 + select-hose: 2.0.0 + spdy-transport: 3.0.0 + transitivePeerDependencies: + - supports-color + + speakingurl@14.0.1: {} + + spec-change@1.11.11: + dependencies: + arg: 5.0.2 + debug: 4.4.0(supports-color@8.1.1) + deep-equal: 2.2.3 + dependency-tree: 11.0.1 + lazy-ass: 2.0.3 + tinyglobby: 0.2.12 + transitivePeerDependencies: + - supports-color + + split2@4.2.0: {} + + split@0.3.3: + dependencies: + through: 2.3.8 + + sprintf-js@1.0.3: {} + + 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 + + ssim.js@3.5.0: {} + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + stackback@0.0.2: {} + + start-server-and-test@2.0.10: + dependencies: + arg: 5.0.2 + bluebird: 3.7.2 + check-more-types: 2.24.0 + debug: 4.4.0(supports-color@8.1.1) + execa: 5.1.1 + lazy-ass: 1.6.0 + ps-tree: 1.2.0 + wait-on: 8.0.2(debug@4.4.0) + transitivePeerDependencies: + - supports-color + + statuses@1.5.0: {} + + statuses@2.0.1: {} + + std-env@3.8.0: {} + + stop-iteration-iterator@1.0.0: + dependencies: + internal-slot: 1.1.0 + + stream-combiner@0.0.4: + dependencies: + duplexer: 0.1.2 + + string-argv@0.3.2: {} + + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.4.0 + get-east-asian-width: 1.3.0 + strip-ansi: 7.1.0 + + string.prototype.matchall@4.0.12: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.2.7 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.0 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.3 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + stringify-object@3.3.0: + dependencies: + get-own-enumerable-property-symbols: 3.0.2 + is-obj: 1.0.1 + is-regexp: 1.0.0 + + strip-ansi@3.0.1: + dependencies: + ansi-regex: 2.1.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-bom@3.0.0: {} + + strip-bom@4.0.0: {} + + strip-comments@2.0.1: {} + + strip-eof@1.0.0: {} + + strip-final-newline@2.0.0: {} + + strip-final-newline@3.0.0: {} + + strip-indent@4.0.0: + dependencies: + min-indent: 1.0.1 + + strip-json-comments@3.1.1: {} + + stylis@4.3.6: {} + + stylus-lookup@6.0.0: + dependencies: + commander: 12.1.0 + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + + superjson@2.2.2: + dependencies: + copy-anything: 3.0.5 + + supports-color@2.0.0: {} + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + symbol-tree@3.2.4: {} + + synckit@0.10.3: + dependencies: + '@pkgr/core': 0.2.1 + tslib: 2.8.1 + + synckit@0.9.2: + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.8.1 + + tabbable@6.2.0: {} + + tailwindcss@3.4.17: + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.3 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.7 + lilconfig: 3.1.3 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.5.3 + postcss-import: 15.1.0(postcss@8.5.3) + postcss-js: 4.0.1(postcss@8.5.3) + postcss-load-config: 4.0.2(postcss@8.5.3) + postcss-nested: 6.2.0(postcss@8.5.3) + postcss-selector-parser: 6.1.2 + resolve: 1.22.10 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + + tapable@2.2.1: {} + + teen_process@1.16.0: + dependencies: + '@babel/runtime': 7.26.9 + bluebird: 3.7.2 + lodash: 4.17.21 + shell-quote: 1.8.2 + source-map-support: 0.5.21 + which: 2.0.2 + + temp-dir@2.0.0: {} + + tempy@0.6.0: + dependencies: + is-stream: 2.0.1 + temp-dir: 2.0.0 + type-fest: 0.16.0 + unique-string: 2.0.0 + + term-img@4.1.0: + dependencies: + ansi-escapes: 4.3.2 + iterm2-version: 4.2.0 + + term-size@2.2.1: {} + + terser-webpack-plugin@5.3.10(esbuild@0.25.0)(webpack@5.95.0(esbuild@0.25.0)): + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.2 + terser: 5.34.1 + webpack: 5.95.0(esbuild@0.25.0) + optionalDependencies: + esbuild: 0.25.0 + + terser-webpack-plugin@5.3.10(esbuild@0.25.0)(webpack@5.95.0): + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.2 + terser: 5.34.1 + webpack: 5.95.0(esbuild@0.25.0)(webpack-cli@4.10.0) + optionalDependencies: + esbuild: 0.25.0 + + terser@5.34.1: + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.14.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + terser@5.39.0: + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.14.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + + test-exclude@7.0.1: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 10.4.5 + minimatch: 9.0.5 + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + thread-stream@2.7.0: + dependencies: + real-require: 0.2.0 + + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + + throat@6.0.2: {} + + throttleit@1.0.1: {} + + through@2.3.8: {} + + thunky@1.1.0: {} + + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinyglobby@0.2.12: + dependencies: + fdir: 6.4.3(picomatch@4.0.2) + picomatch: 4.0.2 + + tinypool@1.0.2: {} + + tinyrainbow@2.0.0: {} + + tinyspy@3.0.2: {} + + tldts-core@6.1.78: {} + + tldts@6.1.78: + dependencies: + tldts-core: 6.1.78 + + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + + tmp@0.2.3: {} + + tmpl@1.0.5: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toad-cache@3.7.0: {} + + toidentifier@1.0.1: {} + + totalist@3.0.1: {} + + tough-cookie@5.1.1: + dependencies: + tldts: 6.1.78 + + tr46@0.0.3: {} + + tr46@1.0.1: + dependencies: + punycode: 2.3.1 + + tr46@5.0.0: + dependencies: + punycode: 2.3.1 + + traverse@0.3.9: {} + + tree-kill@1.2.2: {} + + trim-lines@3.0.1: {} + + trough@2.2.0: {} + + ts-api-utils@1.3.0(typescript@5.7.3): + dependencies: + typescript: 5.7.3 + + ts-api-utils@2.0.1(typescript@5.7.3): + dependencies: + typescript: 5.7.3 + + ts-dedent@2.2.0: {} + + ts-interface-checker@0.1.13: {} + + ts-toolbelt@6.15.5: {} + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@2.8.1: {} + + tsx@4.19.3: + dependencies: + esbuild: 0.25.0 + get-tsconfig: 4.8.1 + optionalDependencies: + fsevents: 2.3.3 + + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 + + tunnel@0.0.6: {} + + tweetnacl@0.14.5: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-detect@4.0.8: {} + + type-fest@0.16.0: {} + + type-fest@0.20.2: {} + + type-fest@0.21.3: {} + + type-fest@0.8.1: {} + + type-fest@4.35.0: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + type-is@2.0.1: + dependencies: + content-type: 1.0.5 + media-typer: 1.1.0 + mime-types: 3.0.1 + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typedarray-to-buffer@3.1.5: + dependencies: + is-typedarray: 1.0.0 + + typedoc-plugin-markdown@4.4.2(typedoc@0.27.8(typescript@5.7.3)): + dependencies: + typedoc: 0.27.8(typescript@5.7.3) + + typedoc@0.27.8(typescript@5.7.3): + dependencies: + '@gerrit0/mini-shiki': 1.27.2 + lunr: 2.3.9 + markdown-it: 14.1.0 + minimatch: 9.0.5 + typescript: 5.7.3 + yaml: 2.7.0 + + typescript-eslint@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/parser': 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + eslint: 9.24.0(jiti@2.4.2) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + typescript@5.7.3: {} + + uc.micro@1.0.6: {} + + uc.micro@2.1.0: {} + + ufo@1.5.4: {} + + uglify-js@3.19.3: {} + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.3 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + unconfig@7.0.0: + dependencies: + '@antfu/utils': 8.1.1 + defu: 6.1.4 + jiti: 2.4.2 + + underscore@1.1.7: {} + + undici-types@5.26.5: {} + + undici-types@6.20.0: {} + + undici@5.28.4: + dependencies: + '@fastify/busboy': 2.1.1 + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.1.0 + + unicode-match-property-value-ecmascript@2.2.0: {} + + unicode-property-aliases-ecmascript@2.1.0: {} + + unicorn-magic@0.1.0: {} + + unicorn-magic@0.3.0: {} + + unified@11.0.4: + dependencies: + '@types/unist': 3.0.3 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 6.0.3 + + unified@11.0.5: + dependencies: + '@types/unist': 3.0.3 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 6.0.3 + + unique-string@2.0.0: + dependencies: + crypto-random-string: 2.0.0 + + unist-util-flatmap@1.0.0: {} + + unist-util-inspect@8.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-is@6.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@2.0.3: + dependencies: + '@types/unist': 2.0.11 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.1: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + + unist-util-visit@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + + universalify@0.1.2: {} + + universalify@2.0.1: {} + + unocss@66.0.0(postcss@8.5.3)(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)): + dependencies: + '@unocss/astro': 66.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) + '@unocss/cli': 66.0.0 + '@unocss/core': 66.0.0 + '@unocss/postcss': 66.0.0(postcss@8.5.3) + '@unocss/preset-attributify': 66.0.0 + '@unocss/preset-icons': 66.0.0 + '@unocss/preset-mini': 66.0.0 + '@unocss/preset-tagify': 66.0.0 + '@unocss/preset-typography': 66.0.0 + '@unocss/preset-uno': 66.0.0 + '@unocss/preset-web-fonts': 66.0.0 + '@unocss/preset-wind': 66.0.0 + '@unocss/preset-wind3': 66.0.0 + '@unocss/transformer-attributify-jsx': 66.0.0 + '@unocss/transformer-compile-class': 66.0.0 + '@unocss/transformer-directives': 66.0.0 + '@unocss/transformer-variant-group': 66.0.0 + '@unocss/vite': 66.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) + optionalDependencies: + vite: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) + transitivePeerDependencies: + - postcss + - supports-color + - vue + + unpipe@1.0.0: {} + + unplugin-utils@0.2.4: + dependencies: + pathe: 2.0.3 + picomatch: 4.0.2 + + unplugin-vue-components@28.4.0(@babel/parser@7.26.9)(vue@3.5.13(typescript@5.7.3)): + dependencies: + chokidar: 3.6.0 + debug: 4.4.0(supports-color@8.1.1) + local-pkg: 1.0.0 + magic-string: 0.30.17 + mlly: 1.7.4 + tinyglobby: 0.2.12 + unplugin: 2.2.0 + unplugin-utils: 0.2.4 + vue: 3.5.13(typescript@5.7.3) + optionalDependencies: + '@babel/parser': 7.26.9 + transitivePeerDependencies: + - supports-color + + unplugin@2.2.0: + dependencies: + acorn: 8.14.0 + webpack-virtual-modules: 0.6.2 + + untildify@4.0.0: {} + + upath@1.2.0: {} + + update-browserslist-db@1.1.2(browserslist@4.24.0): + dependencies: + browserslist: 4.24.0 + escalade: 3.2.0 + picocolors: 1.1.1 + + update-browserslist-db@1.1.2(browserslist@4.24.4): + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + utils-merge@1.0.1: {} + + uuid@11.1.0: {} + + uuid@8.3.2: {} + + uuid@9.0.1: {} + + v8-to-istanbul@9.3.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + + vary@1.1.2: {} + + verror@1.10.0: + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + + vfile-message@4.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.2 + + vite-node@3.0.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0): + dependencies: + cac: 6.7.14 + debug: 4.4.0(supports-color@8.1.1) + es-module-lexer: 1.6.0 + pathe: 2.0.3 + vite: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite-plugin-istanbul@7.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0)): + dependencies: + '@istanbuljs/load-nyc-config': 1.1.0 + espree: 10.3.0 + istanbul-lib-instrument: 6.0.3 + picocolors: 1.1.1 + source-map: 0.7.4 + test-exclude: 7.0.1 + vite: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) + transitivePeerDependencies: + - supports-color + + vite-plugin-pwa@1.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0): + dependencies: + debug: 4.4.0(supports-color@8.1.1) + pretty-bytes: 6.1.1 + tinyglobby: 0.2.12 + vite: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) + workbox-build: 7.1.1(@types/babel__core@7.20.5) + workbox-window: 7.3.0 + transitivePeerDependencies: + - supports-color + + vite@5.4.14(@types/node@22.13.5)(terser@5.39.0): + dependencies: + esbuild: 0.21.5 + postcss: 8.5.3 + rollup: 4.34.8 + optionalDependencies: + '@types/node': 22.13.5 + fsevents: 2.3.3 + terser: 5.39.0 + + vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0): + dependencies: + esbuild: 0.24.2 + postcss: 8.5.3 + rollup: 4.34.8 + optionalDependencies: + '@types/node': 22.13.5 + fsevents: 2.3.3 + jiti: 2.4.2 + terser: 5.39.0 + tsx: 4.19.3 + yaml: 2.7.0 + + vitepress-plugin-search@1.0.4-alpha.22(flexsearch@0.7.43)(vitepress@1.6.3(@algolia/client-search@5.20.3)(@types/node@22.13.5)(axios@1.8.4)(postcss@8.5.3)(search-insights@2.17.2)(terser@5.39.0)(typescript@5.7.3))(vue@3.5.13(typescript@5.7.3)): + dependencies: + '@types/flexsearch': 0.7.6 + '@types/markdown-it': 12.2.3 + flexsearch: 0.7.43 + glob-to-regexp: 0.4.1 + markdown-it: 13.0.2 + vitepress: 1.6.3(@algolia/client-search@5.20.3)(@types/node@22.13.5)(axios@1.8.4)(postcss@8.5.3)(search-insights@2.17.2)(terser@5.39.0)(typescript@5.7.3) + vue: 3.5.13(typescript@5.7.3) + + vitepress@1.6.3(@algolia/client-search@5.20.3)(@types/node@22.13.5)(axios@1.8.4)(postcss@8.5.3)(search-insights@2.17.2)(terser@5.39.0)(typescript@5.7.3): + dependencies: + '@docsearch/css': 3.8.2 + '@docsearch/js': 3.8.2(@algolia/client-search@5.20.3)(search-insights@2.17.2) + '@iconify-json/simple-icons': 1.2.25 + '@shikijs/core': 2.5.0 + '@shikijs/transformers': 2.5.0 + '@shikijs/types': 2.5.0 + '@types/markdown-it': 14.1.2 + '@vitejs/plugin-vue': 5.2.1(vite@5.4.14(@types/node@22.13.5)(terser@5.39.0))(vue@3.5.13(typescript@5.7.3)) + '@vue/devtools-api': 7.7.2 + '@vue/shared': 3.5.13 + '@vueuse/core': 12.7.0(typescript@5.7.3) + '@vueuse/integrations': 12.7.0(axios@1.8.4)(focus-trap@7.6.4)(typescript@5.7.3) + focus-trap: 7.6.4 + mark.js: 8.11.1 + minisearch: 7.1.2 + shiki: 2.5.0 + vite: 5.4.14(@types/node@22.13.5)(terser@5.39.0) + vue: 3.5.13(typescript@5.7.3) + optionalDependencies: + postcss: 8.5.3 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/node' + - '@types/react' + - async-validator + - axios + - change-case + - drauu + - fuse.js + - idb-keyval + - jwt-decode + - less + - lightningcss + - nprogress + - qrcode + - react + - react-dom + - sass + - sass-embedded + - search-insights + - sortablejs + - stylus + - sugarss + - terser + - typescript + - universal-cookie + + vitest@3.0.6(@types/debug@4.1.12)(@types/node@22.13.5)(@vitest/ui@3.0.6)(jiti@2.4.2)(jsdom@26.0.0)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0): + dependencies: + '@vitest/expect': 3.0.6 + '@vitest/mocker': 3.0.6(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0)) + '@vitest/pretty-format': 3.0.6 + '@vitest/runner': 3.0.6 + '@vitest/snapshot': 3.0.6 + '@vitest/spy': 3.0.6 + '@vitest/utils': 3.0.6 + chai: 5.2.0 + debug: 4.4.0(supports-color@8.1.1) + expect-type: 1.1.0 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.8.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) + vite-node: 3.0.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/debug': 4.1.12 + '@types/node': 22.13.5 + '@vitest/ui': 3.0.6(vitest@3.0.6) + jsdom: 26.0.0 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vscode-json-languageservice@4.2.1: + dependencies: + jsonc-parser: 3.3.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-nls: 5.2.0 + vscode-uri: 3.1.0 + + vscode-jsonrpc@8.2.0: {} + + vscode-languageserver-protocol@3.17.5: + dependencies: + vscode-jsonrpc: 8.2.0 + vscode-languageserver-types: 3.17.5 + + vscode-languageserver-textdocument@1.0.12: {} + + vscode-languageserver-types@3.17.5: {} + + vscode-languageserver@9.0.1: + dependencies: + vscode-languageserver-protocol: 3.17.5 + + vscode-nls@5.2.0: {} + + vscode-uri@3.0.8: {} + + vscode-uri@3.1.0: {} + + vue-demi@0.14.10(vue@3.5.13(typescript@5.7.3)): + dependencies: + vue: 3.5.13(typescript@5.7.3) + + vue-flow-layout@0.1.1(vue@3.5.13(typescript@5.7.3)): + dependencies: + vue: 3.5.13(typescript@5.7.3) + + vue@3.5.13(typescript@5.7.3): + dependencies: + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-sfc': 3.5.13 + '@vue/runtime-dom': 3.5.13 + '@vue/server-renderer': 3.5.13(vue@3.5.13(typescript@5.7.3)) + '@vue/shared': 3.5.13 + optionalDependencies: + typescript: 5.7.3 + + vuex@4.1.0(vue@3.5.13(typescript@5.7.3)): + dependencies: + '@vue/devtools-api': 6.6.4 + vue: 3.5.13(typescript@5.7.3) + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + wait-on@8.0.2(debug@4.4.0): + dependencies: + axios: 1.7.9(debug@4.4.0) + joi: 17.13.3 + lodash: 4.17.21 + minimist: 1.2.8 + rxjs: 7.8.1 + transitivePeerDependencies: + - debug + + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + + watchpack@2.4.2: + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + + wbuf@1.7.3: + dependencies: + minimalistic-assert: 1.0.1 + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + optional: true + + web-streams-polyfill@3.3.3: {} + + webdriver@7.31.1(typescript@5.7.3): + dependencies: + '@types/node': 18.19.76 + '@wdio/config': 7.31.1(typescript@5.7.3) + '@wdio/logger': 7.26.0 + '@wdio/protocols': 7.27.0 + '@wdio/types': 7.30.2(typescript@5.7.3) + '@wdio/utils': 7.30.2(typescript@5.7.3) + got: 11.8.6 + ky: 0.30.0 + lodash.merge: 4.6.2 + transitivePeerDependencies: + - typescript + + webidl-conversions@3.0.1: {} + + webidl-conversions@4.0.2: {} + + webidl-conversions@7.0.0: {} + + webpack-cli@4.10.0(webpack-dev-server@4.15.2)(webpack@5.95.0): + dependencies: + '@discoveryjs/json-ext': 0.5.7 + '@webpack-cli/configtest': 1.2.0(webpack-cli@4.10.0)(webpack@5.95.0) + '@webpack-cli/info': 1.5.0(webpack-cli@4.10.0) + '@webpack-cli/serve': 1.7.0(webpack-cli@4.10.0)(webpack-dev-server@4.15.2) + colorette: 2.0.20 + commander: 7.2.0 + cross-spawn: 7.0.3 + fastest-levenshtein: 1.0.16 + import-local: 3.2.0 + interpret: 2.2.0 + rechoir: 0.7.1 + webpack: 5.95.0(esbuild@0.25.0)(webpack-cli@4.10.0) + webpack-merge: 5.10.0 + optionalDependencies: + webpack-dev-server: 4.15.2(webpack-cli@4.10.0)(webpack@5.95.0) + + webpack-dev-middleware@5.3.4(webpack@5.95.0): + dependencies: + colorette: 2.0.20 + memfs: 3.5.3 + mime-types: 2.1.35 + range-parser: 1.2.1 + schema-utils: 4.2.0 + webpack: 5.95.0(esbuild@0.25.0)(webpack-cli@4.10.0) + + webpack-dev-server@4.15.2(webpack-cli@4.10.0)(webpack@5.95.0): + dependencies: + '@types/bonjour': 3.5.13 + '@types/connect-history-api-fallback': 1.5.4 + '@types/express': 4.17.21 + '@types/serve-index': 1.9.4 + '@types/serve-static': 1.15.7 + '@types/sockjs': 0.3.36 + '@types/ws': 8.5.12 + ansi-html-community: 0.0.8 + bonjour-service: 1.2.1 + chokidar: 3.6.0 + colorette: 2.0.20 + compression: 1.7.4 + connect-history-api-fallback: 2.0.0 + default-gateway: 6.0.3 + express: 4.21.0 + graceful-fs: 4.2.11 + html-entities: 2.5.2 + http-proxy-middleware: 2.0.7(@types/express@4.17.21) + ipaddr.js: 2.2.0 + launch-editor: 2.9.1 + open: 8.4.2 + p-retry: 4.6.2 + rimraf: 3.0.2 + schema-utils: 4.2.0 + selfsigned: 2.4.1 + serve-index: 1.9.1 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack-dev-middleware: 5.3.4(webpack@5.95.0) + ws: 8.18.0 + optionalDependencies: + webpack: 5.95.0(esbuild@0.25.0)(webpack-cli@4.10.0) + webpack-cli: 4.10.0(webpack-dev-server@4.15.2)(webpack@5.95.0) + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + + webpack-merge@5.10.0: + dependencies: + clone-deep: 4.0.1 + flat: 5.0.2 + wildcard: 2.0.1 + + webpack-sources@3.2.3: {} + + webpack-virtual-modules@0.6.2: {} + + webpack@5.95.0(esbuild@0.25.0): + dependencies: + '@types/estree': 1.0.6 '@webassemblyjs/ast': 1.12.1 '@webassemblyjs/wasm-edit': 1.12.1 '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.11.3 - acorn-import-assertions: 1.9.0(acorn@8.11.3) - browserslist: 4.23.0 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.16.0 - es-module-lexer: 1.4.1 + acorn: 8.12.1 + acorn-import-attributes: 1.9.5(acorn@8.12.1) + browserslist: 4.24.0 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.17.1 + es-module-lexer: 1.5.4 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -15734,437 +20878,336 @@ packages: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(esbuild@0.20.2)(webpack@5.91.0) - watchpack: 2.4.1 - webpack-cli: 4.10.0(webpack-dev-server@4.15.2)(webpack@5.91.0) + terser-webpack-plugin: 5.3.10(esbuild@0.25.0)(webpack@5.95.0(esbuild@0.25.0)) + watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' - esbuild - uglify-js - dev: true - /websocket-driver@0.7.4: - resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} - engines: {node: '>=0.8.0'} + webpack@5.95.0(esbuild@0.25.0)(webpack-cli@4.10.0): + dependencies: + '@types/estree': 1.0.6 + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/wasm-edit': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + acorn: 8.12.1 + acorn-import-attributes: 1.9.5(acorn@8.12.1) + browserslist: 4.24.0 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.17.1 + es-module-lexer: 1.5.4 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.10(esbuild@0.25.0)(webpack@5.95.0) + watchpack: 2.4.2 + webpack-sources: 3.2.3 + optionalDependencies: + webpack-cli: 4.10.0(webpack-dev-server@4.15.2)(webpack@5.95.0) + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + + websocket-driver@0.7.4: dependencies: http-parser-js: 0.5.8 safe-buffer: 5.2.1 websocket-extensions: 0.1.4 - dev: true - /websocket-extensions@0.1.4: - resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} - engines: {node: '>=0.8.0'} - dev: true + websocket-extensions@0.1.4: {} - /whatwg-encoding@3.1.1: - resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} - engines: {node: '>=18'} + whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 - dev: true - /whatwg-mimetype@4.0.0: - resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} - engines: {node: '>=18'} - dev: true + whatwg-mimetype@4.0.0: {} - /whatwg-url@14.0.0: - resolution: {integrity: sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==} - engines: {node: '>=18'} + whatwg-url@14.0.0: dependencies: tr46: 5.0.0 webidl-conversions: 7.0.0 - dev: true - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + whatwg-url@14.1.1: + dependencies: + tr46: 5.0.0 + webidl-conversions: 7.0.0 + + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - dev: true - /whatwg-url@7.1.0: - resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + whatwg-url@7.1.0: dependencies: lodash.sortby: 4.7.0 tr46: 1.0.1 webidl-conversions: 4.0.2 - dev: true - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + which-boxed-primitive@1.1.1: dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: true + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 - /which-module@2.0.1: - resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - dev: true + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.3 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.0 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.18 - /which-typed-array@1.1.15: - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} - engines: {node: '>= 0.4'} + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.3 + + which-module@2.0.1: {} + + which-typed-array@1.1.18: dependencies: available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 + call-bind: 1.0.8 + call-bound: 1.0.3 + for-each: 0.3.5 + gopd: 1.2.0 has-tostringtag: 1.0.2 - dev: true - /which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + which@1.3.1: dependencies: isexe: 2.0.0 - /why-is-node-running@2.2.2: - resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} - engines: {node: '>=8'} - hasBin: true + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 stackback: 0.0.2 - dev: true - /widest-line@3.1.0: - resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} - engines: {node: '>=8'} + widest-line@3.1.0: dependencies: string-width: 4.2.3 - dev: true - /wildcard@2.0.1: - resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} - dev: true + wildcard@2.0.1: {} - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: true + word-wrap@1.2.5: {} - /workbox-background-sync@7.0.0: - resolution: {integrity: sha512-S+m1+84gjdueM+jIKZ+I0Lx0BDHkk5Nu6a3kTVxP4fdj3gKouRNmhO8H290ybnJTOPfBDtTMXSQA/QLTvr7PeA==} + workbox-background-sync@7.1.0: dependencies: idb: 7.1.1 - workbox-core: 7.0.0 - dev: true + workbox-core: 7.1.0 - /workbox-broadcast-update@7.0.0: - resolution: {integrity: sha512-oUuh4jzZrLySOo0tC0WoKiSg90bVAcnE98uW7F8GFiSOXnhogfNDGZelPJa+6KpGBO5+Qelv04Hqx2UD+BJqNQ==} + workbox-broadcast-update@7.1.0: dependencies: - workbox-core: 7.0.0 - dev: true + workbox-core: 7.1.0 - /workbox-build@7.0.0: - resolution: {integrity: sha512-CttE7WCYW9sZC+nUYhQg3WzzGPr4IHmrPnjKiu3AMXsiNQKx+l4hHl63WTrnicLmKEKHScWDH8xsGBdrYgtBzg==} - engines: {node: '>=16.0.0'} + workbox-build@7.1.1(@types/babel__core@7.20.5): dependencies: - '@apideck/better-ajv-errors': 0.3.6(ajv@8.12.0) - '@babel/core': 7.24.4 - '@babel/preset-env': 7.24.4(@babel/core@7.24.4) - '@babel/runtime': 7.24.4 - '@rollup/plugin-babel': 5.3.1(@babel/core@7.24.4)(rollup@2.79.1) - '@rollup/plugin-node-resolve': 11.2.1(rollup@2.79.1) - '@rollup/plugin-replace': 2.4.2(rollup@2.79.1) + '@apideck/better-ajv-errors': 0.3.6(ajv@8.17.1) + '@babel/core': 7.26.9 + '@babel/preset-env': 7.26.9(@babel/core@7.26.9) + '@babel/runtime': 7.26.9 + '@rollup/plugin-babel': 5.3.1(@babel/core@7.26.9)(@types/babel__core@7.20.5)(rollup@2.79.2) + '@rollup/plugin-node-resolve': 15.3.1(rollup@2.79.2) + '@rollup/plugin-replace': 2.4.2(rollup@2.79.2) + '@rollup/plugin-terser': 0.4.4(rollup@2.79.2) '@surma/rollup-plugin-off-main-thread': 2.2.3 - ajv: 8.12.0 + ajv: 8.17.1 common-tags: 1.8.2 fast-json-stable-stringify: 2.1.0 fs-extra: 9.1.0 glob: 7.2.3 lodash: 4.17.21 pretty-bytes: 5.6.0 - rollup: 2.79.1 - rollup-plugin-terser: 7.0.2(rollup@2.79.1) + rollup: 2.79.2 source-map: 0.8.0-beta.0 stringify-object: 3.3.0 strip-comments: 2.0.1 tempy: 0.6.0 upath: 1.2.0 - workbox-background-sync: 7.0.0 - workbox-broadcast-update: 7.0.0 - workbox-cacheable-response: 7.0.0 - workbox-core: 7.0.0 - workbox-expiration: 7.0.0 - workbox-google-analytics: 7.0.0 - workbox-navigation-preload: 7.0.0 - workbox-precaching: 7.0.0 - workbox-range-requests: 7.0.0 - workbox-recipes: 7.0.0 - workbox-routing: 7.0.0 - workbox-strategies: 7.0.0 - workbox-streams: 7.0.0 - workbox-sw: 7.0.0 - workbox-window: 7.0.0 + workbox-background-sync: 7.1.0 + workbox-broadcast-update: 7.1.0 + workbox-cacheable-response: 7.1.0 + workbox-core: 7.1.0 + workbox-expiration: 7.1.0 + workbox-google-analytics: 7.1.0 + workbox-navigation-preload: 7.1.0 + workbox-precaching: 7.1.0 + workbox-range-requests: 7.1.0 + workbox-recipes: 7.1.0 + workbox-routing: 7.1.0 + workbox-strategies: 7.1.0 + workbox-streams: 7.1.0 + workbox-sw: 7.1.0 + workbox-window: 7.1.0 transitivePeerDependencies: - '@types/babel__core' - supports-color - dev: true - /workbox-cacheable-response@7.0.0: - resolution: {integrity: sha512-0lrtyGHn/LH8kKAJVOQfSu3/80WDc9Ma8ng0p2i/5HuUndGttH+mGMSvOskjOdFImLs2XZIimErp7tSOPmu/6g==} + workbox-cacheable-response@7.1.0: dependencies: - workbox-core: 7.0.0 - dev: true + workbox-core: 7.1.0 - /workbox-core@7.0.0: - resolution: {integrity: sha512-81JkAAZtfVP8darBpfRTovHg8DGAVrKFgHpOArZbdFd78VqHr5Iw65f2guwjE2NlCFbPFDoez3D3/6ZvhI/rwQ==} - dev: true + workbox-core@7.1.0: {} - /workbox-expiration@7.0.0: - resolution: {integrity: sha512-MLK+fogW+pC3IWU9SFE+FRStvDVutwJMR5if1g7oBJx3qwmO69BNoJQVaMXq41R0gg3MzxVfwOGKx3i9P6sOLQ==} + workbox-core@7.3.0: {} + + workbox-expiration@7.1.0: dependencies: idb: 7.1.1 - workbox-core: 7.0.0 - dev: true + workbox-core: 7.1.0 - /workbox-google-analytics@7.0.0: - resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==} - deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained + workbox-google-analytics@7.1.0: dependencies: - workbox-background-sync: 7.0.0 - workbox-core: 7.0.0 - workbox-routing: 7.0.0 - workbox-strategies: 7.0.0 - dev: true + workbox-background-sync: 7.1.0 + workbox-core: 7.1.0 + workbox-routing: 7.1.0 + workbox-strategies: 7.1.0 - /workbox-navigation-preload@7.0.0: - resolution: {integrity: sha512-juWCSrxo/fiMz3RsvDspeSLGmbgC0U9tKqcUPZBCf35s64wlaLXyn2KdHHXVQrb2cqF7I0Hc9siQalainmnXJA==} + workbox-navigation-preload@7.1.0: dependencies: - workbox-core: 7.0.0 - dev: true + workbox-core: 7.1.0 - /workbox-precaching@7.0.0: - resolution: {integrity: sha512-EC0vol623LJqTJo1mkhD9DZmMP604vHqni3EohhQVwhJlTgyKyOkMrZNy5/QHfOby+39xqC01gv4LjOm4HSfnA==} + workbox-precaching@7.1.0: dependencies: - workbox-core: 7.0.0 - workbox-routing: 7.0.0 - workbox-strategies: 7.0.0 - dev: true + workbox-core: 7.1.0 + workbox-routing: 7.1.0 + workbox-strategies: 7.1.0 - /workbox-range-requests@7.0.0: - resolution: {integrity: sha512-SxAzoVl9j/zRU9OT5+IQs7pbJBOUOlriB8Gn9YMvi38BNZRbM+RvkujHMo8FOe9IWrqqwYgDFBfv6sk76I1yaQ==} + workbox-range-requests@7.1.0: dependencies: - workbox-core: 7.0.0 - dev: true + workbox-core: 7.1.0 - /workbox-recipes@7.0.0: - resolution: {integrity: sha512-DntcK9wuG3rYQOONWC0PejxYYIDHyWWZB/ueTbOUDQgefaeIj1kJ7pdP3LZV2lfrj8XXXBWt+JDRSw1lLLOnww==} + workbox-recipes@7.1.0: dependencies: - workbox-cacheable-response: 7.0.0 - workbox-core: 7.0.0 - workbox-expiration: 7.0.0 - workbox-precaching: 7.0.0 - workbox-routing: 7.0.0 - workbox-strategies: 7.0.0 - dev: true + workbox-cacheable-response: 7.1.0 + workbox-core: 7.1.0 + workbox-expiration: 7.1.0 + workbox-precaching: 7.1.0 + workbox-routing: 7.1.0 + workbox-strategies: 7.1.0 - /workbox-routing@7.0.0: - resolution: {integrity: sha512-8YxLr3xvqidnbVeGyRGkaV4YdlKkn5qZ1LfEePW3dq+ydE73hUUJJuLmGEykW3fMX8x8mNdL0XrWgotcuZjIvA==} + workbox-routing@7.1.0: dependencies: - workbox-core: 7.0.0 - dev: true + workbox-core: 7.1.0 - /workbox-strategies@7.0.0: - resolution: {integrity: sha512-dg3qJU7tR/Gcd/XXOOo7x9QoCI9nk74JopaJaYAQ+ugLi57gPsXycVdBnYbayVj34m6Y8ppPwIuecrzkpBVwbA==} + workbox-strategies@7.1.0: dependencies: - workbox-core: 7.0.0 - dev: true + workbox-core: 7.1.0 - /workbox-streams@7.0.0: - resolution: {integrity: sha512-moVsh+5to//l6IERWceYKGiftc+prNnqOp2sgALJJFbnNVpTXzKISlTIsrWY+ogMqt+x1oMazIdHj25kBSq/HQ==} + workbox-streams@7.1.0: dependencies: - workbox-core: 7.0.0 - workbox-routing: 7.0.0 - dev: true + workbox-core: 7.1.0 + workbox-routing: 7.1.0 - /workbox-sw@7.0.0: - resolution: {integrity: sha512-SWfEouQfjRiZ7GNABzHUKUyj8pCoe+RwjfOIajcx6J5mtgKkN+t8UToHnpaJL5UVVOf5YhJh+OHhbVNIHe+LVA==} - dev: true + workbox-sw@7.1.0: {} - /workbox-window@7.0.0: - resolution: {integrity: sha512-j7P/bsAWE/a7sxqTzXo3P2ALb1reTfZdvVp6OJ/uLr/C2kZAMvjeWGm8V4htQhor7DOvYg0sSbFN2+flT5U0qA==} + workbox-window@7.1.0: dependencies: - '@types/trusted-types': 2.0.3 - workbox-core: 7.0.0 - dev: true + '@types/trusted-types': 2.0.7 + workbox-core: 7.1.0 - /wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} + workbox-window@7.3.0: dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true + '@types/trusted-types': 2.0.7 + workbox-core: 7.3.0 - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + wrap-ansi@6.2.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: dependencies: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 - /wrap-ansi@9.0.0: - resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} - engines: {node: '>=18'} + wrap-ansi@9.0.0: dependencies: ansi-styles: 6.2.1 - string-width: 7.1.0 + string-width: 7.2.0 strip-ansi: 7.1.0 - dev: true - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true + wrappy@1.0.2: {} - /write-file-atomic@3.0.3: - resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + write-file-atomic@3.0.3: dependencies: imurmurhash: 0.1.4 is-typedarray: 1.0.0 signal-exit: 3.0.7 typedarray-to-buffer: 3.1.5 - dev: true - /write-file-atomic@4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + write-file-atomic@4.0.2: dependencies: imurmurhash: 0.1.4 signal-exit: 3.0.7 - dev: true - /ws@8.13.0: - resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true + ws@8.17.1: {} - /ws@8.16.0: - resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true + ws@8.18.0: {} - /ws@8.5.0: - resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true + xdg-basedir@5.1.0: {} - /xdg-basedir@5.1.0: - resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} - engines: {node: '>=12'} - dev: true + xml-name-validator@5.0.0: {} - /xml-name-validator@5.0.0: - resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} - engines: {node: '>=18'} - dev: true + xmlbuilder@15.1.1: {} - /xmlbuilder@15.1.1: - resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} - engines: {node: '>=8.0'} - dev: true + xmlchars@2.2.0: {} - /xmlchars@2.2.0: - resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - dev: true - - /xxhashjs@0.2.2: - resolution: {integrity: sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==} + xxhashjs@0.2.2: dependencies: cuint: 0.2.2 - dev: true - /y18n@4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - dev: true + y18n@4.0.3: {} - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true + y18n@5.0.8: {} - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true + yallist@3.1.1: {} - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true + yaml@2.7.0: {} - /yaml@2.3.4: - resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} - engines: {node: '>= 14'} - dev: true - - /yaml@2.4.1: - resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} - engines: {node: '>= 14'} - hasBin: true - - /yargs-parser@18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} + yargs-parser@18.1.3: dependencies: camelcase: 5.3.1 decamelize: 1.2.0 - dev: true - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: true + yargs-parser@20.2.9: {} - /yargs@15.4.1: - resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} - engines: {node: '>=8'} + yargs-parser@21.1.1: {} + + yargs@15.4.1: dependencies: cliui: 6.0.0 decamelize: 1.2.0 @@ -16177,38 +21220,24 @@ packages: which-module: 2.0.1 y18n: 4.0.3 yargs-parser: 18.1.3 - dev: true - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} + yargs@17.7.2: dependencies: cliui: 8.0.1 - escalade: 3.1.2 + escalade: 3.2.0 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: true - /yauzl@2.10.0: - resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yauzl@2.10.0: dependencies: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 - dev: true - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true + yocto-queue@0.1.0: {} - /yocto-queue@1.0.0: - resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} - engines: {node: '>=12.20'} - dev: true + yocto-queue@1.1.1: {} - /zwitch@2.0.4: - resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - dev: true + zwitch@2.0.4: {} diff --git a/renovate.json b/renovate.json index 01390f0f6..8a35d9d50 100644 --- a/renovate.json +++ b/renovate.json @@ -1,4 +1,5 @@ { + "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:base", ":rebaseStalePrs", @@ -31,8 +32,17 @@ "groupSlug": "all-patch", "matchPackagePatterns": ["*"], "matchUpdateTypes": ["patch"] + }, + { + "groupName": "eslint", + "matchPackagePatterns": ["eslint"] + }, + { + "groupName": "dompurify", + "matchPackagePatterns": ["dompurify"] } ], "dependencyDashboard": false, - "dependencyDashboardAutoclose": true + "dependencyDashboardAutoclose": true, + "rangeStrategy": "bump" } diff --git a/scripts/compare-timings.ts b/scripts/compare-timings.ts new file mode 100644 index 000000000..1dbfc41d0 --- /dev/null +++ b/scripts/compare-timings.ts @@ -0,0 +1,115 @@ +/** + * Compares new E2E test timings with previous timings and determines whether to keep the new timings. + * + * The script will: + * 1. Read old timings from git HEAD + * 2. Read new timings from the current file + * 3. Compare the timings and specs + * 4. Keep new timings if: + * - Specs were added/removed + * - Any timing changed by 20% or more + * 5. Revert to old timings if: + * - No significant timing changes + * + * This helps prevent unnecessary timing updates when test performance hasn't changed significantly. + */ + +import fs from 'node:fs'; +import path from 'node:path'; +import { execSync } from 'node:child_process'; + +interface Timing { + spec: string; + duration: number; +} + +interface TimingsFile { + durations: Timing[]; +} + +interface CleanupOptions { + keepNew: boolean; + reason: string; +} + +const TIMINGS_FILE = 'cypress/timings.json'; +const TIMINGS_PATH = path.join(process.cwd(), TIMINGS_FILE); + +function log(message: string): void { + // eslint-disable-next-line no-console + console.log(message); +} + +function readOldTimings(): TimingsFile { + try { + const oldContent = execSync(`git show HEAD:${TIMINGS_FILE}`, { encoding: 'utf8' }); + return JSON.parse(oldContent); + } catch { + log('Error getting old timings, using empty file'); + return { durations: [] }; + } +} + +function readNewTimings(): TimingsFile { + return JSON.parse(fs.readFileSync(TIMINGS_PATH, 'utf8')); +} + +function cleanupFiles({ keepNew, reason }: CleanupOptions): void { + if (keepNew) { + log(`Keeping new timings: ${reason}`); + } else { + log(`Reverting to old timings: ${reason}`); + execSync(`git checkout HEAD -- ${TIMINGS_FILE}`); + } +} + +function compareTimings(): void { + const oldTimings = readOldTimings(); + const newTimings = readNewTimings(); + + const oldSpecs = new Set(oldTimings.durations.map((d) => d.spec)); + const newSpecs = new Set(newTimings.durations.map((d) => d.spec)); + + // Check if specs were added or removed + const addedSpecs = [...newSpecs].filter((spec) => !oldSpecs.has(spec)); + const removedSpecs = [...oldSpecs].filter((spec) => !newSpecs.has(spec)); + + if (addedSpecs.length > 0 || removedSpecs.length > 0) { + log('Specs changed:'); + if (addedSpecs.length > 0) { + log(`Added: ${addedSpecs.join(', ')}`); + } + if (removedSpecs.length > 0) { + log(`Removed: ${removedSpecs.join(', ')}`); + } + return cleanupFiles({ keepNew: true, reason: 'Specs were added or removed' }); + } + + // Check timing variations + const timingChanges = newTimings.durations.map((newTiming) => { + const oldTiming = oldTimings.durations.find((d) => d.spec === newTiming.spec); + if (!oldTiming) { + throw new Error(`Could not find old timing for spec: ${newTiming.spec}`); + } + const change = Math.abs(newTiming.duration - oldTiming.duration); + const changePercent = change / oldTiming.duration; + return { spec: newTiming.spec, change, changePercent }; + }); + + // Filter changes that's more than 5 seconds and 20% different + const significantChanges = timingChanges.filter((t) => t.change > 5000 && t.changePercent >= 0.2); + + if (significantChanges.length === 0) { + log('No significant timing changes detected (threshold: 5s and 20%)'); + return cleanupFiles({ keepNew: false, reason: 'No significant timing changes' }); + } + + log('Significant timing changes:'); + significantChanges.forEach((t) => { + log(`${t.spec}: ${t.change.toFixed(1)}ms (${(t.changePercent * 100).toFixed(1)}%)`); + }); + + cleanupFiles({ keepNew: true, reason: 'Significant timing changes detected' }); +} + +compareTimings(); diff --git a/scripts/editor.bash b/scripts/editor.bash index 381012d30..d04246cc7 100755 --- a/scripts/editor.bash +++ b/scripts/editor.bash @@ -19,10 +19,12 @@ pnpm build:esbuild pnpm build:types # Clone the Mermaid Live Editor repository -rm -rf mermaid-live-editor -git clone --single-branch https://github.com/mermaid-js/mermaid-live-editor.git - +if [ ! -d "mermaid-live-editor" ]; then + git clone --single-branch https://github.com/mermaid-js/mermaid-live-editor.git +fi cd mermaid-live-editor +git clean -xdf +rm -rf docs/ # We have to use npm instead of yarn because it causes trouble in netlify # Install dependencies diff --git a/scripts/jison/lint.mts b/scripts/jison/lint.mts index 596ce308b..f52010e28 100644 --- a/scripts/jison/lint.mts +++ b/scripts/jison/lint.mts @@ -6,8 +6,9 @@ import { ESLint } from 'eslint'; import jison from 'jison'; const linter = new ESLint({ - overrideConfig: { rules: { 'no-console': 'error' }, parser: '@typescript-eslint/parser' }, - useEslintrc: false, + // @ts-expect-error ESLint types are incorrect + overrideConfigFile: true, + overrideConfig: { rules: { 'no-console': 'error' } }, }); const lint = async (file: string): Promise => { diff --git a/scripts/size.ts b/scripts/size.ts index 2190fd9ef..1c486197b 100644 --- a/scripts/size.ts +++ b/scripts/size.ts @@ -25,6 +25,7 @@ const formatBytes = (bytes: number): string => { if (bytes == 0) { return '0 Bytes'; } + bytes = Math.abs(bytes); const base = 1024; const decimals = 2; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; diff --git a/scripts/tsc-check.ts b/scripts/tsc-check.ts new file mode 100644 index 000000000..2e5b3016d --- /dev/null +++ b/scripts/tsc-check.ts @@ -0,0 +1,174 @@ +/** + * Verify the as-built tarballs can be imported into a fresh, out-of-tree TypeScript project. + */ + +/* eslint-disable no-console */ +import { mkdtemp, mkdir, writeFile, readFile, readdir, copyFile, rm } from 'node:fs/promises'; +import { execFileSync } from 'child_process'; +import * as path from 'path'; +import { fileURLToPath } from 'url'; +import { tmpdir } from 'node:os'; + +const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file +const __dirname = path.dirname(__filename); // get the name of the directory + +/** + * Packages to build and import + */ +const PACKAGES = { + mermaid: 'mermaid', + '@mermaid-js/layout-elk': 'mermaid-layout-elk', + // TODO: these don't import cleanly yet due to exotic tsconfig.json requirements + // '@mermaid-js/mermaid-zenuml': 'mermaid-zenuml', + // '@mermaid-js/parser': 'parser', +}; + +/** + * Files to create in the temporary package. + */ +const SRC = { + // a minimal description of a buildable package + 'package.json': (tarballs: Record) => + JSON.stringify( + { + dependencies: tarballs, + scripts: { build: 'tsc -b --verbose' }, + devDependencies: { + // these are somewhat-unexpectedly required, and a downstream would need + // to match the real `package.json` values + 'type-fest': '*', + '@types/d3': '^7.4.3', + typescript: '*', + }, + }, + null, + 2 + ), + // a fairly strict TypeScript configuration + 'tsconfig.json': () => + JSON.stringify( + { + compilerOptions: { + allowSyntheticDefaultImports: true, + composite: true, + declaration: true, + esModuleInterop: true, + incremental: true, + lib: ['dom', 'es2020'], + module: 'esnext', + moduleResolution: 'node', + noEmitOnError: true, + noImplicitAny: true, + noUnusedLocals: true, + sourceMap: true, + target: 'es2020', + rootDir: './src', + outDir: './lib', + strict: true, + tsBuildInfoFile: 'lib/.tsbuildinfo', + }, + }, + null, + 2 + ), + // the simplest possible script: will everything even import? + 'src/index.ts': (tarballs) => { + const imports: string[] = []; + const outputs: string[] = []; + let i = 0; + for (const pkg of Object.keys(tarballs)) { + imports.push(`import * as pkg_${i} from '${pkg}';`); + outputs.push(`console.log(pkg_${i});`); + i++; + } + return [...imports, ...outputs].join('\n'); + }, +}; + +/** + * Commands to run after source files are created. + * + * `npm` is used to detect any unwanted `pnpm`-specific runtime "features". + */ +const COMMANDS = [ + ['npm', 'install'], + ['npm', 'run', 'build'], +]; + +/** + * Built files to expect after commands are executed. + */ +const LIB = ['lib/index.js', 'lib/index.js.map', 'lib/index.d.ts', 'lib/.tsbuildinfo']; + +/** + * Run a small out-of-tree build. + */ +async function main() { + console.warn('Checking out-of-tree TypeScript build using', Object.keys(PACKAGES).join('\n')); + const cwd = await mkdtemp(path.join(tmpdir(), 'mermaid-tsc-check-')); + console.warn('... creating temporary folder', cwd); + const tarballs = await buildTarballs(cwd); + + for (const [filename, generate] of Object.entries(SRC)) { + const dest = path.join(cwd, filename); + await mkdir(path.dirname(dest), { recursive: true }); + console.warn('... creating', dest); + const text = generate(tarballs); + await writeFile(dest, text); + console.info(text); + } + + for (const argv of COMMANDS) { + console.warn('... in', cwd); + console.warn('>>>', ...argv); + execFileSync(argv[0], argv.slice(1), { cwd }); + } + + for (const lib of LIB) { + const checkLib = path.join(cwd, lib); + console.warn('... checking built file', checkLib); + await readFile(checkLib, 'utf-8'); + } + + console.warn('... deleting', cwd); + await rm(cwd, { recursive: true, force: true }); + console.warn('... tsc-check OK for\n', Object.keys(PACKAGES).join('\n')); +} + +/** Build all the tarballs. */ +async function buildTarballs(tmp: string): Promise> { + const dist = path.join(tmp, 'dist'); + await mkdir(dist); + const promises: Promise[] = []; + const tarballs: Record = {}; + for (const [pkg, srcPath] of Object.entries(PACKAGES)) { + promises.push(buildOneTarball(pkg, srcPath, dist, tarballs)); + } + await Promise.all(promises); + return tarballs; +} + +/** Build a single tarball. */ +async function buildOneTarball( + pkg: string, + srcPath: string, + dist: string, + tarballs: Record +): Promise { + const cwd = await mkdtemp(path.join(dist, 'pack-')); + const pkgDir = path.join(__dirname, '../packages', srcPath); + const argv = ['pnpm', 'pack', '--pack-destination', cwd]; + console.warn('>>>', ...argv); + execFileSync(argv[0], argv.slice(1), { cwd: pkgDir }); + const built = await readdir(cwd); + const dest = path.join(dist, built[0]); + await copyFile(path.join(cwd, built[0]), dest); + await rm(cwd, { recursive: true, force: true }); + tarballs[pkg] = dest; +} + +void main().catch((err) => { + console.error(err); + console.error('!!! tsc-check FAIL: temp folder left in place. see logs above for failure notes'); + process.exit(1); +}); diff --git a/tests/webpack/package.json b/tests/webpack/package.json index 5d211ca1b..12bb73195 100644 --- a/tests/webpack/package.json +++ b/tests/webpack/package.json @@ -1,5 +1,5 @@ { - "name": "webpack", + "name": "@mermaid-js/webpack-test", "version": "1.0.0", "description": "", "private": true, diff --git a/tests/webpack/src/index.js b/tests/webpack/src/index.js index e667cfc5d..dc5c253ba 100644 --- a/tests/webpack/src/index.js +++ b/tests/webpack/src/index.js @@ -1,5 +1,5 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable no-console */ +// eslint-disable-next-line @typescript-eslint/no-require-imports const mermaid = require('mermaid'); import mindmap from '@mermaid-js/mermaid-mindmap'; diff --git a/tests/webpack/webpack.config.js b/tests/webpack/webpack.config.js index 3c35a3922..2afc94374 100644 --- a/tests/webpack/webpack.config.js +++ b/tests/webpack/webpack.config.js @@ -1,4 +1,4 @@ -// eslint-disable-next-line @typescript-eslint/no-var-requires +// eslint-disable-next-line @typescript-eslint/no-require-imports const path = require('path'); module.exports = { diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index 5fd73bf1f..7b7934881 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -3,16 +3,21 @@ "extends": "./tsconfig.json", "compilerOptions": { // ensure that nobody can accidentally use this config for a build - "noEmit": true + "noEmit": true, + "allowJs": true }, "include": [ - "packages", - "tests", - "scripts", - "cypress", - "__mocks__", - "./.eslintrc.cjs", - "./*", - "demos/dev" + "./.build/*.ts", + "./.esbuild/*.ts", + "./.vite/*.ts", + "./cypress.config.ts", + "./tests", + "./scripts", + "./cypress", + "./__mocks__", + "./demos/dev", + "./vite.config.ts", + "./vitest.workspace.js", + "eslint.config.js" ] } diff --git a/tsconfig.json b/tsconfig.json index 4cbf209a3..bd343b278 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,7 @@ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ /* Language and Environment */ - "target": "ES6" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "target": "ES2018" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, "lib": [ "DOM", "ES2022" @@ -66,7 +66,7 @@ // "newLine": "crlf", /* Set the newline character for emitting files. */ // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + "noEmitOnError": false /* Disable emitting files if any type checking errors are reported. */, // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ @@ -75,7 +75,7 @@ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, - "preserveSymlinks": true /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */, + // "preserveSymlinks": true /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */, "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, /* Type Checking */ @@ -91,7 +91,7 @@ // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noImplicitReturns": true, /* Enable error reporting for code paths that do not explicitly return in a function. */ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ @@ -103,5 +103,5 @@ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ "skipLibCheck": true /* Skip type checking all .d.ts files. */ }, - "include": ["./package.json"] + "exclude": ["**/node_modules/*", "**/dist/*", ".git", "coverage"] } diff --git a/vite.config.ts b/vite.config.ts index 0cbf36013..0930de5b6 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -10,7 +10,6 @@ export default defineConfig({ plugins: [ jison(), jsonSchemaPlugin(), // handles .schema.yaml JSON Schema files - // @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite typescript({ compilerOptions: { declaration: false } }), ], test: { @@ -25,6 +24,7 @@ export default defineConfig({ exclude: [...defaultExclude, './tests/**', '**/__mocks__/**', '**/generated/'], }, includeSource: ['packages/*/src/**/*.{js,ts}'], + clearMocks: true, }, build: { /** If you set esmExternals to true, this plugins assumes that diff --git a/vitest.workspace.js b/vitest.workspace.js new file mode 100644 index 000000000..7140a6017 --- /dev/null +++ b/vitest.workspace.js @@ -0,0 +1,3 @@ +import { defineWorkspace } from 'vitest/config'; + +export default defineWorkspace(['./vite.config.ts', './packages/mermaid/src/docs/vite.config.ts']);